[REACTOS]
[reactos.git] / reactos / deprecated / csrsrv / server.c
1 /*
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)
7 */
8
9 /* INCLUDES ******************************************************************/
10 #include "srv.h"
11
12 #define NDEBUG
13 #include <debug.h>
14
15 /* DATA **********************************************************************/
16
17 PCSR_API_ROUTINE CsrServerApiDispatchTable[5] =
18 {
19 CsrSrvClientConnect,
20 CsrSrvUnusedFunction,
21 CsrSrvUnusedFunction,
22 CsrSrvIdentifyAlertableThread,
23 CsrSrvSetPriorityClass
24 };
25
26 BOOLEAN CsrServerApiServerValidTable[5] =
27 {
28 TRUE,
29 FALSE,
30 TRUE,
31 TRUE,
32 TRUE
33 };
34
35 PCHAR CsrServerApiNameTable[5] =
36 {
37 "ClientConnect",
38 "ThreadConnect",
39 "ProfileControl",
40 "IdentifyAlertableThread",
41 "SetPriorityClass"
42 };
43
44 PCSR_SERVER_DLL CsrLoadedServerDll[CSR_SERVER_DLL_MAX];
45 PVOID CsrSrvSharedSectionHeap;
46 PVOID CsrSrvSharedSectionBase;
47 PVOID *CsrSrvSharedStaticServerData;
48 ULONG CsrSrvSharedSectionSize;
49 HANDLE CsrSrvSharedSection;
50
51 /* PRIVATE FUNCTIONS**********************************************************/
52
53 /*++
54 * @name CsrServerDllInitialization
55 * @implemented NT4
56 *
57 * The CsrServerDllInitialization is the initialization routine for
58 * the this Server DLL.
59 *
60 * @param LoadedServerDll
61 * Pointer to the CSR Server DLL structure representing this Server DLL.
62 *
63 * @return STATUS_SUCCESS.
64 *
65 * @remarks None.
66 *
67 *--*/
68 NTSTATUS
69 NTAPI
70 CsrServerDllInitialization(IN PCSR_SERVER_DLL LoadedServerDll)
71 {
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;
81
82 /* All done */
83 return STATUS_SUCCESS;
84 }
85
86 /*++
87 * @name CsrLoadServerDll
88 * @implemented NT4
89 *
90 * The CsrLoadServerDll routine loads a CSR Server DLL and calls its entrypoint
91 *
92 * @param DllString
93 * Pointer to the CSR Server DLL to load and call.
94 *
95 * @param EntryPoint
96 * Pointer to the name of the server's initialization function. If
97 * this parameter is NULL, the default ServerDllInitialize will be
98 * assumed.
99 *
100 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
101 * otherwise.
102 *
103 * @remarks None.
104 *
105 *--*/
106 NTSTATUS
107 NTAPI
108 CsrLoadServerDll(IN PCHAR DllString,
109 IN PCHAR EntryPoint OPTIONAL,
110 IN ULONG ServerId)
111 {
112 NTSTATUS Status;
113 ANSI_STRING DllName;
114 UNICODE_STRING TempString, ErrorString;
115 ULONG_PTR Parameters[2];
116 HANDLE hServerDll = NULL;
117 ULONG Size;
118 PCSR_SERVER_DLL ServerDll;
119 STRING EntryPointString;
120 PCSR_SERVER_DLL_INIT_CALLBACK ServerDllInitProcedure;
121 ULONG Response;
122
123 /* Check if it's beyond the maximum we support */
124 if (ServerId >= CSR_SERVER_DLL_MAX) return STATUS_TOO_MANY_NAMES;
125
126 /* Check if it's already been loaded */
127 if (CsrLoadedServerDll[ServerId]) return STATUS_INVALID_PARAMETER;
128
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;
134
135 /* If we are loading ourselves, don't actually load us */
136 if (ServerId != CSR_SRV_SERVER)
137 {
138 /* Load the DLL */
139 Status = LdrLoadDll(NULL, 0, &TempString, &hServerDll);
140 if (!NT_SUCCESS(Status))
141 {
142 /* Setup error parameters */
143 Parameters[0] = (ULONG_PTR)&TempString;
144 Parameters[1] = (ULONG_PTR)&ErrorString;
145 RtlInitUnicodeString(&ErrorString, L"Default Load Path");
146
147 /* Send a hard error */
148 NtRaiseHardError(Status,
149 2,
150 3,
151 Parameters,
152 OptionOk,
153 &Response);
154 }
155
156 /* Get rid of the string */
157 RtlFreeUnicodeString(&TempString);
158 if (!NT_SUCCESS(Status)) return Status;
159 }
160
161 /* Allocate a CSR DLL Object */
162 Size = sizeof(CSR_SERVER_DLL) + DllName.MaximumLength;
163 ServerDll = RtlAllocateHeap(CsrHeap, HEAP_ZERO_MEMORY, Size);
164 if (!ServerDll)
165 {
166 if (hServerDll) LdrUnloadDll(hServerDll);
167 return STATUS_NO_MEMORY;
168 }
169
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);
177 if (DllName.Length)
178 {
179 strncpy(ServerDll->Name.Buffer, DllName.Buffer, DllName.Length);
180 }
181 ServerDll->ServerId = ServerId;
182 ServerDll->ServerHandle = hServerDll;
183
184 /* Now get the entrypoint */
185 if (hServerDll)
186 {
187 /* Initialize a string for the entrypoint, or use the default */
188 RtlInitAnsiString(&EntryPointString,
189 !(EntryPoint) ? "ServerDllInitialization" :
190 EntryPoint);
191
192 /* Get a pointer to it */
193 Status = LdrGetProcedureAddress(hServerDll,
194 &EntryPointString,
195 0,
196 (PVOID)&ServerDllInitProcedure);
197 }
198 else
199 {
200 /* No handle, so we are loading ourselves */
201 ServerDllInitProcedure = CsrServerDllInitialization;
202 Status = STATUS_SUCCESS;
203 }
204
205 /* Check if we got the pointer, and call it */
206 if (NT_SUCCESS(Status))
207 {
208 /* Get the result from the Server DLL */
209 Status = ServerDllInitProcedure(ServerDll);
210
211 /* Check for Success */
212 if (NT_SUCCESS(Status))
213 {
214 /*
215 * Add this Server's Per-Process Data Size to the total that each
216 * process will need.
217 */
218 CsrTotalPerProcessDataLength += ServerDll->SizeOfProcessData;
219
220 /* Save the pointer in our list */
221 CsrLoadedServerDll[ServerDll->ServerId] = ServerDll;
222
223 /* Does it use our generic heap? */
224 if (ServerDll->SharedSection != CsrSrvSharedSectionHeap)
225 {
226 /* No, save the pointer to its shared section in our list */
227 CsrSrvSharedStaticServerData[ServerDll->ServerId] = ServerDll->SharedSection;
228 }
229
230 /* ReactOS Specific hax */
231 if (ServerDll->HighestApiSupported == 0xDEADBABE)
232 {
233 Status = CsrApiRegisterDefinitions((PVOID)ServerDll->DispatchTable);
234 }
235 }
236 else
237 {
238 /* Use shared failure code */
239 goto LoadFailed;
240 }
241 }
242 else
243 {
244 LoadFailed:
245 /* Server Init failed, unload it */
246 if (hServerDll) LdrUnloadDll(hServerDll);
247
248 /* Delete the Object */
249 RtlFreeHeap(CsrHeap, 0, ServerDll);
250 }
251
252 /* Return to caller */
253 return Status;
254 }
255
256 /*++
257 * @name CsrSrvClientConnect
258 *
259 * The CsrSrvClientConnect CSR API handles a new connection to a server DLL.
260 *
261 * @param ApiMessage
262 * Pointer to the CSR API Message for this request.
263 *
264 * @param Reply
265 * Optional reply to this request.
266 *
267 * @return STATUS_SUCCESS in case of success, STATUS_INVALID_PARAMETER
268 * or STATUS_TOO_MANY_NAMES in case of failure.
269 *
270 * @remarks None.
271 *
272 *--*/
273 NTSTATUS
274 NTAPI
275 CsrSrvClientConnect(IN OUT PCSR_API_MESSAGE ApiMessage,
276 IN OUT PULONG Reply OPTIONAL)
277 {
278 /* Hack */
279 return STATUS_SUCCESS;
280 #if 0
281 NTSTATUS Status;
282 PCSR_CLIENT_CONNECT ClientConnect;
283 PCSR_SERVER_DLL ServerDll;
284 PCSR_PROCESS CurrentProcess = ((PCSR_THREAD)NtCurrentTeb()->CsrClientThread)->Process;
285
286 /* Load the Message, set default reply */
287 ClientConnect = (PCSR_CLIENT_CONNECT)&ApiMessage->CsrClientConnect;
288 *Reply = 0;
289
290 /* Validate the ServerID */
291 if (ClientConnect->ServerId >= CSR_SERVER_DLL_MAX)
292 {
293 return STATUS_TOO_MANY_NAMES;
294 }
295 else if (!CsrLoadedServerDll[ClientConnect->ServerId])
296 {
297 return STATUS_INVALID_PARAMETER;
298 }
299
300 /* Validate the Message Buffer */
301 if (!(CsrValidateMessageBuffer(ApiMessage,
302 ClientConnect->ConnectionInfo,
303 ClientConnect->ConnectionInfoSize,
304 1)))
305 {
306 /* Fail due to buffer overflow or other invalid buffer */
307 return STATUS_INVALID_PARAMETER;
308 }
309
310 /* Load the Server DLL */
311 ServerDll = CsrLoadedServerDll[ClientConnect->ServerId];
312
313 /* Check if it has a Connect Callback */
314 if (ServerDll->ConnectCallback)
315 {
316 /* Call the callback */
317 Status = ServerDll->ConnectCallback(CurrentProcess,
318 ClientConnect->ConnectionInfo,
319 &ClientConnect->ConnectionInfoSize);
320 }
321 else
322 {
323 /* Assume success */
324 Status = STATUS_SUCCESS;
325 }
326
327 /* Return status */
328 return Status;
329 #endif
330 }
331
332 /*++
333 * @name CsrSrvCreateSharedSection
334 *
335 * The CsrSrvCreateSharedSection creates the Shared Section that all CSR Server
336 * DLLs and Clients can use to share data.
337 *
338 * @param ParameterValue
339 * Specially formatted string from our registry command-line which
340 * specifies various arguments for the shared section.
341 *
342 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
343 * otherwise.
344 *
345 * @remarks None.
346 *
347 *--*/
348 NTSTATUS
349 NTAPI
350 CsrSrvCreateSharedSection(IN PCHAR ParameterValue)
351 {
352 PCHAR SizeValue = ParameterValue;
353 ULONG Size;
354 NTSTATUS Status;
355 LARGE_INTEGER SectionSize;
356 ULONG ViewSize = 0;
357 PPEB Peb = NtCurrentPeb();
358
359 /* If there's no parameter, fail */
360 if (!ParameterValue) return STATUS_INVALID_PARAMETER;
361
362 /* Find the first comma, and null terminate */
363 while (*SizeValue)
364 {
365 if (*SizeValue == ',')
366 {
367 *SizeValue++ = ANSI_NULL;
368 break;
369 }
370 else
371 {
372 SizeValue++;
373 }
374 }
375
376 /* Make sure it's valid */
377 if (!*SizeValue) return STATUS_INVALID_PARAMETER;
378
379 /* Convert it to an integer */
380 Status = RtlCharToInteger(SizeValue, 0, &Size);
381 if (!NT_SUCCESS(Status)) return Status;
382
383 /* Multiply by 1024 entries and round to page size */
384 CsrSrvSharedSectionSize = ROUND_UP(Size * 1024, CsrNtSysInfo.PageSize);
385
386 /* Create the Secion */
387 SectionSize.LowPart = CsrSrvSharedSectionSize;
388 SectionSize.HighPart = 0;
389 Status = NtCreateSection(&CsrSrvSharedSection,
390 SECTION_ALL_ACCESS,
391 NULL,
392 &SectionSize,
393 PAGE_EXECUTE_READWRITE,
394 SEC_BASED | SEC_RESERVE,
395 NULL);
396 if (!NT_SUCCESS(Status)) return Status;
397
398 /* Map the section */
399 Status = NtMapViewOfSection(CsrSrvSharedSection,
400 NtCurrentProcess(),
401 &CsrSrvSharedSectionBase,
402 0,
403 0,
404 NULL,
405 &ViewSize,
406 ViewUnmap,
407 MEM_TOP_DOWN,
408 PAGE_EXECUTE_READWRITE);
409 if (!NT_SUCCESS(Status))
410 {
411 /* Fail */
412 NtClose(CsrSrvSharedSection);
413 return Status;
414 }
415
416 /* FIXME: Write the value to registry */
417
418 /* The Heap is the same place as the Base */
419 CsrSrvSharedSectionHeap = CsrSrvSharedSectionBase;
420
421 /* Create the heap */
422 if (!(RtlCreateHeap(HEAP_ZERO_MEMORY | HEAP_CLASS_7,
423 CsrSrvSharedSectionHeap,
424 CsrSrvSharedSectionSize,
425 PAGE_SIZE,
426 0,
427 0)))
428 {
429 /* Failure, unmap section and return */
430 NtUnmapViewOfSection(NtCurrentProcess(), CsrSrvSharedSectionBase);
431 NtClose(CsrSrvSharedSection);
432 return STATUS_NO_MEMORY;
433 }
434
435 /* Now allocate space from the heap for the Shared Data */
436 CsrSrvSharedStaticServerData = RtlAllocateHeap(CsrSrvSharedSectionHeap,
437 0,
438 CSR_SERVER_DLL_MAX *
439 sizeof(PVOID));
440 if (!CsrSrvSharedStaticServerData) return STATUS_NO_MEMORY;
441
442 /* Write the values to the PEB */
443 Peb->ReadOnlySharedMemoryBase = CsrSrvSharedSectionBase;
444 Peb->ReadOnlySharedMemoryHeap = CsrSrvSharedSectionHeap;
445 Peb->ReadOnlyStaticServerData = CsrSrvSharedStaticServerData;
446
447 /* Return */
448 return STATUS_SUCCESS;
449 }
450
451 /*++
452 * @name CsrSrvAttachSharedSection
453 *
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.
457 *
458 * @param CsrProcess
459 * Pointer to the CSR Process that is attempting a connection.
460 *
461 * @param ConnectInfo
462 * Pointer to the CSR Connection Info structure for the incoming
463 * connection.
464 *
465 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
466 * otherwise.
467 *
468 * @remarks None.
469 *
470 *--*/
471 NTSTATUS
472 NTAPI
473 CsrSrvAttachSharedSection(IN PCSR_PROCESS CsrProcess OPTIONAL,
474 OUT PCSR_CONNECTION_INFO ConnectInfo)
475 {
476 NTSTATUS Status;
477 ULONG ViewSize = 0;
478
479 /* Check if we have a process */
480 if (CsrProcess)
481 {
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,
487 0,
488 0,
489 NULL,
490 &ViewSize,
491 ViewUnmap,
492 SEC_NO_CHANGE,
493 PAGE_EXECUTE_READ);
494 if (!NT_SUCCESS(Status)) return Status;
495 }
496
497 /* Write the values in the Connection Info structure */
498 ConnectInfo->SharedSectionBase = CsrSrvSharedSectionBase;
499 ConnectInfo->SharedSectionHeap = CsrSrvSharedSectionHeap;
500 ConnectInfo->SharedSectionData = CsrSrvSharedStaticServerData;
501
502 /* Return success */
503 return STATUS_SUCCESS;
504 }
505
506 /*++
507 * @name CsrSrvIdentifyAlertableThread
508 * @implemented NT4
509 *
510 * The CsrSrvIdentifyAlertableThread CSR API marks a CSR Thread as alertable.
511 *
512 * @param ApiMessage
513 * Pointer to the CSR API Message for this request.
514 *
515 * @param Reply
516 * Pointer to an optional reply to this request.
517 *
518 * @return STATUS_SUCCESS.
519 *
520 * @remarks None.
521 *
522 *--*/
523 NTSTATUS
524 NTAPI
525 CsrSrvIdentifyAlertableThread(IN OUT PCSR_API_MESSAGE ApiMessage,
526 IN OUT PULONG Reply)
527 {
528 PCSR_THREAD CsrThread = NtCurrentTeb()->CsrClientThread;
529
530 /* Set the alertable flag */
531 CsrThread->Flags |= CsrThreadAltertable;
532
533 /* Return success */
534 return STATUS_SUCCESS;
535 }
536
537 /*++
538 * @name CsrSrvSetPriorityClass
539 * @implemented NT4
540 *
541 * The CsrSrvSetPriorityClass CSR API is deprecated.
542 *
543 * @param ApiMessage
544 * Pointer to the CSR API Message for this request.
545 *
546 * @param Reply
547 * Pointer to an optional reply to this request.
548 *
549 * @return STATUS_SUCCESS.
550 *
551 * @remarks None.
552 *
553 *--*/
554 NTSTATUS
555 NTAPI
556 CsrSrvSetPriorityClass(IN OUT PCSR_API_MESSAGE ApiMessage,
557 IN OUT PULONG Reply)
558 {
559 /* Deprecated */
560 return STATUS_SUCCESS;
561 }
562
563 /*++
564 * @name CsrSrvUnusedFunction
565 * @implemented NT4
566 *
567 * The CsrSrvUnusedFunction CSR API is a stub for deprecated APIs.
568 *
569 * The CsrSrvSetPriorityClass CSR API is deprecated.
570 *
571 * @param ApiMessage
572 * Pointer to the CSR API Message for this request.
573 *
574 * @param Reply
575 * Pointer to an optional reply to this request.
576 *
577 * @return STATUS_INVALID_PARAMETER.
578 *
579 * @remarks CsrSrvSetPriorityClass does not use this stub because it must
580 * return success.
581 *
582 *--*/
583 NTSTATUS
584 NTAPI
585 CsrSrvUnusedFunction(IN OUT PCSR_API_MESSAGE ApiMessage,
586 IN OUT PULONG Reply)
587 {
588 /* Deprecated */
589 return STATUS_INVALID_PARAMETER;
590 }
591
592 /* PUBLIC FUNCTIONS***********************************************************/
593
594 /*++
595 * @name CsrSetCallingSpooler
596 * @implemented NT4
597 *
598 * the CsrSetCallingSpooler routine is deprecated.
599 *
600 * @param Reserved
601 * Deprecated
602 *
603 * @return None.
604 *
605 * @remarks This routine was used in archaic versions of NT for Printer Drivers.
606 *
607 *--*/
608 VOID
609 NTAPI
610 CsrSetCallingSpooler(ULONG Reserved)
611 {
612 /* Deprecated */
613 return;
614 }
615
616 /*++
617 * @name CsrUnhandledExceptionFilter
618 * @implemented NT5
619 *
620 * The CsrUnhandledExceptionFilter routine handles all exceptions
621 * within SEH-protected blocks.
622 *
623 * @param ExceptionPointers
624 * System-defined Argument.
625 *
626 * @return EXCEPTION_EXECUTE_HANDLER.
627 *
628 * @remarks None.
629 *
630 *--*/
631 LONG
632 NTAPI
633 CsrUnhandledExceptionFilter(IN PEXCEPTION_POINTERS ExceptionInfo)
634 {
635 SYSTEM_KERNEL_DEBUGGER_INFORMATION DebuggerInfo;
636 EXCEPTION_DISPOSITION Result = EXCEPTION_EXECUTE_HANDLER;
637 BOOLEAN OldValue;
638 NTSTATUS Status;
639 UNICODE_STRING ErrorSource;
640 ULONG_PTR ErrorParameters[4];
641 ULONG Response;
642
643 /* Check if a debugger is installed */
644 Status = NtQuerySystemInformation(SystemKernelDebuggerInformation,
645 &DebuggerInfo,
646 sizeof(DebuggerInfo),
647 NULL);
648
649 /* Check if this is Session 0, and the Debugger is Enabled */
650 if ((NtCurrentPeb()->SessionId) && (NT_SUCCESS(Status)) &&
651 (DebuggerInfo.KernelDebuggerEnabled))
652 {
653 /* Call the Unhandled Exception Filter */
654 if ((Result = RtlUnhandledExceptionFilter(ExceptionInfo)) !=
655 EXCEPTION_CONTINUE_EXECUTION)
656 {
657 /* We're going to raise an error. Get Shutdown Privilege first */
658 Status = RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE,
659 TRUE,
660 TRUE,
661 &OldValue);
662
663 /* Use the Process token if that failed */
664 if (Status == STATUS_NO_TOKEN)
665 {
666 Status = RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE,
667 TRUE,
668 FALSE,
669 &OldValue);
670 }
671
672 /* Initialize our Name String */
673 RtlInitUnicodeString(&ErrorSource, L"Windows SubSystem");
674
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;
680
681 /* Bugcheck */
682 Status = NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED,
683 4,
684 1,
685 ErrorParameters,
686 OptionShutdownSystem,
687 &Response);
688 }
689
690 /* Just terminate us */
691 NtTerminateProcess(NtCurrentProcess(),
692 ExceptionInfo->ExceptionRecord->ExceptionCode);
693 }
694
695 return Result;
696 }
697
698 /* EOF */