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