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
= NULL
;
47 PVOID CsrSrvSharedSectionBase
= NULL
;
48 PVOID
*CsrSrvSharedStaticServerData
= NULL
;
49 ULONG CsrSrvSharedSectionSize
= 0;
50 HANDLE CsrSrvSharedSection
= NULL
;
52 /* PRIVATE FUNCTIONS **********************************************************/
55 * @name CsrServerDllInitialization
58 * The CsrServerDllInitialization is the initialization routine
59 * for 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.
96 * If this parameter is NULL, the default ServerDllInitialize
99 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
106 CsrLoadServerDll(IN PCHAR DllString
,
107 IN PCHAR EntryPoint OPTIONAL
,
112 UNICODE_STRING TempString
, ErrorString
;
113 ULONG_PTR Parameters
[2];
114 HANDLE hServerDll
= NULL
;
116 PCSR_SERVER_DLL ServerDll
;
117 STRING EntryPointString
;
118 PCSR_SERVER_DLL_INIT_CALLBACK ServerDllInitProcedure
;
121 /* Check if it's beyond the maximum we support */
122 if (ServerId
>= CSR_SERVER_DLL_MAX
) return STATUS_TOO_MANY_NAMES
;
124 /* Check if it's already been loaded */
125 if (CsrLoadedServerDll
[ServerId
]) return STATUS_INVALID_PARAMETER
;
127 /* Convert the name to Unicode */
128 ASSERT(DllString
!= NULL
);
129 RtlInitAnsiString(&DllName
, DllString
);
130 Status
= RtlAnsiStringToUnicodeString(&TempString
, &DllName
, TRUE
);
131 if (!NT_SUCCESS(Status
)) return Status
;
133 /* If we are loading ourselves, don't actually load us */
134 if (ServerId
!= CSRSRV_SERVERDLL_INDEX
)
137 Status
= LdrLoadDll(NULL
, 0, &TempString
, &hServerDll
);
138 if (!NT_SUCCESS(Status
))
140 /* Setup error parameters */
141 Parameters
[0] = (ULONG_PTR
)&TempString
;
142 Parameters
[1] = (ULONG_PTR
)&ErrorString
;
143 RtlInitUnicodeString(&ErrorString
, L
"Default Load Path");
145 /* Send a hard error */
146 NtRaiseHardError(Status
,
154 /* Get rid of the string */
155 RtlFreeUnicodeString(&TempString
);
156 if (!NT_SUCCESS(Status
)) return Status
;
159 /* Allocate a CSR DLL Object */
160 Size
= sizeof(CSR_SERVER_DLL
) + DllName
.MaximumLength
;
161 ServerDll
= RtlAllocateHeap(CsrHeap
, HEAP_ZERO_MEMORY
, Size
);
164 if (hServerDll
) LdrUnloadDll(hServerDll
);
165 return STATUS_NO_MEMORY
;
168 /* Set up the Object */
169 ServerDll
->Length
= Size
;
170 ServerDll
->SharedSection
= CsrSrvSharedSectionHeap
; // Send to the server dll our shared heap pointer.
171 ServerDll
->Event
= CsrInitializationEvent
;
172 ServerDll
->Name
.Length
= DllName
.Length
;
173 ServerDll
->Name
.MaximumLength
= DllName
.MaximumLength
;
174 ServerDll
->Name
.Buffer
= (PCHAR
)(ServerDll
+ 1);
177 strncpy(ServerDll
->Name
.Buffer
, DllName
.Buffer
, DllName
.Length
);
179 ServerDll
->ServerId
= ServerId
;
180 ServerDll
->ServerHandle
= hServerDll
;
182 /* Now get the entrypoint */
185 /* Initialize a string for the entrypoint, or use the default */
186 RtlInitAnsiString(&EntryPointString
,
187 EntryPoint
? EntryPoint
: "ServerDllInitialization");
189 /* Get a pointer to it */
190 Status
= LdrGetProcedureAddress(hServerDll
,
193 (PVOID
)&ServerDllInitProcedure
);
197 /* No handle, so we are loading ourselves */
198 ServerDllInitProcedure
= CsrServerDllInitialization
;
199 Status
= STATUS_SUCCESS
;
202 /* Check if we got the pointer, and call it */
203 if (NT_SUCCESS(Status
))
205 /* Get the result from the Server DLL */
206 Status
= ServerDllInitProcedure(ServerDll
);
207 if (NT_SUCCESS(Status
))
210 * Add this Server's Per-Process Data Size to the total that each
213 CsrTotalPerProcessDataLength
+= ServerDll
->SizeOfProcessData
;
215 /* Save the pointer in our list */
216 CsrLoadedServerDll
[ServerDll
->ServerId
] = ServerDll
;
218 /* Does it use our generic heap? */
219 if (ServerDll
->SharedSection
!= CsrSrvSharedSectionHeap
)
221 /* No, save the pointer to its shared section in our list */
222 CsrSrvSharedStaticServerData
[ServerDll
->ServerId
] = ServerDll
->SharedSection
;
227 if (!NT_SUCCESS(Status
))
229 /* Server Init failed, unload it */
230 if (hServerDll
) LdrUnloadDll(hServerDll
);
232 /* Delete the Object */
233 RtlFreeHeap(CsrHeap
, 0, ServerDll
);
236 /* Return to caller */
241 * @name CsrSrvClientConnect
243 * The CsrSrvClientConnect CSR API handles a new connection to a server DLL.
246 * Pointer to the CSR API Message for this request.
249 * Optional reply to this request.
251 * @return STATUS_SUCCESS in case of success, STATUS_INVALID_PARAMETER
252 * or STATUS_TOO_MANY_NAMES in case of failure.
257 CSR_API(CsrSrvClientConnect
)
260 PCSR_CLIENT_CONNECT ClientConnect
= &ApiMessage
->Data
.CsrClientConnect
;
261 PCSR_SERVER_DLL ServerDll
;
262 PCSR_PROCESS CurrentProcess
= CsrGetClientThread()->Process
;
264 /* Set default reply */
265 *ReplyCode
= CsrReplyImmediately
;
267 /* Validate the ServerID */
268 if (ClientConnect
->ServerId
>= CSR_SERVER_DLL_MAX
)
270 return STATUS_TOO_MANY_NAMES
;
272 else if (!CsrLoadedServerDll
[ClientConnect
->ServerId
])
274 return STATUS_INVALID_PARAMETER
;
277 /* Validate the Message Buffer */
278 if (!(CsrValidateMessageBuffer(ApiMessage
,
279 &ClientConnect
->ConnectionInfo
,
280 ClientConnect
->ConnectionInfoSize
,
283 /* Fail due to buffer overflow or other invalid buffer */
284 return STATUS_INVALID_PARAMETER
;
287 /* Load the Server DLL */
288 ServerDll
= CsrLoadedServerDll
[ClientConnect
->ServerId
];
290 /* Check if it has a Connect Callback */
291 if (ServerDll
->ConnectCallback
)
293 /* Call the callback */
294 Status
= ServerDll
->ConnectCallback(CurrentProcess
,
295 ClientConnect
->ConnectionInfo
,
296 &ClientConnect
->ConnectionInfoSize
);
301 Status
= STATUS_SUCCESS
;
309 * @name CsrSrvCreateSharedSection
311 * The CsrSrvCreateSharedSection creates the Shared Section that all
312 * CSR Server DLLs and Clients can use to share data.
314 * @param ParameterValue
315 * Specially formatted string from our registry command-line which
316 * specifies various arguments for the shared section.
318 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
325 CsrSrvCreateSharedSection(IN PCHAR ParameterValue
)
327 PCHAR SizeValue
= ParameterValue
;
330 LARGE_INTEGER SectionSize
;
332 PPEB Peb
= NtCurrentPeb();
334 /* If there's no parameter, fail */
335 if (!ParameterValue
) return STATUS_INVALID_PARAMETER
;
337 /* Find the first comma, and null terminate */
340 if (*SizeValue
== ',')
342 *SizeValue
++ = ANSI_NULL
;
351 /* Make sure it's valid */
352 if (!*SizeValue
) return STATUS_INVALID_PARAMETER
;
354 /* Convert it to an integer */
355 Status
= RtlCharToInteger(SizeValue
, 0, &Size
);
356 if (!NT_SUCCESS(Status
)) return Status
;
358 /* Multiply by 1024 entries and round to page size */
359 CsrSrvSharedSectionSize
= ROUND_UP(Size
* 1024, CsrNtSysInfo
.PageSize
);
361 /* Create the Secion */
362 SectionSize
.LowPart
= CsrSrvSharedSectionSize
;
363 SectionSize
.HighPart
= 0;
364 Status
= NtCreateSection(&CsrSrvSharedSection
,
368 PAGE_EXECUTE_READWRITE
,
369 SEC_BASED
| SEC_RESERVE
,
371 if (!NT_SUCCESS(Status
)) return Status
;
373 /* Map the section */
374 Status
= NtMapViewOfSection(CsrSrvSharedSection
,
376 &CsrSrvSharedSectionBase
,
383 PAGE_EXECUTE_READWRITE
);
384 if (!NT_SUCCESS(Status
))
387 NtClose(CsrSrvSharedSection
);
391 /* FIXME: Write the value to registry */
393 /* The Heap is the same place as the Base */
394 CsrSrvSharedSectionHeap
= CsrSrvSharedSectionBase
;
396 /* Create the heap */
397 if (!(RtlCreateHeap(HEAP_ZERO_MEMORY
| HEAP_CLASS_7
,
398 CsrSrvSharedSectionHeap
,
399 CsrSrvSharedSectionSize
,
404 /* Failure, unmap section and return */
405 NtUnmapViewOfSection(NtCurrentProcess(), CsrSrvSharedSectionBase
);
406 NtClose(CsrSrvSharedSection
);
407 return STATUS_NO_MEMORY
;
410 /* Now allocate space from the heap for the Shared Data */
411 CsrSrvSharedStaticServerData
= RtlAllocateHeap(CsrSrvSharedSectionHeap
,
413 CSR_SERVER_DLL_MAX
* sizeof(PVOID
));
414 if (!CsrSrvSharedStaticServerData
) return STATUS_NO_MEMORY
;
416 /* Write the values to the PEB */
417 Peb
->ReadOnlySharedMemoryBase
= CsrSrvSharedSectionBase
;
418 Peb
->ReadOnlySharedMemoryHeap
= CsrSrvSharedSectionHeap
;
419 Peb
->ReadOnlyStaticServerData
= CsrSrvSharedStaticServerData
;
422 return STATUS_SUCCESS
;
426 * @name CsrSrvAttachSharedSection
428 * The CsrSrvAttachSharedSection maps the CSR Shared Section into a new
429 * CSR Process' address space, and returns the pointers to the section
430 * through the Connection Info structure.
433 * Pointer to the CSR Process that is attempting a connection.
436 * Pointer to the CSR Connection Info structure for the incoming
439 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
446 CsrSrvAttachSharedSection(IN PCSR_PROCESS CsrProcess OPTIONAL
,
447 OUT PCSR_CONNECTION_INFO ConnectInfo
)
452 /* Check if we have a process */
455 /* Map the section into this process */
456 Status
= NtMapViewOfSection(CsrSrvSharedSection
,
457 CsrProcess
->ProcessHandle
,
458 &CsrSrvSharedSectionBase
,
466 if (!NT_SUCCESS(Status
)) return Status
;
469 /* Write the values in the Connection Info structure */
470 ConnectInfo
->SharedSectionBase
= CsrSrvSharedSectionBase
;
471 ConnectInfo
->SharedSectionHeap
= CsrSrvSharedSectionHeap
;
472 ConnectInfo
->SharedSectionData
= CsrSrvSharedStaticServerData
;
475 return STATUS_SUCCESS
;
479 * @name CsrSrvIdentifyAlertableThread
482 * The CsrSrvIdentifyAlertableThread CSR API marks a CSR Thread as alertable.
485 * Pointer to the CSR API Message for this request.
488 * Pointer to an optional reply to this request.
490 * @return STATUS_SUCCESS.
495 CSR_API(CsrSrvIdentifyAlertableThread
)
497 PCSR_THREAD CsrThread
= CsrGetClientThread();
499 /* Set the alertable flag */
500 CsrThread
->Flags
|= CsrThreadAlertable
;
503 return STATUS_SUCCESS
;
507 * @name CsrSrvSetPriorityClass
510 * The CsrSrvSetPriorityClass CSR API is deprecated.
513 * Pointer to the CSR API Message for this request.
516 * Pointer to an optional reply to this request.
518 * @return STATUS_SUCCESS.
523 CSR_API(CsrSrvSetPriorityClass
)
526 return STATUS_SUCCESS
;
530 * @name CsrSrvUnusedFunction
533 * The CsrSrvUnusedFunction CSR API is a stub for deprecated APIs.
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_INVALID_PARAMETER.
545 * @remarks CsrSrvSetPriorityClass does not use this stub because
546 * it must return success.
549 CSR_API(CsrSrvUnusedFunction
)
552 return STATUS_INVALID_PARAMETER
;
555 /* PUBLIC FUNCTIONS ***********************************************************/
558 * @name CsrSetCallingSpooler
561 * the CsrSetCallingSpooler routine is deprecated.
568 * @remarks This routine was used in archaic versions of NT for Printer Drivers.
573 CsrSetCallingSpooler(ULONG Reserved
)
580 * @name CsrUnhandledExceptionFilter
583 * The CsrUnhandledExceptionFilter routine handles all exceptions
584 * within SEH-protected blocks.
586 * @param ExceptionPointers
587 * System-defined Argument.
589 * @return EXCEPTION_EXECUTE_HANDLER.
594 EXCEPTION_DISPOSITION
596 CsrUnhandledExceptionFilter(IN PEXCEPTION_POINTERS ExceptionInfo
)
598 SYSTEM_KERNEL_DEBUGGER_INFORMATION DebuggerInfo
;
599 EXCEPTION_DISPOSITION Result
= EXCEPTION_EXECUTE_HANDLER
;
602 UNICODE_STRING ErrorSource
;
603 ULONG_PTR ErrorParameters
[4];
606 DPRINT1("CsrUnhandledExceptionFilter called\n");
608 /* Check if a debugger is installed */
609 Status
= NtQuerySystemInformation(SystemKernelDebuggerInformation
,
611 sizeof(DebuggerInfo
),
614 /* Check if this is Session 0, and the Debugger is Enabled */
615 if ((NtCurrentPeb()->SessionId
!= 0) && (NT_SUCCESS(Status
)) &&
616 (DebuggerInfo
.KernelDebuggerEnabled
))
618 /* Call the Unhandled Exception Filter */
619 Result
= RtlUnhandledExceptionFilter(ExceptionInfo
);
620 if (Result
!= EXCEPTION_CONTINUE_EXECUTION
)
622 /* We're going to raise an error. Get Shutdown Privilege first */
623 Status
= RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE
,
628 /* Use the Process token if that failed */
629 if (Status
== STATUS_NO_TOKEN
)
631 Status
= RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE
,
637 /* Initialize our Name String */
638 RtlInitUnicodeString(&ErrorSource
, L
"Windows SubSystem");
640 /* Set the parameters */
641 ErrorParameters
[0] = (ULONG_PTR
)&ErrorSource
;
642 ErrorParameters
[1] = ExceptionInfo
->ExceptionRecord
->ExceptionCode
;
643 ErrorParameters
[2] = (ULONG_PTR
)ExceptionInfo
->ExceptionRecord
->ExceptionAddress
;
644 ErrorParameters
[3] = (ULONG_PTR
)ExceptionInfo
->ContextRecord
;
647 Status
= NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED
,
651 OptionShutdownSystem
,
655 /* Just terminate us */
656 NtTerminateProcess(NtCurrentProcess(),
657 ExceptionInfo
->ExceptionRecord
->ExceptionCode
);