2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS CSR Sub System
4 * FILE: subsystems/win32/csrss/csrsrv/server.c
5 * PURPOSE: CSR Server DLL Server Functions
6 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
9 /* INCLUDES ******************************************************************/
15 /* DATA **********************************************************************/
17 PCSR_API_ROUTINE CsrServerApiDispatchTable
[5] =
22 CsrSrvIdentifyAlertableThread
,
23 CsrSrvSetPriorityClass
26 BOOLEAN CsrServerApiServerValidTable
[5] =
35 PCHAR CsrServerApiNameTable
[5] =
40 "IdentifyAlertableThread",
44 PCSR_SERVER_DLL CsrLoadedServerDll
[CSR_SERVER_DLL_MAX
];
45 PVOID CsrSrvSharedSectionHeap
;
46 PVOID CsrSrvSharedSectionBase
;
47 PVOID
*CsrSrvSharedStaticServerData
;
48 ULONG CsrSrvSharedSectionSize
;
49 HANDLE CsrSrvSharedSection
;
51 /* PRIVATE FUNCTIONS**********************************************************/
54 * @name CsrServerDllInitialization
57 * The CsrServerDllInitialization is the initialization routine for
58 * the this Server DLL.
60 * @param LoadedServerDll
61 * Pointer to the CSR Server DLL structure representing this Server DLL.
63 * @return STATUS_SUCCESS.
70 CsrServerDllInitialization(IN PCSR_SERVER_DLL LoadedServerDll
)
72 /* Setup the DLL Object */
73 LoadedServerDll
->ApiBase
= 0;
74 LoadedServerDll
->HighestApiSupported
= CsrpMaxApiNumber
;
75 LoadedServerDll
->DispatchTable
= CsrServerApiDispatchTable
;
76 LoadedServerDll
->ValidTable
= CsrServerApiServerValidTable
;
77 LoadedServerDll
->NameTable
= CsrServerApiNameTable
;
78 LoadedServerDll
->SizeOfProcessData
= 0;
79 LoadedServerDll
->ConnectCallback
= NULL
;
80 LoadedServerDll
->DisconnectCallback
= NULL
;
83 return STATUS_SUCCESS
;
87 * @name CsrLoadServerDll
90 * The CsrLoadServerDll routine loads a CSR Server DLL and calls its entrypoint
93 * Pointer to the CSR Server DLL to load and call.
96 * Pointer to the name of the server's initialization function. If
97 * this parameter is NULL, the default ServerDllInitialize will be
100 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
108 CsrLoadServerDll(IN PCHAR DllString
,
109 IN PCHAR EntryPoint OPTIONAL
,
114 UNICODE_STRING TempString
, ErrorString
;
115 ULONG_PTR Parameters
[2];
116 HANDLE hServerDll
= NULL
;
118 PCSR_SERVER_DLL ServerDll
;
119 STRING EntryPointString
;
120 PCSR_SERVER_DLL_INIT_CALLBACK ServerDllInitProcedure
;
123 /* Check if it's beyond the maximum we support */
124 if (ServerId
>= CSR_SERVER_DLL_MAX
) return STATUS_TOO_MANY_NAMES
;
126 /* Check if it's already been loaded */
127 if (CsrLoadedServerDll
[ServerId
]) return STATUS_INVALID_PARAMETER
;
129 /* Convert the name to Unicode */
130 ASSERT(DllString
!= NULL
);
131 RtlInitAnsiString(&DllName
, DllString
);
132 Status
= RtlAnsiStringToUnicodeString(&TempString
, &DllName
, TRUE
);
133 if (!NT_SUCCESS(Status
)) return Status
;
135 /* If we are loading ourselves, don't actually load us */
136 if (ServerId
!= CSR_SRV_SERVER
)
139 Status
= LdrLoadDll(NULL
, 0, &TempString
, &hServerDll
);
140 if (!NT_SUCCESS(Status
))
142 /* Setup error parameters */
143 Parameters
[0] = (ULONG_PTR
)&TempString
;
144 Parameters
[1] = (ULONG_PTR
)&ErrorString
;
145 RtlInitUnicodeString(&ErrorString
, L
"Default Load Path");
147 /* Send a hard error */
148 NtRaiseHardError(Status
,
156 /* Get rid of the string */
157 RtlFreeUnicodeString(&TempString
);
158 if (!NT_SUCCESS(Status
)) return Status
;
161 /* Allocate a CSR DLL Object */
162 Size
= sizeof(CSR_SERVER_DLL
) + DllName
.MaximumLength
;
163 ServerDll
= RtlAllocateHeap(CsrHeap
, HEAP_ZERO_MEMORY
, Size
);
166 if (hServerDll
) LdrUnloadDll(hServerDll
);
167 return STATUS_NO_MEMORY
;
170 /* Set up the Object */
171 ServerDll
->Length
= Size
;
172 ServerDll
->SharedSection
= CsrSrvSharedSectionHeap
;
173 ServerDll
->Event
= CsrInitializationEvent
;
174 ServerDll
->Name
.Length
= DllName
.Length
;
175 ServerDll
->Name
.MaximumLength
= DllName
.MaximumLength
;
176 ServerDll
->Name
.Buffer
= (PCHAR
)(ServerDll
+ 1);
179 strncpy(ServerDll
->Name
.Buffer
, DllName
.Buffer
, DllName
.Length
);
181 ServerDll
->ServerId
= ServerId
;
182 ServerDll
->ServerHandle
= hServerDll
;
184 /* Now get the entrypoint */
187 /* Initialize a string for the entrypoint, or use the default */
188 RtlInitAnsiString(&EntryPointString
,
189 !(EntryPoint
) ? "ServerDllInitialization" :
192 /* Get a pointer to it */
193 Status
= LdrGetProcedureAddress(hServerDll
,
196 (PVOID
)&ServerDllInitProcedure
);
200 /* No handle, so we are loading ourselves */
201 ServerDllInitProcedure
= CsrServerDllInitialization
;
202 Status
= STATUS_SUCCESS
;
205 /* Check if we got the pointer, and call it */
206 if (NT_SUCCESS(Status
))
208 /* Get the result from the Server DLL */
209 Status
= ServerDllInitProcedure(ServerDll
);
211 /* Check for Success */
212 if (NT_SUCCESS(Status
))
215 * Add this Server's Per-Process Data Size to the total that each
218 CsrTotalPerProcessDataLength
+= ServerDll
->SizeOfProcessData
;
220 /* Save the pointer in our list */
221 CsrLoadedServerDll
[ServerDll
->ServerId
] = ServerDll
;
223 /* Does it use our generic heap? */
224 if (ServerDll
->SharedSection
!= CsrSrvSharedSectionHeap
)
226 /* No, save the pointer to its shared section in our list */
227 CsrSrvSharedStaticServerData
[ServerDll
->ServerId
] = ServerDll
->SharedSection
;
230 /* ReactOS Specific hax */
231 if (ServerDll
->HighestApiSupported
== 0xDEADBABE)
233 Status
= CsrApiRegisterDefinitions((PVOID
)ServerDll
->DispatchTable
);
238 /* Use shared failure code */
245 /* Server Init failed, unload it */
246 if (hServerDll
) LdrUnloadDll(hServerDll
);
248 /* Delete the Object */
249 RtlFreeHeap(CsrHeap
, 0, ServerDll
);
252 /* Return to caller */
257 * @name CsrSrvClientConnect
259 * The CsrSrvClientConnect CSR API handles a new connection to a server DLL.
262 * Pointer to the CSR API Message for this request.
265 * Optional reply to this request.
267 * @return STATUS_SUCCESS in case of success, STATUS_INVALID_PARAMETER
268 * or STATUS_TOO_MANY_NAMES in case of failure.
275 CsrSrvClientConnect(IN OUT PCSR_API_MESSAGE ApiMessage
,
276 IN OUT PULONG Reply OPTIONAL
)
279 return STATUS_SUCCESS
;
282 PCSR_CLIENT_CONNECT ClientConnect
;
283 PCSR_SERVER_DLL ServerDll
;
284 PCSR_PROCESS CurrentProcess
= ((PCSR_THREAD
)NtCurrentTeb()->CsrClientThread
)->Process
;
286 /* Load the Message, set default reply */
287 ClientConnect
= (PCSR_CLIENT_CONNECT
)&ApiMessage
->CsrClientConnect
;
290 /* Validate the ServerID */
291 if (ClientConnect
->ServerId
>= CSR_SERVER_DLL_MAX
)
293 return STATUS_TOO_MANY_NAMES
;
295 else if (!CsrLoadedServerDll
[ClientConnect
->ServerId
])
297 return STATUS_INVALID_PARAMETER
;
300 /* Validate the Message Buffer */
301 if (!(CsrValidateMessageBuffer(ApiMessage
,
302 ClientConnect
->ConnectionInfo
,
303 ClientConnect
->ConnectionInfoSize
,
306 /* Fail due to buffer overflow or other invalid buffer */
307 return STATUS_INVALID_PARAMETER
;
310 /* Load the Server DLL */
311 ServerDll
= CsrLoadedServerDll
[ClientConnect
->ServerId
];
313 /* Check if it has a Connect Callback */
314 if (ServerDll
->ConnectCallback
)
316 /* Call the callback */
317 Status
= ServerDll
->ConnectCallback(CurrentProcess
,
318 ClientConnect
->ConnectionInfo
,
319 &ClientConnect
->ConnectionInfoSize
);
324 Status
= STATUS_SUCCESS
;
333 * @name CsrSrvCreateSharedSection
335 * The CsrSrvCreateSharedSection creates the Shared Section that all CSR Server
336 * DLLs and Clients can use to share data.
338 * @param ParameterValue
339 * Specially formatted string from our registry command-line which
340 * specifies various arguments for the shared section.
342 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
350 CsrSrvCreateSharedSection(IN PCHAR ParameterValue
)
352 PCHAR SizeValue
= ParameterValue
;
355 LARGE_INTEGER SectionSize
;
357 PPEB Peb
= NtCurrentPeb();
359 /* If there's no parameter, fail */
360 if (!ParameterValue
) return STATUS_INVALID_PARAMETER
;
362 /* Find the first comma, and null terminate */
365 if (*SizeValue
== ',')
367 *SizeValue
++ = ANSI_NULL
;
376 /* Make sure it's valid */
377 if (!*SizeValue
) return STATUS_INVALID_PARAMETER
;
379 /* Convert it to an integer */
380 Status
= RtlCharToInteger(SizeValue
, 0, &Size
);
381 if (!NT_SUCCESS(Status
)) return Status
;
383 /* Multiply by 1024 entries and round to page size */
384 CsrSrvSharedSectionSize
= ROUND_UP(Size
* 1024, CsrNtSysInfo
.PageSize
);
386 /* Create the Secion */
387 SectionSize
.LowPart
= CsrSrvSharedSectionSize
;
388 SectionSize
.HighPart
= 0;
389 Status
= NtCreateSection(&CsrSrvSharedSection
,
393 PAGE_EXECUTE_READWRITE
,
394 SEC_BASED
| SEC_RESERVE
,
396 if (!NT_SUCCESS(Status
)) return Status
;
398 /* Map the section */
399 Status
= NtMapViewOfSection(CsrSrvSharedSection
,
401 &CsrSrvSharedSectionBase
,
408 PAGE_EXECUTE_READWRITE
);
409 if (!NT_SUCCESS(Status
))
412 NtClose(CsrSrvSharedSection
);
416 /* FIXME: Write the value to registry */
418 /* The Heap is the same place as the Base */
419 CsrSrvSharedSectionHeap
= CsrSrvSharedSectionBase
;
421 /* Create the heap */
422 if (!(RtlCreateHeap(HEAP_ZERO_MEMORY
| HEAP_CLASS_7
,
423 CsrSrvSharedSectionHeap
,
424 CsrSrvSharedSectionSize
,
429 /* Failure, unmap section and return */
430 NtUnmapViewOfSection(NtCurrentProcess(), CsrSrvSharedSectionBase
);
431 NtClose(CsrSrvSharedSection
);
432 return STATUS_NO_MEMORY
;
435 /* Now allocate space from the heap for the Shared Data */
436 CsrSrvSharedStaticServerData
= RtlAllocateHeap(CsrSrvSharedSectionHeap
,
440 if (!CsrSrvSharedStaticServerData
) return STATUS_NO_MEMORY
;
442 /* Write the values to the PEB */
443 Peb
->ReadOnlySharedMemoryBase
= CsrSrvSharedSectionBase
;
444 Peb
->ReadOnlySharedMemoryHeap
= CsrSrvSharedSectionHeap
;
445 Peb
->ReadOnlyStaticServerData
= CsrSrvSharedStaticServerData
;
448 return STATUS_SUCCESS
;
452 * @name CsrSrvAttachSharedSection
454 * The CsrSrvAttachSharedSection maps the CSR Shared Section into a new
455 * CSR Process' address space, and returns the pointers to the section
456 * through the Connection Info structure.
459 * Pointer to the CSR Process that is attempting a connection.
462 * Pointer to the CSR Connection Info structure for the incoming
465 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
473 CsrSrvAttachSharedSection(IN PCSR_PROCESS CsrProcess OPTIONAL
,
474 OUT PCSR_CONNECTION_INFO ConnectInfo
)
479 /* Check if we have a process */
482 /* Map the section into this process */
483 DPRINT("CSR Process Handle: %p. CSR Process: %p\n", CsrProcess
->ProcessHandle
, CsrProcess
);
484 Status
= NtMapViewOfSection(CsrSrvSharedSection
,
485 CsrProcess
->ProcessHandle
,
486 &CsrSrvSharedSectionBase
,
494 if (!NT_SUCCESS(Status
)) return Status
;
497 /* Write the values in the Connection Info structure */
498 ConnectInfo
->SharedSectionBase
= CsrSrvSharedSectionBase
;
499 ConnectInfo
->SharedSectionHeap
= CsrSrvSharedSectionHeap
;
500 ConnectInfo
->SharedSectionData
= CsrSrvSharedStaticServerData
;
503 return STATUS_SUCCESS
;
507 * @name CsrSrvIdentifyAlertableThread
510 * The CsrSrvIdentifyAlertableThread CSR API marks a CSR Thread as alertable.
513 * Pointer to the CSR API Message for this request.
516 * Pointer to an optional reply to this request.
518 * @return STATUS_SUCCESS.
525 CsrSrvIdentifyAlertableThread(IN OUT PCSR_API_MESSAGE ApiMessage
,
528 PCSR_THREAD CsrThread
= NtCurrentTeb()->CsrClientThread
;
530 /* Set the alertable flag */
531 CsrThread
->Flags
|= CsrThreadAltertable
;
534 return STATUS_SUCCESS
;
538 * @name CsrSrvSetPriorityClass
541 * The CsrSrvSetPriorityClass CSR API is deprecated.
544 * Pointer to the CSR API Message for this request.
547 * Pointer to an optional reply to this request.
549 * @return STATUS_SUCCESS.
556 CsrSrvSetPriorityClass(IN OUT PCSR_API_MESSAGE ApiMessage
,
560 return STATUS_SUCCESS
;
564 * @name CsrSrvUnusedFunction
567 * The CsrSrvUnusedFunction CSR API is a stub for deprecated APIs.
569 * The CsrSrvSetPriorityClass CSR API is deprecated.
572 * Pointer to the CSR API Message for this request.
575 * Pointer to an optional reply to this request.
577 * @return STATUS_INVALID_PARAMETER.
579 * @remarks CsrSrvSetPriorityClass does not use this stub because it must
585 CsrSrvUnusedFunction(IN OUT PCSR_API_MESSAGE ApiMessage
,
589 return STATUS_INVALID_PARAMETER
;
592 /* PUBLIC FUNCTIONS***********************************************************/
595 * @name CsrSetCallingSpooler
598 * the CsrSetCallingSpooler routine is deprecated.
605 * @remarks This routine was used in archaic versions of NT for Printer Drivers.
610 CsrSetCallingSpooler(ULONG Reserved
)
617 * @name CsrUnhandledExceptionFilter
620 * The CsrUnhandledExceptionFilter routine handles all exceptions
621 * within SEH-protected blocks.
623 * @param ExceptionPointers
624 * System-defined Argument.
626 * @return EXCEPTION_EXECUTE_HANDLER.
633 CsrUnhandledExceptionFilter(IN PEXCEPTION_POINTERS ExceptionInfo
)
635 SYSTEM_KERNEL_DEBUGGER_INFORMATION DebuggerInfo
;
636 EXCEPTION_DISPOSITION Result
= EXCEPTION_EXECUTE_HANDLER
;
639 UNICODE_STRING ErrorSource
;
640 ULONG_PTR ErrorParameters
[4];
643 /* Check if a debugger is installed */
644 Status
= NtQuerySystemInformation(SystemKernelDebuggerInformation
,
646 sizeof(DebuggerInfo
),
649 /* Check if this is Session 0, and the Debugger is Enabled */
650 if ((NtCurrentPeb()->SessionId
) && (NT_SUCCESS(Status
)) &&
651 (DebuggerInfo
.KernelDebuggerEnabled
))
653 /* Call the Unhandled Exception Filter */
654 if ((Result
= RtlUnhandledExceptionFilter(ExceptionInfo
)) !=
655 EXCEPTION_CONTINUE_EXECUTION
)
657 /* We're going to raise an error. Get Shutdown Privilege first */
658 Status
= RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE
,
663 /* Use the Process token if that failed */
664 if (Status
== STATUS_NO_TOKEN
)
666 Status
= RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE
,
672 /* Initialize our Name String */
673 RtlInitUnicodeString(&ErrorSource
, L
"Windows SubSystem");
675 /* Set the parameters */
676 ErrorParameters
[0] = (ULONG_PTR
)&ErrorSource
;
677 ErrorParameters
[1] = ExceptionInfo
->ExceptionRecord
->ExceptionCode
;
678 ErrorParameters
[2] = (ULONG_PTR
)ExceptionInfo
->ExceptionRecord
->ExceptionAddress
;
679 ErrorParameters
[3] = (ULONG_PTR
)ExceptionInfo
->ContextRecord
;
682 Status
= NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED
,
686 OptionShutdownSystem
,
690 /* Just terminate us */
691 NtTerminateProcess(NtCurrentProcess(),
692 ExceptionInfo
->ExceptionRecord
->ExceptionCode
);