2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS CSR Sub System
4 * FILE: subsys/csr/csrsrv/api.c
5 * PURPOSE: CSR Server DLL API LPC Implementation
6 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
9 /* INCLUDES ******************************************************************/
16 /* DATA **********************************************************************/
17 BOOLEAN (*CsrClientThreadSetup
)(VOID
) = NULL
;
18 ULONG CsrMaxApiRequestThreads
;
19 UNICODE_STRING CsrSbApiPortName
;
20 UNICODE_STRING CsrApiPortName
;
23 PCSR_THREAD CsrSbApiRequestThreadPtr
;
24 ULONG CsrpStaticThreadCount
;
25 ULONG CsrpDynamicThreadTotal
;
27 /* PRIVATE FUNCTIONS *********************************************************/
30 * @name CsrCheckRequestThreads
32 * The CsrCheckRequestThreads routine checks if there are no more threads
33 * to handle CSR API Requests, and creates a new thread if possible, to
38 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
39 * if a new thread couldn't be created.
46 CsrCheckRequestThreads(VOID
)
52 /* Decrease the count, and see if we're out */
53 if (!(InterlockedDecrement(&CsrpStaticThreadCount
)))
55 /* Check if we've still got space for a Dynamic Thread */
56 if (CsrpDynamicThreadTotal
< CsrMaxApiRequestThreads
)
58 /* Create a new dynamic thread */
59 Status
= RtlCreateUserThread(NtCurrentProcess(),
65 (PVOID
)CsrApiRequestThread
,
70 if(NT_SUCCESS(Status
))
72 /* Increase the thread counts */
73 CsrpStaticThreadCount
++;
74 CsrpDynamicThreadTotal
++;
76 /* Add a new server thread */
77 if (CsrAddStaticServerThread(hThread
,
79 CsrThreadIsServerThread
))
82 NtResumeThread(hThread
,NULL
);
86 /* Failed to create a new static thread */
87 CsrpStaticThreadCount
--;
88 CsrpDynamicThreadTotal
--;
91 NtTerminateThread(hThread
,0);
95 return STATUS_UNSUCCESSFUL
;
102 return STATUS_SUCCESS
;
106 * @name CsrSbApiPortInitialize
108 * The CsrSbApiPortInitialize routine initializes the LPC Port used for
109 * communications with the Session Manager (SM) and initializes the static
110 * thread that will handle connection requests and APIs.
114 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
122 CsrSbApiPortInitialize(VOID
)
125 PSECURITY_DESCRIPTOR PortSd
;
126 OBJECT_ATTRIBUTES ObjectAttributes
;
128 HANDLE hRequestThread
;
131 /* Calculate how much space we'll need for the Port Name */
132 Size
= CsrDirectoryName
.Length
+ sizeof(SB_PORT_NAME
) + sizeof(WCHAR
);
134 /* Allocate space for it, and create it */
135 CsrSbApiPortName
.Buffer
= RtlAllocateHeap(CsrHeap
, 0, Size
);
136 CsrSbApiPortName
.Length
= 0;
137 CsrSbApiPortName
.MaximumLength
= (USHORT
)Size
;
138 RtlAppendUnicodeStringToString(&CsrSbApiPortName
, &CsrDirectoryName
);
139 RtlAppendUnicodeToString(&CsrSbApiPortName
, UNICODE_PATH_SEP
);
140 RtlAppendUnicodeToString(&CsrSbApiPortName
, SB_PORT_NAME
);
142 /* Create Security Descriptor for this Port */
143 CsrCreateLocalSystemSD(&PortSd
);
145 /* Initialize the Attributes */
146 InitializeObjectAttributes(&ObjectAttributes
,
152 /* Create the Port Object */
153 Status
= NtCreatePort(&CsrSbApiPort
,
155 sizeof(SB_CONNECTION_INFO
),
156 sizeof(SB_API_MESSAGE
),
157 32 * sizeof(SB_API_MESSAGE
));
158 if(!NT_SUCCESS(Status
))
163 /* Create the Thread to handle the API Requests */
164 Status
= RtlCreateUserThread(NtCurrentProcess(),
170 (PVOID
)CsrSbApiRequestThread
,
174 if(!NT_SUCCESS(Status
))
179 /* Add it as a Static Server Thread */
180 CsrSbApiRequestThreadPtr
= CsrAddStaticServerThread(hRequestThread
,
185 return NtResumeThread(hRequestThread
, NULL
);
189 * @name CsrApiPortInitialize
191 * The CsrApiPortInitialize routine initializes the LPC Port used for
192 * communications with the Client/Server Runtime (CSR) and initializes the
193 * static thread that will handle connection requests and APIs.
197 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
205 CsrApiPortInitialize(VOID
)
208 OBJECT_ATTRIBUTES ObjectAttributes
;
210 HANDLE hRequestEvent
, hThread
;
212 PLIST_ENTRY ListHead
, NextEntry
;
213 PCSR_THREAD ServerThread
;
215 /* Calculate how much space we'll need for the Port Name */
216 Size
= CsrDirectoryName
.Length
+ sizeof(CSR_PORT_NAME
) + sizeof(WCHAR
);
218 /* Allocate space for it, and create it */
219 CsrApiPortName
.Buffer
= RtlAllocateHeap(CsrHeap
, 0, Size
);
220 CsrApiPortName
.Length
= 0;
221 CsrApiPortName
.MaximumLength
= (USHORT
)Size
;
222 RtlAppendUnicodeStringToString(&CsrApiPortName
, &CsrDirectoryName
);
223 RtlAppendUnicodeToString(&CsrApiPortName
, UNICODE_PATH_SEP
);
224 RtlAppendUnicodeToString(&CsrApiPortName
, CSR_PORT_NAME
);
226 /* FIXME: Create a Security Descriptor */
228 /* Initialize the Attributes */
229 InitializeObjectAttributes(&ObjectAttributes
,
235 /* Create the Port Object */
236 Status
= NtCreatePort(&CsrApiPort
,
238 sizeof(CSR_CONNECTION_INFO
),
239 sizeof(CSR_API_MESSAGE
),
241 if(!NT_SUCCESS(Status
))
246 /* Create the event the Port Thread will use */
247 Status
= NtCreateEvent(&hRequestEvent
,
250 SynchronizationEvent
,
252 if(!NT_SUCCESS(Status
))
257 /* Create the Request Thread */
258 Status
= RtlCreateUserThread(NtCurrentProcess(),
264 (PVOID
)CsrApiRequestThread
,
265 (PVOID
)hRequestEvent
,
268 if(!NT_SUCCESS(Status
))
273 /* Add this as a static thread to CSRSRV */
274 CsrAddStaticServerThread(hThread
, &ClientId
, CsrThreadIsServerThread
);
276 /* Get the Thread List Pointers */
277 ListHead
= &CsrRootProcess
->ThreadList
;
278 NextEntry
= ListHead
->Flink
;
280 /* Start looping the list */
281 while (NextEntry
!= ListHead
)
284 ServerThread
= CONTAINING_RECORD(NextEntry
, CSR_THREAD
, Link
);
287 Status
= NtResumeThread(ServerThread
->ThreadHandle
, NULL
);
289 /* Is this a Server Thread? */
290 if (ServerThread
->Flags
& CsrThreadIsServerThread
)
292 /* If so, then wait for it to initialize */
293 NtWaitForSingleObject(hRequestEvent
, FALSE
, NULL
);
297 NextEntry
= NextEntry
->Flink
;
300 /* We don't need this anymore */
301 NtClose(hRequestEvent
);
308 * @name CsrApiRequestThread
310 * The CsrApiRequestThread routine handles incoming messages or connection
311 * requests on the CSR API LPC Port.
314 * System-default user-defined parameter. Unused.
316 * @return The thread exit code, if the thread is terminated.
318 * @remarks Before listening on the port, the routine will first attempt
319 * to connect to the user subsystem.
324 CsrApiRequestThread(IN PVOID Parameter
)
326 PTEB Teb
= NtCurrentTeb();
327 LARGE_INTEGER TimeOut
;
328 PCSR_THREAD CurrentThread
;
330 PCSR_API_MESSAGE ReplyMsg
= NULL
;
331 CSR_API_MESSAGE ReceiveMsg
;
332 PCSR_THREAD CsrThread
;
333 PCSR_PROCESS CsrProcess
;
334 PHARDERROR_MSG HardErrorMsg
;
338 PCSR_SERVER_DLL ServerDll
;
339 PCLIENT_DIED_MSG ClientDiedMsg
;
340 PDBGKM_MSG DebugMessage
;
341 ULONG ServerId
, ApiId
;
344 /* Probably because of the way GDI is loaded, this has to be done here */
345 Teb
->GdiClientPID
= HandleToUlong(Teb
->Cid
.UniqueProcess
);
346 Teb
->GdiClientTID
= HandleToUlong(Teb
->Cid
.UniqueThread
);
348 /* Set up the timeout for the connect (30 seconds) */
349 TimeOut
.QuadPart
= -30 * 1000 * 1000 * 10;
351 /* Connect to user32 */
352 while (!CsrConnectToUser())
354 /* Keep trying until we get a response */
355 Teb
->Win32ClientInfo
[0] = 0;
356 NtDelayExecution(FALSE
, &TimeOut
);
360 CurrentThread
= Teb
->CsrClientThread
;
362 /* If we got an event... */
365 /* Set it, to let stuff waiting on us load */
366 NtSetEvent((HANDLE
)Parameter
, NULL
);
368 /* Increase the Thread Counts */
369 InterlockedIncrement(&CsrpStaticThreadCount
);
370 InterlockedIncrement(&CsrpDynamicThreadTotal
);
373 /* Now start the loop */
376 /* Make sure the real CID is set */
377 Teb
->RealClientId
= Teb
->Cid
;
379 /* Wait for a message to come through */
380 Status
= NtReplyWaitReceivePort(CsrApiPort
,
382 (PPORT_MESSAGE
)ReplyMsg
,
383 (PPORT_MESSAGE
)&ReceiveMsg
);
385 /* Check if we didn't get success */
386 if(Status
!= STATUS_SUCCESS
)
388 /* If we only got a warning, keep going */
389 if (NT_SUCCESS(Status
)) continue;
391 /* We failed big time, so start out fresh */
396 /* Use whatever Client ID we got */
397 Teb
->RealClientId
= ReceiveMsg
.Header
.ClientId
;
399 /* Get the Message Type */
400 MessageType
= ReceiveMsg
.Header
.u2
.s2
.Type
;
402 /* Handle connection requests */
403 if (MessageType
== LPC_CONNECTION_REQUEST
)
405 /* Handle the Connection Request */
406 CsrApiHandleConnectionRequest(&ReceiveMsg
);
411 /* It's some other kind of request. Get the lock for the lookup*/
412 CsrAcquireProcessLock();
414 /* Now do the lookup to get the CSR_THREAD */
415 CsrThread
= CsrLocateThreadByClientId(&CsrProcess
,
416 &ReceiveMsg
.Header
.ClientId
);
418 /* Did we find a thread? */
421 /* This wasn't a CSR Thread, release lock */
422 CsrReleaseProcessLock();
424 /* If this was an exception, handle it */
425 if (MessageType
== LPC_EXCEPTION
)
427 ReplyMsg
= &ReceiveMsg
;
428 ReplyMsg
->Status
= DBG_CONTINUE
;
430 else if (MessageType
== LPC_PORT_CLOSED
||
431 MessageType
== LPC_CLIENT_DIED
)
433 /* The Client or Port are gone, loop again */
436 else if (MessageType
== LPC_ERROR_EVENT
)
438 /* If it's a hard error, handle this too */
439 HardErrorMsg
= (PHARDERROR_MSG
)&ReceiveMsg
;
441 /* Default it to unhandled */
442 HardErrorMsg
->Response
= ResponseNotHandled
;
444 /* Check if there are free api threads */
445 CsrCheckRequestThreads();
446 if (CsrpStaticThreadCount
)
448 /* Loop every Server DLL */
449 for (i
= 0; i
< CSR_SERVER_DLL_MAX
; i
++)
451 /* Get the Server DLL */
452 ServerDll
= CsrLoadedServerDll
[i
];
454 /* Check if it's valid and if it has a Hard Error Callback */
455 if (ServerDll
&& ServerDll
->HardErrorCallback
)
458 (*ServerDll
->HardErrorCallback
)(CsrThread
, HardErrorMsg
);
460 /* If it's handled, get out of here */
461 if (HardErrorMsg
->Response
!= ResponseNotHandled
) break;
466 /* Increase the thread count */
467 InterlockedIncrement(&CsrpStaticThreadCount
);
469 /* If the response was 0xFFFFFFFF, we'll ignore it */
470 if (HardErrorMsg
->Response
== 0xFFFFFFFF)
476 ReplyMsg
= &ReceiveMsg
;
479 else if (MessageType
== LPC_REQUEST
)
481 /* This is an API Message coming from a non-CSR Thread */
482 ReplyMsg
= &ReceiveMsg
;
483 ReplyMsg
->Status
= STATUS_ILLEGAL_FUNCTION
;
485 else if (MessageType
== LPC_DATAGRAM
)
487 /* This is an API call, get the Server ID */
488 ServerId
= CSR_SERVER_ID_FROM_OPCODE(ReceiveMsg
.Opcode
);
490 /* Make sure that the ID is within limits, and the Server DLL loaded */
491 if ((ServerId
>= CSR_SERVER_DLL_MAX
) ||
492 (!(ServerDll
= CsrLoadedServerDll
[ServerId
])))
494 /* We are beyond the Maximum Server ID */
500 ApiId
= CSR_API_ID_FROM_OPCODE(ReceiveMsg
.Opcode
);
502 /* Normalize it with our Base ID */
503 ApiId
-= ServerDll
->ApiBase
;
505 /* Make sure that the ID is within limits, and the entry exists */
506 if ((ApiId
>= ServerDll
->HighestApiSupported
))
508 /* We are beyond the Maximum API ID, or it doesn't exist */
513 ReceiveMsg
.Status
= STATUS_SUCCESS
;
515 /* Validation complete, start SEH */
518 /* Make sure we have enough threads */
519 CsrCheckRequestThreads();
521 /* Call the API and get the result */
523 (ServerDll
->DispatchTable
[ApiId
])(&ReceiveMsg
, &Reply
);
525 /* Increase the static thread count */
526 InterlockedIncrement(&CsrpStaticThreadCount
);
528 _SEH_EXCEPT(CsrUnhandledExceptionFilter
)
537 /* Some other ignored message type */
545 /* We have a valid thread, was this an LPC Request? */
546 if (MessageType
!= LPC_REQUEST
)
548 /* It's not an API, check if the client died */
549 if (MessageType
== LPC_CLIENT_DIED
)
551 /* Get the information and check if it matches our thread */
552 ClientDiedMsg
= (PCLIENT_DIED_MSG
)&ReceiveMsg
;
553 if (ClientDiedMsg
->CreateTime
.QuadPart
== CsrThread
->CreateTime
.QuadPart
)
555 /* Reference the thread */
556 CsrThread
->ReferenceCount
++;
558 /* Destroy the thread in the API Message */
559 CsrDestroyThread(&ReceiveMsg
.Header
.ClientId
);
561 /* Check if the thread was actually ourselves */
562 if (CsrProcess
->ThreadCount
== 1)
564 /* Kill the process manually here */
565 CsrDestroyProcess(&CsrThread
->ClientId
, 0);
568 /* Remove our extra reference */
569 CsrLockedDereferenceThread(CsrThread
);
572 /* Release the lock and keep looping */
573 CsrReleaseProcessLock();
578 /* Reference the thread and release the lock */
579 CsrThread
->ReferenceCount
++;
580 CsrReleaseProcessLock();
582 /* Check if this was an exception */
583 if (MessageType
== LPC_EXCEPTION
)
585 /* Kill the process */
586 NtTerminateProcess(CsrProcess
->ProcessHandle
, STATUS_ABANDONED
);
588 /* Destroy it from CSR */
589 CsrDestroyProcess(&ReceiveMsg
.Header
.ClientId
, STATUS_ABANDONED
);
591 /* Return a Debug Message */
592 DebugMessage
= (PDBGKM_MSG
)&ReceiveMsg
;
593 DebugMessage
->Status
= DBG_CONTINUE
;
594 ReplyMsg
= &ReceiveMsg
;
596 /* Remove our extra reference */
597 CsrDereferenceThread(CsrThread
);
599 else if (MessageType
== LPC_ERROR_EVENT
)
601 /* If it's a hard error, handle this too */
602 HardErrorMsg
= (PHARDERROR_MSG
)&ReceiveMsg
;
604 /* Default it to unhandled */
605 HardErrorMsg
->Response
= ResponseNotHandled
;
607 /* Check if there are free api threads */
608 CsrCheckRequestThreads();
609 if (CsrpStaticThreadCount
)
611 /* Loop every Server DLL */
612 for (i
= 0; i
< CSR_SERVER_DLL_MAX
; i
++)
614 /* Get the Server DLL */
615 ServerDll
= CsrLoadedServerDll
[i
];
617 /* Check if it's valid and if it has a Hard Error Callback */
618 if (ServerDll
&& ServerDll
->HardErrorCallback
)
621 (*ServerDll
->HardErrorCallback
)(CsrThread
, HardErrorMsg
);
623 /* If it's handled, get out of here */
624 if (HardErrorMsg
->Response
!= ResponseNotHandled
) break;
629 /* Increase the thread count */
630 InterlockedIncrement(&CsrpStaticThreadCount
);
632 /* If the response was 0xFFFFFFFF, we'll ignore it */
633 if (HardErrorMsg
->Response
== 0xFFFFFFFF)
639 CsrDereferenceThread(CsrThread
);
640 ReplyMsg
= &ReceiveMsg
;
646 CsrDereferenceThread(CsrThread
);
654 /* We got an API Request */
655 CsrDereferenceThread(CsrThread
);
656 CsrReleaseProcessLock();
658 /* FIXME: Handle the API */
662 /* We're out of the loop for some reason, terminate! */
663 NtTerminateThread(NtCurrentThread(), Status
);
668 * @name CsrApiHandleConnectionRequest
670 * The CsrApiHandleConnectionRequest routine handles and accepts a new
671 * connection request to the CSR API LPC Port.
674 * Pointer to the incoming CSR API Message which contains the
675 * connection request.
677 * @return STATUS_SUCCESS in case of success, or status code which caused
678 * the routine to error.
680 * @remarks This routine is responsible for attaching the Shared Section to
681 * new clients connecting to CSR.
686 CsrApiHandleConnectionRequest(IN PCSR_API_MESSAGE ApiMessage
)
688 PCSR_THREAD CsrThread
= NULL
;
689 PCSR_PROCESS CsrProcess
= NULL
;
690 NTSTATUS Status
= STATUS_SUCCESS
;
691 PCSR_CONNECTION_INFO ConnectInfo
= &ApiMessage
->ConnectionInfo
;
692 BOOLEAN AllowConnection
= FALSE
;
693 REMOTE_PORT_VIEW RemotePortView
;
696 /* Acquire the Process Lock */
697 CsrAcquireProcessLock();
699 /* Lookup the CSR Thread */
700 CsrThread
= CsrLocateThreadByClientId(NULL
, &ApiMessage
->Header
.ClientId
);
702 /* Check if we have a thread */
705 /* Get the Process */
706 CsrProcess
= CsrThread
->Process
;
708 /* Make sure we have a Process as well */
711 /* Reference the Process */
712 CsrProcess
->ReferenceCount
++;
714 /* Release the lock */
715 CsrReleaseProcessLock();
717 /* Duplicate the Object Directory */
718 Status
= NtDuplicateObject(NtCurrentProcess(),
720 CsrProcess
->ProcessHandle
,
721 &ConnectInfo
->ObjectDirectory
,
724 DUPLICATE_SAME_ACCESS
|
725 DUPLICATE_SAME_ATTRIBUTES
);
727 /* Acquire the lock */
728 CsrAcquireProcessLock();
730 /* Check for success */
731 if (NT_SUCCESS(Status
))
733 /* Attach the Shared Section */
734 Status
= CsrSrvAttachSharedSection(CsrProcess
, ConnectInfo
);
736 /* Check how this went */
737 if (NT_SUCCESS(Status
)) AllowConnection
= TRUE
;
740 /* Dereference the project */
741 CsrProcess
->ReferenceCount
--;
745 /* Release the lock */
746 CsrReleaseProcessLock();
748 /* Setup the Port View Structure */
749 RemotePortView
.Length
= sizeof(REMOTE_PORT_VIEW
);
750 RemotePortView
.ViewSize
= 0;
751 RemotePortView
.ViewBase
= NULL
;
753 /* Save the Process ID */
754 ConnectInfo
->ProcessId
= NtCurrentTeb()->Cid
.UniqueProcess
;
756 /* Accept the Connection */
757 Status
= NtAcceptConnectPort(&hPort
,
758 AllowConnection
? UlongToPtr(CsrProcess
->SequenceNumber
) : 0,
764 /* Check if the connection was established, or if we allowed it */
765 if (NT_SUCCESS(Status
) && AllowConnection
)
767 /* Set some Port Data in the Process */
768 CsrProcess
->ClientPort
= hPort
;
769 CsrProcess
->ClientViewBase
= (ULONG_PTR
)RemotePortView
.ViewBase
;
770 CsrProcess
->ClientViewBounds
= (ULONG_PTR
)((ULONG_PTR
)RemotePortView
.ViewBase
+
771 (ULONG_PTR
)RemotePortView
.ViewSize
);
773 /* Complete the connection */
774 Status
= NtCompleteConnectPort(hPort
);
777 /* The accept or complete could've failed, let debug builds know */
778 if (!NT_SUCCESS(Status
))
780 DPRINT1("CSRSS: Failure to accept connection. Status: %lx\n", Status
);
783 /* Return status to caller */
788 * @name CsrSbApiRequestThread
790 * The CsrSbApiRequestThread routine handles incoming messages or connection
791 * requests on the SM API LPC Port.
794 * System-default user-defined parameter. Unused.
796 * @return The thread exit code, if the thread is terminated.
798 * @remarks Before listening on the port, the routine will first attempt
799 * to connect to the user subsystem.
804 CsrSbApiRequestThread(IN PVOID Parameter
)
807 SB_API_MESSAGE ReceiveMsg
;
808 PSB_API_MESSAGE ReplyMsg
= NULL
;
815 /* Wait for a message to come in */
816 Status
= NtReplyWaitReceivePort(CsrSbApiPort
,
818 (PPORT_MESSAGE
)ReplyMsg
,
819 (PPORT_MESSAGE
)&ReceiveMsg
);
821 /* Check if we didn't get success */
822 if(Status
!= STATUS_SUCCESS
)
824 /* If we only got a warning, keep going */
825 if (NT_SUCCESS(Status
)) continue;
827 /* We failed big time, so start out fresh */
832 /* Save the message type */
833 MessageType
= ReceiveMsg
.Header
.u2
.s2
.Type
;
835 /* Check if this is a connection request */
836 if (MessageType
== LPC_CONNECTION_REQUEST
)
838 /* Handle connection request */
839 CsrSbApiHandleConnectionRequest(&ReceiveMsg
);
846 /* Check if the port died */
847 if (MessageType
== LPC_PORT_CLOSED
)
849 /* Close the handle if we have one */
850 if (PortContext
) NtClose((HANDLE
)PortContext
);
852 /* Client died, start over */
856 else if (MessageType
== LPC_CLIENT_DIED
)
858 /* Client died, start over */
864 * It's an API Message, check if it's within limits. If it's not, the
865 * NT Behaviour is to set this to the Maximum API.
867 if (ReceiveMsg
.Opcode
> 4) ReceiveMsg
.Opcode
= 4;
869 /* Reuse the message */
870 ReplyMsg
= &ReceiveMsg
;
872 /* Make sure that the message is supported */
873 if (ReceiveMsg
.Opcode
< 4)
876 if (!(CsrServerSbApiDispatch
[ReceiveMsg
.Opcode
])(&ReceiveMsg
))
878 /* It failed, so return nothing */
884 /* We don't support this API Number */
885 ReplyMsg
->Status
= STATUS_NOT_IMPLEMENTED
;
891 * @name CsrSbApiHandleConnectionRequest
893 * The CsrSbApiHandleConnectionRequest routine handles and accepts a new
894 * connection request to the SM API LPC Port.
897 * Pointer to the incoming CSR API Message which contains the
898 * connection request.
900 * @return STATUS_SUCCESS in case of success, or status code which caused
901 * the routine to error.
908 CsrSbApiHandleConnectionRequest(IN PSB_API_MESSAGE Message
)
911 REMOTE_PORT_VIEW RemotePortView
;
914 /* Set the Port View Structure Length */
915 RemotePortView
.Length
= sizeof(REMOTE_PORT_VIEW
);
917 /* Accept the connection */
918 Status
= NtAcceptConnectPort(&hPort
,
920 (PPORT_MESSAGE
)Message
,
925 if (!NT_SUCCESS(Status
))
927 DPRINT1("CSRSS: Sb Accept Connection failed %lx\n", Status
);
931 /* Complete the Connection */
932 if (!NT_SUCCESS(Status
= NtCompleteConnectPort(hPort
)))
934 DPRINT1("CSRSS: Sb Complete Connection failed %lx\n",Status
);
941 /* PUBLIC FUNCTIONS **********************************************************/
944 * @name CsrCallServerFromServer
947 * The CsrCallServerFromServer routine calls a CSR API from within a server.
948 * It avoids using LPC messages since the request isn't coming from a client.
951 * Pointer to the CSR API Message to send to the server.
954 * Pointer to the CSR API Message to receive from the server.
956 * @return STATUS_SUCCESS in case of success, STATUS_ILLEGAL_FUNCTION
957 * if the opcode is invalid, or STATUS_ACCESS_VIOLATION if there
958 * was a problem executing the API.
965 CsrCallServerFromServer(PCSR_API_MESSAGE ReceiveMsg
,
966 PCSR_API_MESSAGE ReplyMsg
)
969 PCSR_SERVER_DLL ServerDll
;
974 /* Get the Server ID */
975 ServerId
= CSR_SERVER_ID_FROM_OPCODE(ReceiveMsg
->Opcode
);
977 /* Make sure that the ID is within limits, and the Server DLL loaded */
978 if ((ServerId
>= CSR_SERVER_DLL_MAX
) ||
979 (!(ServerDll
= CsrLoadedServerDll
[ServerId
])))
981 /* We are beyond the Maximum Server ID */
982 ReplyMsg
->Status
= (ULONG
)STATUS_ILLEGAL_FUNCTION
;
983 return STATUS_ILLEGAL_FUNCTION
;
988 ApiId
= CSR_API_ID_FROM_OPCODE(ReceiveMsg
->Opcode
);
990 /* Normalize it with our Base ID */
991 ApiId
-= ServerDll
->ApiBase
;
993 /* Make sure that the ID is within limits, and the entry exists */
994 if ((ApiId
>= ServerDll
->HighestApiSupported
) ||
995 (ServerDll
->ValidTable
&& !ServerDll
->ValidTable
[ApiId
]))
997 /* We are beyond the Maximum API ID, or it doesn't exist */
998 ReplyMsg
->Status
= (ULONG
)STATUS_ILLEGAL_FUNCTION
;
999 return STATUS_ILLEGAL_FUNCTION
;
1003 /* Validation complete, start SEH */
1006 /* Call the API and get the result */
1007 Status
= (ServerDll
->DispatchTable
[ApiId
])(ReceiveMsg
, &Reply
);
1009 /* Return the result, no matter what it is */
1010 ReplyMsg
->Status
= Status
;
1014 /* If we got an exception, return access violation */
1015 ReplyMsg
->Status
= STATUS_ACCESS_VIOLATION
;
1019 /* Return success */
1020 return STATUS_SUCCESS
;
1024 * @name CsrConnectToUser
1027 * The CsrConnectToUser connects to the User subsystem.
1031 * @return A pointer to the CSR Thread
1038 CsrConnectToUser(VOID
)
1041 ANSI_STRING DllName
;
1042 UNICODE_STRING TempName
;
1045 PTEB Teb
= NtCurrentTeb();
1046 PCSR_THREAD CsrThread
;
1048 /* Check if we didn't already find it */
1049 if (!CsrClientThreadSetup
)
1051 /* Get the DLL Handle for user32.dll */
1052 RtlInitAnsiString(&DllName
, "user32");
1053 RtlAnsiStringToUnicodeString(&TempName
, &DllName
, TRUE
);
1054 Status
= LdrGetDllHandle(NULL
,
1058 RtlFreeUnicodeString(&TempName
);
1060 /* If we got teh handle, get the Client Thread Startup Entrypoint */
1061 if (NT_SUCCESS(Status
))
1063 RtlInitAnsiString(&StartupName
,"ClientThreadSetup");
1064 Status
= LdrGetProcedureAddress(hUser32
,
1067 (PVOID
)&CsrClientThreadSetup
);
1071 /* Connect to user32 */
1072 CsrClientThreadSetup();
1074 /* Save pointer to this thread in TEB */
1075 CsrThread
= CsrLocateThreadInProcess(NULL
, &Teb
->Cid
);
1076 if (CsrThread
) Teb
->CsrClientThread
= CsrThread
;
1083 * @name CsrQueryApiPort
1086 * The CsrQueryApiPort routine returns a handle to the CSR API LPC port.
1090 * @return A handle to the port.
1097 CsrQueryApiPort(VOID
)
1099 DPRINT("CSRSRV: %s called\n", __FUNCTION__
);
1104 * @name CsrCaptureArguments
1105 * @implemented NT5.1
1107 * The CsrCaptureArguments routine validates a CSR Capture Buffer and
1108 * re-captures it into a server CSR Capture Buffer.
1111 * Pointer to the CSR Thread performing the validation.
1114 * Pointer to the CSR API Message containing the Capture Buffer
1115 * that needs to be validated.
1117 * @return TRUE if validation succeeded, FALSE otherwise.
1124 CsrCaptureArguments(IN PCSR_THREAD CsrThread
,
1125 IN PCSR_API_MESSAGE ApiMessage
)
1127 PCSR_CAPTURE_BUFFER LocalCaptureBuffer
= NULL
;
1128 ULONG LocalLength
= 0;
1129 PCSR_CAPTURE_BUFFER RemoteCaptureBuffer
= NULL
;
1130 SIZE_T BufferDistance
= 0;
1131 ULONG PointerCount
= 0;
1132 ULONG_PTR
**PointerOffsets
= NULL
;
1133 ULONG_PTR
*CurrentPointer
= NULL
;
1135 /* Use SEH to make sure this is valid */
1138 /* Get the buffer we got from whoever called NTDLL */
1139 LocalCaptureBuffer
= ApiMessage
->CsrCaptureData
;
1140 LocalLength
= LocalCaptureBuffer
->Size
;
1142 /* Now check if the buffer is inside our mapped section */
1143 if (((ULONG_PTR
)LocalCaptureBuffer
< CsrThread
->Process
->ClientViewBase
) ||
1144 (((ULONG_PTR
)LocalCaptureBuffer
+ LocalLength
) >= CsrThread
->Process
->ClientViewBounds
))
1146 /* Return failure */
1147 ApiMessage
->Status
= STATUS_INVALID_PARAMETER
;
1151 /* Check if the Length is valid */
1152 if (((LocalCaptureBuffer
->PointerCount
* 4 + sizeof(CSR_CAPTURE_BUFFER
)) >
1153 LocalLength
) ||(LocalLength
> MAXWORD
))
1155 /* Return failure */
1156 ApiMessage
->Status
= STATUS_INVALID_PARAMETER
;
1162 /* Return failure */
1163 ApiMessage
->Status
= STATUS_INVALID_PARAMETER
;
1167 /* We validated the incoming buffer, now allocate the remote one */
1168 RemoteCaptureBuffer
= RtlAllocateHeap(CsrHeap
, 0, LocalLength
);
1169 if (!RemoteCaptureBuffer
)
1171 /* We're out of memory */
1172 ApiMessage
->Status
= STATUS_NO_MEMORY
;
1176 /* Copy the client's buffer */
1177 RtlMoveMemory(RemoteCaptureBuffer
, LocalCaptureBuffer
, LocalLength
);
1179 /* Copy the length */
1180 RemoteCaptureBuffer
->Size
= LocalLength
;
1182 /* Calculate the difference between our buffer and the client's */
1183 BufferDistance
= (ULONG_PTR
)RemoteCaptureBuffer
- (ULONG_PTR
)LocalCaptureBuffer
;
1185 /* Save the pointer count and offset pointer */
1186 PointerCount
= RemoteCaptureBuffer
->PointerCount
;
1187 PointerOffsets
= (ULONG_PTR
**)(RemoteCaptureBuffer
+ 1);
1189 /* Start the loop */
1190 while (PointerCount
)
1192 /* Get the current pointer */
1193 if ((CurrentPointer
= *PointerOffsets
++))
1195 /* Add it to the CSR Message structure */
1196 CurrentPointer
+= (ULONG_PTR
)ApiMessage
;
1198 /* Validate the bounds of the current pointer */
1199 if ((*CurrentPointer
>= CsrThread
->Process
->ClientViewBase
) &&
1200 (*CurrentPointer
< CsrThread
->Process
->ClientViewBounds
))
1202 /* Modify the pointer to take into account its new position */
1203 *CurrentPointer
+= BufferDistance
;
1207 /* Invalid pointer, fail */
1208 ApiMessage
->Status
= (ULONG
)STATUS_INVALID_PARAMETER
;
1212 /* Move to the next Pointer */
1216 /* Check if we got success */
1217 if (ApiMessage
->Status
!= STATUS_SUCCESS
)
1219 /* Failure. Free the buffer and return*/
1220 RtlFreeHeap(CsrHeap
, 0, RemoteCaptureBuffer
);
1225 /* Success, save the previous buffer */
1226 RemoteCaptureBuffer
->PreviousCaptureBuffer
= LocalCaptureBuffer
;
1227 ApiMessage
->CsrCaptureData
= RemoteCaptureBuffer
;
1235 * @name CsrReleaseCapturedArguments
1236 * @implemented NT5.1
1238 * The CsrReleaseCapturedArguments routine releases a Capture Buffer
1239 * that was previously captured with CsrCaptureArguments.
1242 * Pointer to the CSR API Message containing the Capture Buffer
1243 * that needs to be released.
1252 CsrReleaseCapturedArguments(IN PCSR_API_MESSAGE ApiMessage
)
1254 PCSR_CAPTURE_BUFFER RemoteCaptureBuffer
;
1255 PCSR_CAPTURE_BUFFER LocalCaptureBuffer
;
1256 SIZE_T BufferDistance
;
1258 ULONG_PTR
**PointerOffsets
;
1259 ULONG_PTR
*CurrentPointer
;
1261 /* Get the capture buffers */
1262 RemoteCaptureBuffer
= ApiMessage
->CsrCaptureData
;
1263 LocalCaptureBuffer
= RemoteCaptureBuffer
->PreviousCaptureBuffer
;
1265 /* Free the previous one */
1266 RemoteCaptureBuffer
->PreviousCaptureBuffer
= NULL
;
1268 /* Find out the difference between the two buffers */
1269 BufferDistance
= (ULONG_PTR
)LocalCaptureBuffer
- (ULONG_PTR
)RemoteCaptureBuffer
;
1271 /* Save the pointer count and offset pointer */
1272 PointerCount
= RemoteCaptureBuffer
->PointerCount
;
1273 PointerOffsets
= (ULONG_PTR
**)(RemoteCaptureBuffer
+ 1);
1275 /* Start the loop */
1276 while (PointerCount
)
1278 /* Get the current pointer */
1279 if ((CurrentPointer
= *PointerOffsets
++))
1281 /* Add it to the CSR Message structure */
1282 CurrentPointer
+= (ULONG_PTR
)ApiMessage
;
1284 /* Modify the pointer to take into account its new position */
1285 *CurrentPointer
+= BufferDistance
;
1288 /* Move to the next Pointer */
1292 /* Copy the data back */
1293 RtlMoveMemory(LocalCaptureBuffer
,
1294 RemoteCaptureBuffer
,
1295 RemoteCaptureBuffer
->Size
);
1297 /* Free our allocated buffer */
1298 RtlFreeHeap(CsrHeap
, 0, RemoteCaptureBuffer
);
1302 * @name CsrValidateMessageBuffer
1303 * @implemented NT5.1
1305 * The CsrValidateMessageBuffer routine validates a captured message buffer
1306 * present in the CSR Api Message
1309 * Pointer to the CSR API Message containing the CSR Capture Buffer.
1312 * Pointer to the message buffer to validate.
1314 * @param ArgumentSize
1315 * Size of the message to check.
1317 * @param ArgumentCount
1318 * Number of messages to check.
1320 * @return TRUE if validation suceeded, FALSE otherwise.
1327 CsrValidateMessageBuffer(IN PCSR_API_MESSAGE ApiMessage
,
1329 IN ULONG ArgumentSize
,
1330 IN ULONG ArgumentCount
)
1332 PCSR_CAPTURE_BUFFER CaptureBuffer
= ApiMessage
->CsrCaptureData
;
1333 SIZE_T BufferDistance
;
1335 ULONG_PTR
**PointerOffsets
;
1336 ULONG_PTR
*CurrentPointer
;
1339 /* Make sure there are some arguments */
1340 if (!ArgumentCount
) return FALSE
;
1342 /* Check if didn't get a buffer and there aren't any arguments to check */
1343 if (!(*Buffer
) && (!(ArgumentCount
* ArgumentSize
))) return TRUE
;
1345 /* Check if we have no capture buffer */
1348 /* In this case, check only the Process ID */
1349 if (NtCurrentTeb()->Cid
.UniqueProcess
==
1350 ApiMessage
->Header
.ClientId
.UniqueProcess
)
1352 /* There is a match, validation succeeded */
1358 /* Make sure that there is still space left in the buffer */
1359 if ((CaptureBuffer
->Size
- (ULONG_PTR
)*Buffer
+ (ULONG_PTR
)CaptureBuffer
) <
1360 (ArgumentCount
* ArgumentSize
))
1362 /* Find out the difference between the two buffers */
1363 BufferDistance
= (ULONG_PTR
)Buffer
- (ULONG_PTR
)ApiMessage
;
1365 /* Save the pointer count */
1366 PointerCount
= CaptureBuffer
->PointerCount
;
1367 PointerOffsets
= (ULONG_PTR
**)(CaptureBuffer
+ 1);
1369 /* Start the loop */
1370 for (i
= 0; i
< PointerCount
; i
++)
1372 /* Get the current pointer */
1373 CurrentPointer
= *PointerOffsets
++;
1375 /* Check if its' equal to the difference */
1376 if (*CurrentPointer
== BufferDistance
) return TRUE
;
1386 * @name CsrValidateMessageString
1387 * @implemented NT5.1
1389 * The CsrValidateMessageString validates a captured Wide-Character String
1390 * present in a CSR API Message.
1393 * Pointer to the CSR API Message containing the CSR Capture Buffer.
1395 * @param MessageString
1396 * Pointer to the buffer containing the string to validate.
1398 * @return TRUE if validation suceeded, FALSE otherwise.
1405 CsrValidateMessageString(IN PCSR_API_MESSAGE ApiMessage
,
1406 IN LPWSTR
*MessageString
)
1408 DPRINT("CSRSRV: %s called\n", __FUNCTION__
);