9bd3cd6ff263b775c245e432e0b44437f9db4e99
[reactos.git] / reactos / subsystems / win32 / csrss / api / process.c
1 /*
2 * reactos/subsys/csrss/api/process.c
3 *
4 * "\windows\ApiPort" port process management functions
5 *
6 * ReactOS Operating System
7 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include <csrss.h>
12
13 #define NDEBUG
14 #include <debug.h>
15
16 #define LOCK RtlEnterCriticalSection(&ProcessDataLock)
17 #define UNLOCK RtlLeaveCriticalSection(&ProcessDataLock)
18
19 /* GLOBALS *******************************************************************/
20
21 static ULONG NrProcess;
22 static PCSRSS_PROCESS_DATA ProcessData[256];
23 RTL_CRITICAL_SECTION ProcessDataLock;
24
25 /* FUNCTIONS *****************************************************************/
26
27 #define CsrHeap RtlGetProcessHeap()
28
29 #define CsrHashThread(t) \
30 (HandleToUlong(t)&(256 - 1))
31
32 LIST_ENTRY CsrThreadHashTable[256];
33 PCSRSS_PROCESS_DATA CsrRootProcess;
34
35 PCSR_THREAD
36 NTAPI
37 CsrAllocateThread(IN PCSRSS_PROCESS_DATA CsrProcess)
38 {
39 PCSR_THREAD CsrThread;
40
41 /* Allocate the structure */
42 CsrThread = RtlAllocateHeap(CsrHeap, HEAP_ZERO_MEMORY, sizeof(CSR_THREAD));
43 if (!CsrThread) return(NULL);
44
45 /* Reference the Thread and Process */
46 CsrThread->ReferenceCount++;
47 // CsrProcess->ReferenceCount++;
48
49 /* Set the Parent Process */
50 CsrThread->Process = CsrProcess;
51
52 /* Return Thread */
53 return CsrThread;
54 }
55
56 PCSR_THREAD
57 NTAPI
58 CsrLocateThreadByClientId(OUT PCSRSS_PROCESS_DATA *Process OPTIONAL,
59 IN PCLIENT_ID ClientId)
60 {
61 ULONG i;
62 PLIST_ENTRY ListHead, NextEntry;
63 PCSR_THREAD FoundThread;
64
65 /* Hash the Thread */
66 i = CsrHashThread(ClientId->UniqueThread);
67
68 /* Set the list pointers */
69 ListHead = &CsrThreadHashTable[i];
70 NextEntry = ListHead->Flink;
71
72 /* Star the loop */
73 while (NextEntry != ListHead)
74 {
75 /* Get the thread */
76 FoundThread = CONTAINING_RECORD(NextEntry, CSR_THREAD, HashLinks);
77
78 /* Compare the CID */
79 if (FoundThread->ClientId.UniqueThread == ClientId->UniqueThread)
80 {
81 /* Match found, return the process */
82 *Process = FoundThread->Process;
83
84 /* Return thread too */
85 // DPRINT1("Found: %p %p\n", FoundThread, FoundThread->Process);
86 return FoundThread;
87 }
88
89 /* Next */
90 NextEntry = NextEntry->Flink;
91 }
92
93 /* Nothing found */
94 return NULL;
95 }
96
97 PCSR_THREAD
98 NTAPI
99 CsrLocateThreadInProcess(IN PCSRSS_PROCESS_DATA CsrProcess OPTIONAL,
100 IN PCLIENT_ID Cid)
101 {
102 PLIST_ENTRY ListHead, NextEntry;
103 PCSR_THREAD FoundThread = NULL;
104
105 /* Use the Root Process if none was specified */
106 if (!CsrProcess) CsrProcess = CsrRootProcess;
107
108 /* Save the List pointers */
109 // DPRINT1("Searching in: %p %d\n", CsrProcess, CsrProcess->ThreadCount);
110 ListHead = &CsrProcess->ThreadList;
111 NextEntry = ListHead->Flink;
112
113 /* Start the Loop */
114 while (NextEntry != ListHead)
115 {
116 /* Get Thread Entry */
117 FoundThread = CONTAINING_RECORD(NextEntry, CSR_THREAD, Link);
118
119 /* Check for TID Match */
120 if (FoundThread->ClientId.UniqueThread == Cid->UniqueThread) break;
121
122 /* Next entry */
123 NextEntry = NextEntry->Flink;
124 }
125
126 /* Return what we found */
127 // DPRINT1("Found: %p\n", FoundThread);
128 return FoundThread;
129 }
130
131 VOID
132 NTAPI
133 CsrInsertThread(IN PCSRSS_PROCESS_DATA Process,
134 IN PCSR_THREAD Thread)
135 {
136 ULONG i;
137
138 /* Insert it into the Regular List */
139 InsertTailList(&Process->ThreadList, &Thread->Link);
140
141 /* Increase Thread Count */
142 Process->ThreadCount++;
143
144 /* Hash the Thread */
145 i = CsrHashThread(Thread->ClientId.UniqueThread);
146 // DPRINT1("TID %lx HASH: %lx\n", Thread->ClientId.UniqueThread, i);
147
148 /* Insert it there too */
149 InsertHeadList(&CsrThreadHashTable[i], &Thread->HashLinks);
150 }
151
152
153 #define CsrAcquireProcessLock() LOCK
154 #define CsrReleaseProcessLock() UNLOCK
155
156 NTSTATUS
157 NTAPI
158 CsrCreateThreadData(IN PCSRSS_PROCESS_DATA CsrProcess,
159 IN HANDLE hThread,
160 IN PCLIENT_ID ClientId)
161 {
162 NTSTATUS Status;
163 PCSR_THREAD CsrThread;
164 //PCSRSS_PROCESS_DATA CurrentProcess;
165 PCSR_THREAD CurrentThread = NtCurrentTeb()->CsrClientThread;
166 CLIENT_ID CurrentCid;
167 KERNEL_USER_TIMES KernelTimes;
168
169 // DPRINT1("CSRSRV: %s called\n", __FUNCTION__);
170
171 /* Get the current thread and CID */
172 CurrentCid = CurrentThread->ClientId;
173 // DPRINT1("CALLER PID/TID: %lx/%lx\n", CurrentCid.UniqueProcess, CurrentCid.UniqueThread);
174
175 /* Acquire the Process Lock */
176 CsrAcquireProcessLock();
177 #if 0
178 /* Get the current Process and make sure the Thread is valid with this CID */
179 CurrentThread = CsrLocateThreadByClientId(&CurrentProcess,
180 &CurrentCid);
181
182 /* Something is wrong if we get an empty thread back */
183 if (!CurrentThread)
184 {
185 DPRINT1("CSRSRV:%s: invalid thread!\n", __FUNCTION__);
186 CsrReleaseProcessLock();
187 return STATUS_THREAD_IS_TERMINATING;
188 }
189 #endif
190 /* Get the Thread Create Time */
191 Status = NtQueryInformationThread(hThread,
192 ThreadTimes,
193 (PVOID)&KernelTimes,
194 sizeof(KernelTimes),
195 NULL);
196
197 /* Allocate a CSR Thread Structure */
198 if (!(CsrThread = CsrAllocateThread(CsrProcess)))
199 {
200 DPRINT1("CSRSRV:%s: out of memory!\n", __FUNCTION__);
201 CsrReleaseProcessLock();
202 return STATUS_NO_MEMORY;
203 }
204
205 /* Save the data we have */
206 CsrThread->CreateTime = KernelTimes.CreateTime;
207 CsrThread->ClientId = *ClientId;
208 CsrThread->ThreadHandle = hThread;
209 CsrThread->Flags = 0;
210
211 /* Insert the Thread into the Process */
212 CsrInsertThread(CsrProcess, CsrThread);
213
214 /* Release the lock and return */
215 CsrReleaseProcessLock();
216 return STATUS_SUCCESS;
217 }
218
219 PCSR_THREAD
220 NTAPI
221 CsrAddStaticServerThread(IN HANDLE hThread,
222 IN PCLIENT_ID ClientId,
223 IN ULONG ThreadFlags)
224 {
225 PCSR_THREAD CsrThread;
226
227 /* Get the Lock */
228 CsrAcquireProcessLock();
229
230 /* Allocate the Server Thread */
231 if ((CsrThread = CsrAllocateThread(CsrRootProcess)))
232 {
233 /* Setup the Object */
234 // DPRINT1("New CSR thread created: %lx PID/TID: %lx/%lx\n", CsrThread, ClientId->UniqueProcess, ClientId->UniqueThread);
235 CsrThread->ThreadHandle = hThread;
236 CsrThread->ClientId = *ClientId;
237 CsrThread->Flags = ThreadFlags;
238
239 /* Insert it into the Thread List */
240 InsertTailList(&CsrRootProcess->ThreadList, &CsrThread->Link);
241
242 /* Increment the thread count */
243 CsrRootProcess->ThreadCount++;
244 }
245
246 /* Release the Process Lock and return */
247 CsrReleaseProcessLock();
248 return CsrThread;
249 }
250
251 VOID WINAPI CsrInitProcessData(VOID)
252 {
253 ULONG i;
254 RtlZeroMemory (ProcessData, sizeof ProcessData);
255 NrProcess = sizeof ProcessData / sizeof ProcessData[0];
256 RtlInitializeCriticalSection( &ProcessDataLock );
257
258 CsrRootProcess = CsrCreateProcessData(NtCurrentTeb()->ClientId.UniqueProcess);
259
260 /* Initialize the Thread Hash List */
261 for (i = 0; i < 256; i++) InitializeListHead(&CsrThreadHashTable[i]);
262 }
263
264 PCSRSS_PROCESS_DATA WINAPI CsrGetProcessData(HANDLE ProcessId)
265 {
266 ULONG hash;
267 PCSRSS_PROCESS_DATA pProcessData;
268
269 hash = ((ULONG_PTR)ProcessId >> 2) % (sizeof(ProcessData) / sizeof(*ProcessData));
270
271 LOCK;
272
273 pProcessData = ProcessData[hash];
274
275 while (pProcessData && pProcessData->ProcessId != ProcessId)
276 {
277 pProcessData = pProcessData->next;
278 }
279 UNLOCK;
280 return pProcessData;
281 }
282
283 PCSRSS_PROCESS_DATA WINAPI CsrCreateProcessData(HANDLE ProcessId)
284 {
285 ULONG hash;
286 PCSRSS_PROCESS_DATA pProcessData;
287 OBJECT_ATTRIBUTES ObjectAttributes;
288 CLIENT_ID ClientId;
289 NTSTATUS Status;
290
291 hash = ((ULONG_PTR)ProcessId >> 2) % (sizeof(ProcessData) / sizeof(*ProcessData));
292
293 LOCK;
294
295 pProcessData = ProcessData[hash];
296
297 while (pProcessData && pProcessData->ProcessId != ProcessId)
298 {
299 pProcessData = pProcessData->next;
300 }
301 if (pProcessData == NULL)
302 {
303 pProcessData = RtlAllocateHeap(CsrssApiHeap,
304 HEAP_ZERO_MEMORY,
305 sizeof(CSRSS_PROCESS_DATA));
306 if (pProcessData)
307 {
308 pProcessData->ProcessId = ProcessId;
309 pProcessData->next = ProcessData[hash];
310 ProcessData[hash] = pProcessData;
311
312 ClientId.UniqueThread = NULL;
313 ClientId.UniqueProcess = pProcessData->ProcessId;
314 InitializeObjectAttributes(&ObjectAttributes,
315 NULL,
316 0,
317 NULL,
318 NULL);
319
320 /* using OpenProcess is not optimal due to HANDLE vs. DWORD PIDs... */
321 Status = NtOpenProcess(&pProcessData->Process,
322 PROCESS_ALL_ACCESS,
323 &ObjectAttributes,
324 &ClientId);
325 if (!NT_SUCCESS(Status))
326 {
327 ProcessData[hash] = pProcessData->next;
328 RtlFreeHeap(CsrssApiHeap, 0, pProcessData);
329 pProcessData = NULL;
330 }
331 else
332 {
333 RtlInitializeCriticalSection(&pProcessData->HandleTableLock);
334 }
335 }
336 }
337 else
338 {
339 DPRINT1("Process data for pid %d already exist\n", ProcessId);
340 }
341 UNLOCK;
342 if (pProcessData == NULL)
343 {
344 DPRINT1("CsrCreateProcessData() failed\n");
345 }
346 else
347 {
348 pProcessData->Terminated = FALSE;
349
350 /* Set default shutdown parameters */
351 pProcessData->ShutdownLevel = 0x280;
352 pProcessData->ShutdownFlags = 0;
353 }
354
355 pProcessData->ThreadCount = 0;
356 InitializeListHead(&pProcessData->ThreadList);
357 return pProcessData;
358 }
359
360 NTSTATUS WINAPI CsrFreeProcessData(HANDLE Pid)
361 {
362 ULONG hash;
363 UINT c;
364 PCSRSS_PROCESS_DATA pProcessData, *pPrevLink;
365 HANDLE Process;
366
367 hash = ((ULONG_PTR)Pid >> 2) % (sizeof(ProcessData) / sizeof(*ProcessData));
368 pPrevLink = &ProcessData[hash];
369
370 LOCK;
371
372 while ((pProcessData = *pPrevLink) && pProcessData->ProcessId != Pid)
373 {
374 pPrevLink = &pProcessData->next;
375 }
376
377 if (pProcessData)
378 {
379 DPRINT("CsrFreeProcessData pid: %d\n", Pid);
380 Process = pProcessData->Process;
381 if (pProcessData->HandleTable)
382 {
383 for (c = 0; c < pProcessData->HandleTableSize; c++)
384 {
385 if (pProcessData->HandleTable[c].Object)
386 {
387 CsrReleaseObjectByPointer(pProcessData->HandleTable[c].Object);
388 }
389 }
390 RtlFreeHeap(CsrssApiHeap, 0, pProcessData->HandleTable);
391 }
392 RtlDeleteCriticalSection(&pProcessData->HandleTableLock);
393 if (pProcessData->Console)
394 {
395 RemoveEntryList(&pProcessData->ProcessEntry);
396 CsrReleaseObjectByPointer((Object_t *) pProcessData->Console);
397 }
398 if (pProcessData->CsrSectionViewBase)
399 {
400 NtUnmapViewOfSection(NtCurrentProcess(), pProcessData->CsrSectionViewBase);
401 }
402 if (pProcessData->ServerCommunicationPort)
403 {
404 NtClose(pProcessData->ServerCommunicationPort);
405 }
406 *pPrevLink = pProcessData->next;
407
408 RtlFreeHeap(CsrssApiHeap, 0, pProcessData);
409 UNLOCK;
410 if (Process)
411 {
412 NtClose(Process);
413 }
414 return STATUS_SUCCESS;
415 }
416
417 UNLOCK;
418 return STATUS_INVALID_PARAMETER;
419 }
420
421 VOID
422 NTAPI
423 CsrSetToNormalPriority(VOID)
424 {
425 KPRIORITY BasePriority = (8 + 1) + 4;
426
427 /* Set the Priority */
428 NtSetInformationProcess(NtCurrentProcess(),
429 ProcessBasePriority,
430 &BasePriority,
431 sizeof(KPRIORITY));
432 }
433
434 VOID
435 NTAPI
436 CsrSetToShutdownPriority(VOID)
437 {
438 KPRIORITY SetBasePriority = (8 + 1) + 6;
439 BOOLEAN Old;
440
441 /* Get the shutdown privilege */
442 if (NT_SUCCESS(RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE,
443 TRUE,
444 FALSE,
445 &Old)))
446 {
447 /* Set the Priority */
448 NtSetInformationProcess(NtCurrentProcess(),
449 ProcessBasePriority,
450 &SetBasePriority,
451 sizeof(KPRIORITY));
452 }
453 }
454
455 NTSTATUS
456 NTAPI
457 CsrGetProcessLuid(HANDLE hProcess OPTIONAL,
458 PLUID Luid)
459 {
460 HANDLE hToken = NULL;
461 NTSTATUS Status;
462 ULONG Length;
463 PTOKEN_STATISTICS TokenStats;
464
465 /* Check if we have a handle to a CSR Process */
466 if (!hProcess)
467 {
468 /* We don't, so try opening the Thread's Token */
469 Status = NtOpenThreadToken(NtCurrentThread(),
470 TOKEN_QUERY,
471 FALSE,
472 &hToken);
473
474 /* Check for success */
475 if (!NT_SUCCESS(Status))
476 {
477 /* If we got some other failure, then return and quit */
478 if (Status != STATUS_NO_TOKEN) return Status;
479
480 /* We don't have a Thread Token, use a Process Token */
481 hProcess = NtCurrentProcess();
482 hToken = NULL;
483 }
484 }
485
486 /* Check if we have a token by now */
487 if (!hToken)
488 {
489 /* No token yet, so open the Process Token */
490 Status = NtOpenProcessToken(hProcess,
491 TOKEN_QUERY,
492 &hToken);
493 if (!NT_SUCCESS(Status))
494 {
495 /* Still no token, return the error */
496 return Status;
497 }
498 }
499
500 /* Now get the size we'll need for the Token Information */
501 Status = NtQueryInformationToken(hToken,
502 TokenStatistics,
503 NULL,
504 0,
505 &Length);
506
507 /* Allocate memory for the Token Info */
508 if (!(TokenStats = RtlAllocateHeap(CsrHeap, 0, Length)))
509 {
510 /* Fail and close the token */
511 NtClose(hToken);
512 return STATUS_NO_MEMORY;
513 }
514
515 /* Now query the information */
516 Status = NtQueryInformationToken(hToken,
517 TokenStatistics,
518 TokenStats,
519 Length,
520 &Length);
521
522 /* Close the handle */
523 NtClose(hToken);
524
525 /* Check for success */
526 if (NT_SUCCESS(Status))
527 {
528 /* Return the LUID */
529 *Luid = TokenStats->AuthenticationId;
530 }
531
532 /* Free the query information */
533 RtlFreeHeap(CsrHeap, 0, TokenStats);
534
535 /* Return the Status */
536 return Status;
537 }
538
539 SECURITY_QUALITY_OF_SERVICE CsrSecurityQos =
540 {
541 sizeof(SECURITY_QUALITY_OF_SERVICE),
542 SecurityImpersonation,
543 SECURITY_STATIC_TRACKING,
544 FALSE
545 };
546
547 BOOLEAN
548 NTAPI
549 CsrImpersonateClient(IN PCSR_THREAD CsrThread)
550 {
551 NTSTATUS Status;
552 PCSR_THREAD CurrentThread = NtCurrentTeb()->CsrClientThread;
553
554 /* Use the current thread if none given */
555 if (!CsrThread) CsrThread = CurrentThread;
556
557 /* Still no thread, something is wrong */
558 if (!CsrThread)
559 {
560 /* Failure */
561 return FALSE;
562 }
563
564 /* Make the call */
565 Status = NtImpersonateThread(NtCurrentThread(),
566 CsrThread->ThreadHandle,
567 &CsrSecurityQos);
568
569 if (!NT_SUCCESS(Status))
570 {
571 /* Failure */
572 return FALSE;
573 }
574
575 /* Increase the impersonation count for the current thread */
576 if (CurrentThread) ++CurrentThread->ImpersonationCount;
577
578 /* Return Success */
579 return TRUE;
580 }
581
582 BOOLEAN
583 NTAPI
584 CsrRevertToSelf(VOID)
585 {
586 NTSTATUS Status;
587 PCSR_THREAD CurrentThread = NtCurrentTeb()->CsrClientThread;
588 HANDLE ImpersonationToken = NULL;
589
590 /* Check if we have a Current Thread */
591 if (CurrentThread)
592 {
593 /* Make sure impersonation is on */
594 if (!CurrentThread->ImpersonationCount)
595 {
596 return FALSE;
597 }
598 else if (--CurrentThread->ImpersonationCount > 0)
599 {
600 /* Success; impersonation count decreased but still not zero */
601 return TRUE;
602 }
603 }
604
605 /* Impersonation has been totally removed, revert to ourselves */
606 Status = NtSetInformationThread(NtCurrentThread(),
607 ThreadImpersonationToken,
608 &ImpersonationToken,
609 sizeof(HANDLE));
610
611 /* Return TRUE or FALSE */
612 return NT_SUCCESS(Status);
613 }
614
615 PCSRSS_PROCESS_DATA
616 NTAPI
617 FindProcessForShutdown(IN PLUID CallerLuid)
618 {
619 ULONG Hash;
620 PCSRSS_PROCESS_DATA CsrProcess, ReturnCsrProcess = NULL;
621 NTSTATUS Status;
622 ULONG Level = 0;
623 LUID ProcessLuid;
624 LUID SystemLuid = SYSTEM_LUID;
625 BOOLEAN IsSystemLuid = FALSE, IsOurLuid = FALSE;
626
627 for (Hash = 0; Hash < (sizeof(ProcessData) / sizeof(*ProcessData)); Hash++)
628 {
629 /* Get this process hash bucket */
630 CsrProcess = ProcessData[Hash];
631 while (CsrProcess)
632 {
633 /* Skip this process if it's already been processed*/
634 if (CsrProcess->Flags & CsrProcessSkipShutdown) goto Next;
635
636 /* Get the LUID of this Process */
637 Status = CsrGetProcessLuid(CsrProcess->Process, &ProcessLuid);
638
639 /* Check if we didn't get access to the LUID */
640 if (Status == STATUS_ACCESS_DENIED)
641 {
642 /* FIXME:Check if we have any threads */
643 }
644
645 if (!NT_SUCCESS(Status))
646 {
647 /* We didn't have access, so skip it */
648 CsrProcess->Flags |= CsrProcessSkipShutdown;
649 goto Next;
650 }
651
652 /* Check if this is the System LUID */
653 if ((IsSystemLuid = RtlEqualLuid(&ProcessLuid, &SystemLuid)))
654 {
655 /* Mark this process */
656 CsrProcess->ShutdownFlags |= CsrShutdownSystem;
657 }
658 else if (!(IsOurLuid = RtlEqualLuid(&ProcessLuid, CallerLuid)))
659 {
660 /* Our LUID doesn't match with the caller's */
661 CsrProcess->ShutdownFlags |= CsrShutdownOther;
662 }
663
664 /* Check if we're past the previous level */
665 if (CsrProcess->ShutdownLevel > Level)
666 {
667 /* Update the level */
668 Level = CsrProcess->ShutdownLevel;
669
670 /* Set the final process */
671 ReturnCsrProcess = CsrProcess;
672 }
673 Next:
674 /* Next process */
675 CsrProcess = CsrProcess->next;
676 }
677 }
678
679 /* Check if we found a process */
680 if (ReturnCsrProcess)
681 {
682 /* Skip this one next time */
683 ReturnCsrProcess->Flags |= CsrProcessSkipShutdown;
684 }
685
686 return ReturnCsrProcess;
687 }
688
689 /* This is really "CsrShutdownProcess", mostly */
690 NTSTATUS
691 WINAPI
692 CsrEnumProcesses(IN CSRSS_ENUM_PROCESS_PROC EnumProc,
693 IN PVOID Context)
694 {
695 PVOID* RealContext = (PVOID*)Context;
696 PLUID CallerLuid = RealContext[0];
697 PCSRSS_PROCESS_DATA CsrProcess = NULL;
698 NTSTATUS Status = STATUS_UNSUCCESSFUL;
699 BOOLEAN FirstTry;
700 ULONG Result = 0;
701 ULONG Hash;
702
703 /* Acquire process lock */
704 CsrAcquireProcessLock();
705
706 /* Start the loop */
707 for (Hash = 0; Hash < (sizeof(ProcessData) / sizeof(*ProcessData)); Hash++)
708 {
709 /* Get the Process */
710 CsrProcess = ProcessData[Hash];
711 while (CsrProcess)
712 {
713 /* Remove the skip flag, set shutdown flags to 0*/
714 CsrProcess->Flags &= ~CsrProcessSkipShutdown;
715 CsrProcess->ShutdownFlags = 0;
716
717 /* Move to the next */
718 CsrProcess = CsrProcess->next;
719 }
720 }
721
722 /* Set shudown Priority */
723 CsrSetToShutdownPriority();
724
725 /* Loop all processes */
726 DPRINT1("Enumerating for LUID: %lx %lx\n", CallerLuid->HighPart, CallerLuid->LowPart);
727
728 /* Start looping */
729 while (TRUE)
730 {
731 /* Find the next process to shutdown */
732 FirstTry = TRUE;
733 if (!(CsrProcess = FindProcessForShutdown(CallerLuid)))
734 {
735 /* Done, quit */
736 CsrReleaseProcessLock();
737 Status = STATUS_SUCCESS;
738 goto Quickie;
739 }
740
741 LoopAgain:
742 /* Release the lock, make the callback, and acquire it back */
743 DPRINT1("Found process: %lx\n", CsrProcess->ProcessId);
744 CsrReleaseProcessLock();
745 Result = (ULONG)EnumProc(CsrProcess, (PVOID)((ULONG_PTR)Context | FirstTry));
746 CsrAcquireProcessLock();
747
748 /* Check the result */
749 DPRINT1("Result: %d\n", Result);
750 if (Result == CsrShutdownCsrProcess)
751 {
752 /* The callback unlocked the process */
753 break;
754 }
755 else if (Result == CsrShutdownNonCsrProcess)
756 {
757 /* A non-CSR process, the callback didn't touch it */
758 //continue;
759 }
760 else if (Result == CsrShutdownCancelled)
761 {
762 /* Shutdown was cancelled, unlock and exit */
763 CsrReleaseProcessLock();
764 Status = STATUS_CANCELLED;
765 goto Quickie;
766 }
767
768 /* No matches during the first try, so loop again */
769 if (FirstTry && Result == CsrShutdownNonCsrProcess)
770 {
771 FirstTry = FALSE;
772 goto LoopAgain;
773 }
774 }
775
776 Quickie:
777 /* Return to normal priority */
778 CsrSetToNormalPriority();
779 return Status;
780 }
781
782 NTSTATUS
783 NTAPI
784 CsrLockProcessByClientId(IN HANDLE Pid,
785 OUT PCSRSS_PROCESS_DATA *CsrProcess OPTIONAL)
786 {
787 ULONG Hash;
788 PCSRSS_PROCESS_DATA CurrentProcess = NULL;
789 NTSTATUS Status = STATUS_UNSUCCESSFUL;
790
791 /* Acquire the lock */
792 CsrAcquireProcessLock();
793
794 /* Start the loop */
795 for (Hash = 0; Hash < (sizeof(ProcessData) / sizeof(*ProcessData)); Hash++)
796 {
797 /* Get the Process */
798 CurrentProcess = ProcessData[Hash];
799 while (CurrentProcess)
800 {
801 /* Check for PID match */
802 if (CurrentProcess->ProcessId == Pid)
803 {
804 /* Get out of here with success */
805 // DPRINT1("Found %p for PID %lx\n", CurrentProcess, Pid);
806 Status = STATUS_SUCCESS;
807 goto Found;
808 }
809
810 /* Move to the next */
811 CurrentProcess = CurrentProcess->next;
812 }
813 }
814
815 /* Nothing found, release the lock */
816 Found:
817 if (!CurrentProcess) CsrReleaseProcessLock();
818
819 /* Return the status and process */
820 if (CsrProcess) *CsrProcess = CurrentProcess;
821 return Status;
822 }
823
824 /**********************************************************************
825 * CSRSS API
826 *********************************************************************/
827
828 CSR_API(CsrCreateProcess)
829 {
830 PCSRSS_PROCESS_DATA NewProcessData;
831 NTSTATUS Status;
832
833 Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
834 Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
835
836 NewProcessData = CsrCreateProcessData(Request->Data.CreateProcessRequest.NewProcessId);
837 if (NewProcessData == NULL)
838 {
839 return(STATUS_NO_MEMORY);
840 }
841
842 if (!(Request->Data.CreateProcessRequest.Flags & (CREATE_NEW_CONSOLE|DETACHED_PROCESS)))
843 {
844 NewProcessData->ParentConsole = ProcessData->Console;
845 NewProcessData->bInheritHandles = Request->Data.CreateProcessRequest.bInheritHandles;
846 if (Request->Data.CreateProcessRequest.bInheritHandles)
847 {
848 Status = CsrDuplicateHandleTable(ProcessData, NewProcessData);
849 }
850 }
851
852 if (Request->Data.CreateProcessRequest.Flags & CREATE_NEW_PROCESS_GROUP)
853 {
854 NewProcessData->ProcessGroup = (DWORD)(ULONG_PTR)NewProcessData->ProcessId;
855 }
856 else
857 {
858 NewProcessData->ProcessGroup = ProcessData->ProcessGroup;
859 }
860
861 return(STATUS_SUCCESS);
862 }
863
864 CSR_API(CsrCreateThread)
865 {
866 PCSR_THREAD CurrentThread;
867 HANDLE ThreadHandle;
868 NTSTATUS Status;
869 PCSRSS_PROCESS_DATA CsrProcess;
870
871 Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
872 Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
873
874 CurrentThread = NtCurrentTeb()->CsrClientThread;
875 CsrProcess = CurrentThread->Process;
876 // DPRINT1("Current thread: %p %p\n", CurrentThread, CsrProcess);
877 // DPRINT1("Request CID: %lx %lx %lx\n",
878 // CsrProcess->ProcessId,
879 // NtCurrentTeb()->ClientId.UniqueProcess,
880 // Request->Data.CreateThreadRequest.ClientId.UniqueProcess);
881
882 if (CsrProcess->ProcessId != Request->Data.CreateThreadRequest.ClientId.UniqueProcess)
883 {
884 if (Request->Data.CreateThreadRequest.ClientId.UniqueProcess == NtCurrentTeb()->ClientId.UniqueProcess)
885 {
886 return STATUS_SUCCESS;
887 }
888
889 Status = CsrLockProcessByClientId(Request->Data.CreateThreadRequest.ClientId.UniqueProcess,
890 &CsrProcess);
891 // DPRINT1("Found matching process: %p\n", CsrProcess);
892 if (!NT_SUCCESS(Status)) return Status;
893 }
894
895 // DPRINT1("PIDs: %lx %lx\n", CurrentThread->Process->ProcessId, CsrProcess->ProcessId);
896 // DPRINT1("Thread handle is: %lx Process Handle is: %lx %lx\n",
897 // Request->Data.CreateThreadRequest.ThreadHandle,
898 // CurrentThread->Process->Process,
899 // CsrProcess->Process);
900 Status = NtDuplicateObject(CsrProcess->Process,
901 Request->Data.CreateThreadRequest.ThreadHandle,
902 NtCurrentProcess(),
903 &ThreadHandle,
904 0,
905 0,
906 DUPLICATE_SAME_ACCESS);
907 //DPRINT1("Duplicate status: %lx\n", Status);
908 if (!NT_SUCCESS(Status))
909 {
910 Status = NtDuplicateObject(CurrentThread->Process->Process,
911 Request->Data.CreateThreadRequest.ThreadHandle,
912 NtCurrentProcess(),
913 &ThreadHandle,
914 0,
915 0,
916 DUPLICATE_SAME_ACCESS);
917 // DPRINT1("Duplicate status: %lx\n", Status);
918 }
919
920 Status = STATUS_SUCCESS; // hack
921 if (NT_SUCCESS(Status))
922 {
923 Status = CsrCreateThreadData(CsrProcess,
924 ThreadHandle,
925 &Request->Data.CreateThreadRequest.ClientId);
926 // DPRINT1("Create status: %lx\n", Status);
927 }
928
929 if (CsrProcess != CurrentThread->Process) CsrReleaseProcessLock();
930
931 return Status;
932 }
933
934 CSR_API(CsrTerminateProcess)
935 {
936 Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
937 Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
938
939 ProcessData->Terminated = TRUE;
940 return STATUS_SUCCESS;
941 }
942
943 CSR_API(CsrConnectProcess)
944 {
945 Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
946 Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
947
948 return(STATUS_SUCCESS);
949 }
950
951 CSR_API(CsrGetShutdownParameters)
952 {
953 Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
954 Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
955
956 Request->Data.GetShutdownParametersRequest.Level = ProcessData->ShutdownLevel;
957 Request->Data.GetShutdownParametersRequest.Flags = ProcessData->ShutdownFlags;
958
959 return(STATUS_SUCCESS);
960 }
961
962 CSR_API(CsrSetShutdownParameters)
963 {
964 Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
965 Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
966
967 ProcessData->ShutdownLevel = Request->Data.SetShutdownParametersRequest.Level;
968 ProcessData->ShutdownFlags = Request->Data.SetShutdownParametersRequest.Flags;
969
970 return(STATUS_SUCCESS);
971 }
972
973 CSR_API(CsrGetInputHandle)
974 {
975 Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
976 Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
977
978 if (ProcessData->Console)
979 {
980 Request->Status = CsrInsertObject(ProcessData,
981 &Request->Data.GetInputHandleRequest.InputHandle,
982 (Object_t *)ProcessData->Console,
983 Request->Data.GetInputHandleRequest.Access,
984 Request->Data.GetInputHandleRequest.Inheritable);
985 }
986 else
987 {
988 Request->Data.GetInputHandleRequest.InputHandle = INVALID_HANDLE_VALUE;
989 Request->Status = STATUS_SUCCESS;
990 }
991
992 return Request->Status;
993 }
994
995 CSR_API(CsrGetOutputHandle)
996 {
997 Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
998 Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
999
1000 if (ProcessData->Console)
1001 {
1002 RtlEnterCriticalSection(&ProcessDataLock);
1003 Request->Status = CsrInsertObject(ProcessData,
1004 &Request->Data.GetOutputHandleRequest.OutputHandle,
1005 &ProcessData->Console->ActiveBuffer->Header,
1006 Request->Data.GetOutputHandleRequest.Access,
1007 Request->Data.GetOutputHandleRequest.Inheritable);
1008 RtlLeaveCriticalSection(&ProcessDataLock);
1009 }
1010 else
1011 {
1012 Request->Data.GetOutputHandleRequest.OutputHandle = INVALID_HANDLE_VALUE;
1013 Request->Status = STATUS_SUCCESS;
1014 }
1015
1016 return Request->Status;
1017 }
1018
1019 CSR_API(CsrCloseHandle)
1020 {
1021 Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
1022 Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
1023
1024 return CsrReleaseObject(ProcessData, Request->Data.CloseHandleRequest.Handle);
1025 }
1026
1027 CSR_API(CsrVerifyHandle)
1028 {
1029 Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
1030 Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
1031
1032 Request->Status = CsrVerifyObject(ProcessData, Request->Data.VerifyHandleRequest.Handle);
1033 if (!NT_SUCCESS(Request->Status))
1034 {
1035 DPRINT("CsrVerifyObject failed, status=%x\n", Request->Status);
1036 }
1037
1038 return Request->Status;
1039 }
1040
1041 CSR_API(CsrDuplicateHandle)
1042 {
1043 ULONG_PTR Index;
1044 PCSRSS_HANDLE Entry;
1045 DWORD DesiredAccess;
1046
1047 Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
1048 Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
1049
1050 Index = (ULONG_PTR)Request->Data.DuplicateHandleRequest.Handle >> 2;
1051 RtlEnterCriticalSection(&ProcessData->HandleTableLock);
1052 if (Index >= ProcessData->HandleTableSize
1053 || (Entry = &ProcessData->HandleTable[Index])->Object == NULL)
1054 {
1055 DPRINT1("Couldn't dup invalid handle %p\n", Request->Data.DuplicateHandleRequest.Handle);
1056 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
1057 return STATUS_INVALID_HANDLE;
1058 }
1059
1060 if (Request->Data.DuplicateHandleRequest.Options & DUPLICATE_SAME_ACCESS)
1061 {
1062 DesiredAccess = Entry->Access;
1063 }
1064 else
1065 {
1066 DesiredAccess = Request->Data.DuplicateHandleRequest.Access;
1067 /* Make sure the source handle has all the desired flags */
1068 if (~Entry->Access & DesiredAccess)
1069 {
1070 DPRINT1("Handle %p only has access %X; requested %X\n",
1071 Request->Data.DuplicateHandleRequest.Handle, Entry->Access, DesiredAccess);
1072 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
1073 return STATUS_INVALID_PARAMETER;
1074 }
1075 }
1076
1077 Request->Status = CsrInsertObject(ProcessData,
1078 &Request->Data.DuplicateHandleRequest.Handle,
1079 Entry->Object,
1080 DesiredAccess,
1081 Request->Data.DuplicateHandleRequest.Inheritable);
1082 if (NT_SUCCESS(Request->Status)
1083 && Request->Data.DuplicateHandleRequest.Options & DUPLICATE_CLOSE_SOURCE)
1084 {
1085 /* Close the original handle. This cannot drop the count to 0, since a new handle now exists */
1086 _InterlockedDecrement(&Entry->Object->ReferenceCount);
1087 Entry->Object = NULL;
1088 }
1089
1090 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
1091 return Request->Status;
1092 }
1093
1094 CSR_API(CsrGetInputWaitHandle)
1095 {
1096 Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
1097 Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
1098
1099 Request->Data.GetConsoleInputWaitHandle.InputWaitHandle = ProcessData->ConsoleEvent;
1100 return STATUS_SUCCESS;
1101 }
1102
1103 /* EOF */