2 * subsystems/win32/csrss/csrsrv/api/wapi.c
4 * CSRSS port message processing
6 * ReactOS Operating System
10 /* INCLUDES ******************************************************************/
17 /* GLOBALS *******************************************************************/
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
;
26 /* FUNCTIONS *****************************************************************/
29 CsrApiRegisterDefinitions(PCSRSS_API_DEFINITION NewDefinitions
)
32 PCSRSS_API_DEFINITION Scan
;
33 PCSRSS_API_DEFINITION New
;
35 DPRINT("CSR: %s called\n", __FUNCTION__
);
38 for (Scan
= NewDefinitions
; 0 != Scan
->Handler
; Scan
++)
43 New
= RtlAllocateHeap(CsrHeap
, 0,
44 (ApiDefinitionsCount
+ NewCount
)
45 * sizeof(CSRSS_API_DEFINITION
));
48 DPRINT1("Unable to allocate memory\n");
49 return STATUS_NO_MEMORY
;
51 if (0 != ApiDefinitionsCount
)
53 RtlCopyMemory(New
, ApiDefinitions
,
54 ApiDefinitionsCount
* sizeof(CSRSS_API_DEFINITION
));
55 RtlFreeHeap(CsrHeap
, 0, ApiDefinitions
);
57 RtlCopyMemory(New
+ ApiDefinitionsCount
, NewDefinitions
,
58 NewCount
* sizeof(CSRSS_API_DEFINITION
));
60 ApiDefinitionsCount
+= NewCount
;
62 return STATUS_SUCCESS
;
68 CsrApiCallHandler(PCSR_PROCESS ProcessData,
69 PCSR_API_MESSAGE Request)
74 IN OUT PCSR_API_MESSAGE ApiMessage
,
81 DPRINT("CSR: Calling handler for ApiNumber: %x.\n", ApiMessage
->ApiNumber
);
82 ApiId
= CSR_API_NUMBER_TO_API_ID(ApiMessage
->ApiNumber
);
83 DPRINT("CSR: ApiID: %x ServerID: %x\n", ApiId
, CSR_API_NUMBER_TO_SERVER_ID(ApiMessage
->ApiNumber
));
85 /* FIXME: Extract DefIndex instead of looping */
86 for (DefIndex
= 0; DefIndex
< ApiDefinitionsCount
; DefIndex
++)
88 if (ApiDefinitions
[DefIndex
].ApiID
== ApiId
)
90 if (ApiMessage
->Header
.u1
.s1
.DataLength
< ApiDefinitions
[DefIndex
].MinRequestSize
)
92 DPRINT1("Request ApiID %d min request size %d actual %d\n",
93 ApiId
, ApiDefinitions
[DefIndex
].MinRequestSize
,
94 ApiMessage
->Header
.u1
.s1
.DataLength
);
95 ApiMessage
->Status
= STATUS_INVALID_PARAMETER
;
99 ApiMessage
->Status
= (ApiDefinitions
[DefIndex
].Handler
)(ApiMessage
, Reply
);
104 DPRINT1("CSR: Unknown request ApiNumber 0x%x\n", ApiMessage
->ApiNumber
);
105 ApiMessage
->Status
= STATUS_INVALID_SYSTEM_SERVICE
;
109 CallHardError(IN PCSR_THREAD ThreadData
,
110 IN PHARDERROR_MSG HardErrorMessage
);
115 CsrHandleHardError(IN PCSR_THREAD ThreadData
,
116 IN OUT PHARDERROR_MSG Message
)
118 DPRINT1("CSR: received hard error %lx\n", Message
->Status
);
120 /* Call the hard error handler in win32csr */
121 CallHardError(ThreadData
, Message
);
125 * @name CsrCallServerFromServer
128 * The CsrCallServerFromServer routine calls a CSR API from within a server.
129 * It avoids using LPC messages since the request isn't coming from a client.
132 * Pointer to the CSR API Message to send to the server.
135 * Pointer to the CSR API Message to receive from the server.
137 * @return STATUS_SUCCESS in case of success, STATUS_ILLEGAL_FUNCTION
138 * if the ApiNumber is invalid, or STATUS_ACCESS_VIOLATION if there
139 * was a problem executing the API.
146 CsrCallServerFromServer(PCSR_API_MESSAGE ReceiveMsg
,
147 PCSR_API_MESSAGE ReplyMsg
)
151 PCSR_SERVER_DLL ServerDll
;
156 /* Get the Server ID */
157 ServerId
= CSR_SERVER_ID_FROM_OPCODE(ReceiveMsg
->ApiNumber
);
159 /* Make sure that the ID is within limits, and the Server DLL loaded */
160 if ((ServerId
>= CSR_SERVER_DLL_MAX
) ||
161 (!(ServerDll
= CsrLoadedServerDll
[ServerId
])))
163 /* We are beyond the Maximum Server ID */
164 DPRINT1("CSRSS: %lx is invalid ServerDllIndex (%08x)\n", ServerId
, ServerDll
);
165 ReplyMsg
->Status
= (ULONG
)STATUS_ILLEGAL_FUNCTION
;
166 return STATUS_ILLEGAL_FUNCTION
;
171 ApiId
= CSR_API_NUMBER_TO_API_ID(ReceiveMsg
->ApiNumber
);
173 /* Normalize it with our Base ID */
174 ApiId
-= ServerDll
->ApiBase
;
176 /* Make sure that the ID is within limits, and the entry exists */
177 if ((ApiId
>= ServerDll
->HighestApiSupported
) ||
178 ((ServerDll
->ValidTable
) && !(ServerDll
->ValidTable
[ApiId
])))
180 /* We are beyond the Maximum API ID, or it doesn't exist */
181 DPRINT1("CSRSS: %lx (%s) is invalid ApiTableIndex for %Z or is an "
182 "invalid API to call from the server.\n",
183 ServerDll
->ValidTable
[ApiId
],
184 ((ServerDll
->NameTable
) && (ServerDll
->NameTable
[ApiId
])) ?
185 ServerDll
->NameTable
[ApiId
] : "*** UNKNOWN ***", &ServerDll
->Name
);
187 ReplyMsg
->Status
= (ULONG
)STATUS_ILLEGAL_FUNCTION
;
188 return STATUS_ILLEGAL_FUNCTION
;
194 DPRINT1("CSRSS: %s Api Request received from server process\n",
195 ServerDll
->NameTable
[ApiId
]);
198 /* Validation complete, start SEH */
201 /* Call the API and get the result */
202 Status
= (ServerDll
->DispatchTable
[ApiId
])(ReceiveMsg
, &Reply
);
204 /* Return the result, no matter what it is */
205 ReplyMsg
->Status
= Status
;
207 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
209 /* If we got an exception, return access violation */
210 ReplyMsg
->Status
= STATUS_ACCESS_VIOLATION
;
215 return STATUS_SUCCESS
;
217 #else // Hacky reactos code
219 PCSR_PROCESS ProcessData
;
222 /* Get the Process Data */
223 CsrLockProcessByClientId(&ReceiveMsg
->Header
.ClientId
.UniqueProcess
, &ProcessData
);
226 DPRINT1("Message: Unable to find data for process 0x%x\n",
227 ReceiveMsg
->Header
.ClientId
.UniqueProcess
);
228 return STATUS_NOT_SUPPORTED
;
231 /* Validation complete, start SEH */
234 /* Call the API and get the result */
235 CsrApiCallHandler(ReplyMsg
, /*ProcessData*/ &ReplyCode
);
237 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
239 /* If we got an exception, return access violation */
240 ReplyMsg
->Status
= STATUS_ACCESS_VIOLATION
;
244 /* Release the process reference */
245 CsrUnlockProcess(ProcessData
);
248 return STATUS_SUCCESS
;
253 * @name CsrApiPortInitialize
255 * The CsrApiPortInitialize routine initializes the LPC Port used for
256 * communications with the Client/Server Runtime (CSR) and initializes the
257 * static thread that will handle connection requests and APIs.
261 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
269 CsrApiPortInitialize(VOID
)
272 OBJECT_ATTRIBUTES ObjectAttributes
;
274 HANDLE hRequestEvent
, hThread
;
276 PLIST_ENTRY ListHead
, NextEntry
;
277 PCSR_THREAD ServerThread
;
279 /* Calculate how much space we'll need for the Port Name */
280 Size
= CsrDirectoryName
.Length
+ sizeof(CSR_PORT_NAME
) + sizeof(WCHAR
);
282 /* Create the buffer for it */
283 CsrApiPortName
.Buffer
= RtlAllocateHeap(CsrHeap
, 0, Size
);
284 if (!CsrApiPortName
.Buffer
) return STATUS_NO_MEMORY
;
286 /* Setup the rest of the empty string */
287 CsrApiPortName
.Length
= 0;
288 CsrApiPortName
.MaximumLength
= (USHORT
)Size
;
289 RtlAppendUnicodeStringToString(&CsrApiPortName
, &CsrDirectoryName
);
290 RtlAppendUnicodeToString(&CsrApiPortName
, UNICODE_PATH_SEP
);
291 RtlAppendUnicodeToString(&CsrApiPortName
, CSR_PORT_NAME
);
294 DPRINT1("CSRSS: Creating %wZ port and associated threads\n", &CsrApiPortName
);
295 DPRINT1("CSRSS: sizeof( CONNECTINFO ) == %ld sizeof( API_MSG ) == %ld\n",
296 sizeof(CSR_CONNECTION_INFO
), sizeof(CSR_API_MESSAGE
));
299 /* FIXME: Create a Security Descriptor */
301 /* Initialize the Attributes */
302 InitializeObjectAttributes(&ObjectAttributes
,
308 /* Create the Port Object */
309 Status
= NtCreatePort(&CsrApiPort
,
311 LPC_MAX_DATA_LENGTH
, // hack ; sizeof(CSR_CONNECTION_INFO),
312 LPC_MAX_MESSAGE_LENGTH
, // hack ; sizeof(CSR_API_MESSAGE),
314 if (NT_SUCCESS(Status
))
316 /* Create the event the Port Thread will use */
317 Status
= NtCreateEvent(&hRequestEvent
,
320 SynchronizationEvent
,
322 if (NT_SUCCESS(Status
))
324 /* Create the Request Thread */
325 Status
= RtlCreateUserThread(NtCurrentProcess(),
331 (PVOID
)ClientConnectionThread
,//CsrApiRequestThread,
332 (PVOID
)hRequestEvent
,
335 if (NT_SUCCESS(Status
))
337 /* Add this as a static thread to CSRSRV */
338 CsrAddStaticServerThread(hThread
, &ClientId
, CsrThreadIsServerThread
);
340 /* Get the Thread List Pointers */
341 ListHead
= &CsrRootProcess
->ThreadList
;
342 NextEntry
= ListHead
->Flink
;
344 /* Start looping the list */
345 while (NextEntry
!= ListHead
)
348 ServerThread
= CONTAINING_RECORD(NextEntry
, CSR_THREAD
, Link
);
351 Status
= NtResumeThread(ServerThread
->ThreadHandle
, NULL
);
353 /* Is this a Server Thread? */
354 if (ServerThread
->Flags
& CsrThreadIsServerThread
)
356 /* If so, then wait for it to initialize */
357 Status
= NtWaitForSingleObject(hRequestEvent
, FALSE
, NULL
);
358 ASSERT(NT_SUCCESS(Status
));
362 NextEntry
= NextEntry
->Flink
;
365 /* We don't need this anymore */
366 NtClose(hRequestEvent
);
375 PBASE_STATIC_SERVER_DATA BaseStaticServerData
;
379 CreateBaseAcls(OUT PACL
* Dacl
,
380 OUT PACL
* RestrictedDacl
)
382 PSID SystemSid
, WorldSid
, RestrictedSid
;
383 SID_IDENTIFIER_AUTHORITY NtAuthority
= {SECURITY_NT_AUTHORITY
};
384 SID_IDENTIFIER_AUTHORITY WorldAuthority
= {SECURITY_WORLD_SID_AUTHORITY
};
386 UCHAR KeyValueBuffer
[0x40];
387 PKEY_VALUE_PARTIAL_INFORMATION KeyValuePartialInfo
;
388 UNICODE_STRING KeyName
;
389 ULONG ProtectionMode
= 0;
390 ULONG AclLength
, ResultLength
;
392 OBJECT_ATTRIBUTES ObjectAttributes
;
394 /* Open the Session Manager Key */
395 RtlInitUnicodeString(&KeyName
, SM_REG_KEY
);
396 InitializeObjectAttributes(&ObjectAttributes
,
398 OBJ_CASE_INSENSITIVE
,
401 Status
= NtOpenKey(&hKey
, KEY_READ
, &ObjectAttributes
);
402 if (NT_SUCCESS(Status
))
404 /* Read the key value */
405 RtlInitUnicodeString(&KeyName
, L
"ProtectionMode");
406 Status
= NtQueryValueKey(hKey
,
408 KeyValuePartialInformation
,
410 sizeof(KeyValueBuffer
),
413 /* Make sure it's what we expect it to be */
414 KeyValuePartialInfo
= (PKEY_VALUE_PARTIAL_INFORMATION
)KeyValueBuffer
;
415 if ((NT_SUCCESS(Status
)) && (KeyValuePartialInfo
->Type
== REG_DWORD
) &&
416 (*(PULONG
)KeyValuePartialInfo
->Data
))
418 /* Save the Protection Mode */
419 ProtectionMode
= *(PULONG
)KeyValuePartialInfo
->Data
;
422 /* Close the handle */
426 /* Allocate the System SID */
427 Status
= RtlAllocateAndInitializeSid(&NtAuthority
,
428 1, SECURITY_LOCAL_SYSTEM_RID
,
431 ASSERT(NT_SUCCESS(Status
));
433 /* Allocate the World SID */
434 Status
= RtlAllocateAndInitializeSid(&WorldAuthority
,
435 1, SECURITY_WORLD_RID
,
438 ASSERT(NT_SUCCESS(Status
));
440 /* Allocate the restricted SID */
441 Status
= RtlAllocateAndInitializeSid(&NtAuthority
,
442 1, SECURITY_RESTRICTED_CODE_RID
,
445 ASSERT(NT_SUCCESS(Status
));
447 /* Allocate one ACL with 3 ACEs each for one SID */
448 AclLength
= sizeof(ACL
) + 3 * sizeof(ACCESS_ALLOWED_ACE
) +
449 RtlLengthSid(SystemSid
) +
450 RtlLengthSid(RestrictedSid
) +
451 RtlLengthSid(WorldSid
);
452 *Dacl
= RtlAllocateHeap(CsrHeap
, 0, AclLength
);
453 ASSERT(*Dacl
!= NULL
);
455 /* Set the correct header fields */
456 Status
= RtlCreateAcl(*Dacl
, AclLength
, ACL_REVISION2
);
457 ASSERT(NT_SUCCESS(Status
));
459 /* Give the appropriate rights to each SID */
460 /* FIXME: Should check SessionId/ProtectionMode */
461 Status
= RtlAddAccessAllowedAce(*Dacl
, ACL_REVISION2
, DIRECTORY_QUERY
| DIRECTORY_TRAVERSE
| DIRECTORY_CREATE_OBJECT
| DIRECTORY_CREATE_SUBDIRECTORY
| READ_CONTROL
, WorldSid
);
462 ASSERT(NT_SUCCESS(Status
));
463 Status
= RtlAddAccessAllowedAce(*Dacl
, ACL_REVISION2
, DIRECTORY_ALL_ACCESS
, SystemSid
);
464 ASSERT(NT_SUCCESS(Status
));
465 Status
= RtlAddAccessAllowedAce(*Dacl
, ACL_REVISION2
, DIRECTORY_TRAVERSE
, RestrictedSid
);
466 ASSERT(NT_SUCCESS(Status
));
468 /* Now allocate the restricted DACL */
469 *RestrictedDacl
= RtlAllocateHeap(CsrHeap
, 0, AclLength
);
470 ASSERT(*RestrictedDacl
!= NULL
);
473 Status
= RtlCreateAcl(*RestrictedDacl
, AclLength
, ACL_REVISION2
);
474 ASSERT(NT_SUCCESS(Status
));
476 /* And add the same ACEs as before */
477 /* FIXME: Not really fully correct */
478 Status
= RtlAddAccessAllowedAce(*RestrictedDacl
, ACL_REVISION2
, DIRECTORY_QUERY
| DIRECTORY_TRAVERSE
| DIRECTORY_CREATE_OBJECT
| DIRECTORY_CREATE_SUBDIRECTORY
| READ_CONTROL
, WorldSid
);
479 ASSERT(NT_SUCCESS(Status
));
480 Status
= RtlAddAccessAllowedAce(*RestrictedDacl
, ACL_REVISION2
, DIRECTORY_ALL_ACCESS
, SystemSid
);
481 ASSERT(NT_SUCCESS(Status
));
482 Status
= RtlAddAccessAllowedAce(*RestrictedDacl
, ACL_REVISION2
, DIRECTORY_TRAVERSE
, RestrictedSid
);
483 ASSERT(NT_SUCCESS(Status
));
485 /* The SIDs are captured, can free them now */
486 RtlFreeHeap(CsrHeap
, 0, SystemSid
);
487 RtlFreeHeap(CsrHeap
, 0, WorldSid
);
488 RtlFreeHeap(CsrHeap
, 0, RestrictedSid
);
493 CsrpHandleConnectionRequest(PPORT_MESSAGE Request
)
496 HANDLE ServerPort
= NULL
;//, ServerThread = NULL;
497 PCSR_PROCESS ProcessData
= NULL
;
498 REMOTE_PORT_VIEW RemotePortView
;
499 // CLIENT_ID ClientId;
500 BOOLEAN AllowConnection
= FALSE
;
501 PCSR_CONNECTION_INFO ConnectInfo
;
504 DPRINT("CSR: %s: Handling: %p\n", __FUNCTION__
, Request
);
506 ConnectInfo
= (PCSR_CONNECTION_INFO
)(Request
+ 1);
508 /* Save the process ID */
509 RtlZeroMemory(ConnectInfo
, sizeof(CSR_CONNECTION_INFO
));
511 CsrLockProcessByClientId(Request
->ClientId
.UniqueProcess
, &ProcessData
);
514 DPRINT1("CSRSRV: Unknown process: %lx. Will be rejecting connection\n",
515 Request
->ClientId
.UniqueProcess
);
518 if ((ProcessData
) && (ProcessData
!= CsrRootProcess
))
520 /* Attach the Shared Section */
521 Status
= CsrSrvAttachSharedSection(ProcessData
, ConnectInfo
);
522 if (NT_SUCCESS(Status
))
524 DPRINT("Connection ok\n");
525 AllowConnection
= TRUE
;
529 DPRINT1("Shared section map failed: %lx\n", Status
);
532 else if (ProcessData
== CsrRootProcess
)
534 AllowConnection
= TRUE
;
537 /* Release the process */
538 if (ProcessData
) CsrUnlockProcess(ProcessData
);
540 /* Setup the Port View Structure */
541 RemotePortView
.Length
= sizeof(REMOTE_PORT_VIEW
);
542 RemotePortView
.ViewSize
= 0;
543 RemotePortView
.ViewBase
= NULL
;
545 /* Save the Process ID */
546 ConnectInfo
->ProcessId
= NtCurrentTeb()->ClientId
.UniqueProcess
;
548 Status
= NtAcceptConnectPort(&ServerPort
,
549 AllowConnection
? UlongToPtr(ProcessData
->SequenceNumber
) : 0,
554 if (!NT_SUCCESS(Status
))
556 DPRINT1("CSRSS: NtAcceptConnectPort - failed. Status == %X\n", Status
);
558 else if (AllowConnection
)
562 DPRINT1("CSRSS: ClientId: %lx.%lx has ClientView: Base=%p, Size=%lx\n",
563 Request
->ClientId
.UniqueProcess
,
564 Request
->ClientId
.UniqueThread
,
565 RemotePortView
.ViewBase
,
566 RemotePortView
.ViewSize
);
569 /* Set some Port Data in the Process */
570 ProcessData
->ClientPort
= ServerPort
;
571 ProcessData
->ClientViewBase
= (ULONG_PTR
)RemotePortView
.ViewBase
;
572 ProcessData
->ClientViewBounds
= (ULONG_PTR
)((ULONG_PTR
)RemotePortView
.ViewBase
+
573 (ULONG_PTR
)RemotePortView
.ViewSize
);
575 /* Complete the connection */
576 Status
= NtCompleteConnectPort(ServerPort
);
577 if (!NT_SUCCESS(Status
))
579 DPRINT1("CSRSS: NtCompleteConnectPort - failed. Status == %X\n", Status
);
584 DPRINT1("CSRSS: Rejecting Connection Request from ClientId: %lx.%lx\n",
585 Request
->ClientId
.UniqueProcess
,
586 Request
->ClientId
.UniqueThread
);
593 * @name CsrConnectToUser
596 * The CsrConnectToUser connects to the User subsystem.
600 * @return A pointer to the CSR Thread
607 CsrConnectToUser(VOID
)
609 PTEB Teb
= NtCurrentTeb();
610 PCSR_THREAD CsrThread
;
614 UNICODE_STRING TempName
;
618 /* Check if we didn't already find it */
619 if (!CsrClientThreadSetup
)
621 /* Get the DLL Handle for user32.dll */
622 RtlInitAnsiString(&DllName
, "user32");
623 RtlAnsiStringToUnicodeString(&TempName
, &DllName
, TRUE
);
624 Status
= LdrGetDllHandle(NULL
,
628 RtlFreeUnicodeString(&TempName
);
630 /* If we got teh handle, get the Client Thread Startup Entrypoint */
631 if (NT_SUCCESS(Status
))
633 RtlInitAnsiString(&StartupName
,"ClientThreadSetup");
634 Status
= LdrGetProcedureAddress(hUser32
,
637 (PVOID
)&CsrClientThreadSetup
);
641 /* Connect to user32 */
642 CsrClientThreadSetup();
644 /* Save pointer to this thread in TEB */
645 CsrThread
= CsrLocateThreadInProcess(NULL
, &Teb
->ClientId
);
646 if (CsrThread
) Teb
->CsrClientThread
= CsrThread
;
653 * @name CsrpCheckRequestThreads
655 * The CsrpCheckRequestThreads routine checks if there are no more threads
656 * to handle CSR API Requests, and creates a new thread if possible, to
661 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
662 * if a new thread couldn't be created.
669 CsrpCheckRequestThreads(VOID
)
675 /* Decrease the count, and see if we're out */
676 if (!(_InterlockedDecrement(&CsrpStaticThreadCount
)))
678 /* Check if we've still got space for a Dynamic Thread */
679 if (CsrpDynamicThreadTotal
< CsrMaxApiRequestThreads
)
681 /* Create a new dynamic thread */
682 Status
= RtlCreateUserThread(NtCurrentProcess(),
688 (PVOID
)ClientConnectionThread
,//CsrApiRequestThread,
693 if (NT_SUCCESS(Status
))
695 /* Increase the thread counts */
696 _InterlockedIncrement(&CsrpStaticThreadCount
);
697 _InterlockedIncrement(&CsrpDynamicThreadTotal
);
699 /* Add a new server thread */
700 if (CsrAddStaticServerThread(hThread
,
702 CsrThreadIsServerThread
))
705 NtResumeThread(hThread
, NULL
);
709 /* Failed to create a new static thread */
710 _InterlockedDecrement(&CsrpStaticThreadCount
);
711 _InterlockedDecrement(&CsrpDynamicThreadTotal
);
714 DPRINT1("Failing\n");
715 NtTerminateThread(hThread
, 0);
719 return STATUS_UNSUCCESSFUL
;
726 return STATUS_SUCCESS
;
731 ClientConnectionThread(IN PVOID Parameter
)
733 PTEB Teb
= NtCurrentTeb();
734 LARGE_INTEGER TimeOut
;
736 BYTE RawRequest
[LPC_MAX_DATA_LENGTH
];
737 PCSR_API_MESSAGE Request
= (PCSR_API_MESSAGE
)RawRequest
;
738 PCSR_API_MESSAGE Reply
;
739 PCSR_PROCESS CsrProcess
;
740 PCSR_THREAD ServerThread
, CsrThread
;
743 PDBGKM_MSG DebugMessage
;
744 PHARDERROR_MSG HardErrorMsg
;
745 PCLIENT_DIED_MSG ClientDiedMsg
;
746 DPRINT("CSR: %s called\n", __FUNCTION__
);
748 /* Setup LPC loop port and message */
750 ReplyPort
= CsrApiPort
;
752 /* Connect to user32 */
753 while (!CsrConnectToUser())
755 /* Set up the timeout for the connect (30 seconds) */
756 TimeOut
.QuadPart
= -30 * 1000 * 1000 * 10;
758 /* Keep trying until we get a response */
759 Teb
->Win32ClientInfo
[0] = 0;
760 NtDelayExecution(FALSE
, &TimeOut
);
764 ServerThread
= Teb
->CsrClientThread
;
766 /* If we got an event... */
769 /* Set it, to let stuff waiting on us load */
770 Status
= NtSetEvent((HANDLE
)Parameter
, NULL
);
771 ASSERT(NT_SUCCESS(Status
));
773 /* Increase the Thread Counts */
774 _InterlockedIncrement(&CsrpStaticThreadCount
);
775 _InterlockedIncrement(&CsrpDynamicThreadTotal
);
778 /* Now start the loop */
781 /* Make sure the real CID is set */
782 Teb
->RealClientId
= Teb
->ClientId
;
785 if (Teb
->CountOfOwnedCriticalSections
)
787 DPRINT1("CSRSRV: FATAL ERROR. CsrThread is Idle while holding %lu critical sections\n",
788 Teb
->CountOfOwnedCriticalSections
);
789 DPRINT1("CSRSRV: Last Receive Message %lx ReplyMessage %lx\n",
794 /* Send the reply and wait for a new request */
795 DPRINT("Replying to: %lx (%lx)\n", ReplyPort
, CsrApiPort
);
796 Status
= NtReplyWaitReceivePort(ReplyPort
,
800 /* Check if we didn't get success */
801 if (Status
!= STATUS_SUCCESS
)
803 /* Was it a failure or another success code? */
804 if (!NT_SUCCESS(Status
))
806 /* Check for specific status cases */
807 if ((Status
!= STATUS_INVALID_CID
) &&
808 (Status
!= STATUS_UNSUCCESSFUL
) &&
809 ((Status
== STATUS_INVALID_HANDLE
) || (ReplyPort
== CsrApiPort
)))
811 /* Notify the debugger */
812 DPRINT1("CSRSS: ReceivePort failed - Status == %X\n", Status
);
813 DPRINT1("CSRSS: ReplyPortHandle %lx CsrApiPort %lx\n", ReplyPort
, CsrApiPort
);
816 /* We failed big time, so start out fresh */
818 ReplyPort
= CsrApiPort
;
819 DPRINT1("failed: %lx\n", Status
);
824 /* A bizare "success" code, just try again */
825 DPRINT1("NtReplyWaitReceivePort returned \"success\" status 0x%x\n", Status
);
830 /* Use whatever Client ID we got */
831 Teb
->RealClientId
= Request
->Header
.ClientId
;
833 /* Get the Message Type */
834 MessageType
= Request
->Header
.u2
.s2
.Type
;
836 /* Handle connection requests */
837 if (MessageType
== LPC_CONNECTION_REQUEST
)
839 /* Handle the Connection Request */
840 DPRINT("Accepting new connection\n");
841 CsrpHandleConnectionRequest((PPORT_MESSAGE
)Request
);
843 ReplyPort
= CsrApiPort
;
847 /* It's some other kind of request. Get the lock for the lookup */
848 CsrAcquireProcessLock();
850 /* Now do the lookup to get the CSR_THREAD */
851 CsrThread
= CsrLocateThreadByClientId(&CsrProcess
,
852 &Request
->Header
.ClientId
);
854 /* Did we find a thread? */
857 /* This wasn't a CSR Thread, release lock */
858 CsrReleaseProcessLock();
860 /* If this was an exception, handle it */
861 if (MessageType
== LPC_EXCEPTION
)
863 DPRINT1("Exception from unknown thread, just continue\n");
865 ReplyPort
= CsrApiPort
;
866 Reply
->Status
= DBG_CONTINUE
;
868 else if (MessageType
== LPC_PORT_CLOSED
||
869 MessageType
== LPC_CLIENT_DIED
)
871 /* The Client or Port are gone, loop again */
872 DPRINT("Death from unknown thread, just continue\n");
874 ReplyPort
= CsrApiPort
;
876 else if (MessageType
== LPC_ERROR_EVENT
)
878 /* If it's a hard error, handle this too */
879 DPRINT1("Hard error from unknown thread, call handlers\n");
881 HardErrorMsg
= (PHARDERROR_MSG
)Request
;
883 /* Default it to unhandled */
884 HardErrorMsg
->Response
= ResponseNotHandled
;
886 /* Check if there are free api threads */
887 CsrpCheckRequestThreads();
888 if (CsrpStaticThreadCount
)
890 CsrHandleHardError(CsrThread
, (PHARDERROR_MSG
)Request
);
893 /* If the response was 0xFFFFFFFF, we'll ignore it */
894 if (HardErrorMsg
->Response
== 0xFFFFFFFF)
897 ReplyPort
= CsrApiPort
;
901 if (CsrThread
) CsrDereferenceThread(CsrThread
);
903 ReplyPort
= CsrApiPort
;
906 else if (MessageType
== LPC_REQUEST
)
908 /* This is an API Message coming from a non-CSR Thread */
909 DPRINT1("No thread found for request %lx and clientID %lx.%lx\n",
910 Request
->ApiNumber
& 0xFFFF,
911 Request
->Header
.ClientId
.UniqueProcess
,
912 Request
->Header
.ClientId
.UniqueThread
);
914 ReplyPort
= CsrApiPort
;
915 Reply
->Status
= STATUS_ILLEGAL_FUNCTION
;
917 else if (MessageType
== LPC_DATAGRAM
)
919 DPRINT1("Kernel datagram: not yet supported\n");
921 ReplyPort
= CsrApiPort
;
925 /* Some other ignored message type */
927 ReplyPort
= CsrApiPort
;
934 /* We have a valid thread, was this an LPC Request? */
935 if (MessageType
!= LPC_REQUEST
)
937 /* It's not an API, check if the client died */
938 if (MessageType
== LPC_CLIENT_DIED
)
940 /* Get the information and check if it matches our thread */
941 ClientDiedMsg
= (PCLIENT_DIED_MSG
)Request
;
942 if (ClientDiedMsg
->CreateTime
.QuadPart
== CsrThread
->CreateTime
.QuadPart
)
944 /* Reference the thread */
945 CsrLockedReferenceThread(CsrThread
);
947 /* Destroy the thread in the API Message */
948 CsrDestroyThread(&Request
->Header
.ClientId
);
950 /* Check if the thread was actually ourselves */
951 if (CsrProcess
->ThreadCount
== 1)
953 /* Kill the process manually here */
954 DPRINT1("Last thread\n");
955 CsrDestroyProcess(&CsrThread
->ClientId
, 0);
958 /* Remove our extra reference */
959 CsrLockedDereferenceThread(CsrThread
);
962 /* Release the lock and keep looping */
963 CsrReleaseProcessLock();
965 ReplyPort
= CsrApiPort
;
969 /* Reference the thread and release the lock */
970 CsrLockedReferenceThread(CsrThread
);
971 CsrReleaseProcessLock();
973 /* If this was an exception, handle it */
974 if (MessageType
== LPC_EXCEPTION
)
976 /* Kill the process */
977 DPRINT1("Exception in %lx.%lx. Killing...\n",
978 Request
->Header
.ClientId
.UniqueProcess
,
979 Request
->Header
.ClientId
.UniqueThread
);
980 NtTerminateProcess(CsrProcess
->ProcessHandle
, STATUS_ABANDONED
);
982 /* Destroy it from CSR */
983 CsrDestroyProcess(&Request
->Header
.ClientId
, STATUS_ABANDONED
);
985 /* Return a Debug Message */
986 DebugMessage
= (PDBGKM_MSG
)Request
;
987 DebugMessage
->ReturnedStatus
= DBG_CONTINUE
;
989 ReplyPort
= CsrApiPort
;
991 /* Remove our extra reference */
992 CsrDereferenceThread(CsrThread
);
994 else if (MessageType
== LPC_ERROR_EVENT
)
996 DPRINT1("Hard error from known CSR thread... handling\n");
997 goto HandleHardError
;
1001 /* Something else */
1002 DPRINT1("Unhandled message type: %lx\n", MessageType
);
1003 CsrDereferenceThread(CsrThread
);
1011 /* We got an API Request */
1012 CsrLockedReferenceThread(CsrThread
);
1013 CsrReleaseProcessLock();
1015 /* Assume success */
1017 Request
->Status
= STATUS_SUCCESS
;
1019 /* Now we reply to a particular client */
1020 ReplyPort
= CsrThread
->Process
->ClientPort
;
1022 DPRINT("CSR: Got CSR API: %x [Message Origin: %x]\n",
1024 Request
->Header
.ClientId
.UniqueThread
);
1026 /* Validation complete, start SEH */
1031 /* Make sure we have enough threads */
1032 CsrpCheckRequestThreads();
1034 /* Set the client thread pointer */
1035 NtCurrentTeb()->CsrClientThread
= CsrThread
;
1037 /* Call the Handler */
1038 CsrApiCallHandler(Request
, &ReplyCode
);
1040 /* Increase the static thread count */
1041 _InterlockedIncrement(&CsrpStaticThreadCount
);
1043 /* Restore the server thread */
1044 NtCurrentTeb()->CsrClientThread
= ServerThread
;
1046 /* Check if this is a dead client now */
1047 if (Request
->ApiNumber
== 0xBABE)
1049 /* Reply to the death message */
1050 NtReplyPort(ReplyPort
, &Reply
->Header
);
1052 /* Reply back to the API port now */
1053 ReplyPort
= CsrApiPort
;
1056 /* Drop the reference */
1057 CsrDereferenceThread(CsrThread
);
1061 /* Drop the reference */
1062 CsrDereferenceThread(CsrThread
);
1065 _SEH2_EXCEPT(CsrUnhandledExceptionFilter(_SEH2_GetExceptionInformation()))
1068 ReplyPort
= CsrApiPort
;
1073 /* Close the port and exit the thread */
1074 // NtClose(ServerPort);
1076 DPRINT1("CSR: %s done\n", __FUNCTION__
);
1077 /* We're out of the loop for some reason, terminate! */
1078 NtTerminateThread(NtCurrentThread(), Status
);
1083 * @name CsrReleaseCapturedArguments
1084 * @implemented NT5.1
1086 * The CsrReleaseCapturedArguments routine releases a Capture Buffer
1087 * that was previously captured with CsrCaptureArguments.
1090 * Pointer to the CSR API Message containing the Capture Buffer
1091 * that needs to be released.
1100 CsrReleaseCapturedArguments(IN PCSR_API_MESSAGE ApiMessage
)
1102 PCSR_CAPTURE_BUFFER RemoteCaptureBuffer
, LocalCaptureBuffer
;
1103 SIZE_T BufferDistance
;
1105 ULONG_PTR
**PointerOffsets
, *CurrentPointer
;
1107 /* Get the capture buffers */
1108 RemoteCaptureBuffer
= ApiMessage
->CsrCaptureData
;
1109 LocalCaptureBuffer
= RemoteCaptureBuffer
->PreviousCaptureBuffer
;
1111 /* Free the previous one */
1112 RemoteCaptureBuffer
->PreviousCaptureBuffer
= NULL
;
1114 /* Find out the difference between the two buffers */
1115 BufferDistance
= (ULONG_PTR
)LocalCaptureBuffer
- (ULONG_PTR
)RemoteCaptureBuffer
;
1117 /* Save the pointer count and offset pointer */
1118 PointerCount
= RemoteCaptureBuffer
->PointerCount
;
1119 PointerOffsets
= (ULONG_PTR
**)(RemoteCaptureBuffer
+ 1);
1121 /* Start the loop */
1122 while (PointerCount
)
1124 /* Get the current pointer */
1125 CurrentPointer
= *PointerOffsets
++;
1128 /* Add it to the CSR Message structure */
1129 CurrentPointer
+= (ULONG_PTR
)ApiMessage
;
1131 /* Modify the pointer to take into account its new position */
1132 *CurrentPointer
+= BufferDistance
;
1135 /* Move to the next Pointer */
1139 /* Copy the data back */
1140 RtlMoveMemory(LocalCaptureBuffer
, RemoteCaptureBuffer
, RemoteCaptureBuffer
->Size
);
1142 /* Free our allocated buffer */
1143 RtlFreeHeap(CsrHeap
, 0, RemoteCaptureBuffer
);