e4b884bf8ac60293219b82da6c2a18545cdb718f
[reactos.git] / reactos / subsystems / win32 / csrss / csrsrv / api / wapi.c
1 /* $Id$
2 *
3 * subsystems/win32/csrss/csrsrv/api/wapi.c
4 *
5 * CSRSS port message processing
6 *
7 * ReactOS Operating System
8 *
9 */
10
11 /* INCLUDES ******************************************************************/
12
13 #include <srv.h>
14
15 #define NDEBUG
16 #include <debug.h>
17
18 /* GLOBALS *******************************************************************/
19
20 static unsigned ApiDefinitionsCount = 0;
21 static PCSRSS_API_DEFINITION ApiDefinitions = NULL;
22 UNICODE_STRING CsrApiPortName;
23 volatile LONG CsrpStaticThreadCount;
24 volatile LONG CsrpDynamicThreadTotal;
25 extern ULONG CsrMaxApiRequestThreads;
26
27 /* FUNCTIONS *****************************************************************/
28
29 NTSTATUS FASTCALL
30 CsrApiRegisterDefinitions(PCSRSS_API_DEFINITION NewDefinitions)
31 {
32 unsigned NewCount;
33 PCSRSS_API_DEFINITION Scan;
34 PCSRSS_API_DEFINITION New;
35
36 DPRINT("CSR: %s called\n", __FUNCTION__);
37
38 NewCount = 0;
39 for (Scan = NewDefinitions; 0 != Scan->Handler; Scan++)
40 {
41 NewCount++;
42 }
43
44 New = RtlAllocateHeap(CsrHeap, 0,
45 (ApiDefinitionsCount + NewCount)
46 * sizeof(CSRSS_API_DEFINITION));
47 if (NULL == New)
48 {
49 DPRINT1("Unable to allocate memory\n");
50 return STATUS_NO_MEMORY;
51 }
52 if (0 != ApiDefinitionsCount)
53 {
54 RtlCopyMemory(New, ApiDefinitions,
55 ApiDefinitionsCount * sizeof(CSRSS_API_DEFINITION));
56 RtlFreeHeap(CsrHeap, 0, ApiDefinitions);
57 }
58 RtlCopyMemory(New + ApiDefinitionsCount, NewDefinitions,
59 NewCount * sizeof(CSRSS_API_DEFINITION));
60 ApiDefinitions = New;
61 ApiDefinitionsCount += NewCount;
62
63 return STATUS_SUCCESS;
64 }
65
66 VOID
67 FASTCALL
68 CsrApiCallHandler(PCSR_PROCESS ProcessData,
69 PCSR_API_MESSAGE Request)
70 {
71 unsigned DefIndex;
72 ULONG Type;
73
74 DPRINT("CSR: Calling handler for type: %x.\n", Request->Type);
75 Type = Request->Type & 0xFFFF; /* FIXME: USE MACRO */
76 DPRINT("CSR: API Number: %x ServerID: %x\n",Type, Request->Type >> 16);
77
78 /* FIXME: Extract DefIndex instead of looping */
79 for (DefIndex = 0; DefIndex < ApiDefinitionsCount; DefIndex++)
80 {
81 if (ApiDefinitions[DefIndex].Type == Type)
82 {
83 if (Request->Header.u1.s1.DataLength < ApiDefinitions[DefIndex].MinRequestSize)
84 {
85 DPRINT1("Request type %d min request size %d actual %d\n",
86 Type, ApiDefinitions[DefIndex].MinRequestSize,
87 Request->Header.u1.s1.DataLength);
88 Request->Status = STATUS_INVALID_PARAMETER;
89 }
90 else
91 {
92 Request->Status = (ApiDefinitions[DefIndex].Handler)(ProcessData, Request);
93 }
94 return;
95 }
96 }
97 DPRINT1("CSR: Unknown request type 0x%x\n", Request->Type);
98 Request->Status = STATUS_INVALID_SYSTEM_SERVICE;
99 }
100
101 VOID
102 CallHardError(IN PCSR_THREAD ThreadData,
103 IN PHARDERROR_MSG HardErrorMessage);
104
105 static
106 VOID
107 NTAPI
108 CsrHandleHardError(IN PCSR_THREAD ThreadData,
109 IN OUT PHARDERROR_MSG Message)
110 {
111 DPRINT1("CSR: received hard error %lx\n", Message->Status);
112
113 /* Call the hard error handler in win32csr */
114 CallHardError(ThreadData, Message);
115 }
116
117 /*++
118 * @name CsrCallServerFromServer
119 * @implemented NT4
120 *
121 * The CsrCallServerFromServer routine calls a CSR API from within a server.
122 * It avoids using LPC messages since the request isn't coming from a client.
123 *
124 * @param ReceiveMsg
125 * Pointer to the CSR API Message to send to the server.
126 *
127 * @param ReplyMsg
128 * Pointer to the CSR API Message to receive from the server.
129 *
130 * @return STATUS_SUCCESS in case of success, STATUS_ILLEGAL_FUNCTION
131 * if the opcode is invalid, or STATUS_ACCESS_VIOLATION if there
132 * was a problem executing the API.
133 *
134 * @remarks None.
135 *
136 *--*/
137 NTSTATUS
138 NTAPI
139 CsrCallServerFromServer(PCSR_API_MESSAGE ReceiveMsg,
140 PCSR_API_MESSAGE ReplyMsg)
141 {
142 #if 0 // real code
143 ULONG ServerId;
144 PCSR_SERVER_DLL ServerDll;
145 ULONG ApiId;
146 ULONG Reply;
147 NTSTATUS Status;
148
149 /* Get the Server ID */
150 ServerId = CSR_SERVER_ID_FROM_OPCODE(ReceiveMsg->Opcode);
151
152 /* Make sure that the ID is within limits, and the Server DLL loaded */
153 if ((ServerId >= CSR_SERVER_DLL_MAX) ||
154 (!(ServerDll = CsrLoadedServerDll[ServerId])))
155 {
156 /* We are beyond the Maximum Server ID */
157 DPRINT1("CSRSS: %lx is invalid ServerDllIndex (%08x)\n", ServerId, ServerDll);
158 ReplyMsg->Status = (ULONG)STATUS_ILLEGAL_FUNCTION;
159 return STATUS_ILLEGAL_FUNCTION;
160 }
161 else
162 {
163 /* Get the API ID */
164 ApiId = CSR_API_ID_FROM_OPCODE(ReceiveMsg->Opcode);
165
166 /* Normalize it with our Base ID */
167 ApiId -= ServerDll->ApiBase;
168
169 /* Make sure that the ID is within limits, and the entry exists */
170 if ((ApiId >= ServerDll->HighestApiSupported) ||
171 ((ServerDll->ValidTable) && !(ServerDll->ValidTable[ApiId])))
172 {
173 /* We are beyond the Maximum API ID, or it doesn't exist */
174 DPRINT1("CSRSS: %lx (%s) is invalid ApiTableIndex for %Z or is an "
175 "invalid API to call from the server.\n",
176 ServerDll->ValidTable[ApiId],
177 ((ServerDll->NameTable) && (ServerDll->NameTable[ApiId])) ?
178 ServerDll->NameTable[ApiId] : "*** UNKNOWN ***", &ServerDll->Name);
179 DbgBreakPoint();
180 ReplyMsg->Status = (ULONG)STATUS_ILLEGAL_FUNCTION;
181 return STATUS_ILLEGAL_FUNCTION;
182 }
183 }
184
185 if (CsrDebug & 2)
186 {
187 DPRINT1("CSRSS: %s Api Request received from server process\n",
188 ServerDll->NameTable[ApiId]);
189 }
190
191 /* Validation complete, start SEH */
192 _SEH2_TRY
193 {
194 /* Call the API and get the result */
195 Status = (ServerDll->DispatchTable[ApiId])(ReceiveMsg, &Reply);
196
197 /* Return the result, no matter what it is */
198 ReplyMsg->Status = Status;
199 }
200 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
201 {
202 /* If we got an exception, return access violation */
203 ReplyMsg->Status = STATUS_ACCESS_VIOLATION;
204 }
205 _SEH2_END;
206
207 /* Return success */
208 return STATUS_SUCCESS;
209 #else // Hacky reactos code
210 PCSR_PROCESS ProcessData;
211
212 /* Get the Process Data */
213 CsrLockProcessByClientId(&ReceiveMsg->Header.ClientId.UniqueProcess, &ProcessData);
214 if (!ProcessData)
215 {
216 DPRINT1("Message: Unable to find data for process 0x%x\n",
217 ReceiveMsg->Header.ClientId.UniqueProcess);
218 return STATUS_NOT_SUPPORTED;
219 }
220
221 /* Validation complete, start SEH */
222 _SEH2_TRY
223 {
224 /* Call the API and get the result */
225 CsrApiCallHandler(ProcessData, ReplyMsg);
226 }
227 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
228 {
229 /* If we got an exception, return access violation */
230 ReplyMsg->Status = STATUS_ACCESS_VIOLATION;
231 }
232 _SEH2_END;
233
234 /* Release the process reference */
235 CsrUnlockProcess(ProcessData);
236
237 /* Return success */
238 return STATUS_SUCCESS;
239 #endif
240 }
241
242 /*++
243 * @name CsrApiPortInitialize
244 *
245 * The CsrApiPortInitialize routine initializes the LPC Port used for
246 * communications with the Client/Server Runtime (CSR) and initializes the
247 * static thread that will handle connection requests and APIs.
248 *
249 * @param None
250 *
251 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
252 * othwerwise.
253 *
254 * @remarks None.
255 *
256 *--*/
257 NTSTATUS
258 NTAPI
259 CsrApiPortInitialize(VOID)
260 {
261 ULONG Size;
262 OBJECT_ATTRIBUTES ObjectAttributes;
263 NTSTATUS Status;
264 HANDLE hRequestEvent, hThread;
265 CLIENT_ID ClientId;
266 PLIST_ENTRY ListHead, NextEntry;
267 PCSR_THREAD ServerThread;
268
269 /* Calculate how much space we'll need for the Port Name */
270 Size = CsrDirectoryName.Length + sizeof(CSR_PORT_NAME) + sizeof(WCHAR);
271
272 /* Create the buffer for it */
273 CsrApiPortName.Buffer = RtlAllocateHeap(CsrHeap, 0, Size);
274 if (!CsrApiPortName.Buffer) return STATUS_NO_MEMORY;
275
276 /* Setup the rest of the empty string */
277 CsrApiPortName.Length = 0;
278 CsrApiPortName.MaximumLength = (USHORT)Size;
279 RtlAppendUnicodeStringToString(&CsrApiPortName, &CsrDirectoryName);
280 RtlAppendUnicodeToString(&CsrApiPortName, UNICODE_PATH_SEP);
281 RtlAppendUnicodeToString(&CsrApiPortName, CSR_PORT_NAME);
282 if (CsrDebug & 1)
283 {
284 DPRINT1("CSRSS: Creating %wZ port and associated threads\n", &CsrApiPortName);
285 DPRINT1("CSRSS: sizeof( CONNECTINFO ) == %ld sizeof( API_MSG ) == %ld\n",
286 sizeof(CSR_CONNECTION_INFO), sizeof(CSR_API_MESSAGE));
287 }
288
289 /* FIXME: Create a Security Descriptor */
290
291 /* Initialize the Attributes */
292 InitializeObjectAttributes(&ObjectAttributes,
293 &CsrApiPortName,
294 0,
295 NULL,
296 NULL /* FIXME*/);
297
298 /* Create the Port Object */
299 Status = NtCreatePort(&CsrApiPort,
300 &ObjectAttributes,
301 LPC_MAX_DATA_LENGTH, // hack
302 LPC_MAX_MESSAGE_LENGTH, // hack
303 16 * PAGE_SIZE);
304 if (NT_SUCCESS(Status))
305 {
306 /* Create the event the Port Thread will use */
307 Status = NtCreateEvent(&hRequestEvent,
308 EVENT_ALL_ACCESS,
309 NULL,
310 SynchronizationEvent,
311 FALSE);
312 if (NT_SUCCESS(Status))
313 {
314 /* Create the Request Thread */
315 Status = RtlCreateUserThread(NtCurrentProcess(),
316 NULL,
317 TRUE,
318 0,
319 0,
320 0,
321 (PVOID)ClientConnectionThread,//CsrApiRequestThread,
322 (PVOID)hRequestEvent,
323 &hThread,
324 &ClientId);
325 if (NT_SUCCESS(Status))
326 {
327 /* Add this as a static thread to CSRSRV */
328 CsrAddStaticServerThread(hThread, &ClientId, CsrThreadIsServerThread);
329
330 /* Get the Thread List Pointers */
331 ListHead = &CsrRootProcess->ThreadList;
332 NextEntry = ListHead->Flink;
333
334 /* Start looping the list */
335 while (NextEntry != ListHead)
336 {
337 /* Get the Thread */
338 ServerThread = CONTAINING_RECORD(NextEntry, CSR_THREAD, Link);
339
340 /* Start it up */
341 Status = NtResumeThread(ServerThread->ThreadHandle, NULL);
342
343 /* Is this a Server Thread? */
344 if (ServerThread->Flags & CsrThreadIsServerThread)
345 {
346 /* If so, then wait for it to initialize */
347 Status = NtWaitForSingleObject(hRequestEvent, FALSE, NULL);
348 ASSERT(NT_SUCCESS(Status));
349 }
350
351 /* Next thread */
352 NextEntry = NextEntry->Flink;
353 }
354
355 /* We don't need this anymore */
356 NtClose(hRequestEvent);
357 }
358 }
359 }
360
361 /* Return */
362 return Status;
363 }
364
365 PBASE_STATIC_SERVER_DATA BaseStaticServerData;
366
367 NTSTATUS
368 NTAPI
369 CreateBaseAcls(OUT PACL* Dacl,
370 OUT PACL* RestrictedDacl)
371 {
372 PSID SystemSid, WorldSid, RestrictedSid;
373 SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
374 SID_IDENTIFIER_AUTHORITY WorldAuthority = {SECURITY_WORLD_SID_AUTHORITY};
375 NTSTATUS Status;
376 UCHAR KeyValueBuffer[0x40];
377 PKEY_VALUE_PARTIAL_INFORMATION KeyValuePartialInfo;
378 UNICODE_STRING KeyName;
379 ULONG ProtectionMode = 0;
380 ULONG AclLength, ResultLength;
381 HANDLE hKey;
382 OBJECT_ATTRIBUTES ObjectAttributes;
383
384 /* Open the Session Manager Key */
385 RtlInitUnicodeString(&KeyName, SM_REG_KEY);
386 InitializeObjectAttributes(&ObjectAttributes,
387 &KeyName,
388 OBJ_CASE_INSENSITIVE,
389 NULL,
390 NULL);
391 Status = NtOpenKey(&hKey, KEY_READ, &ObjectAttributes);
392 if (NT_SUCCESS(Status))
393 {
394 /* Read the key value */
395 RtlInitUnicodeString(&KeyName, L"ProtectionMode");
396 Status = NtQueryValueKey(hKey,
397 &KeyName,
398 KeyValuePartialInformation,
399 KeyValueBuffer,
400 sizeof(KeyValueBuffer),
401 &ResultLength);
402
403 /* Make sure it's what we expect it to be */
404 KeyValuePartialInfo = (PKEY_VALUE_PARTIAL_INFORMATION)KeyValueBuffer;
405 if ((NT_SUCCESS(Status)) && (KeyValuePartialInfo->Type == REG_DWORD) &&
406 (*(PULONG)KeyValuePartialInfo->Data))
407 {
408 /* Save the Protection Mode */
409 ProtectionMode = *(PULONG)KeyValuePartialInfo->Data;
410 }
411
412 /* Close the handle */
413 NtClose(hKey);
414 }
415
416 /* Allocate the System SID */
417 Status = RtlAllocateAndInitializeSid(&NtAuthority,
418 1, SECURITY_LOCAL_SYSTEM_RID,
419 0, 0, 0, 0, 0, 0, 0,
420 &SystemSid);
421 ASSERT(NT_SUCCESS(Status));
422
423 /* Allocate the World SID */
424 Status = RtlAllocateAndInitializeSid(&WorldAuthority,
425 1, SECURITY_WORLD_RID,
426 0, 0, 0, 0, 0, 0, 0,
427 &WorldSid);
428 ASSERT(NT_SUCCESS(Status));
429
430 /* Allocate the restricted SID */
431 Status = RtlAllocateAndInitializeSid(&NtAuthority,
432 1, SECURITY_RESTRICTED_CODE_RID,
433 0, 0, 0, 0, 0, 0, 0,
434 &RestrictedSid);
435 ASSERT(NT_SUCCESS(Status));
436
437 /* Allocate one ACL with 3 ACEs each for one SID */
438 AclLength = sizeof(ACL) + 3 * sizeof(ACCESS_ALLOWED_ACE) +
439 RtlLengthSid(SystemSid) +
440 RtlLengthSid(RestrictedSid) +
441 RtlLengthSid(WorldSid);
442 *Dacl = RtlAllocateHeap(CsrHeap, 0, AclLength);
443 ASSERT(*Dacl != NULL);
444
445 /* Set the correct header fields */
446 Status = RtlCreateAcl(*Dacl, AclLength, ACL_REVISION2);
447 ASSERT(NT_SUCCESS(Status));
448
449 /* Give the appropriate rights to each SID */
450 /* FIXME: Should check SessionId/ProtectionMode */
451 Status = RtlAddAccessAllowedAce(*Dacl, ACL_REVISION2, DIRECTORY_QUERY | DIRECTORY_TRAVERSE | DIRECTORY_CREATE_OBJECT | DIRECTORY_CREATE_SUBDIRECTORY | READ_CONTROL, WorldSid);
452 ASSERT(NT_SUCCESS(Status));
453 Status = RtlAddAccessAllowedAce(*Dacl, ACL_REVISION2, DIRECTORY_ALL_ACCESS, SystemSid);
454 ASSERT(NT_SUCCESS(Status));
455 Status = RtlAddAccessAllowedAce(*Dacl, ACL_REVISION2, DIRECTORY_TRAVERSE, RestrictedSid);
456 ASSERT(NT_SUCCESS(Status));
457
458 /* Now allocate the restricted DACL */
459 *RestrictedDacl = RtlAllocateHeap(CsrHeap, 0, AclLength);
460 ASSERT(*RestrictedDacl != NULL);
461
462 /* Initialize it */
463 Status = RtlCreateAcl(*RestrictedDacl, AclLength, ACL_REVISION2);
464 ASSERT(NT_SUCCESS(Status));
465
466 /* And add the same ACEs as before */
467 /* FIXME: Not really fully correct */
468 Status = RtlAddAccessAllowedAce(*RestrictedDacl, ACL_REVISION2, DIRECTORY_QUERY | DIRECTORY_TRAVERSE | DIRECTORY_CREATE_OBJECT | DIRECTORY_CREATE_SUBDIRECTORY | READ_CONTROL, WorldSid);
469 ASSERT(NT_SUCCESS(Status));
470 Status = RtlAddAccessAllowedAce(*RestrictedDacl, ACL_REVISION2, DIRECTORY_ALL_ACCESS, SystemSid);
471 ASSERT(NT_SUCCESS(Status));
472 Status = RtlAddAccessAllowedAce(*RestrictedDacl, ACL_REVISION2, DIRECTORY_TRAVERSE, RestrictedSid);
473 ASSERT(NT_SUCCESS(Status));
474
475 /* The SIDs are captured, can free them now */
476 RtlFreeHeap(CsrHeap, 0, SystemSid);
477 RtlFreeHeap(CsrHeap, 0, WorldSid);
478 RtlFreeHeap(CsrHeap, 0, RestrictedSid);
479 return Status;
480 }
481
482 VOID
483 WINAPI
484 BasepFakeStaticServerData(VOID)
485 {
486 NTSTATUS Status;
487 WCHAR Buffer[MAX_PATH];
488 PWCHAR HeapBuffer;
489 UNICODE_STRING SystemRootString;
490 UNICODE_STRING UnexpandedSystemRootString = RTL_CONSTANT_STRING(L"%SystemRoot%");
491 UNICODE_STRING BaseSrvCSDString;
492 UNICODE_STRING BaseSrvWindowsDirectory;
493 UNICODE_STRING BaseSrvWindowsSystemDirectory;
494 UNICODE_STRING BnoString;
495 OBJECT_ATTRIBUTES ObjectAttributes;
496 ULONG SessionId;
497 HANDLE BaseSrvNamedObjectDirectory;
498 HANDLE BaseSrvRestrictedObjectDirectory;
499 PACL BnoDacl, BnoRestrictedDacl;
500 PSECURITY_DESCRIPTOR BnoSd;
501 HANDLE SymHandle;
502 UNICODE_STRING DirectoryName, SymlinkName;
503 ULONG LuidEnabled;
504 RTL_QUERY_REGISTRY_TABLE BaseServerRegistryConfigurationTable[2] =
505 {
506 {
507 NULL,
508 RTL_QUERY_REGISTRY_DIRECT,
509 L"CSDVersion",
510 &BaseSrvCSDString
511 },
512 {0}
513 };
514
515 /* Get the session ID */
516 SessionId = NtCurrentPeb()->SessionId;
517
518 /* Get the Windows directory */
519 RtlInitEmptyUnicodeString(&SystemRootString, Buffer, sizeof(Buffer));
520 Status = RtlExpandEnvironmentStrings_U(NULL,
521 &UnexpandedSystemRootString,
522 &SystemRootString,
523 NULL);
524 ASSERT(NT_SUCCESS(Status));
525
526 /* Create the base directory */
527 Buffer[SystemRootString.Length / sizeof(WCHAR)] = UNICODE_NULL;
528 Status = RtlCreateUnicodeString(&BaseSrvWindowsDirectory,
529 SystemRootString.Buffer);
530 ASSERT(NT_SUCCESS(Status));
531
532 /* Create the system directory */
533 wcscat(SystemRootString.Buffer, L"\\system32");
534 Status = RtlCreateUnicodeString(&BaseSrvWindowsSystemDirectory,
535 SystemRootString.Buffer);
536 ASSERT(NT_SUCCESS(Status));
537
538 /* FIXME: Check Session ID */
539 wcscpy(Buffer, L"\\BaseNamedObjects");
540 RtlInitUnicodeString(&BnoString, Buffer);
541
542 /* Allocate the server data */
543 BaseStaticServerData = RtlAllocateHeap(CsrSrvSharedSectionHeap,
544 HEAP_ZERO_MEMORY,
545 sizeof(BASE_STATIC_SERVER_DATA));
546 ASSERT(BaseStaticServerData != NULL);
547
548 /* Process timezone information */
549 BaseStaticServerData->TermsrvClientTimeZoneId = TIME_ZONE_ID_INVALID;
550 BaseStaticServerData->TermsrvClientTimeZoneChangeNum = 0;
551 Status = NtQuerySystemInformation(SystemTimeOfDayInformation,
552 &BaseStaticServerData->TimeOfDay,
553 sizeof(BaseStaticServerData->TimeOfDay),
554 NULL);
555 ASSERT(NT_SUCCESS(Status));
556
557 /* Make a shared heap copy of the Windows directory */
558 BaseStaticServerData->WindowsDirectory = BaseSrvWindowsDirectory;
559 HeapBuffer = RtlAllocateHeap(CsrSrvSharedSectionHeap,
560 0,
561 BaseSrvWindowsDirectory.MaximumLength);
562 ASSERT(HeapBuffer);
563 RtlCopyMemory(HeapBuffer,
564 BaseStaticServerData->WindowsDirectory.Buffer,
565 BaseSrvWindowsDirectory.MaximumLength);
566 BaseStaticServerData->WindowsDirectory.Buffer = HeapBuffer;
567
568 /* Make a shared heap copy of the System directory */
569 BaseStaticServerData->WindowsSystemDirectory = BaseSrvWindowsSystemDirectory;
570 HeapBuffer = RtlAllocateHeap(CsrSrvSharedSectionHeap,
571 0,
572 BaseSrvWindowsSystemDirectory.MaximumLength);
573 ASSERT(HeapBuffer);
574 RtlCopyMemory(HeapBuffer,
575 BaseStaticServerData->WindowsSystemDirectory.Buffer,
576 BaseSrvWindowsSystemDirectory.MaximumLength);
577 BaseStaticServerData->WindowsSystemDirectory.Buffer = HeapBuffer;
578
579 /* This string is not used */
580 RtlInitEmptyUnicodeString(&BaseStaticServerData->WindowsSys32x86Directory,
581 NULL,
582 0);
583
584 /* Make a shared heap copy of the BNO directory */
585 BaseStaticServerData->NamedObjectDirectory = BnoString;
586 BaseStaticServerData->NamedObjectDirectory.MaximumLength = BnoString.Length +
587 sizeof(UNICODE_NULL);
588 HeapBuffer = RtlAllocateHeap(CsrSrvSharedSectionHeap,
589 0,
590 BaseStaticServerData->NamedObjectDirectory.MaximumLength);
591 ASSERT(HeapBuffer);
592 RtlCopyMemory(HeapBuffer,
593 BaseStaticServerData->NamedObjectDirectory.Buffer,
594 BaseStaticServerData->NamedObjectDirectory.MaximumLength);
595 BaseStaticServerData->NamedObjectDirectory.Buffer = HeapBuffer;
596
597 /*
598 * Confirmed that in Windows, CSDNumber and RCNumber are actually Length
599 * and MaximumLength of the CSD String, since the same UNICODE_STRING is
600 * being queried twice, the first time as a ULONG!
601 *
602 * Somehow, in Windows this doesn't cause a buffer overflow, but it might
603 * in ReactOS, so this code is disabled until someone figures out WTF.
604 */
605 BaseStaticServerData->CSDNumber = 0;
606 BaseStaticServerData->RCNumber = 0;
607
608 /* Initialize the CSD string and query its value from the registry */
609 RtlInitEmptyUnicodeString(&BaseSrvCSDString, Buffer, sizeof(Buffer));
610 Status = RtlQueryRegistryValues(RTL_REGISTRY_WINDOWS_NT,
611 L"",
612 BaseServerRegistryConfigurationTable,
613 NULL,
614 NULL);
615 if (NT_SUCCESS(Status))
616 {
617 /* Copy into the shared buffer */
618 wcsncpy(BaseStaticServerData->CSDVersion,
619 BaseSrvCSDString.Buffer,
620 BaseSrvCSDString.Length / sizeof(WCHAR));
621 }
622 else
623 {
624 /* NULL-terminate to indicate nothing is there */
625 BaseStaticServerData->CSDVersion[0] = UNICODE_NULL;
626 }
627
628 /* Cache the system information */
629 Status = NtQuerySystemInformation(SystemBasicInformation,
630 &BaseStaticServerData->SysInfo,
631 sizeof(BaseStaticServerData->SysInfo),
632 NULL);
633 ASSERT(NT_SUCCESS(Status));
634
635 /* FIXME: Should query the registry for these */
636 BaseStaticServerData->DefaultSeparateVDM = FALSE;
637 BaseStaticServerData->IsWowTaskReady = FALSE;
638
639 /* Allocate a security descriptor and create it */
640 BnoSd = RtlAllocateHeap(CsrHeap, 0, 1024);
641 ASSERT(BnoSd);
642 Status = RtlCreateSecurityDescriptor(BnoSd, SECURITY_DESCRIPTOR_REVISION);
643 ASSERT(NT_SUCCESS(Status));
644
645 /* Create the BNO and \Restricted DACLs */
646 Status = CreateBaseAcls(&BnoDacl, &BnoRestrictedDacl);
647 ASSERT(NT_SUCCESS(Status));
648
649 /* Set the BNO DACL as active for now */
650 Status = RtlSetDaclSecurityDescriptor(BnoSd, TRUE, BnoDacl, FALSE);
651 ASSERT(NT_SUCCESS(Status));
652
653 /* Create the BNO directory */
654 RtlInitUnicodeString(&BnoString, L"\\BaseNamedObjects");
655 InitializeObjectAttributes(&ObjectAttributes,
656 &BnoString,
657 OBJ_OPENIF | OBJ_PERMANENT | OBJ_CASE_INSENSITIVE,
658 NULL,
659 BnoSd);
660 Status = NtCreateDirectoryObject(&BaseSrvNamedObjectDirectory,
661 DIRECTORY_ALL_ACCESS,
662 &ObjectAttributes);
663 ASSERT(NT_SUCCESS(Status));
664
665 /* Check if we are session 0 */
666 if (!SessionId)
667 {
668 /* Mark this as a session 0 directory */
669 Status = NtSetInformationObject(BaseSrvNamedObjectDirectory,
670 ObjectSessionInformation,
671 NULL,
672 0);
673 ASSERT(NT_SUCCESS(Status));
674 }
675
676 /* Check if LUID device maps are enabled */
677 Status = NtQueryInformationProcess(NtCurrentProcess(),
678 ProcessLUIDDeviceMapsEnabled,
679 &LuidEnabled,
680 sizeof(LuidEnabled),
681 NULL);
682 ASSERT(NT_SUCCESS(Status));
683 BaseStaticServerData->LUIDDeviceMapsEnabled = LuidEnabled;
684 if (!BaseStaticServerData->LUIDDeviceMapsEnabled)
685 {
686 /* Make Global point back to BNO */
687 RtlInitUnicodeString(&DirectoryName, L"Global");
688 RtlInitUnicodeString(&SymlinkName, L"\\BaseNamedObjects");
689 InitializeObjectAttributes(&ObjectAttributes,
690 &DirectoryName,
691 OBJ_OPENIF | OBJ_PERMANENT | OBJ_CASE_INSENSITIVE,
692 BaseSrvNamedObjectDirectory,
693 BnoSd);
694 Status = NtCreateSymbolicLinkObject(&SymHandle,
695 SYMBOLIC_LINK_ALL_ACCESS,
696 &ObjectAttributes,
697 &SymlinkName);
698 if ((NT_SUCCESS(Status)) && !(SessionId)) NtClose(SymHandle);
699
700 /* Make local point back to \Sessions\x\BNO */
701 RtlInitUnicodeString(&DirectoryName, L"Local");
702 ASSERT(SessionId == 0);
703 InitializeObjectAttributes(&ObjectAttributes,
704 &DirectoryName,
705 OBJ_OPENIF | OBJ_PERMANENT | OBJ_CASE_INSENSITIVE,
706 BaseSrvNamedObjectDirectory,
707 BnoSd);
708 Status = NtCreateSymbolicLinkObject(&SymHandle,
709 SYMBOLIC_LINK_ALL_ACCESS,
710 &ObjectAttributes,
711 &SymlinkName);
712 if ((NT_SUCCESS(Status)) && !(SessionId)) NtClose(SymHandle);
713
714 /* Make Session point back to BNOLINKS */
715 RtlInitUnicodeString(&DirectoryName, L"Session");
716 RtlInitUnicodeString(&SymlinkName, L"\\Sessions\\BNOLINKS");
717 InitializeObjectAttributes(&ObjectAttributes,
718 &DirectoryName,
719 OBJ_OPENIF | OBJ_PERMANENT | OBJ_CASE_INSENSITIVE,
720 BaseSrvNamedObjectDirectory,
721 BnoSd);
722 Status = NtCreateSymbolicLinkObject(&SymHandle,
723 SYMBOLIC_LINK_ALL_ACCESS,
724 &ObjectAttributes,
725 &SymlinkName);
726 if ((NT_SUCCESS(Status)) && !(SessionId)) NtClose(SymHandle);
727
728 /* Create the BNO\Restricted directory and set the restricted DACL */
729 RtlInitUnicodeString(&DirectoryName, L"Restricted");
730 Status = RtlSetDaclSecurityDescriptor(BnoSd, TRUE, BnoRestrictedDacl, FALSE);
731 ASSERT(NT_SUCCESS(Status));
732 InitializeObjectAttributes(&ObjectAttributes,
733 &DirectoryName,
734 OBJ_OPENIF | OBJ_PERMANENT | OBJ_CASE_INSENSITIVE,
735 BaseSrvNamedObjectDirectory,
736 BnoSd);
737 Status = NtCreateDirectoryObject(&BaseSrvRestrictedObjectDirectory,
738 DIRECTORY_ALL_ACCESS,
739 &ObjectAttributes);
740 ASSERT(NT_SUCCESS(Status));
741 }
742
743 /* Finally, set the pointer */
744 CsrSrvSharedStaticServerData[CSR_CONSOLE] = BaseStaticServerData;
745 }
746
747 NTSTATUS WINAPI
748 CsrpHandleConnectionRequest (PPORT_MESSAGE Request)
749 {
750 NTSTATUS Status;
751 HANDLE ServerPort = NULL;//, ServerThread = NULL;
752 PCSR_PROCESS ProcessData = NULL;
753 REMOTE_PORT_VIEW RemotePortView;
754 // CLIENT_ID ClientId;
755 BOOLEAN AllowConnection = FALSE;
756 PCSR_CONNECTION_INFO ConnectInfo;
757 ServerPort = NULL;
758
759 DPRINT("CSR: %s: Handling: %p\n", __FUNCTION__, Request);
760
761 ConnectInfo = (PCSR_CONNECTION_INFO)(Request + 1);
762
763 /* Save the process ID */
764 RtlZeroMemory(ConnectInfo, sizeof(CSR_CONNECTION_INFO));
765
766 CsrLockProcessByClientId(Request->ClientId.UniqueProcess, &ProcessData);
767 if (!ProcessData)
768 {
769 DPRINT1("CSRSRV: Unknown process: %lx. Will be rejecting connection\n",
770 Request->ClientId.UniqueProcess);
771 }
772
773 if ((ProcessData) && (ProcessData != CsrRootProcess))
774 {
775 /* Attach the Shared Section */
776 Status = CsrSrvAttachSharedSection(ProcessData, ConnectInfo);
777 if (NT_SUCCESS(Status))
778 {
779 DPRINT("Connection ok\n");
780 AllowConnection = TRUE;
781 }
782 else
783 {
784 DPRINT1("Shared section map failed: %lx\n", Status);
785 }
786 }
787 else if (ProcessData == CsrRootProcess)
788 {
789 AllowConnection = TRUE;
790 }
791
792 /* Release the process */
793 if (ProcessData) CsrUnlockProcess(ProcessData);
794
795 /* Setup the Port View Structure */
796 RemotePortView.Length = sizeof(REMOTE_PORT_VIEW);
797 RemotePortView.ViewSize = 0;
798 RemotePortView.ViewBase = NULL;
799
800 /* Save the Process ID */
801 ConnectInfo->ProcessId = NtCurrentTeb()->ClientId.UniqueProcess;
802
803 Status = NtAcceptConnectPort(&ServerPort,
804 AllowConnection ? UlongToPtr(ProcessData->SequenceNumber) : 0,
805 Request,
806 AllowConnection,
807 NULL,
808 &RemotePortView);
809 if (!NT_SUCCESS(Status))
810 {
811 DPRINT1("CSRSS: NtAcceptConnectPort - failed. Status == %X\n", Status);
812 }
813 else if (AllowConnection)
814 {
815 if (CsrDebug & 2)
816 {
817 DPRINT1("CSRSS: ClientId: %lx.%lx has ClientView: Base=%p, Size=%lx\n",
818 Request->ClientId.UniqueProcess,
819 Request->ClientId.UniqueThread,
820 RemotePortView.ViewBase,
821 RemotePortView.ViewSize);
822 }
823
824 /* Set some Port Data in the Process */
825 ProcessData->ClientPort = ServerPort;
826 ProcessData->ClientViewBase = (ULONG_PTR)RemotePortView.ViewBase;
827 ProcessData->ClientViewBounds = (ULONG_PTR)((ULONG_PTR)RemotePortView.ViewBase +
828 (ULONG_PTR)RemotePortView.ViewSize);
829
830 /* Complete the connection */
831 Status = NtCompleteConnectPort(ServerPort);
832 if (!NT_SUCCESS(Status))
833 {
834 DPRINT1("CSRSS: NtCompleteConnectPort - failed. Status == %X\n", Status);
835 }
836 }
837 else
838 {
839 DPRINT1("CSRSS: Rejecting Connection Request from ClientId: %lx.%lx\n",
840 Request->ClientId.UniqueProcess,
841 Request->ClientId.UniqueThread);
842 }
843
844 return Status;
845 }
846
847 PCSR_THREAD
848 NTAPI
849 CsrConnectToUser(VOID)
850 {
851 PTEB Teb = NtCurrentTeb();
852 PCSR_THREAD CsrThread;
853 #if 0
854 NTSTATUS Status;
855 ANSI_STRING DllName;
856 UNICODE_STRING TempName;
857 HANDLE hUser32;
858 STRING StartupName;
859
860 /* Check if we didn't already find it */
861 if (!CsrClientThreadSetup)
862 {
863 /* Get the DLL Handle for user32.dll */
864 RtlInitAnsiString(&DllName, "user32");
865 RtlAnsiStringToUnicodeString(&TempName, &DllName, TRUE);
866 Status = LdrGetDllHandle(NULL,
867 NULL,
868 &TempName,
869 &hUser32);
870 RtlFreeUnicodeString(&TempName);
871
872 /* If we got teh handle, get the Client Thread Startup Entrypoint */
873 if (NT_SUCCESS(Status))
874 {
875 RtlInitAnsiString(&StartupName,"ClientThreadSetup");
876 Status = LdrGetProcedureAddress(hUser32,
877 &StartupName,
878 0,
879 (PVOID)&CsrClientThreadSetup);
880 }
881 }
882
883 /* Connect to user32 */
884 CsrClientThreadSetup();
885 #endif
886 /* Save pointer to this thread in TEB */
887 CsrThread = CsrLocateThreadInProcess(NULL, &Teb->ClientId);
888 if (CsrThread) Teb->CsrClientThread = CsrThread;
889
890 /* Return it */
891 return CsrThread;
892 }
893
894 /*++
895 * @name CsrpCheckRequestThreads
896 *
897 * The CsrpCheckRequestThreads routine checks if there are no more threads
898 * to handle CSR API Requests, and creates a new thread if possible, to
899 * avoid starvation.
900 *
901 * @param None.
902 *
903 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
904 * if a new thread couldn't be created.
905 *
906 * @remarks None.
907 *
908 *--*/
909 NTSTATUS
910 NTAPI
911 CsrpCheckRequestThreads(VOID)
912 {
913 HANDLE hThread;
914 CLIENT_ID ClientId;
915 NTSTATUS Status;
916
917 /* Decrease the count, and see if we're out */
918 if (!(_InterlockedDecrement(&CsrpStaticThreadCount)))
919 {
920 /* Check if we've still got space for a Dynamic Thread */
921 if (CsrpDynamicThreadTotal < CsrMaxApiRequestThreads)
922 {
923 /* Create a new dynamic thread */
924 Status = RtlCreateUserThread(NtCurrentProcess(),
925 NULL,
926 TRUE,
927 0,
928 0,
929 0,
930 (PVOID)ClientConnectionThread,//CsrApiRequestThread,
931 NULL,
932 &hThread,
933 &ClientId);
934 /* Check success */
935 if (NT_SUCCESS(Status))
936 {
937 /* Increase the thread counts */
938 _InterlockedIncrement(&CsrpStaticThreadCount);
939 _InterlockedIncrement(&CsrpDynamicThreadTotal);
940
941 /* Add a new server thread */
942 if (CsrAddStaticServerThread(hThread,
943 &ClientId,
944 CsrThreadIsServerThread))
945 {
946 /* Activate it */
947 NtResumeThread(hThread, NULL);
948 }
949 else
950 {
951 /* Failed to create a new static thread */
952 _InterlockedDecrement(&CsrpStaticThreadCount);
953 _InterlockedDecrement(&CsrpDynamicThreadTotal);
954
955 /* Terminate it */
956 DPRINT1("Failing\n");
957 NtTerminateThread(hThread, 0);
958 NtClose(hThread);
959
960 /* Return */
961 return STATUS_UNSUCCESSFUL;
962 }
963 }
964 }
965 }
966
967 /* Success */
968 return STATUS_SUCCESS;
969 }
970
971 VOID
972 WINAPI
973 ClientConnectionThread(IN PVOID Parameter)
974 {
975 PTEB Teb = NtCurrentTeb();
976 LARGE_INTEGER TimeOut;
977 NTSTATUS Status;
978 BYTE RawRequest[LPC_MAX_DATA_LENGTH];
979 PCSR_API_MESSAGE Request = (PCSR_API_MESSAGE)RawRequest;
980 PCSR_API_MESSAGE Reply;
981 PCSR_PROCESS CsrProcess;
982 PCSR_THREAD ServerThread, CsrThread;
983 ULONG MessageType;
984 HANDLE ReplyPort;
985 PDBGKM_MSG DebugMessage;
986 PHARDERROR_MSG HardErrorMsg;
987 PCLIENT_DIED_MSG ClientDiedMsg;
988 DPRINT("CSR: %s called\n", __FUNCTION__);
989
990 /* Setup LPC loop port and message */
991 Reply = NULL;
992 ReplyPort = CsrApiPort;
993
994 /* Connect to user32 */
995 while (!CsrConnectToUser())
996 {
997 /* Set up the timeout for the connect (30 seconds) */
998 TimeOut.QuadPart = -30 * 1000 * 1000 * 10;
999
1000 /* Keep trying until we get a response */
1001 Teb->Win32ClientInfo[0] = 0;
1002 NtDelayExecution(FALSE, &TimeOut);
1003 }
1004
1005 /* Get our thread */
1006 ServerThread = Teb->CsrClientThread;
1007
1008 /* If we got an event... */
1009 if (Parameter)
1010 {
1011 /* Set it, to let stuff waiting on us load */
1012 Status = NtSetEvent((HANDLE)Parameter, NULL);
1013 ASSERT(NT_SUCCESS(Status));
1014
1015 /* Increase the Thread Counts */
1016 _InterlockedIncrement(&CsrpStaticThreadCount);
1017 _InterlockedIncrement(&CsrpDynamicThreadTotal);
1018 }
1019
1020 /* Now start the loop */
1021 while (TRUE)
1022 {
1023 /* Make sure the real CID is set */
1024 Teb->RealClientId = Teb->ClientId;
1025
1026 /* Debug check */
1027 if (Teb->CountOfOwnedCriticalSections)
1028 {
1029 DPRINT1("CSRSRV: FATAL ERROR. CsrThread is Idle while holding %lu critical sections\n",
1030 Teb->CountOfOwnedCriticalSections);
1031 DPRINT1("CSRSRV: Last Receive Message %lx ReplyMessage %lx\n",
1032 Request, Reply);
1033 DbgBreakPoint();
1034 }
1035
1036 /* Send the reply and wait for a new request */
1037 DPRINT("Replying to: %lx (%lx)\n", ReplyPort, CsrApiPort);
1038 Status = NtReplyWaitReceivePort(ReplyPort,
1039 0,
1040 &Reply->Header,
1041 &Request->Header);
1042 /* Check if we didn't get success */
1043 if (Status != STATUS_SUCCESS)
1044 {
1045 /* Was it a failure or another success code? */
1046 if (!NT_SUCCESS(Status))
1047 {
1048 /* Check for specific status cases */
1049 if ((Status != STATUS_INVALID_CID) &&
1050 (Status != STATUS_UNSUCCESSFUL) &&
1051 ((Status == STATUS_INVALID_HANDLE) || (ReplyPort == CsrApiPort)))
1052 {
1053 /* Notify the debugger */
1054 DPRINT1("CSRSS: ReceivePort failed - Status == %X\n", Status);
1055 DPRINT1("CSRSS: ReplyPortHandle %lx CsrApiPort %lx\n", ReplyPort, CsrApiPort);
1056 }
1057
1058 /* We failed big time, so start out fresh */
1059 Reply = NULL;
1060 ReplyPort = CsrApiPort;
1061 DPRINT1("failed: %lx\n", Status);
1062 continue;
1063 }
1064 else
1065 {
1066 /* A bizare "success" code, just try again */
1067 DPRINT1("NtReplyWaitReceivePort returned \"success\" status 0x%x\n", Status);
1068 continue;
1069 }
1070 }
1071
1072 /* Use whatever Client ID we got */
1073 Teb->RealClientId = Request->Header.ClientId;
1074
1075 /* Get the Message Type */
1076 MessageType = Request->Header.u2.s2.Type;
1077
1078 /* Handle connection requests */
1079 if (MessageType == LPC_CONNECTION_REQUEST)
1080 {
1081 /* Handle the Connection Request */
1082 DPRINT("Accepting new connection\n");
1083 CsrpHandleConnectionRequest((PPORT_MESSAGE)Request);
1084 Reply = NULL;
1085 ReplyPort = CsrApiPort;
1086 continue;
1087 }
1088
1089 /* It's some other kind of request. Get the lock for the lookup */
1090 CsrAcquireProcessLock();
1091
1092 /* Now do the lookup to get the CSR_THREAD */
1093 CsrThread = CsrLocateThreadByClientId(&CsrProcess,
1094 &Request->Header.ClientId);
1095
1096 /* Did we find a thread? */
1097 if (!CsrThread)
1098 {
1099 /* This wasn't a CSR Thread, release lock */
1100 CsrReleaseProcessLock();
1101
1102 /* If this was an exception, handle it */
1103 if (MessageType == LPC_EXCEPTION)
1104 {
1105 DPRINT1("Exception from unknown thread, just continue\n");
1106 Reply = Request;
1107 ReplyPort = CsrApiPort;
1108 Reply->Status = DBG_CONTINUE;
1109 }
1110 else if (MessageType == LPC_PORT_CLOSED ||
1111 MessageType == LPC_CLIENT_DIED)
1112 {
1113 /* The Client or Port are gone, loop again */
1114 DPRINT("Death from unknown thread, just continue\n");
1115 Reply = NULL;
1116 ReplyPort = CsrApiPort;
1117 }
1118 else if (MessageType == LPC_ERROR_EVENT)
1119 {
1120 /* If it's a hard error, handle this too */
1121 DPRINT1("Hard error from unknown thread, call handlers\n");
1122 HandleHardError:
1123 HardErrorMsg = (PHARDERROR_MSG)Request;
1124
1125 /* Default it to unhandled */
1126 HardErrorMsg->Response = ResponseNotHandled;
1127
1128 /* Check if there are free api threads */
1129 CsrpCheckRequestThreads();
1130 if (CsrpStaticThreadCount)
1131 {
1132 CsrHandleHardError(CsrThread, (PHARDERROR_MSG)Request);
1133 }
1134
1135 /* If the response was 0xFFFFFFFF, we'll ignore it */
1136 if (HardErrorMsg->Response == 0xFFFFFFFF)
1137 {
1138 Reply = NULL;
1139 ReplyPort = CsrApiPort;
1140 }
1141 else
1142 {
1143 if (CsrThread) CsrDereferenceThread(CsrThread);
1144 Reply = Request;
1145 ReplyPort = CsrApiPort;
1146 }
1147 }
1148 else if (MessageType == LPC_REQUEST)
1149 {
1150 /* This is an API Message coming from a non-CSR Thread */
1151 DPRINT1("No thread found for request %lx and clientID %lx.%lx\n",
1152 Request->Type & 0xFFFF,
1153 Request->Header.ClientId.UniqueProcess,
1154 Request->Header.ClientId.UniqueThread);
1155 Reply = Request;
1156 ReplyPort = CsrApiPort;
1157 Reply->Status = STATUS_ILLEGAL_FUNCTION;
1158 }
1159 else if (MessageType == LPC_DATAGRAM)
1160 {
1161 DPRINT1("Kernel datagram: not yet supported\n");
1162 Reply = NULL;
1163 ReplyPort = CsrApiPort;
1164 }
1165 else
1166 {
1167 /* Some other ignored message type */
1168 Reply = NULL;
1169 ReplyPort = CsrApiPort;
1170 }
1171
1172 /* Keep going */
1173 continue;
1174 }
1175
1176 /* We have a valid thread, was this an LPC Request? */
1177 if (MessageType != LPC_REQUEST)
1178 {
1179 /* It's not an API, check if the client died */
1180 if (MessageType == LPC_CLIENT_DIED)
1181 {
1182 /* Get the information and check if it matches our thread */
1183 ClientDiedMsg = (PCLIENT_DIED_MSG)Request;
1184 if (ClientDiedMsg->CreateTime.QuadPart == CsrThread->CreateTime.QuadPart)
1185 {
1186 /* Reference the thread */
1187 CsrLockedReferenceThread(CsrThread);
1188
1189 /* Destroy the thread in the API Message */
1190 CsrDestroyThread(&Request->Header.ClientId);
1191
1192 /* Check if the thread was actually ourselves */
1193 if (CsrProcess->ThreadCount == 1)
1194 {
1195 /* Kill the process manually here */
1196 DPRINT1("Last thread\n");
1197 CsrDestroyProcess(&CsrThread->ClientId, 0);
1198 }
1199
1200 /* Remove our extra reference */
1201 CsrLockedDereferenceThread(CsrThread);
1202 }
1203
1204 /* Release the lock and keep looping */
1205 CsrReleaseProcessLock();
1206 Reply = NULL;
1207 ReplyPort = CsrApiPort;
1208 continue;
1209 }
1210
1211 /* Reference the thread and release the lock */
1212 CsrLockedReferenceThread(CsrThread);
1213 CsrReleaseProcessLock();
1214
1215 /* If this was an exception, handle it */
1216 if (MessageType == LPC_EXCEPTION)
1217 {
1218 /* Kill the process */
1219 DPRINT1("Exception in %lx.%lx. Killing...\n",
1220 Request->Header.ClientId.UniqueProcess,
1221 Request->Header.ClientId.UniqueThread);
1222 NtTerminateProcess(CsrProcess->ProcessHandle, STATUS_ABANDONED);
1223
1224 /* Destroy it from CSR */
1225 CsrDestroyProcess(&Request->Header.ClientId, STATUS_ABANDONED);
1226
1227 /* Return a Debug Message */
1228 DebugMessage = (PDBGKM_MSG)Request;
1229 DebugMessage->ReturnedStatus = DBG_CONTINUE;
1230 Reply = Request;
1231 ReplyPort = CsrApiPort;
1232
1233 /* Remove our extra reference */
1234 CsrDereferenceThread(CsrThread);
1235 }
1236 else if (MessageType == LPC_ERROR_EVENT)
1237 {
1238 DPRINT1("Hard error from known CSR thread... handling\n");
1239 goto HandleHardError;
1240 }
1241 else
1242 {
1243 /* Something else */
1244 DPRINT1("Unhandled message type: %lx\n", MessageType);
1245 CsrDereferenceThread(CsrThread);
1246 Reply = NULL;
1247 }
1248
1249 /* Keep looping */
1250 continue;
1251 }
1252
1253 /* We got an API Request */
1254 CsrLockedReferenceThread(CsrThread);
1255 CsrReleaseProcessLock();
1256
1257 /* Assume success */
1258 Reply = Request;
1259 Request->Status = STATUS_SUCCESS;
1260
1261 /* Now we reply to a particular client */
1262 ReplyPort = CsrThread->Process->ClientPort;
1263
1264 DPRINT("CSR: Got CSR API: %x [Message Origin: %x]\n",
1265 Request->Type,
1266 Request->Header.ClientId.UniqueThread);
1267
1268 /* Validation complete, start SEH */
1269 _SEH2_TRY
1270 {
1271 /* Make sure we have enough threads */
1272 CsrpCheckRequestThreads();
1273
1274 /* Set the client thread pointer */
1275 NtCurrentTeb()->CsrClientThread = CsrThread;
1276
1277 /* Call the Handler */
1278 CsrApiCallHandler(CsrThread->Process, Request);
1279
1280 /* Increase the static thread count */
1281 _InterlockedIncrement(&CsrpStaticThreadCount);
1282
1283 /* Restore the server thread */
1284 NtCurrentTeb()->CsrClientThread = ServerThread;
1285
1286 /* Check if this is a dead client now */
1287 if (Request->Type == 0xBABE)
1288 {
1289 /* Reply to the death message */
1290 NtReplyPort(ReplyPort, &Reply->Header);
1291
1292 /* Reply back to the API port now */
1293 ReplyPort = CsrApiPort;
1294 Reply = NULL;
1295
1296 /* Drop the reference */
1297 CsrDereferenceThread(CsrThread);
1298 }
1299 else
1300 {
1301 /* Drop the reference */
1302 CsrDereferenceThread(CsrThread);
1303 }
1304 }
1305 _SEH2_EXCEPT(CsrUnhandledExceptionFilter(_SEH2_GetExceptionInformation()))
1306 {
1307 Reply = NULL;
1308 ReplyPort = CsrApiPort;
1309 }
1310 _SEH2_END;
1311 }
1312
1313 /* Close the port and exit the thread */
1314 // NtClose(ServerPort);
1315
1316 DPRINT1("CSR: %s done\n", __FUNCTION__);
1317 /* We're out of the loop for some reason, terminate! */
1318 NtTerminateThread(NtCurrentThread(), Status);
1319 //return Status;
1320 }
1321
1322 /*++
1323 * @name CsrReleaseCapturedArguments
1324 * @implemented NT5.1
1325 *
1326 * The CsrReleaseCapturedArguments routine releases a Capture Buffer
1327 * that was previously captured with CsrCaptureArguments.
1328 *
1329 * @param ApiMessage
1330 * Pointer to the CSR API Message containing the Capture Buffer
1331 * that needs to be released.
1332 *
1333 * @return None.
1334 *
1335 * @remarks None.
1336 *
1337 *--*/
1338 VOID
1339 NTAPI
1340 CsrReleaseCapturedArguments(IN PCSR_API_MESSAGE ApiMessage)
1341 {
1342 PCSR_CAPTURE_BUFFER RemoteCaptureBuffer, LocalCaptureBuffer;
1343 SIZE_T BufferDistance;
1344 ULONG PointerCount;
1345 ULONG_PTR **PointerOffsets, *CurrentPointer;
1346
1347 /* Get the capture buffers */
1348 RemoteCaptureBuffer = ApiMessage->CsrCaptureData;
1349 LocalCaptureBuffer = RemoteCaptureBuffer->PreviousCaptureBuffer;
1350
1351 /* Free the previous one */
1352 RemoteCaptureBuffer->PreviousCaptureBuffer = NULL;
1353
1354 /* Find out the difference between the two buffers */
1355 BufferDistance = (ULONG_PTR)LocalCaptureBuffer - (ULONG_PTR)RemoteCaptureBuffer;
1356
1357 /* Save the pointer count and offset pointer */
1358 PointerCount = RemoteCaptureBuffer->PointerCount;
1359 PointerOffsets = (ULONG_PTR**)(RemoteCaptureBuffer + 1);
1360
1361 /* Start the loop */
1362 while (PointerCount)
1363 {
1364 /* Get the current pointer */
1365 CurrentPointer = *PointerOffsets++;
1366 if (CurrentPointer)
1367 {
1368 /* Add it to the CSR Message structure */
1369 CurrentPointer += (ULONG_PTR)ApiMessage;
1370
1371 /* Modify the pointer to take into account its new position */
1372 *CurrentPointer += BufferDistance;
1373 }
1374
1375 /* Move to the next Pointer */
1376 PointerCount--;
1377 }
1378
1379 /* Copy the data back */
1380 RtlMoveMemory(LocalCaptureBuffer, RemoteCaptureBuffer, RemoteCaptureBuffer->Size);
1381
1382 /* Free our allocated buffer */
1383 RtlFreeHeap(CsrHeap, 0, RemoteCaptureBuffer);
1384 }
1385
1386 /* EOF */