2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS CSR Sub System
4 * FILE: subsys/csr/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 CsrLoadServerDll
57 * The CsrLoadServerDll routine loads a CSR Server DLL and calls its entrypoint
60 * Pointer to the CSR Server DLL to load and call.
63 * Pointer to the name of the server's initialization function. If
64 * this parameter is NULL, the default ServerDllInitialize will be
67 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
75 CsrLoadServerDll(IN PCHAR DllString
,
76 IN PCHAR EntryPoint OPTIONAL
,
81 UNICODE_STRING TempString
, ErrorString
;
82 ULONG_PTR Parameters
[2];
83 HANDLE hServerDll
= NULL
;
85 PCSR_SERVER_DLL ServerDll
;
86 STRING EntryPointString
;
87 PCSR_SERVER_DLL_INIT_CALLBACK ServerDllInitProcedure
;
90 /* Check if it's beyond the maximum we support */
91 if (ServerId
>= CSR_SERVER_DLL_MAX
) return STATUS_TOO_MANY_NAMES
;
93 /* Check if it's already been loaded */
94 if (CsrLoadedServerDll
[ServerId
]) return STATUS_INVALID_PARAMETER
;
96 /* Convert the name to Unicode */
97 ASSERT(DllString
!= NULL
);
98 RtlInitAnsiString(&DllName
, DllString
);
99 Status
= RtlAnsiStringToUnicodeString(&TempString
, &DllName
, TRUE
);
100 if (!NT_SUCCESS(Status
)) return Status
;
102 /* If we are loading ourselves, don't actually load us */
103 if (ServerId
!= CSR_SRV_SERVER
)
106 Status
= LdrLoadDll(NULL
, 0, &TempString
, &hServerDll
);
107 if (!NT_SUCCESS(Status
))
109 /* Setup error parameters */
110 Parameters
[0] = (ULONG_PTR
)&TempString
;
111 Parameters
[1] = (ULONG_PTR
)&ErrorString
;
112 RtlInitUnicodeString(&ErrorString
, L
"Default Load Path");
114 /* Send a hard error */
115 NtRaiseHardError(Status
,
123 /* Get rid of the string */
124 RtlFreeUnicodeString(&TempString
);
125 if (!NT_SUCCESS(Status
)) return Status
;
128 /* Allocate a CSR DLL Object */
129 Size
= sizeof(CSR_SERVER_DLL
) + DllName
.MaximumLength
;
130 ServerDll
= RtlAllocateHeap(CsrHeap
, HEAP_ZERO_MEMORY
, Size
);
133 if (hServerDll
) LdrUnloadDll(hServerDll
);
134 return STATUS_NO_MEMORY
;
137 /* Set up the Object */
138 ServerDll
->Length
= Size
;
139 ServerDll
->SharedSection
= CsrSrvSharedSectionHeap
;
140 ServerDll
->Event
= CsrInitializationEvent
;
141 ServerDll
->Name
.Length
= DllName
.Length
;
142 ServerDll
->Name
.MaximumLength
= DllName
.MaximumLength
;
143 ServerDll
->Name
.Buffer
= (PCHAR
)(ServerDll
+ 1);
146 strncpy(ServerDll
->Name
.Buffer
, DllName
.Buffer
, DllName
.Length
);
148 ServerDll
->ServerId
= ServerId
;
149 ServerDll
->ServerHandle
= hServerDll
;
151 /* Now get the entrypoint */
154 /* Initialize a string for the entrypoint, or use the default */
155 RtlInitAnsiString(&EntryPointString
,
156 !(EntryPoint
) ? "ServerDllInitialization" :
159 /* Get a pointer to it */
160 Status
= LdrGetProcedureAddress(hServerDll
,
163 (PVOID
)&ServerDllInitProcedure
);
167 /* No handle, so we are loading ourselves */
168 ServerDllInitProcedure
= CsrServerDllInitialization
;
169 Status
= STATUS_SUCCESS
;
172 /* Check if we got the pointer, and call it */
173 if (NT_SUCCESS(Status
))
175 /* Get the result from the Server DLL */
176 Status
= ServerDllInitProcedure(ServerDll
);
178 /* Check for Success */
179 if (NT_SUCCESS(Status
))
182 * Add this Server's Per-Process Data Size to the total that each
185 CsrTotalPerProcessDataLength
+= ServerDll
->SizeOfProcessData
;
187 /* Save the pointer in our list */
188 CsrLoadedServerDll
[ServerDll
->ServerId
] = ServerDll
;
190 /* Does it use our generic heap? */
191 if (ServerDll
->SharedSection
!= CsrSrvSharedSectionHeap
)
193 /* No, save the pointer to its shared section in our list */
194 CsrSrvSharedStaticServerData
[ServerDll
->ServerId
] = ServerDll
->SharedSection
;
199 /* Use shared failure code */
206 /* Server Init failed, unload it */
207 if (hServerDll
) LdrUnloadDll(hServerDll
);
209 /* Delete the Object */
210 RtlFreeHeap(CsrHeap
, 0, ServerDll
);
213 /* Return to caller */
218 * @name CsrServerDllInitialization
221 * The CsrServerDllInitialization is the initialization routine for
222 * the this Server DLL.
224 * @param LoadedServerDll
225 * Pointer to the CSR Server DLL structure representing this Server DLL.
227 * @return STATUS_SUCCESS.
234 CsrServerDllInitialization(IN PCSR_SERVER_DLL LoadedServerDll
)
236 /* Setup the DLL Object */
237 LoadedServerDll
->ApiBase
= 0;
238 LoadedServerDll
->HighestApiSupported
= 5;
239 LoadedServerDll
->DispatchTable
= CsrServerApiDispatchTable
;
240 LoadedServerDll
->ValidTable
= CsrServerApiServerValidTable
;
241 LoadedServerDll
->NameTable
= CsrServerApiNameTable
;
242 LoadedServerDll
->SizeOfProcessData
= 0;
243 LoadedServerDll
->ConnectCallback
= NULL
;
244 LoadedServerDll
->DisconnectCallback
= NULL
;
247 return STATUS_SUCCESS
;
251 * @name CsrSrvClientConnect
253 * The CsrSrvClientConnect CSR API handles a new connection to a server DLL.
256 * Pointer to the CSR API Message for this request.
259 * Optional reply to this request.
261 * @return STATUS_SUCCESS in case of success, STATUS_INVALID_PARAMETER
262 * or STATUS_TOO_MANY_NAMES in case of failure.
269 CsrSrvClientConnect(IN OUT PCSR_API_MESSAGE ApiMessage
,
270 IN OUT PULONG Reply OPTIONAL
)
273 PCSR_CLIENT_CONNECT ClientConnect
;
274 PCSR_SERVER_DLL ServerDll
;
275 PCSR_PROCESS CurrentProcess
= ((PCSR_THREAD
)NtCurrentTeb()->CsrClientThread
)->Process
;
277 /* Load the Message, set default reply */
278 ClientConnect
= (PCSR_CLIENT_CONNECT
)&ApiMessage
->CsrClientConnect
;
281 /* Validate the ServerID */
282 if (ClientConnect
->ServerId
>= CSR_SERVER_DLL_MAX
)
284 return STATUS_TOO_MANY_NAMES
;
286 else if (!CsrLoadedServerDll
[ClientConnect
->ServerId
])
288 return STATUS_INVALID_PARAMETER
;
291 /* Validate the Message Buffer */
292 if (!(CsrValidateMessageBuffer(ApiMessage
,
293 ClientConnect
->ConnectionInfo
,
294 ClientConnect
->ConnectionInfoSize
,
297 /* Fail due to buffer overflow or other invalid buffer */
298 return STATUS_INVALID_PARAMETER
;
301 /* Load the Server DLL */
302 ServerDll
= CsrLoadedServerDll
[ClientConnect
->ServerId
];
304 /* Check if it has a Connect Callback */
305 if (ServerDll
->ConnectCallback
)
307 /* Call the callback */
308 Status
= ServerDll
->ConnectCallback(CurrentProcess
,
309 ClientConnect
->ConnectionInfo
,
310 &ClientConnect
->ConnectionInfoSize
);
315 Status
= STATUS_SUCCESS
;
323 * @name CsrSrvCreateSharedSection
325 * The CsrSrvCreateSharedSection creates the Shared Section that all CSR Server
326 * DLLs and Clients can use to share data.
328 * @param ParameterValue
329 * Specially formatted string from our registry command-line which
330 * specifies various arguments for the shared section.
332 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
340 CsrSrvCreateSharedSection(IN PCHAR ParameterValue
)
342 PCHAR SizeValue
= ParameterValue
;
345 LARGE_INTEGER SectionSize
;
347 PPEB Peb
= NtCurrentPeb();
349 /* If there's no parameter, fail */
350 if (!ParameterValue
) return STATUS_INVALID_PARAMETER
;
352 /* Find the first comma, and null terminate */
355 if (*SizeValue
== ',')
357 *SizeValue
++ = ANSI_NULL
;
366 /* Make sure it's valid */
367 if (!*SizeValue
) return STATUS_INVALID_PARAMETER
;
369 /* Convert it to an integer */
370 Status
= RtlCharToInteger(SizeValue
, 0, &Size
);
371 if (!NT_SUCCESS(Status
)) return Status
;
373 /* Multiply by 1024 entries and round to page size */
374 CsrSrvSharedSectionSize
= ROUND_UP(Size
* 1024, CsrNtSysInfo
.PageSize
);
376 /* Create the Secion */
377 SectionSize
.LowPart
= CsrSrvSharedSectionSize
;
378 SectionSize
.HighPart
= 0;
379 Status
= NtCreateSection(&CsrSrvSharedSection
,
383 PAGE_EXECUTE_READWRITE
,
384 SEC_BASED
| SEC_RESERVE
,
386 if (!NT_SUCCESS(Status
)) return Status
;
388 /* Map the section */
389 Status
= NtMapViewOfSection(CsrSrvSharedSection
,
391 &CsrSrvSharedSectionBase
,
398 PAGE_EXECUTE_READWRITE
);
399 if (!NT_SUCCESS(Status
))
402 NtClose(CsrSrvSharedSection
);
406 /* FIXME: Write the value to registry */
408 /* The Heap is the same place as the Base */
409 CsrSrvSharedSectionHeap
= CsrSrvSharedSectionBase
;
411 /* Create the heap */
412 if (!(RtlCreateHeap(HEAP_ZERO_MEMORY
| HEAP_CLASS_7
,
413 CsrSrvSharedSectionHeap
,
414 CsrSrvSharedSectionSize
,
419 /* Failure, unmap section and return */
420 NtUnmapViewOfSection(NtCurrentProcess(), CsrSrvSharedSectionBase
);
421 NtClose(CsrSrvSharedSection
);
422 return STATUS_NO_MEMORY
;
425 /* Now allocate space from the heap for the Shared Data */
426 CsrSrvSharedStaticServerData
= RtlAllocateHeap(CsrSrvSharedSectionHeap
,
430 if (!CsrSrvSharedStaticServerData
) return STATUS_NO_MEMORY
;
432 /* Write the values to the PEB */
433 Peb
->ReadOnlySharedMemoryBase
= CsrSrvSharedSectionBase
;
434 Peb
->ReadOnlySharedMemoryHeap
= CsrSrvSharedSectionHeap
;
435 Peb
->ReadOnlyStaticServerData
= CsrSrvSharedStaticServerData
;
438 return STATUS_SUCCESS
;
442 * @name CsrSrvAttachSharedSection
444 * The CsrSrvAttachSharedSection maps the CSR Shared Section into a new
445 * CSR Process' address space, and returns the pointers to the section
446 * through the Connection Info structure.
449 * Pointer to the CSR Process that is attempting a connection.
452 * Pointer to the CSR Connection Info structure for the incoming
455 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
463 CsrSrvAttachSharedSection(IN PCSR_PROCESS CsrProcess OPTIONAL
,
464 OUT PCSR_CONNECTION_INFO ConnectInfo
)
469 /* Check if we have a process */
472 /* Map the sectio into this process */
473 Status
= NtMapViewOfSection(CsrSrvSharedSection
,
474 CsrProcess
->ProcessHandle
,
475 &CsrSrvSharedSectionBase
,
483 if (!NT_SUCCESS(Status
)) return Status
;
486 /* Write the values in the Connection Info structure */
487 ConnectInfo
->SharedSectionBase
= CsrSrvSharedSectionBase
;
488 ConnectInfo
->SharedSectionHeap
= CsrSrvSharedSectionHeap
;
489 ConnectInfo
->SharedSectionData
= CsrSrvSharedStaticServerData
;
492 return STATUS_SUCCESS
;
496 * @name CsrSrvIdentifyAlertableThread
499 * The CsrSrvIdentifyAlertableThread CSR API marks a CSR Thread as alertable.
502 * Pointer to the CSR API Message for this request.
505 * Pointer to an optional reply to this request.
507 * @return STATUS_SUCCESS.
514 CsrSrvIdentifyAlertableThread(IN OUT PCSR_API_MESSAGE ApiMessage
,
517 PCSR_THREAD CsrThread
= NtCurrentTeb()->CsrClientThread
;
519 /* Set the alertable flag */
520 CsrThread
->Flags
|= CsrThreadAltertable
;
523 return STATUS_SUCCESS
;
527 * @name CsrSrvSetPriorityClass
530 * The CsrSrvSetPriorityClass CSR API is deprecated.
533 * Pointer to the CSR API Message for this request.
536 * Pointer to an optional reply to this request.
538 * @return STATUS_SUCCESS.
545 CsrSrvSetPriorityClass(IN OUT PCSR_API_MESSAGE ApiMessage
,
549 return STATUS_SUCCESS
;
553 * @name CsrSrvUnusedFunction
556 * The CsrSrvUnusedFunction CSR API is a stub for deprecated APIs.
558 * The CsrSrvSetPriorityClass CSR API is deprecated.
561 * Pointer to the CSR API Message for this request.
564 * Pointer to an optional reply to this request.
566 * @return STATUS_INVALID_PARAMETER.
568 * @remarks CsrSrvSetPriorityClass does not use this stub because it must
574 CsrSrvUnusedFunction(IN OUT PCSR_API_MESSAGE ApiMessage
,
578 return STATUS_INVALID_PARAMETER
;
581 /* PUBLIC FUNCTIONS***********************************************************/
584 * @name CsrSetCallingSpooler
587 * the CsrSetCallingSpooler routine is deprecated.
594 * @remarks This routine was used in archaic versions of NT for Printer Drivers.
599 CsrSetCallingSpooler(ULONG Reserved
)
606 * @name CsrUnhandledExceptionFilter
609 * The CsrUnhandledExceptionFilter routine handles all exceptions
610 * within SEH-protected blocks.
612 * @param ExceptionPointers
613 * System-defined Argument.
615 * @return EXCEPTION_EXECUTE_HANDLER.
622 CsrUnhandledExceptionFilter(IN PEXCEPTION_POINTERS ExceptionInfo
)
624 SYSTEM_KERNEL_DEBUGGER_INFORMATION DebuggerInfo
;
625 EXCEPTION_DISPOSITION Result
= EXCEPTION_EXECUTE_HANDLER
;
628 UNICODE_STRING ErrorSource
;
629 ULONG_PTR ErrorParameters
[4];
632 /* Check if a debugger is installed */
633 Status
= NtQuerySystemInformation(SystemKernelDebuggerInformation
,
635 sizeof(DebuggerInfo
),
638 /* Check if this is Session 0, and the Debugger is Enabled */
639 if ((NtCurrentPeb()->SessionId
) && (NT_SUCCESS(Status
)) &&
640 (DebuggerInfo
.KernelDebuggerEnabled
))
642 /* Call the Unhandled Exception Filter */
643 if ((Result
= RtlUnhandledExceptionFilter(ExceptionInfo
)) !=
644 EXCEPTION_CONTINUE_EXECUTION
)
646 /* We're going to raise an error. Get Shutdown Privilege first */
647 Status
= RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE
,
652 /* Use the Process token if that failed */
653 if (Status
== STATUS_NO_TOKEN
)
655 Status
= RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE
,
661 /* Initialize our Name String */
662 RtlInitUnicodeString(&ErrorSource
, L
"Windows SubSystem");
664 /* Set the parameters */
665 ErrorParameters
[0] = (ULONG_PTR
)&ErrorSource
;
666 ErrorParameters
[1] = ExceptionInfo
->ExceptionRecord
->ExceptionCode
;
667 ErrorParameters
[2] = (ULONG_PTR
)ExceptionInfo
->ExceptionRecord
->ExceptionAddress
;
668 ErrorParameters
[3] = (ULONG_PTR
)ExceptionInfo
->ContextRecord
;
671 Status
= NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED
,
675 OptionShutdownSystem
,
679 /* Just terminate us */
680 NtTerminateProcess(NtCurrentProcess(),
681 ExceptionInfo
->ExceptionRecord
->ExceptionCode
);