2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Client/Server Runtime SubSystem
4 * FILE: subsystems/win32/csrsrv/server.c
5 * PURPOSE: CSR Server DLL Server Functions
6 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
9 /* INCLUDES ******************************************************************/
16 /* DATA **********************************************************************/
18 PCSR_API_ROUTINE CsrServerApiDispatchTable
[CsrpMaxApiNumber
] =
23 CsrSrvIdentifyAlertableThread
,
24 CsrSrvSetPriorityClass
27 BOOLEAN CsrServerApiServerValidTable
[CsrpMaxApiNumber
] =
36 PCHAR CsrServerApiNameTable
[CsrpMaxApiNumber
] =
41 "IdentifyAlertableThread",
45 PCSR_SERVER_DLL CsrLoadedServerDll
[CSR_SERVER_DLL_MAX
];
46 PVOID CsrSrvSharedSectionHeap
;
47 PVOID CsrSrvSharedSectionBase
;
48 PVOID
*CsrSrvSharedStaticServerData
;
49 ULONG CsrSrvSharedSectionSize
;
50 HANDLE CsrSrvSharedSection
;
52 /* PRIVATE FUNCTIONS**********************************************************/
55 * @name CsrServerDllInitialization
58 * The CsrServerDllInitialization is the initialization routine for
59 * the this Server DLL.
61 * @param LoadedServerDll
62 * Pointer to the CSR Server DLL structure representing this Server DLL.
64 * @return STATUS_SUCCESS.
69 CSR_SERVER_DLL_INIT(CsrServerDllInitialization
)
71 /* Setup the DLL Object */
72 LoadedServerDll
->ApiBase
= 0;
73 LoadedServerDll
->HighestApiSupported
= CsrpMaxApiNumber
;
74 LoadedServerDll
->DispatchTable
= CsrServerApiDispatchTable
;
75 LoadedServerDll
->ValidTable
= CsrServerApiServerValidTable
;
76 LoadedServerDll
->NameTable
= CsrServerApiNameTable
;
77 LoadedServerDll
->SizeOfProcessData
= 0;
78 LoadedServerDll
->ConnectCallback
= NULL
;
79 LoadedServerDll
->DisconnectCallback
= NULL
;
82 return STATUS_SUCCESS
;
86 * @name CsrLoadServerDll
89 * The CsrLoadServerDll routine loads a CSR Server DLL and calls its entrypoint
92 * Pointer to the CSR Server DLL to load and call.
95 * Pointer to the name of the server's initialization function. If
96 * this parameter is NULL, the default ServerDllInitialize will be
99 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
107 CsrLoadServerDll(IN PCHAR DllString
,
108 IN PCHAR EntryPoint OPTIONAL
,
113 UNICODE_STRING TempString
, ErrorString
;
114 ULONG_PTR Parameters
[2];
115 HANDLE hServerDll
= NULL
;
117 PCSR_SERVER_DLL ServerDll
;
118 STRING EntryPointString
;
119 PCSR_SERVER_DLL_INIT_CALLBACK ServerDllInitProcedure
;
122 /* Check if it's beyond the maximum we support */
123 if (ServerId
>= CSR_SERVER_DLL_MAX
) return STATUS_TOO_MANY_NAMES
;
125 /* Check if it's already been loaded */
126 if (CsrLoadedServerDll
[ServerId
]) return STATUS_INVALID_PARAMETER
;
128 /* Convert the name to Unicode */
129 ASSERT(DllString
!= NULL
);
130 RtlInitAnsiString(&DllName
, DllString
);
131 Status
= RtlAnsiStringToUnicodeString(&TempString
, &DllName
, TRUE
);
132 if (!NT_SUCCESS(Status
)) return Status
;
134 /* If we are loading ourselves, don't actually load us */
135 if (ServerId
!= CSRSRV_SERVERDLL_INDEX
)
138 Status
= LdrLoadDll(NULL
, 0, &TempString
, &hServerDll
);
139 if (!NT_SUCCESS(Status
))
141 /* Setup error parameters */
142 Parameters
[0] = (ULONG_PTR
)&TempString
;
143 Parameters
[1] = (ULONG_PTR
)&ErrorString
;
144 RtlInitUnicodeString(&ErrorString
, L
"Default Load Path");
146 /* Send a hard error */
147 NtRaiseHardError(Status
,
155 /* Get rid of the string */
156 RtlFreeUnicodeString(&TempString
);
157 if (!NT_SUCCESS(Status
)) return Status
;
160 /* Allocate a CSR DLL Object */
161 Size
= sizeof(CSR_SERVER_DLL
) + DllName
.MaximumLength
;
162 ServerDll
= RtlAllocateHeap(CsrHeap
, HEAP_ZERO_MEMORY
, Size
);
165 if (hServerDll
) LdrUnloadDll(hServerDll
);
166 return STATUS_NO_MEMORY
;
169 /* Set up the Object */
170 ServerDll
->Length
= Size
;
171 ServerDll
->SharedSection
= CsrSrvSharedSectionHeap
; // Send to the server dll our shared heap pointer.
172 ServerDll
->Event
= CsrInitializationEvent
;
173 ServerDll
->Name
.Length
= DllName
.Length
;
174 ServerDll
->Name
.MaximumLength
= DllName
.MaximumLength
;
175 ServerDll
->Name
.Buffer
= (PCHAR
)(ServerDll
+ 1);
178 strncpy(ServerDll
->Name
.Buffer
, DllName
.Buffer
, DllName
.Length
);
180 ServerDll
->ServerId
= ServerId
;
181 ServerDll
->ServerHandle
= hServerDll
;
183 /* Now get the entrypoint */
186 /* Initialize a string for the entrypoint, or use the default */
187 RtlInitAnsiString(&EntryPointString
,
188 EntryPoint
? EntryPoint
: "ServerDllInitialization");
190 /* Get a pointer to it */
191 Status
= LdrGetProcedureAddress(hServerDll
,
194 (PVOID
)&ServerDllInitProcedure
);
198 /* No handle, so we are loading ourselves */
199 ServerDllInitProcedure
= CsrServerDllInitialization
;
200 Status
= STATUS_SUCCESS
;
203 /* Check if we got the pointer, and call it */
204 if (NT_SUCCESS(Status
))
206 /* Get the result from the Server DLL */
207 Status
= ServerDllInitProcedure(ServerDll
);
208 if (NT_SUCCESS(Status
))
211 * Add this Server's Per-Process Data Size to the total that each
214 CsrTotalPerProcessDataLength
+= ServerDll
->SizeOfProcessData
;
216 /* Save the pointer in our list */
217 CsrLoadedServerDll
[ServerDll
->ServerId
] = ServerDll
;
219 /* Does it use our generic heap? */
220 if (ServerDll
->SharedSection
!= CsrSrvSharedSectionHeap
)
222 /* No, save the pointer to its shared section in our list */
223 CsrSrvSharedStaticServerData
[ServerDll
->ServerId
] = ServerDll
->SharedSection
;
226 #if 0 /* HACK: ReactOS Specific hax. REMOVE IT. */
227 if (ServerDll
->HighestApiSupported
== 0xDEADBABE)
229 // CSRSS_API_DEFINITIONS == Old structure.
230 Status
= CsrApiRegisterDefinitions((PVOID
)ServerDll
->DispatchTable
);
236 /* Use shared failure code */
243 /* Server Init failed, unload it */
244 if (hServerDll
) LdrUnloadDll(hServerDll
);
246 /* Delete the Object */
247 RtlFreeHeap(CsrHeap
, 0, ServerDll
);
250 /* Return to caller */
255 * @name CsrSrvClientConnect
257 * The CsrSrvClientConnect CSR API handles a new connection to a server DLL.
260 * Pointer to the CSR API Message for this request.
263 * Optional reply to this request.
265 * @return STATUS_SUCCESS in case of success, STATUS_INVALID_PARAMETER
266 * or STATUS_TOO_MANY_NAMES in case of failure.
273 CsrSrvClientConnect(IN OUT PCSR_API_MESSAGE ApiMessage
,
274 IN OUT PULONG Reply OPTIONAL
)
277 PCSR_CLIENT_CONNECT ClientConnect
;
278 PCSR_SERVER_DLL ServerDll
;
279 PCSR_PROCESS CurrentProcess
= CsrGetClientThread()->Process
;
281 /* Load the Message, set default reply */
282 ClientConnect
= &ApiMessage
->Data
.CsrClientConnect
;
285 /* Validate the ServerID */
286 if (ClientConnect
->ServerId
>= CSR_SERVER_DLL_MAX
)
288 return STATUS_TOO_MANY_NAMES
;
290 else if (!CsrLoadedServerDll
[ClientConnect
->ServerId
])
292 return STATUS_INVALID_PARAMETER
;
295 /* Validate the Message Buffer */
296 if (!(CsrValidateMessageBuffer(ApiMessage
,
297 ClientConnect
->ConnectionInfo
,
298 ClientConnect
->ConnectionInfoSize
,
301 /* Fail due to buffer overflow or other invalid buffer */
302 return STATUS_INVALID_PARAMETER
;
305 /* Load the Server DLL */
306 ServerDll
= CsrLoadedServerDll
[ClientConnect
->ServerId
];
308 /* Check if it has a Connect Callback */
309 if (ServerDll
->ConnectCallback
)
311 /* Call the callback */
312 Status
= ServerDll
->ConnectCallback(CurrentProcess
,
313 ClientConnect
->ConnectionInfo
,
314 &ClientConnect
->ConnectionInfoSize
);
319 Status
= STATUS_SUCCESS
;
327 * @name CsrSrvCreateSharedSection
329 * The CsrSrvCreateSharedSection creates the Shared Section that all CSR Server
330 * DLLs and Clients can use to share data.
332 * @param ParameterValue
333 * Specially formatted string from our registry command-line which
334 * specifies various arguments for the shared section.
336 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
344 CsrSrvCreateSharedSection(IN PCHAR ParameterValue
)
346 PCHAR SizeValue
= ParameterValue
;
349 LARGE_INTEGER SectionSize
;
351 PPEB Peb
= NtCurrentPeb();
353 /* If there's no parameter, fail */
354 if (!ParameterValue
) return STATUS_INVALID_PARAMETER
;
356 /* Find the first comma, and null terminate */
359 if (*SizeValue
== ',')
361 *SizeValue
++ = ANSI_NULL
;
370 /* Make sure it's valid */
371 if (!*SizeValue
) return STATUS_INVALID_PARAMETER
;
373 /* Convert it to an integer */
374 Status
= RtlCharToInteger(SizeValue
, 0, &Size
);
375 if (!NT_SUCCESS(Status
)) return Status
;
377 /* Multiply by 1024 entries and round to page size */
378 CsrSrvSharedSectionSize
= ROUND_UP(Size
* 1024, CsrNtSysInfo
.PageSize
);
380 /* Create the Secion */
381 SectionSize
.LowPart
= CsrSrvSharedSectionSize
;
382 SectionSize
.HighPart
= 0;
383 Status
= NtCreateSection(&CsrSrvSharedSection
,
387 PAGE_EXECUTE_READWRITE
,
388 SEC_BASED
| SEC_RESERVE
,
390 if (!NT_SUCCESS(Status
)) return Status
;
392 /* Map the section */
393 Status
= NtMapViewOfSection(CsrSrvSharedSection
,
395 &CsrSrvSharedSectionBase
,
402 PAGE_EXECUTE_READWRITE
);
403 if (!NT_SUCCESS(Status
))
406 NtClose(CsrSrvSharedSection
);
410 /* FIXME: Write the value to registry */
412 /* The Heap is the same place as the Base */
413 CsrSrvSharedSectionHeap
= CsrSrvSharedSectionBase
;
415 /* Create the heap */
416 if (!(RtlCreateHeap(HEAP_ZERO_MEMORY
| HEAP_CLASS_7
,
417 CsrSrvSharedSectionHeap
,
418 CsrSrvSharedSectionSize
,
423 /* Failure, unmap section and return */
424 NtUnmapViewOfSection(NtCurrentProcess(), CsrSrvSharedSectionBase
);
425 NtClose(CsrSrvSharedSection
);
426 return STATUS_NO_MEMORY
;
429 /* Now allocate space from the heap for the Shared Data */
430 CsrSrvSharedStaticServerData
= RtlAllocateHeap(CsrSrvSharedSectionHeap
,
434 if (!CsrSrvSharedStaticServerData
) return STATUS_NO_MEMORY
;
436 /* Write the values to the PEB */
437 Peb
->ReadOnlySharedMemoryBase
= CsrSrvSharedSectionBase
;
438 Peb
->ReadOnlySharedMemoryHeap
= CsrSrvSharedSectionHeap
;
439 Peb
->ReadOnlyStaticServerData
= CsrSrvSharedStaticServerData
;
442 return STATUS_SUCCESS
;
446 * @name CsrSrvAttachSharedSection
448 * The CsrSrvAttachSharedSection maps the CSR Shared Section into a new
449 * CSR Process' address space, and returns the pointers to the section
450 * through the Connection Info structure.
453 * Pointer to the CSR Process that is attempting a connection.
456 * Pointer to the CSR Connection Info structure for the incoming
459 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
467 CsrSrvAttachSharedSection(IN PCSR_PROCESS CsrProcess OPTIONAL
,
468 OUT PCSR_CONNECTION_INFO ConnectInfo
)
473 /* Check if we have a process */
476 /* Map the section into this process */
477 DPRINT("CSR Process Handle: %p. CSR Process: %p\n", CsrProcess
->ProcessHandle
, CsrProcess
);
478 Status
= NtMapViewOfSection(CsrSrvSharedSection
,
479 CsrProcess
->ProcessHandle
,
480 &CsrSrvSharedSectionBase
,
488 if (!NT_SUCCESS(Status
)) return Status
;
491 /* Write the values in the Connection Info structure */
492 ConnectInfo
->SharedSectionBase
= CsrSrvSharedSectionBase
;
493 ConnectInfo
->SharedSectionHeap
= CsrSrvSharedSectionHeap
;
494 ConnectInfo
->SharedSectionData
= CsrSrvSharedStaticServerData
;
497 return STATUS_SUCCESS
;
501 * @name CsrSrvIdentifyAlertableThread
504 * The CsrSrvIdentifyAlertableThread CSR API marks a CSR Thread as alertable.
507 * Pointer to the CSR API Message for this request.
510 * Pointer to an optional reply to this request.
512 * @return STATUS_SUCCESS.
519 CsrSrvIdentifyAlertableThread(IN OUT PCSR_API_MESSAGE ApiMessage
,
522 PCSR_THREAD CsrThread
= CsrGetClientThread();
524 /* Set the alertable flag */
525 CsrThread
->Flags
|= CsrThreadAltertable
;
528 return STATUS_SUCCESS
;
532 * @name CsrSrvSetPriorityClass
535 * The CsrSrvSetPriorityClass CSR API is deprecated.
538 * Pointer to the CSR API Message for this request.
541 * Pointer to an optional reply to this request.
543 * @return STATUS_SUCCESS.
550 CsrSrvSetPriorityClass(IN OUT PCSR_API_MESSAGE ApiMessage
,
554 return STATUS_SUCCESS
;
558 * @name CsrSrvUnusedFunction
561 * The CsrSrvUnusedFunction CSR API is a stub for deprecated APIs.
563 * The CsrSrvSetPriorityClass CSR API is deprecated.
566 * Pointer to the CSR API Message for this request.
569 * Pointer to an optional reply to this request.
571 * @return STATUS_INVALID_PARAMETER.
573 * @remarks CsrSrvSetPriorityClass does not use this stub because it must
579 CsrSrvUnusedFunction(IN OUT PCSR_API_MESSAGE ApiMessage
,
583 return STATUS_INVALID_PARAMETER
;
586 /* PUBLIC FUNCTIONS***********************************************************/
589 * @name CsrSetCallingSpooler
592 * the CsrSetCallingSpooler routine is deprecated.
599 * @remarks This routine was used in archaic versions of NT for Printer Drivers.
604 CsrSetCallingSpooler(ULONG Reserved
)
611 * @name CsrUnhandledExceptionFilter
614 * The CsrUnhandledExceptionFilter routine handles all exceptions
615 * within SEH-protected blocks.
617 * @param ExceptionPointers
618 * System-defined Argument.
620 * @return EXCEPTION_EXECUTE_HANDLER.
625 EXCEPTION_DISPOSITION
627 CsrUnhandledExceptionFilter(IN PEXCEPTION_POINTERS ExceptionInfo
)
629 SYSTEM_KERNEL_DEBUGGER_INFORMATION DebuggerInfo
;
630 EXCEPTION_DISPOSITION Result
= EXCEPTION_EXECUTE_HANDLER
;
633 UNICODE_STRING ErrorSource
;
634 ULONG_PTR ErrorParameters
[4];
637 /* Check if a debugger is installed */
638 Status
= NtQuerySystemInformation(SystemKernelDebuggerInformation
,
640 sizeof(DebuggerInfo
),
643 /* Check if this is Session 0, and the Debugger is Enabled */
644 if ((NtCurrentPeb()->SessionId
) && (NT_SUCCESS(Status
)) &&
645 (DebuggerInfo
.KernelDebuggerEnabled
))
647 /* Call the Unhandled Exception Filter */
648 if ((Result
= RtlUnhandledExceptionFilter(ExceptionInfo
)) !=
649 EXCEPTION_CONTINUE_EXECUTION
)
651 /* We're going to raise an error. Get Shutdown Privilege first */
652 Status
= RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE
,
657 /* Use the Process token if that failed */
658 if (Status
== STATUS_NO_TOKEN
)
660 Status
= RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE
,
666 /* Initialize our Name String */
667 RtlInitUnicodeString(&ErrorSource
, L
"Windows SubSystem");
669 /* Set the parameters */
670 ErrorParameters
[0] = (ULONG_PTR
)&ErrorSource
;
671 ErrorParameters
[1] = ExceptionInfo
->ExceptionRecord
->ExceptionCode
;
672 ErrorParameters
[2] = (ULONG_PTR
)ExceptionInfo
->ExceptionRecord
->ExceptionAddress
;
673 ErrorParameters
[3] = (ULONG_PTR
)ExceptionInfo
->ContextRecord
;
676 Status
= NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED
,
680 OptionShutdownSystem
,
684 /* Just terminate us */
685 NtTerminateProcess(NtCurrentProcess(),
686 ExceptionInfo
->ExceptionRecord
->ExceptionCode
);