2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Client/Server Runtime SubSystem
4 * FILE: subsystems/win32/csrsrv/api.c
5 * PURPOSE: CSR Server DLL API LPC Implementation
6 * "\windows\ApiPort" port process management functions
7 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
10 /* INCLUDES ******************************************************************/
17 /* GLOBALS *******************************************************************/
19 static unsigned ApiDefinitionsCount
= 0;
20 static PCSRSS_API_DEFINITION ApiDefinitions
= NULL
;
22 BOOLEAN (*CsrClientThreadSetup
)(VOID
) = NULL
;
23 UNICODE_STRING CsrApiPortName
;
24 volatile LONG CsrpStaticThreadCount
;
25 volatile LONG CsrpDynamicThreadTotal
;
26 extern ULONG CsrMaxApiRequestThreads
;
28 /* FUNCTIONS *****************************************************************/
32 CsrApiRegisterDefinitions(PCSRSS_API_DEFINITION NewDefinitions
)
35 PCSRSS_API_DEFINITION Scan
;
36 PCSRSS_API_DEFINITION New
;
38 DPRINT("CSR: %s called\n", __FUNCTION__
);
41 for (Scan
= NewDefinitions
; 0 != Scan
->Handler
; Scan
++)
46 New
= RtlAllocateHeap(CsrHeap
, 0,
47 (ApiDefinitionsCount
+ NewCount
)
48 * sizeof(CSRSS_API_DEFINITION
));
51 DPRINT1("Unable to allocate memory\n");
52 return STATUS_NO_MEMORY
;
54 if (0 != ApiDefinitionsCount
)
56 RtlCopyMemory(New
, ApiDefinitions
,
57 ApiDefinitionsCount
* sizeof(CSRSS_API_DEFINITION
));
58 RtlFreeHeap(CsrHeap
, 0, ApiDefinitions
);
60 RtlCopyMemory(New
+ ApiDefinitionsCount
, NewDefinitions
,
61 NewCount
* sizeof(CSRSS_API_DEFINITION
));
63 ApiDefinitionsCount
+= NewCount
;
65 return STATUS_SUCCESS
;
72 CsrApiCallHandler(PCSR_PROCESS ProcessData,
73 PCSR_API_MESSAGE Request)
78 IN OUT PCSR_API_MESSAGE ApiMessage
,
85 DPRINT("CSR: Calling handler for ApiNumber: %x.\n", ApiMessage
->ApiNumber
);
86 ApiId
= CSR_API_NUMBER_TO_API_ID(ApiMessage
->ApiNumber
);
87 DPRINT("CSR: ApiID: %x ServerID: %x\n", ApiId
, CSR_API_NUMBER_TO_SERVER_ID(ApiMessage
->ApiNumber
));
89 /* FIXME: Extract DefIndex instead of looping */
90 for (DefIndex
= 0; DefIndex
< ApiDefinitionsCount
; DefIndex
++)
92 if (ApiDefinitions
[DefIndex
].ApiID
== ApiId
)
94 if (ApiMessage
->Header
.u1
.s1
.DataLength
< ApiDefinitions
[DefIndex
].MinRequestSize
)
96 DPRINT1("Request ApiID %d min request size %d actual %d\n",
97 ApiId
, ApiDefinitions
[DefIndex
].MinRequestSize
,
98 ApiMessage
->Header
.u1
.s1
.DataLength
);
99 ApiMessage
->Status
= STATUS_INVALID_PARAMETER
;
103 ApiMessage
->Status
= (ApiDefinitions
[DefIndex
].Handler
)(ApiMessage
, Reply
);
108 DPRINT1("CSR: Unknown request ApiNumber 0x%x\n", ApiMessage
->ApiNumber
);
109 ApiMessage
->Status
= STATUS_INVALID_SYSTEM_SERVICE
;
113 CallHardError(IN PCSR_THREAD ThreadData
,
114 IN PHARDERROR_MSG HardErrorMessage
);
120 CsrHandleHardError(IN PCSR_THREAD ThreadData
,
121 IN OUT PHARDERROR_MSG Message
)
123 DPRINT1("CSR: received hard error %lx\n", Message
->Status
);
125 /* Call the hard error handler in win32csr */
126 CallHardError(ThreadData
, Message
);
131 * @name CsrCallServerFromServer
134 * The CsrCallServerFromServer routine calls a CSR API from within a server.
135 * It avoids using LPC messages since the request isn't coming from a client.
138 * Pointer to the CSR API Message to send to the server.
141 * Pointer to the CSR API Message to receive from the server.
143 * @return STATUS_SUCCESS in case of success, STATUS_ILLEGAL_FUNCTION
144 * if the ApiNumber is invalid, or STATUS_ACCESS_VIOLATION if there
145 * was a problem executing the API.
152 CsrCallServerFromServer(IN PCSR_API_MESSAGE ReceiveMsg
,
153 IN OUT PCSR_API_MESSAGE ReplyMsg
)
157 PCSR_SERVER_DLL ServerDll
;
162 /* Get the Server ID */
163 ServerId
= CSR_API_NUMBER_TO_SERVER_ID(ReceiveMsg
->ApiNumber
);
165 /* Make sure that the ID is within limits, and the Server DLL loaded */
166 if ((ServerId
>= CSR_SERVER_DLL_MAX
) ||
167 (!(ServerDll
= CsrLoadedServerDll
[ServerId
])))
169 /* We are beyond the Maximum Server ID */
170 DPRINT1("CSRSS: %lx is invalid ServerDllIndex (%08x)\n", ServerId
, ServerDll
);
171 ReplyMsg
->Status
= (ULONG
)STATUS_ILLEGAL_FUNCTION
;
172 return STATUS_ILLEGAL_FUNCTION
;
177 ApiId
= CSR_API_NUMBER_TO_API_ID(ReceiveMsg
->ApiNumber
);
179 /* Normalize it with our Base ID */
180 ApiId
-= ServerDll
->ApiBase
;
182 /* Make sure that the ID is within limits, and the entry exists */
183 if ((ApiId
>= ServerDll
->HighestApiSupported
) ||
184 ((ServerDll
->ValidTable
) && !(ServerDll
->ValidTable
[ApiId
])))
186 /* We are beyond the Maximum API ID, or it doesn't exist */
187 DPRINT1("CSRSS: %lx (%s) is invalid ApiTableIndex for %Z or is an "
188 "invalid API to call from the server.\n",
189 ServerDll
->ValidTable
[ApiId
],
190 ((ServerDll
->NameTable
) && (ServerDll
->NameTable
[ApiId
])) ?
191 ServerDll
->NameTable
[ApiId
] : "*** UNKNOWN ***", &ServerDll
->Name
);
193 ReplyMsg
->Status
= (ULONG
)STATUS_ILLEGAL_FUNCTION
;
194 return STATUS_ILLEGAL_FUNCTION
;
200 DPRINT1("CSRSS: %s Api Request received from server process\n",
201 ServerDll
->NameTable
[ApiId
]);
204 /* Validation complete, start SEH */
207 /* Call the API and get the result */
208 /// CsrApiCallHandler(ReplyMsg, /*ProcessData*/ &ReplyCode); ///
209 Status
= (ServerDll
->DispatchTable
[ApiId
])(ReceiveMsg
, &Reply
);
211 /* Return the result, no matter what it is */
212 ReplyMsg
->Status
= Status
;
214 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
216 /* If we got an exception, return access violation */
217 ReplyMsg
->Status
= STATUS_ACCESS_VIOLATION
;
222 return STATUS_SUCCESS
;
224 #else // Hacky reactos code
226 PCSR_PROCESS ProcessData
;
229 /* Get the Process Data */
230 CsrLockProcessByClientId(&ReceiveMsg
->Header
.ClientId
.UniqueProcess
, &ProcessData
);
233 DPRINT1("Message: Unable to find data for process 0x%x\n",
234 ReceiveMsg
->Header
.ClientId
.UniqueProcess
);
235 return STATUS_NOT_SUPPORTED
;
238 /* Validation complete, start SEH */
241 /* Call the API and get the result */
242 CsrApiCallHandler(ReplyMsg
, /*ProcessData*/ &ReplyCode
);
244 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
246 /* If we got an exception, return access violation */
247 ReplyMsg
->Status
= STATUS_ACCESS_VIOLATION
;
251 /* Release the process reference */
252 CsrUnlockProcess(ProcessData
);
255 return STATUS_SUCCESS
;
260 * @name CsrApiHandleConnectionRequest
262 * The CsrApiHandleConnectionRequest routine handles and accepts a new
263 * connection request to the CSR API LPC Port.
266 * Pointer to the incoming CSR API Message which contains the
267 * connection request.
269 * @return STATUS_SUCCESS in case of success, or status code which caused
270 * the routine to error.
272 * @remarks This routine is responsible for attaching the Shared Section to
273 * new clients connecting to CSR.
278 CsrApiHandleConnectionRequest(IN PCSR_API_MESSAGE ApiMessage
)
280 PCSR_THREAD CsrThread
= NULL
;
281 PCSR_PROCESS CsrProcess
= NULL
;
282 NTSTATUS Status
= STATUS_SUCCESS
;
283 PCSR_CONNECTION_INFO ConnectInfo
= &ApiMessage
->ConnectionInfo
;
284 BOOLEAN AllowConnection
= FALSE
;
285 REMOTE_PORT_VIEW RemotePortView
;
288 /* Acquire the Process Lock */
289 CsrAcquireProcessLock();
291 /* Lookup the CSR Thread */
292 CsrThread
= CsrLocateThreadByClientId(NULL
, &ApiMessage
->Header
.ClientId
);
294 /* Check if we have a thread */
297 /* Get the Process */
298 CsrProcess
= CsrThread
->Process
;
300 /* Make sure we have a Process as well */
303 /* Reference the Process */
304 CsrLockedReferenceProcess(CsrThread
->Process
);
306 /* Release the lock */
307 CsrReleaseProcessLock();
309 /* Duplicate the Object Directory */
310 Status
= NtDuplicateObject(NtCurrentProcess(),
312 CsrProcess
->ProcessHandle
,
313 &ConnectInfo
->ObjectDirectory
,
316 DUPLICATE_SAME_ACCESS
|
317 DUPLICATE_SAME_ATTRIBUTES
);
319 /* Acquire the lock */
320 CsrAcquireProcessLock();
322 /* Check for success */
323 if (NT_SUCCESS(Status
))
325 /* Attach the Shared Section */
326 Status
= CsrSrvAttachSharedSection(CsrProcess
, ConnectInfo
);
328 /* Check how this went */
329 if (NT_SUCCESS(Status
)) AllowConnection
= TRUE
;
332 /* Dereference the project */
333 CsrLockedDereferenceProcess(CsrProcess
);
337 /* Release the lock */
338 CsrReleaseProcessLock();
340 /* Setup the Port View Structure */
341 RemotePortView
.Length
= sizeof(REMOTE_PORT_VIEW
);
342 RemotePortView
.ViewSize
= 0;
343 RemotePortView
.ViewBase
= NULL
;
345 /* Save the Process ID */
346 ConnectInfo
->ProcessId
= NtCurrentTeb()->ClientId
.UniqueProcess
;
348 /* Accept the Connection */
349 Status
= NtAcceptConnectPort(&hPort
,
350 AllowConnection
? UlongToPtr(CsrProcess
->SequenceNumber
) : 0,
355 if (!NT_SUCCESS(Status
))
357 DPRINT1("CSRSS: NtAcceptConnectPort - failed. Status == %X\n", Status
);
359 else if (AllowConnection
)
363 DPRINT1("CSRSS: ClientId: %lx.%lx has ClientView: Base=%p, Size=%lx\n",
364 ApiMessage
->Header
.ClientId
.UniqueProcess
,
365 ApiMessage
->Header
.ClientId
.UniqueThread
,
366 RemotePortView
.ViewBase
,
367 RemotePortView
.ViewSize
);
370 /* Set some Port Data in the Process */
371 CsrProcess
->ClientPort
= hPort
;
372 CsrProcess
->ClientViewBase
= (ULONG_PTR
)RemotePortView
.ViewBase
;
373 CsrProcess
->ClientViewBounds
= (ULONG_PTR
)((ULONG_PTR
)RemotePortView
.ViewBase
+
374 (ULONG_PTR
)RemotePortView
.ViewSize
);
376 /* Complete the connection */
377 Status
= NtCompleteConnectPort(hPort
);
378 if (!NT_SUCCESS(Status
))
380 DPRINT1("CSRSS: NtCompleteConnectPort - failed. Status == %X\n", Status
);
385 DPRINT1("CSRSS: Rejecting Connection Request from ClientId: %lx.%lx\n",
386 ApiMessage
->Header
.ClientId
.UniqueProcess
,
387 ApiMessage
->Header
.ClientId
.UniqueThread
);
390 /* Return status to caller */
395 * @name CsrpCheckRequestThreads
397 * The CsrpCheckRequestThreads routine checks if there are no more threads
398 * to handle CSR API Requests, and creates a new thread if possible, to
403 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
404 * if a new thread couldn't be created.
411 CsrpCheckRequestThreads(VOID
)
417 /* Decrease the count, and see if we're out */
418 if (!(_InterlockedDecrement(&CsrpStaticThreadCount
)))
420 /* Check if we've still got space for a Dynamic Thread */
421 if (CsrpDynamicThreadTotal
< CsrMaxApiRequestThreads
)
423 /* Create a new dynamic thread */
424 Status
= RtlCreateUserThread(NtCurrentProcess(),
430 (PVOID
)CsrApiRequestThread
,
435 if (NT_SUCCESS(Status
))
437 /* Increase the thread counts */
438 _InterlockedIncrement(&CsrpStaticThreadCount
);
439 _InterlockedIncrement(&CsrpDynamicThreadTotal
);
441 /* Add a new server thread */
442 if (CsrAddStaticServerThread(hThread
,
444 CsrThreadIsServerThread
))
447 NtResumeThread(hThread
, NULL
);
451 /* Failed to create a new static thread */
452 _InterlockedDecrement(&CsrpStaticThreadCount
);
453 _InterlockedDecrement(&CsrpDynamicThreadTotal
);
456 DPRINT1("Failing\n");
457 NtTerminateThread(hThread
, 0);
461 return STATUS_UNSUCCESSFUL
;
468 return STATUS_SUCCESS
;
472 * @name CsrApiRequestThread
474 * The CsrApiRequestThread routine handles incoming messages or connection
475 * requests on the CSR API LPC Port.
478 * System-default user-defined parameter. Unused.
480 * @return The thread exit code, if the thread is terminated.
482 * @remarks Before listening on the port, the routine will first attempt
483 * to connect to the user subsystem.
488 CsrApiRequestThread(IN PVOID Parameter
)
491 PTEB Teb
= NtCurrentTeb();
492 LARGE_INTEGER TimeOut
;
493 PCSR_THREAD CurrentThread
, CsrThread
;
495 PCSR_API_MESSAGE ReplyMsg
;
496 CSR_API_MESSAGE ReceiveMsg
;
497 PCSR_PROCESS CsrProcess
;
498 PHARDERROR_MSG HardErrorMsg
;
500 PCSR_SERVER_DLL ServerDll
;
501 PCLIENT_DIED_MSG ClientDiedMsg
;
502 PDBGKM_MSG DebugMessage
;
503 ULONG ServerId
, ApiId
, Reply
, MessageType
, i
;
506 /* Setup LPC loop port and message */
508 ReplyPort
= CsrApiPort
;
510 /* Connect to user32 */
511 while (!CsrConnectToUser())
513 /* Set up the timeout for the connect (30 seconds) */
514 TimeOut
.QuadPart
= -30 * 1000 * 1000 * 10;
516 /* Keep trying until we get a response */
517 Teb
->Win32ClientInfo
[0] = 0;
518 NtDelayExecution(FALSE
, &TimeOut
);
522 CurrentThread
= Teb
->CsrClientThread
;
524 /* If we got an event... */
527 /* Set it, to let stuff waiting on us load */
528 Status
= NtSetEvent((HANDLE
)Parameter
, NULL
);
529 ASSERT(NT_SUCCESS(Status
));
531 /* Increase the Thread Counts */
532 _InterlockedIncrement(&CsrpStaticThreadCount
);
533 _InterlockedIncrement(&CsrpDynamicThreadTotal
);
536 /* Now start the loop */
539 /* Make sure the real CID is set */
540 Teb
->RealClientId
= Teb
->ClientId
;
543 if (Teb
->CountOfOwnedCriticalSections
)
545 DPRINT1("CSRSRV: FATAL ERROR. CsrThread is Idle while holding %lu critical sections\n",
546 Teb
->CountOfOwnedCriticalSections
);
547 DPRINT1("CSRSRV: Last Receive Message %lx ReplyMessage %lx\n",
548 &ReceiveMsg
, ReplyMsg
);
552 /* Wait for a message to come through */
553 Status
= NtReplyWaitReceivePort(ReplyPort
,
558 /* Check if we didn't get success */
559 if (Status
!= STATUS_SUCCESS
)
561 /* Was it a failure or another success code? */
562 if (!NT_SUCCESS(Status
))
564 /* Check for specific status cases */
565 if ((Status
!= STATUS_INVALID_CID
) &&
566 (Status
!= STATUS_UNSUCCESSFUL
) &&
567 ((Status
== STATUS_INVALID_HANDLE
) || (ReplyPort
== CsrApiPort
)))
569 /* Notify the debugger */
570 DPRINT1("CSRSS: ReceivePort failed - Status == %X\n", Status
);
571 DPRINT1("CSRSS: ReplyPortHandle %lx CsrApiPort %lx\n", ReplyPort
, CsrApiPort
);
574 /* We failed big time, so start out fresh */
576 ReplyPort
= CsrApiPort
;
581 /* A bizare "success" code, just try again */
582 DPRINT1("NtReplyWaitReceivePort returned \"success\" status 0x%x\n", Status
);
587 /* Use whatever Client ID we got */
588 Teb
->RealClientId
= ReceiveMsg
.Header
.ClientId
;
590 /* Get the Message Type */
591 MessageType
= ReceiveMsg
.Header
.u2
.s2
.Type
;
593 /* Handle connection requests */
594 if (MessageType
== LPC_CONNECTION_REQUEST
)
596 /* Handle the Connection Request */
597 CsrApiHandleConnectionRequest(&ReceiveMsg
);
598 ReplyPort
= CsrApiPort
;
603 /* It's some other kind of request. Get the lock for the lookup */
604 CsrAcquireProcessLock();
606 /* Now do the lookup to get the CSR_THREAD */
607 CsrThread
= CsrLocateThreadByClientId(&CsrProcess
,
608 &ReceiveMsg
.Header
.ClientId
);
610 /* Did we find a thread? */
613 /* This wasn't a CSR Thread, release lock */
614 CsrReleaseProcessLock();
616 /* If this was an exception, handle it */
617 if (MessageType
== LPC_EXCEPTION
)
619 ReplyMsg
= &ReceiveMsg
;
620 ReplyPort
= CsrApiPort
;
621 ReplyMsg
->Status
= DBG_CONTINUE
;
623 else if (MessageType
== LPC_PORT_CLOSED
||
624 MessageType
== LPC_CLIENT_DIED
)
626 /* The Client or Port are gone, loop again */
628 ReplyPort
= CsrApiPort
;
630 else if (MessageType
== LPC_ERROR_EVENT
)
632 /* If it's a hard error, handle this too */
633 HardErrorMsg
= (PHARDERROR_MSG
)&ReceiveMsg
;
635 /* Default it to unhandled */
636 HardErrorMsg
->Response
= ResponseNotHandled
;
638 /* Check if there are free api threads */
639 CsrpCheckRequestThreads();
640 if (CsrpStaticThreadCount
)
642 /* Loop every Server DLL */
643 for (i
= 0; i
< CSR_SERVER_DLL_MAX
; i
++)
645 /* Get the Server DLL */
646 ServerDll
= CsrLoadedServerDll
[i
];
648 /* Check if it's valid and if it has a Hard Error Callback */
649 if ((ServerDll
) && (ServerDll
->HardErrorCallback
))
652 ServerDll
->HardErrorCallback(NULL
, HardErrorMsg
);
654 /* If it's handled, get out of here */
655 if (HardErrorMsg
->Response
!= ResponseNotHandled
) break;
660 /* Increase the thread count */
661 _InterlockedIncrement(&CsrpStaticThreadCount
);
663 /* If the response was 0xFFFFFFFF, we'll ignore it */
664 if (HardErrorMsg
->Response
== 0xFFFFFFFF)
667 ReplyPort
= CsrApiPort
;
671 ReplyMsg
= &ReceiveMsg
;
674 else if (MessageType
== LPC_REQUEST
)
676 /* This is an API Message coming from a non-CSR Thread */
677 ReplyMsg
= &ReceiveMsg
;
678 ReplyPort
= CsrApiPort
;
679 ReplyMsg
->Status
= STATUS_ILLEGAL_FUNCTION
;
681 else if (MessageType
== LPC_DATAGRAM
)
683 /* This is an API call, get the Server ID */
684 ServerId
= CSR_API_NUMBER_TO_SERVER_ID(ReceiveMsg
.ApiNumber
);
686 /* Make sure that the ID is within limits, and the Server DLL loaded */
688 if ((ServerId
>= CSR_SERVER_DLL_MAX
) ||
689 (!(ServerDll
= CsrLoadedServerDll
[ServerId
])))
691 /* We are beyond the Maximum Server ID */
692 DPRINT1("CSRSS: %lx is invalid ServerDllIndex (%08x)\n",
693 ServerId
, ServerDll
);
695 ReplyPort
= CsrApiPort
;
701 ApiId
= CSR_API_NUMBER_TO_API_ID(ReceiveMsg
.ApiNumber
);
703 /* Normalize it with our Base ID */
704 ApiId
-= ServerDll
->ApiBase
;
706 /* Make sure that the ID is within limits, and the entry exists */
707 if (ApiId
>= ServerDll
->HighestApiSupported
)
709 /* We are beyond the Maximum API ID, or it doesn't exist */
710 DPRINT1("CSRSS: %lx is invalid ApiTableIndex for %Z\n",
711 CSR_API_NUMBER_TO_API_ID(ReceiveMsg
.ApiNumber
),
713 ReplyPort
= CsrApiPort
;
720 DPRINT1("[%02x] CSRSS: [%02x,%02x] - %s Api called from %08x\n",
721 Teb
->ClientId
.UniqueThread
,
722 ReceiveMsg
.Header
.ClientId
.UniqueProcess
,
723 ReceiveMsg
.Header
.ClientId
.UniqueThread
,
724 ServerDll
->NameTable
[ApiId
],
729 ReceiveMsg
.Status
= STATUS_SUCCESS
;
731 /* Validation complete, start SEH */
734 /* Make sure we have enough threads */
735 CsrpCheckRequestThreads();
737 /* Call the API and get the result */
739 ReplyPort
= CsrApiPort
;
740 ServerDll
->DispatchTable
[ApiId
](&ReceiveMsg
, &Reply
);
742 /* Increase the static thread count */
743 _InterlockedIncrement(&CsrpStaticThreadCount
);
745 _SEH2_EXCEPT(CsrUnhandledExceptionFilter(_SEH2_GetExceptionInformation()))
748 ReplyPort
= CsrApiPort
;
754 /* Some other ignored message type */
756 ReplyPort
= CsrApiPort
;
763 /* We have a valid thread, was this an LPC Request? */
764 if (MessageType
!= LPC_REQUEST
)
766 /* It's not an API, check if the client died */
767 if (MessageType
== LPC_CLIENT_DIED
)
769 /* Get the information and check if it matches our thread */
770 ClientDiedMsg
= (PCLIENT_DIED_MSG
)&ReceiveMsg
;
771 if (ClientDiedMsg
->CreateTime
.QuadPart
== CsrThread
->CreateTime
.QuadPart
)
773 /* Reference the thread */
774 CsrLockedReferenceThread(CsrThread
);
776 /* Destroy the thread in the API Message */
777 CsrDestroyThread(&ReceiveMsg
.Header
.ClientId
);
779 /* Check if the thread was actually ourselves */
780 if (CsrProcess
->ThreadCount
== 1)
782 /* Kill the process manually here */
783 CsrDestroyProcess(&CsrThread
->ClientId
, 0);
786 /* Remove our extra reference */
787 CsrLockedDereferenceThread(CsrThread
);
790 /* Release the lock and keep looping */
791 CsrReleaseProcessLock();
793 ReplyPort
= CsrApiPort
;
797 /* Reference the thread and release the lock */
798 CsrLockedReferenceThread(CsrThread
);
799 CsrReleaseProcessLock();
801 /* Check if this was an exception */
802 if (MessageType
== LPC_EXCEPTION
)
804 /* Kill the process */
805 NtTerminateProcess(CsrProcess
->ProcessHandle
, STATUS_ABANDONED
);
807 /* Destroy it from CSR */
808 CsrDestroyProcess(&ReceiveMsg
.Header
.ClientId
, STATUS_ABANDONED
);
810 /* Return a Debug Message */
811 DebugMessage
= (PDBGKM_MSG
)&ReceiveMsg
;
812 DebugMessage
->ReturnedStatus
= DBG_CONTINUE
;
813 ReplyMsg
= &ReceiveMsg
;
814 ReplyPort
= CsrApiPort
;
816 /* Remove our extra reference */
817 CsrDereferenceThread(CsrThread
);
819 else if (MessageType
== LPC_ERROR_EVENT
)
821 /* If it's a hard error, handle this too */
822 HardErrorMsg
= (PHARDERROR_MSG
)&ReceiveMsg
;
824 /* Default it to unhandled */
825 HardErrorMsg
->Response
= ResponseNotHandled
;
827 /* Check if there are free api threads */
828 CsrpCheckRequestThreads();
829 if (CsrpStaticThreadCount
)
831 /* Loop every Server DLL */
832 for (i
= 0; i
< CSR_SERVER_DLL_MAX
; i
++)
834 /* Get the Server DLL */
835 ServerDll
= CsrLoadedServerDll
[i
];
837 /* Check if it's valid and if it has a Hard Error Callback */
838 if ((ServerDll
) && (ServerDll
->HardErrorCallback
))
841 ServerDll
->HardErrorCallback(CsrThread
, HardErrorMsg
);
843 /* If it's handled, get out of here */
844 if (HardErrorMsg
->Response
!= ResponseNotHandled
) break;
849 /* Increase the thread count */
850 _InterlockedIncrement(&CsrpStaticThreadCount
);
852 /* If the response was 0xFFFFFFFF, we'll ignore it */
853 if (HardErrorMsg
->Response
== 0xFFFFFFFF)
856 ReplyPort
= CsrApiPort
;
860 CsrDereferenceThread(CsrThread
);
861 ReplyMsg
= &ReceiveMsg
;
862 ReplyPort
= CsrApiPort
;
868 CsrDereferenceThread(CsrThread
);
876 /* We got an API Request */
877 CsrLockedReferenceThread(CsrThread
);
878 CsrReleaseProcessLock();
880 /* This is an API call, get the Server ID */
881 ServerId
= CSR_API_NUMBER_TO_SERVER_ID(ReceiveMsg
.ApiNumber
);
883 /* Make sure that the ID is within limits, and the Server DLL loaded */
885 if ((ServerId
>= CSR_SERVER_DLL_MAX
) ||
886 (!(ServerDll
= CsrLoadedServerDll
[ServerId
])))
888 /* We are beyond the Maximum Server ID */
889 DPRINT1("CSRSS: %lx is invalid ServerDllIndex (%08x)\n",
890 ServerId
, ServerDll
);
893 ReplyPort
= CsrApiPort
;
894 ReplyMsg
= &ReceiveMsg
;
895 ReplyMsg
->Status
= STATUS_ILLEGAL_FUNCTION
;
896 CsrDereferenceThread(CsrThread
);
901 ApiId
= CSR_API_NUMBER_TO_API_ID(ReceiveMsg
.ApiNumber
);
903 /* Normalize it with our Base ID */
904 ApiId
-= ServerDll
->ApiBase
;
906 /* Make sure that the ID is within limits, and the entry exists */
907 if (ApiId
>= ServerDll
->HighestApiSupported
)
909 /* We are beyond the Maximum API ID, or it doesn't exist */
910 DPRINT1("CSRSS: %lx is invalid ApiTableIndex for %Z\n",
911 CSR_API_NUMBER_TO_API_ID(ReceiveMsg
.ApiNumber
),
914 ReplyPort
= CsrApiPort
;
915 ReplyMsg
= &ReceiveMsg
;
916 ReplyMsg
->Status
= STATUS_ILLEGAL_FUNCTION
;
917 CsrDereferenceThread(CsrThread
);
923 DPRINT1("[%02x] CSRSS: [%02x,%02x] - %s Api called from %08x\n",
924 Teb
->ClientId
.UniqueThread
,
925 ReceiveMsg
.Header
.ClientId
.UniqueProcess
,
926 ReceiveMsg
.Header
.ClientId
.UniqueThread
,
927 ServerDll
->NameTable
[ApiId
],
932 ReplyMsg
= &ReceiveMsg
;
933 ReceiveMsg
.Status
= STATUS_SUCCESS
;
935 /* Now we reply to a particular client */
936 ReplyPort
= CsrThread
->Process
->ClientPort
;
938 /* Check if there's a capture buffer */
939 if (ReceiveMsg
.CsrCaptureData
)
941 /* Capture the arguments */
942 if (!CsrCaptureArguments(CsrThread
, &ReceiveMsg
))
944 /* Ignore this message if we failed to get the arguments */
945 CsrDereferenceThread(CsrThread
);
950 /* Validation complete, start SEH */
953 /* Make sure we have enough threads */
954 CsrpCheckRequestThreads();
956 Teb
->CsrClientThread
= CsrThread
;
958 /* Call the API and get the result */
960 ServerDll
->DispatchTable
[ApiId
](&ReceiveMsg
, &Reply
);
962 /* Increase the static thread count */
963 _InterlockedIncrement(&CsrpStaticThreadCount
);
965 Teb
->CsrClientThread
= CurrentThread
;
970 if (ReceiveMsg
.CsrCaptureData
)
972 CsrReleaseCapturedArguments(&ReceiveMsg
);
974 CsrDereferenceThread(CsrThread
);
975 ReplyPort
= CsrApiPort
;
979 NtReplyPort(ReplyPort
, &ReplyMsg
->Header
);
980 ReplyPort
= CsrApiPort
;
982 CsrDereferenceThread(CsrThread
);
986 ReplyPort
= CsrApiPort
;
991 if (ReceiveMsg
.CsrCaptureData
)
993 CsrReleaseCapturedArguments(&ReceiveMsg
);
995 CsrDereferenceThread(CsrThread
);
998 _SEH2_EXCEPT(CsrUnhandledExceptionFilter(_SEH2_GetExceptionInformation()))
1001 ReplyPort
= CsrApiPort
;
1006 /* We're out of the loop for some reason, terminate! */
1007 NtTerminateThread(NtCurrentThread(), Status
);
1012 PTEB Teb
= NtCurrentTeb();
1013 LARGE_INTEGER TimeOut
;
1015 BYTE RawRequest
[LPC_MAX_DATA_LENGTH
];
1016 PCSR_API_MESSAGE Request
= (PCSR_API_MESSAGE
)RawRequest
;
1017 PCSR_API_MESSAGE Reply
;
1018 PCSR_PROCESS CsrProcess
;
1019 PCSR_THREAD ServerThread
, CsrThread
;
1022 PDBGKM_MSG DebugMessage
;
1023 PHARDERROR_MSG HardErrorMsg
;
1024 PCLIENT_DIED_MSG ClientDiedMsg
;
1025 DPRINT("CSR: %s called\n", __FUNCTION__
);
1027 /* Setup LPC loop port and message */
1029 ReplyPort
= CsrApiPort
;
1031 /* Connect to user32 */
1032 while (!CsrConnectToUser())
1034 /* Set up the timeout for the connect (30 seconds) */
1035 TimeOut
.QuadPart
= -30 * 1000 * 1000 * 10;
1037 /* Keep trying until we get a response */
1038 Teb
->Win32ClientInfo
[0] = 0;
1039 NtDelayExecution(FALSE
, &TimeOut
);
1042 /* Get our thread */
1043 ServerThread
= Teb
->CsrClientThread
;
1045 /* If we got an event... */
1048 /* Set it, to let stuff waiting on us load */
1049 Status
= NtSetEvent((HANDLE
)Parameter
, NULL
);
1050 ASSERT(NT_SUCCESS(Status
));
1052 /* Increase the Thread Counts */
1053 _InterlockedIncrement(&CsrpStaticThreadCount
);
1054 _InterlockedIncrement(&CsrpDynamicThreadTotal
);
1057 /* Now start the loop */
1060 /* Make sure the real CID is set */
1061 Teb
->RealClientId
= Teb
->ClientId
;
1064 if (Teb
->CountOfOwnedCriticalSections
)
1066 DPRINT1("CSRSRV: FATAL ERROR. CsrThread is Idle while holding %lu critical sections\n",
1067 Teb
->CountOfOwnedCriticalSections
);
1068 DPRINT1("CSRSRV: Last Receive Message %lx ReplyMessage %lx\n",
1073 /* Send the reply and wait for a new request */
1074 DPRINT("Replying to: %lx (%lx)\n", ReplyPort
, CsrApiPort
);
1075 Status
= NtReplyWaitReceivePort(ReplyPort
,
1079 /* Check if we didn't get success */
1080 if (Status
!= STATUS_SUCCESS
)
1082 /* Was it a failure or another success code? */
1083 if (!NT_SUCCESS(Status
))
1085 /* Check for specific status cases */
1086 if ((Status
!= STATUS_INVALID_CID
) &&
1087 (Status
!= STATUS_UNSUCCESSFUL
) &&
1088 ((Status
== STATUS_INVALID_HANDLE
) || (ReplyPort
== CsrApiPort
)))
1090 /* Notify the debugger */
1091 DPRINT1("CSRSS: ReceivePort failed - Status == %X\n", Status
);
1092 DPRINT1("CSRSS: ReplyPortHandle %lx CsrApiPort %lx\n", ReplyPort
, CsrApiPort
);
1095 /* We failed big time, so start out fresh */
1097 ReplyPort
= CsrApiPort
;
1098 DPRINT1("failed: %lx\n", Status
);
1103 /* A bizare "success" code, just try again */
1104 DPRINT1("NtReplyWaitReceivePort returned \"success\" status 0x%x\n", Status
);
1109 /* Use whatever Client ID we got */
1110 Teb
->RealClientId
= Request
->Header
.ClientId
;
1112 /* Get the Message Type */
1113 MessageType
= Request
->Header
.u2
.s2
.Type
;
1115 /* Handle connection requests */
1116 if (MessageType
== LPC_CONNECTION_REQUEST
)
1118 /* Handle the Connection Request */
1119 DPRINT("Accepting new connection\n");
1120 CsrpHandleConnectionRequest((PPORT_MESSAGE
)Request
);
1122 ReplyPort
= CsrApiPort
;
1126 /* It's some other kind of request. Get the lock for the lookup */
1127 CsrAcquireProcessLock();
1129 /* Now do the lookup to get the CSR_THREAD */
1130 CsrThread
= CsrLocateThreadByClientId(&CsrProcess
,
1131 &Request
->Header
.ClientId
);
1133 /* Did we find a thread? */
1136 /* This wasn't a CSR Thread, release lock */
1137 CsrReleaseProcessLock();
1139 /* If this was an exception, handle it */
1140 if (MessageType
== LPC_EXCEPTION
)
1142 DPRINT1("Exception from unknown thread, just continue\n");
1144 ReplyPort
= CsrApiPort
;
1145 Reply
->Status
= DBG_CONTINUE
;
1147 else if (MessageType
== LPC_PORT_CLOSED
||
1148 MessageType
== LPC_CLIENT_DIED
)
1150 /* The Client or Port are gone, loop again */
1151 DPRINT("Death from unknown thread, just continue\n");
1153 ReplyPort
= CsrApiPort
;
1155 else if (MessageType
== LPC_ERROR_EVENT
)
1157 /* If it's a hard error, handle this too */
1158 DPRINT1("Hard error from unknown thread, call handlers\n");
1160 HardErrorMsg
= (PHARDERROR_MSG
)Request
;
1162 /* Default it to unhandled */
1163 HardErrorMsg
->Response
= ResponseNotHandled
;
1165 /* Check if there are free api threads */
1166 CsrpCheckRequestThreads();
1167 if (CsrpStaticThreadCount
)
1169 CsrHandleHardError(CsrThread
, (PHARDERROR_MSG
)Request
);
1172 /* If the response was 0xFFFFFFFF, we'll ignore it */
1173 if (HardErrorMsg
->Response
== 0xFFFFFFFF)
1176 ReplyPort
= CsrApiPort
;
1180 if (CsrThread
) CsrDereferenceThread(CsrThread
);
1182 ReplyPort
= CsrApiPort
;
1185 else if (MessageType
== LPC_REQUEST
)
1187 /* This is an API Message coming from a non-CSR Thread */
1188 DPRINT1("No thread found for request %lx and clientID %lx.%lx\n",
1189 Request
->ApiNumber
& 0xFFFF,
1190 Request
->Header
.ClientId
.UniqueProcess
,
1191 Request
->Header
.ClientId
.UniqueThread
);
1193 ReplyPort
= CsrApiPort
;
1194 Reply
->Status
= STATUS_ILLEGAL_FUNCTION
;
1196 else if (MessageType
== LPC_DATAGRAM
)
1198 DPRINT1("Kernel datagram: not yet supported\n");
1200 ReplyPort
= CsrApiPort
;
1204 /* Some other ignored message type */
1206 ReplyPort
= CsrApiPort
;
1213 /* We have a valid thread, was this an LPC Request? */
1214 if (MessageType
!= LPC_REQUEST
)
1216 /* It's not an API, check if the client died */
1217 if (MessageType
== LPC_CLIENT_DIED
)
1219 /* Get the information and check if it matches our thread */
1220 ClientDiedMsg
= (PCLIENT_DIED_MSG
)Request
;
1221 if (ClientDiedMsg
->CreateTime
.QuadPart
== CsrThread
->CreateTime
.QuadPart
)
1223 /* Reference the thread */
1224 CsrLockedReferenceThread(CsrThread
);
1226 /* Destroy the thread in the API Message */
1227 CsrDestroyThread(&Request
->Header
.ClientId
);
1229 /* Check if the thread was actually ourselves */
1230 if (CsrProcess
->ThreadCount
== 1)
1232 /* Kill the process manually here */
1233 DPRINT1("Last thread\n");
1234 CsrDestroyProcess(&CsrThread
->ClientId
, 0);
1237 /* Remove our extra reference */
1238 CsrLockedDereferenceThread(CsrThread
);
1241 /* Release the lock and keep looping */
1242 CsrReleaseProcessLock();
1244 ReplyPort
= CsrApiPort
;
1248 /* Reference the thread and release the lock */
1249 CsrLockedReferenceThread(CsrThread
);
1250 CsrReleaseProcessLock();
1252 /* If this was an exception, handle it */
1253 if (MessageType
== LPC_EXCEPTION
)
1255 /* Kill the process */
1256 DPRINT1("Exception in %lx.%lx. Killing...\n",
1257 Request
->Header
.ClientId
.UniqueProcess
,
1258 Request
->Header
.ClientId
.UniqueThread
);
1259 NtTerminateProcess(CsrProcess
->ProcessHandle
, STATUS_ABANDONED
);
1261 /* Destroy it from CSR */
1262 CsrDestroyProcess(&Request
->Header
.ClientId
, STATUS_ABANDONED
);
1264 /* Return a Debug Message */
1265 DebugMessage
= (PDBGKM_MSG
)Request
;
1266 DebugMessage
->ReturnedStatus
= DBG_CONTINUE
;
1268 ReplyPort
= CsrApiPort
;
1270 /* Remove our extra reference */
1271 CsrDereferenceThread(CsrThread
);
1273 else if (MessageType
== LPC_ERROR_EVENT
)
1275 DPRINT1("Hard error from known CSR thread... handling\n");
1276 goto HandleHardError
;
1280 /* Something else */
1281 DPRINT1("Unhandled message type: %lx\n", MessageType
);
1282 CsrDereferenceThread(CsrThread
);
1290 /* We got an API Request */
1291 CsrLockedReferenceThread(CsrThread
);
1292 CsrReleaseProcessLock();
1294 /* Assume success */
1296 Request
->Status
= STATUS_SUCCESS
;
1298 /* Now we reply to a particular client */
1299 ReplyPort
= CsrThread
->Process
->ClientPort
;
1301 DPRINT("CSR: Got CSR API: %x [Message Origin: %x]\n",
1303 Request
->Header
.ClientId
.UniqueThread
);
1305 /* Validation complete, start SEH */
1310 /* Make sure we have enough threads */
1311 CsrpCheckRequestThreads();
1313 /* Set the client thread pointer */
1314 NtCurrentTeb()->CsrClientThread
= CsrThread
;
1316 /* Call the Handler */
1317 CsrApiCallHandler(Request
, &ReplyCode
);
1319 /* Increase the static thread count */
1320 _InterlockedIncrement(&CsrpStaticThreadCount
);
1322 /* Restore the server thread */
1323 NtCurrentTeb()->CsrClientThread
= ServerThread
;
1325 /* Check if this is a dead client now */
1326 if (Request
->ApiNumber
== 0xBABE)
1328 /* Reply to the death message */
1329 NtReplyPort(ReplyPort
, &Reply
->Header
);
1331 /* Reply back to the API port now */
1332 ReplyPort
= CsrApiPort
;
1335 /* Drop the reference */
1336 CsrDereferenceThread(CsrThread
);
1340 /* Drop the reference */
1341 CsrDereferenceThread(CsrThread
);
1344 _SEH2_EXCEPT(CsrUnhandledExceptionFilter(_SEH2_GetExceptionInformation()))
1347 ReplyPort
= CsrApiPort
;
1352 /* Close the port and exit the thread */
1353 // NtClose(ServerPort);
1355 DPRINT1("CSR: %s done\n", __FUNCTION__
);
1356 /* We're out of the loop for some reason, terminate! */
1357 NtTerminateThread(NtCurrentThread(), Status
);
1363 * @name CsrApiPortInitialize
1365 * The CsrApiPortInitialize routine initializes the LPC Port used for
1366 * communications with the Client/Server Runtime (CSR) and initializes the
1367 * static thread that will handle connection requests and APIs.
1371 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
1379 CsrApiPortInitialize(VOID
)
1382 OBJECT_ATTRIBUTES ObjectAttributes
;
1384 HANDLE hRequestEvent
, hThread
;
1386 PLIST_ENTRY ListHead
, NextEntry
;
1387 PCSR_THREAD ServerThread
;
1389 /* Calculate how much space we'll need for the Port Name */
1390 Size
= CsrDirectoryName
.Length
+ sizeof(CSR_PORT_NAME
) + sizeof(WCHAR
);
1392 /* Create the buffer for it */
1393 CsrApiPortName
.Buffer
= RtlAllocateHeap(CsrHeap
, 0, Size
);
1394 if (!CsrApiPortName
.Buffer
) return STATUS_NO_MEMORY
;
1396 /* Setup the rest of the empty string */
1397 CsrApiPortName
.Length
= 0;
1398 CsrApiPortName
.MaximumLength
= (USHORT
)Size
;
1399 RtlAppendUnicodeStringToString(&CsrApiPortName
, &CsrDirectoryName
);
1400 RtlAppendUnicodeToString(&CsrApiPortName
, UNICODE_PATH_SEP
);
1401 RtlAppendUnicodeToString(&CsrApiPortName
, CSR_PORT_NAME
);
1404 DPRINT1("CSRSS: Creating %wZ port and associated threads\n", &CsrApiPortName
);
1405 DPRINT1("CSRSS: sizeof( CONNECTINFO ) == %ld sizeof( API_MSG ) == %ld\n",
1406 sizeof(CSR_CONNECTION_INFO
), sizeof(CSR_API_MESSAGE
));
1409 /* FIXME: Create a Security Descriptor */
1411 /* Initialize the Attributes */
1412 InitializeObjectAttributes(&ObjectAttributes
,
1418 /* Create the Port Object */
1419 Status
= NtCreatePort(&CsrApiPort
,
1421 LPC_MAX_DATA_LENGTH
, // hack ; sizeof(CSR_CONNECTION_INFO),
1422 LPC_MAX_MESSAGE_LENGTH
, // hack ; sizeof(CSR_API_MESSAGE),
1424 if (NT_SUCCESS(Status
))
1426 /* Create the event the Port Thread will use */
1427 Status
= NtCreateEvent(&hRequestEvent
,
1430 SynchronizationEvent
,
1432 if (NT_SUCCESS(Status
))
1434 /* Create the Request Thread */
1435 Status
= RtlCreateUserThread(NtCurrentProcess(),
1441 (PVOID
)CsrApiRequestThread
,
1442 (PVOID
)hRequestEvent
,
1445 if (NT_SUCCESS(Status
))
1447 /* Add this as a static thread to CSRSRV */
1448 CsrAddStaticServerThread(hThread
, &ClientId
, CsrThreadIsServerThread
);
1450 /* Get the Thread List Pointers */
1451 ListHead
= &CsrRootProcess
->ThreadList
;
1452 NextEntry
= ListHead
->Flink
;
1454 /* Start looping the list */
1455 while (NextEntry
!= ListHead
)
1457 /* Get the Thread */
1458 ServerThread
= CONTAINING_RECORD(NextEntry
, CSR_THREAD
, Link
);
1461 Status
= NtResumeThread(ServerThread
->ThreadHandle
, NULL
);
1463 /* Is this a Server Thread? */
1464 if (ServerThread
->Flags
& CsrThreadIsServerThread
)
1466 /* If so, then wait for it to initialize */
1467 Status
= NtWaitForSingleObject(hRequestEvent
, FALSE
, NULL
);
1468 ASSERT(NT_SUCCESS(Status
));
1472 NextEntry
= NextEntry
->Flink
;
1475 /* We don't need this anymore */
1476 NtClose(hRequestEvent
);
1486 CsrpHandleConnectionRequest(PPORT_MESSAGE Request
)
1489 HANDLE ServerPort
= NULL
;//, ServerThread = NULL;
1490 PCSR_PROCESS ProcessData
= NULL
;
1491 REMOTE_PORT_VIEW RemotePortView
;
1492 // CLIENT_ID ClientId;
1493 BOOLEAN AllowConnection
= FALSE
;
1494 PCSR_CONNECTION_INFO ConnectInfo
;
1497 DPRINT("CSR: %s: Handling: %p\n", __FUNCTION__
, Request
);
1499 ConnectInfo
= (PCSR_CONNECTION_INFO
)(Request
+ 1);
1501 /* Save the process ID */
1502 RtlZeroMemory(ConnectInfo
, sizeof(CSR_CONNECTION_INFO
));
1504 CsrLockProcessByClientId(Request
->ClientId
.UniqueProcess
, &ProcessData
);
1507 DPRINT1("CSRSRV: Unknown process: %lx. Will be rejecting connection\n",
1508 Request
->ClientId
.UniqueProcess
);
1511 if ((ProcessData
) && (ProcessData
!= CsrRootProcess
))
1513 /* Attach the Shared Section */
1514 Status
= CsrSrvAttachSharedSection(ProcessData
, ConnectInfo
);
1515 if (NT_SUCCESS(Status
))
1517 DPRINT("Connection ok\n");
1518 AllowConnection
= TRUE
;
1522 DPRINT1("Shared section map failed: %lx\n", Status
);
1525 else if (ProcessData
== CsrRootProcess
)
1527 AllowConnection
= TRUE
;
1530 /* Release the process */
1531 if (ProcessData
) CsrUnlockProcess(ProcessData
);
1533 /* Setup the Port View Structure */
1534 RemotePortView
.Length
= sizeof(REMOTE_PORT_VIEW
);
1535 RemotePortView
.ViewSize
= 0;
1536 RemotePortView
.ViewBase
= NULL
;
1538 /* Save the Process ID */
1539 ConnectInfo
->ProcessId
= NtCurrentTeb()->ClientId
.UniqueProcess
;
1541 Status
= NtAcceptConnectPort(&ServerPort
,
1542 AllowConnection
? UlongToPtr(ProcessData
->SequenceNumber
) : 0,
1547 if (!NT_SUCCESS(Status
))
1549 DPRINT1("CSRSS: NtAcceptConnectPort - failed. Status == %X\n", Status
);
1551 else if (AllowConnection
)
1555 DPRINT1("CSRSS: ClientId: %lx.%lx has ClientView: Base=%p, Size=%lx\n",
1556 Request
->ClientId
.UniqueProcess
,
1557 Request
->ClientId
.UniqueThread
,
1558 RemotePortView
.ViewBase
,
1559 RemotePortView
.ViewSize
);
1562 /* Set some Port Data in the Process */
1563 ProcessData
->ClientPort
= ServerPort
;
1564 ProcessData
->ClientViewBase
= (ULONG_PTR
)RemotePortView
.ViewBase
;
1565 ProcessData
->ClientViewBounds
= (ULONG_PTR
)((ULONG_PTR
)RemotePortView
.ViewBase
+
1566 (ULONG_PTR
)RemotePortView
.ViewSize
);
1568 /* Complete the connection */
1569 Status
= NtCompleteConnectPort(ServerPort
);
1570 if (!NT_SUCCESS(Status
))
1572 DPRINT1("CSRSS: NtCompleteConnectPort - failed. Status == %X\n", Status
);
1577 DPRINT1("CSRSS: Rejecting Connection Request from ClientId: %lx.%lx\n",
1578 Request
->ClientId
.UniqueProcess
,
1579 Request
->ClientId
.UniqueThread
);
1586 * @name CsrConnectToUser
1589 * The CsrConnectToUser connects to the User subsystem.
1593 * @return A pointer to the CSR Thread
1600 CsrConnectToUser(VOID
)
1603 ANSI_STRING DllName
;
1604 UNICODE_STRING TempName
;
1607 PTEB Teb
= NtCurrentTeb();
1608 PCSR_THREAD CsrThread
;
1611 /* Check if we didn't already find it */
1612 if (!CsrClientThreadSetup
)
1614 /* Get the DLL Handle for user32.dll */
1615 RtlInitAnsiString(&DllName
, "user32");
1616 RtlAnsiStringToUnicodeString(&TempName
, &DllName
, TRUE
);
1617 Status
= LdrGetDllHandle(NULL
,
1621 RtlFreeUnicodeString(&TempName
);
1623 /* If we got teh handle, get the Client Thread Startup Entrypoint */
1624 if (NT_SUCCESS(Status
))
1626 RtlInitAnsiString(&StartupName
,"ClientThreadSetup");
1627 Status
= LdrGetProcedureAddress(hUser32
,
1630 (PVOID
)&CsrClientThreadSetup
);
1634 /* Connect to user32 */
1637 Connected
= CsrClientThreadSetup();
1639 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1646 DPRINT1("CSRSS: CsrConnectToUser failed\n");
1650 /* Save pointer to this thread in TEB */
1651 CsrAcquireProcessLock();
1652 CsrThread
= CsrLocateThreadInProcess(NULL
, &Teb
->ClientId
);
1653 CsrReleaseProcessLock();
1654 if (CsrThread
) Teb
->CsrClientThread
= CsrThread
;
1661 * @name CsrQueryApiPort
1664 * The CsrQueryApiPort routine returns a handle to the CSR API LPC port.
1668 * @return A handle to the port.
1675 CsrQueryApiPort(VOID
)
1677 DPRINT("CSRSRV: %s called\n", __FUNCTION__
);
1682 * @name CsrCaptureArguments
1683 * @implemented NT5.1
1685 * The CsrCaptureArguments routine validates a CSR Capture Buffer and
1686 * re-captures it into a server CSR Capture Buffer.
1689 * Pointer to the CSR Thread performing the validation.
1692 * Pointer to the CSR API Message containing the Capture Buffer
1693 * that needs to be validated.
1695 * @return TRUE if validation succeeded, FALSE otherwise.
1702 CsrCaptureArguments(IN PCSR_THREAD CsrThread
,
1703 IN PCSR_API_MESSAGE ApiMessage
)
1705 PCSR_CAPTURE_BUFFER LocalCaptureBuffer
= NULL
, RemoteCaptureBuffer
= NULL
;
1706 ULONG LocalLength
= 0, PointerCount
= 0;
1707 SIZE_T BufferDistance
= 0;
1708 ULONG_PTR
**PointerOffsets
= NULL
, *CurrentPointer
= NULL
;
1710 /* Use SEH to make sure this is valid */
1713 /* Get the buffer we got from whoever called NTDLL */
1714 LocalCaptureBuffer
= ApiMessage
->CsrCaptureData
;
1715 LocalLength
= LocalCaptureBuffer
->Size
;
1717 /* Now check if the buffer is inside our mapped section */
1718 if (((ULONG_PTR
)LocalCaptureBuffer
< CsrThread
->Process
->ClientViewBase
) ||
1719 (((ULONG_PTR
)LocalCaptureBuffer
+ LocalLength
) >= CsrThread
->Process
->ClientViewBounds
))
1721 /* Return failure */
1722 DPRINT1("*** CSRSS: CaptureBuffer outside of ClientView\n");
1723 ApiMessage
->Status
= STATUS_INVALID_PARAMETER
;
1724 _SEH2_YIELD(return FALSE
);
1727 /* Check if the Length is valid */
1728 if (((LocalCaptureBuffer
->PointerCount
* 4 + sizeof(CSR_CAPTURE_BUFFER
)) >
1729 LocalLength
) ||(LocalLength
> MAXWORD
))
1731 /* Return failure */
1732 DPRINT1("*** CSRSS: CaptureBuffer %p has bad length\n", LocalCaptureBuffer
);
1734 ApiMessage
->Status
= STATUS_INVALID_PARAMETER
;
1735 _SEH2_YIELD(return FALSE
);
1738 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1740 /* Return failure */
1741 ApiMessage
->Status
= STATUS_INVALID_PARAMETER
;
1742 _SEH2_YIELD(return FALSE
);
1745 /* We validated the incoming buffer, now allocate the remote one */
1746 RemoteCaptureBuffer
= RtlAllocateHeap(CsrHeap
, 0, LocalLength
);
1747 if (!RemoteCaptureBuffer
)
1749 /* We're out of memory */
1750 ApiMessage
->Status
= STATUS_NO_MEMORY
;
1754 /* Copy the client's buffer */
1755 RtlMoveMemory(RemoteCaptureBuffer
, LocalCaptureBuffer
, LocalLength
);
1757 /* Copy the length */
1758 RemoteCaptureBuffer
->Size
= LocalLength
;
1760 /* Calculate the difference between our buffer and the client's */
1761 BufferDistance
= (ULONG_PTR
)RemoteCaptureBuffer
- (ULONG_PTR
)LocalCaptureBuffer
;
1763 /* Save the pointer count and offset pointer */
1764 PointerCount
= RemoteCaptureBuffer
->PointerCount
;
1765 PointerOffsets
= (ULONG_PTR
**)(RemoteCaptureBuffer
+ 1);
1767 /* Start the loop */
1768 while (PointerCount
)
1770 /* Get the current pointer */
1771 if ((CurrentPointer
= *PointerOffsets
++))
1773 /* Add it to the CSR Message structure */
1774 CurrentPointer
+= (ULONG_PTR
)ApiMessage
;
1776 /* Validate the bounds of the current pointer */
1777 if ((*CurrentPointer
>= CsrThread
->Process
->ClientViewBase
) &&
1778 (*CurrentPointer
< CsrThread
->Process
->ClientViewBounds
))
1780 /* Modify the pointer to take into account its new position */
1781 *CurrentPointer
+= BufferDistance
;
1785 /* Invalid pointer, fail */
1786 DPRINT1("*** CSRSS: CaptureBuffer MessagePointer outside of ClientView\n");
1788 ApiMessage
->Status
= STATUS_INVALID_PARAMETER
;
1792 /* Move to the next Pointer */
1796 /* Check if we got success */
1797 if (ApiMessage
->Status
!= STATUS_SUCCESS
)
1799 /* Failure. Free the buffer and return*/
1800 RtlFreeHeap(CsrHeap
, 0, RemoteCaptureBuffer
);
1805 /* Success, save the previous buffer */
1806 RemoteCaptureBuffer
->PreviousCaptureBuffer
= LocalCaptureBuffer
;
1807 ApiMessage
->CsrCaptureData
= RemoteCaptureBuffer
;
1815 * @name CsrReleaseCapturedArguments
1816 * @implemented NT5.1
1818 * The CsrReleaseCapturedArguments routine releases a Capture Buffer
1819 * that was previously captured with CsrCaptureArguments.
1822 * Pointer to the CSR API Message containing the Capture Buffer
1823 * that needs to be released.
1832 CsrReleaseCapturedArguments(IN PCSR_API_MESSAGE ApiMessage
)
1834 PCSR_CAPTURE_BUFFER RemoteCaptureBuffer
, LocalCaptureBuffer
;
1835 SIZE_T BufferDistance
;
1837 ULONG_PTR
**PointerOffsets
, *CurrentPointer
;
1839 /* Get the capture buffers */
1840 RemoteCaptureBuffer
= ApiMessage
->CsrCaptureData
;
1841 LocalCaptureBuffer
= RemoteCaptureBuffer
->PreviousCaptureBuffer
;
1843 /* Free the previous one */
1844 RemoteCaptureBuffer
->PreviousCaptureBuffer
= NULL
;
1846 /* Find out the difference between the two buffers */
1847 BufferDistance
= (ULONG_PTR
)LocalCaptureBuffer
- (ULONG_PTR
)RemoteCaptureBuffer
;
1849 /* Save the pointer count and offset pointer */
1850 PointerCount
= RemoteCaptureBuffer
->PointerCount
;
1851 PointerOffsets
= (ULONG_PTR
**)(RemoteCaptureBuffer
+ 1);
1853 /* Start the loop */
1854 while (PointerCount
)
1856 /* Get the current pointer */
1857 CurrentPointer
= *PointerOffsets
++;
1860 /* Add it to the CSR Message structure */
1861 CurrentPointer
+= (ULONG_PTR
)ApiMessage
;
1863 /* Modify the pointer to take into account its new position */
1864 *CurrentPointer
+= BufferDistance
;
1867 /* Move to the next Pointer */
1871 /* Copy the data back */
1872 RtlMoveMemory(LocalCaptureBuffer
, RemoteCaptureBuffer
, RemoteCaptureBuffer
->Size
);
1874 /* Free our allocated buffer */
1875 RtlFreeHeap(CsrHeap
, 0, RemoteCaptureBuffer
);
1880 * @name CsrValidateMessageBuffer
1881 * @implemented NT5.1
1883 * The CsrValidateMessageBuffer routine validates a captured message buffer
1884 * present in the CSR Api Message
1887 * Pointer to the CSR API Message containing the CSR Capture Buffer.
1890 * Pointer to the message buffer to validate.
1892 * @param ArgumentSize
1893 * Size of the message to check.
1895 * @param ArgumentCount
1896 * Number of messages to check.
1898 * @return TRUE if validation suceeded, FALSE otherwise.
1905 CsrValidateMessageBuffer(IN PCSR_API_MESSAGE ApiMessage
,
1907 IN ULONG ArgumentSize
,
1908 IN ULONG ArgumentCount
)
1910 PCSR_CAPTURE_BUFFER CaptureBuffer
= ApiMessage
->CsrCaptureData
;
1911 SIZE_T BufferDistance
;
1912 ULONG PointerCount
, i
;
1913 ULONG_PTR
**PointerOffsets
, *CurrentPointer
;
1915 /* Make sure there are some arguments */
1916 if (!ArgumentCount
) return FALSE
;
1918 /* Check if didn't get a buffer and there aren't any arguments to check */
1919 if (!(*Buffer
) && (!(ArgumentCount
* ArgumentSize
))) return TRUE
;
1921 /* Check if we have no capture buffer */
1924 /* In this case, check only the Process ID */
1925 if (NtCurrentTeb()->ClientId
.UniqueProcess
==
1926 ApiMessage
->Header
.ClientId
.UniqueProcess
)
1928 /* There is a match, validation succeeded */
1934 /* Make sure that there is still space left in the buffer */
1935 if ((CaptureBuffer
->Size
- (ULONG_PTR
)*Buffer
+ (ULONG_PTR
)CaptureBuffer
) <
1936 (ArgumentCount
* ArgumentSize
))
1938 /* Find out the difference between the two buffers */
1939 BufferDistance
= (ULONG_PTR
)Buffer
- (ULONG_PTR
)ApiMessage
;
1941 /* Save the pointer count */
1942 PointerCount
= CaptureBuffer
->PointerCount
;
1943 PointerOffsets
= (ULONG_PTR
**)(CaptureBuffer
+ 1);
1945 /* Start the loop */
1946 for (i
= 0; i
< PointerCount
; i
++)
1948 /* Get the current pointer */
1949 CurrentPointer
= *PointerOffsets
++;
1951 /* Check if its' equal to the difference */
1952 if (*CurrentPointer
== BufferDistance
) return TRUE
;
1958 DbgPrint("CSRSRV: Bad message buffer %p\n", ApiMessage
);
1964 * @name CsrValidateMessageString
1965 * @implemented NT5.1
1967 * The CsrValidateMessageString validates a captured Wide-Character String
1968 * present in a CSR API Message.
1971 * Pointer to the CSR API Message containing the CSR Capture Buffer.
1973 * @param MessageString
1974 * Pointer to the buffer containing the string to validate.
1976 * @return TRUE if validation suceeded, FALSE otherwise.
1983 CsrValidateMessageString(IN PCSR_API_MESSAGE ApiMessage
,
1984 IN LPWSTR
*MessageString
)
1986 DPRINT1("CSRSRV: %s called\n", __FUNCTION__
);