ReactOS  0.4.15-dev-3017-g1d9542d
api.c
Go to the documentation of this file.
1 /*
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)
8  */
9 
10 /* INCLUDES *******************************************************************/
11 
12 #include "srv.h"
13 
14 #include <ndk/kefuncs.h>
15 
16 #define NDEBUG
17 #include <debug.h>
18 
19 /* GLOBALS ********************************************************************/
20 
26 
27 /* FUNCTIONS ******************************************************************/
28 
29 /*++
30  * @name CsrCallServerFromServer
31  * @implemented NT4
32  *
33  * The CsrCallServerFromServer routine calls a CSR API from within a server.
34  * It avoids using LPC messages since the request isn't coming from a client.
35  *
36  * @param ReceiveMsg
37  * Pointer to the CSR API Message to send to the server.
38  *
39  * @param ReplyMsg
40  * Pointer to the CSR API Message to receive from the server.
41  *
42  * @return STATUS_SUCCESS in case of success, STATUS_ILLEGAL_FUNCTION
43  * if the ApiNumber is invalid, or STATUS_ACCESS_VIOLATION if there
44  * was a problem executing the API.
45  *
46  * @remarks None.
47  *
48  *--*/
50 NTAPI
52  IN OUT PCSR_API_MESSAGE ReplyMsg)
53 {
54  ULONG ServerId;
55  PCSR_SERVER_DLL ServerDll = NULL;
56  ULONG ApiId;
58 
59  /* Get the Server ID */
60  ServerId = CSR_API_NUMBER_TO_SERVER_ID(ReceiveMsg->ApiNumber);
61 
62  /* Make sure that the ID is within limits, and the Server DLL loaded */
63  if ((ServerId >= CSR_SERVER_DLL_MAX) ||
64  (!(ServerDll = CsrLoadedServerDll[ServerId])))
65  {
66  /* We are beyond the Maximum Server ID */
67 #ifdef CSR_DBG
68  DPRINT1("CSRSS: %lx is invalid ServerDllIndex (%08x)\n",
69  ServerId, ServerDll);
70  if (NtCurrentPeb()->BeingDebugged) DbgBreakPoint();
71 #endif
72  ReplyMsg->Status = STATUS_ILLEGAL_FUNCTION;
74  }
75  else
76  {
77  /* Get the API ID, normalized with our Base ID */
78  ApiId = CSR_API_NUMBER_TO_API_ID(ReceiveMsg->ApiNumber) - ServerDll->ApiBase;
79 
80  /* Make sure that the ID is within limits, and the entry exists */
81  if ((ApiId >= ServerDll->HighestApiSupported) ||
82  ((ServerDll->ValidTable) && !(ServerDll->ValidTable[ApiId])))
83  {
84  /* We are beyond the Maximum API ID, or it doesn't exist */
85 #ifdef CSR_DBG
86  DPRINT1("API: %d\n", ApiId);
87  DPRINT1("CSRSS: %lx (%s) is invalid ApiTableIndex for %Z or is an "
88  "invalid API to call from the server.\n",
89  ApiId,
90  ((ServerDll->NameTable) && (ServerDll->NameTable[ApiId])) ?
91  ServerDll->NameTable[ApiId] : "*** UNKNOWN ***",
92  &ServerDll->Name);
93  if (NtCurrentPeb()->BeingDebugged) DbgBreakPoint();
94 #endif
95  ReplyMsg->Status = STATUS_ILLEGAL_FUNCTION;
97  }
98  }
99 
100 #ifdef CSR_DBG
101  if (CsrDebug & 2)
102  {
103  DPRINT1("CSRSS: %s Api Request received from server process\n",
104  ServerDll->NameTable[ApiId]);
105  }
106 #endif
107 
108  /* Validation complete, start SEH */
109  _SEH2_TRY
110  {
111  /* Call the API, get the reply code and return the result */
112  ReplyMsg->Status = ServerDll->DispatchTable[ApiId](ReceiveMsg, &ReplyCode);
113  }
115  {
116  /* If we got an exception, return access violation */
117  ReplyMsg->Status = STATUS_ACCESS_VIOLATION;
118  }
119  _SEH2_END;
120 
121  /* Return success */
122  return STATUS_SUCCESS;
123 }
124 
125 /*++
126  * @name CsrApiHandleConnectionRequest
127  *
128  * The CsrApiHandleConnectionRequest routine handles and accepts a new
129  * connection request to the CSR API LPC Port.
130  *
131  * @param ApiMessage
132  * Pointer to the incoming CSR API Message which contains the
133  * connection request.
134  *
135  * @return STATUS_SUCCESS in case of success, or status code which caused
136  * the routine to error.
137  *
138  * @remarks This routine is responsible for attaching the Shared Section to
139  * new clients connecting to CSR.
140  *
141  *--*/
142 NTSTATUS
143 NTAPI
145 {
146  PCSR_THREAD CsrThread = NULL;
149  PCSR_API_CONNECTINFO ConnectInfo = &ApiMessage->ConnectionInfo;
150  BOOLEAN AllowConnection = FALSE;
151  REMOTE_PORT_VIEW RemotePortView;
153 
154  /* Acquire the Process Lock */
156 
157  /* Lookup the CSR Thread */
158  CsrThread = CsrLocateThreadByClientId(NULL, &ApiMessage->Header.ClientId);
159 
160  /* Check if we have a thread */
161  if (CsrThread)
162  {
163  /* Get the Process and make sure we have it as well */
164  CsrProcess = CsrThread->Process;
165  if (CsrProcess)
166  {
167  /* Reference the Process */
169 
170  /* Attach the Shared Section */
172  if (NT_SUCCESS(Status))
173  {
174  /* Allow the connection and return debugging flag */
175  ConnectInfo->DebugFlags = CsrDebug;
176  AllowConnection = TRUE;
177  }
178 
179  /* Dereference the Process */
181  }
182  }
183 
184  /* Release the Process Lock */
186 
187  /* Setup the Port View Structure */
188  RemotePortView.Length = sizeof(REMOTE_PORT_VIEW);
189  RemotePortView.ViewSize = 0;
190  RemotePortView.ViewBase = NULL;
191 
192  /* Save the Process ID */
193  ConnectInfo->ServerProcessId = NtCurrentTeb()->ClientId.UniqueProcess;
194 
195  /* Accept the Connection */
196  ASSERT(!AllowConnection || CsrProcess);
198  AllowConnection ? UlongToPtr(CsrProcess->SequenceNumber) : 0,
199  &ApiMessage->Header,
200  AllowConnection,
201  NULL,
202  &RemotePortView);
203  if (!NT_SUCCESS(Status))
204  {
205  DPRINT1("CSRSS: NtAcceptConnectPort - failed. Status == %X\n", Status);
206  }
207  else if (AllowConnection)
208  {
209  if (CsrDebug & 2)
210  {
211  DPRINT1("CSRSS: ClientId: %lx.%lx has ClientView: Base=%p, Size=%lx\n",
212  ApiMessage->Header.ClientId.UniqueProcess,
213  ApiMessage->Header.ClientId.UniqueThread,
214  RemotePortView.ViewBase,
215  RemotePortView.ViewSize);
216  }
217 
218  /* Set some Port Data in the Process */
219  CsrProcess->ClientPort = ServerPort;
220  CsrProcess->ClientViewBase = (ULONG_PTR)RemotePortView.ViewBase;
221  CsrProcess->ClientViewBounds = (ULONG_PTR)((ULONG_PTR)RemotePortView.ViewBase +
222  (ULONG_PTR)RemotePortView.ViewSize);
223 
224  /* Complete the connection */
226  if (!NT_SUCCESS(Status))
227  {
228  DPRINT1("CSRSS: NtCompleteConnectPort - failed. Status == %X\n", Status);
229  }
230  }
231  else
232  {
233  DPRINT1("CSRSS: Rejecting Connection Request from ClientId: %lx.%lx\n",
234  ApiMessage->Header.ClientId.UniqueProcess,
235  ApiMessage->Header.ClientId.UniqueThread);
236  }
237 
238  /* Return status to caller */
239  return Status;
240 }
241 
242 /*++
243  * @name CsrpCheckRequestThreads
244  *
245  * The CsrpCheckRequestThreads routine checks if there are no more threads
246  * to handle CSR API Requests, and creates a new thread if possible, to
247  * avoid starvation.
248  *
249  * @param None.
250  *
251  * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
252  * if a new thread couldn't be created.
253  *
254  * @remarks None.
255  *
256  *--*/
257 NTSTATUS
258 NTAPI
260 {
261  HANDLE hThread;
264 
265  /* Decrease the count, and see if we're out */
267  {
268  /* Check if we've still got space for a Dynamic Thread */
270  {
271  /* Create a new dynamic thread */
273  NULL,
274  TRUE,
275  0,
276  0,
277  0,
279  NULL,
280  &hThread,
281  &ClientId);
282  /* Check success */
283  if (NT_SUCCESS(Status))
284  {
285  /* Increase the thread counts */
288 
289  /* Add a new server thread */
291  &ClientId,
293  {
294  /* Activate it */
296  }
297  else
298  {
299  /* Failed to create a new static thread */
302 
303  /* Terminate it */
304  DPRINT1("Failing\n");
306  NtClose(hThread);
307 
308  /* Return */
309  return STATUS_UNSUCCESSFUL;
310  }
311  }
312  }
313  }
314 
315  /* Success */
316  return STATUS_SUCCESS;
317 }
318 
319 /*++
320  * @name CsrApiRequestThread
321  *
322  * The CsrApiRequestThread routine handles incoming messages or connection
323  * requests on the CSR API LPC Port.
324  *
325  * @param Parameter
326  * System-default user-defined parameter. Unused.
327  *
328  * @return The thread exit code, if the thread is terminated.
329  *
330  * @remarks Before listening on the port, the routine will first attempt
331  * to connect to the user subsystem.
332  *
333  *--*/
334 NTSTATUS
335 NTAPI
337 {
338  PTEB Teb = NtCurrentTeb();
339  LARGE_INTEGER TimeOut;
340  PCSR_THREAD CurrentThread, CsrThread;
342  CSR_REPLY_CODE ReplyCode;
343  PCSR_API_MESSAGE ReplyMsg;
344  CSR_API_MESSAGE ReceiveMsg;
346  PHARDERROR_MSG HardErrorMsg;
347  PVOID PortContext;
348  PCSR_SERVER_DLL ServerDll;
349  PCLIENT_DIED_MSG ClientDiedMsg;
350  PDBGKM_MSG DebugMessage;
351  ULONG ServerId, ApiId, MessageType, i;
352  HANDLE ReplyPort;
353 
354  /* Setup LPC loop port and message */
355  ReplyMsg = NULL;
356  ReplyPort = CsrApiPort;
357 
358  /* Connect to user32 */
359  while (!CsrConnectToUser())
360  {
361  /* Set up the timeout for the connect (30 seconds) */
362  TimeOut.QuadPart = -30 * 1000 * 1000 * 10;
363 
364  /* Keep trying until we get a response */
365  Teb->Win32ClientInfo[0] = 0;
366  NtDelayExecution(FALSE, &TimeOut);
367  }
368 
369  /* Get our thread */
370  CurrentThread = Teb->CsrClientThread;
371 
372  /* If we got an event... */
373  if (Parameter)
374  {
375  /* Set it, to let stuff waiting on us load */
378 
379  /* Increase the Thread Counts */
382  }
383 
384  /* Now start the loop */
385  while (TRUE)
386  {
387  /* Make sure the real CID is set */
388  Teb->RealClientId = Teb->ClientId;
389 
390 #ifdef CSR_DBG
391  /* Debug check */
393  {
394  DPRINT1("CSRSRV: FATAL ERROR. CsrThread is Idle while holding %lu critical sections\n",
396  DPRINT1("CSRSRV: Last Receive Message %lx ReplyMessage %lx\n",
397  &ReceiveMsg, ReplyMsg);
398  DbgBreakPoint();
399  }
400 #endif
401 
402  /* Wait for a message to come through */
403  Status = NtReplyWaitReceivePort(ReplyPort,
404  &PortContext,
405  &ReplyMsg->Header,
406  &ReceiveMsg.Header);
407 
408  /* Check if we didn't get success */
409  if (Status != STATUS_SUCCESS)
410  {
411  /* Was it a failure or another success code? */
412  if (!NT_SUCCESS(Status))
413  {
414 #ifdef CSR_DBG
415  /* Check for specific status cases */
416  if ((Status != STATUS_INVALID_CID) &&
418  ((Status != STATUS_INVALID_HANDLE) || (ReplyPort == CsrApiPort)))
419  {
420  /* Notify the debugger */
421  DPRINT1("CSRSS: ReceivePort failed - Status == %X\n", Status);
422  DPRINT1("CSRSS: ReplyPortHandle %lx CsrApiPort %lx\n", ReplyPort, CsrApiPort);
423  }
424 #endif
425 
426  /* We failed big time, so start out fresh */
427  ReplyMsg = NULL;
428  ReplyPort = CsrApiPort;
429  continue;
430  }
431  else
432  {
433  /* A strange "success" code, just try again */
434  DPRINT1("NtReplyWaitReceivePort returned \"success\" status 0x%x\n", Status);
435  continue;
436  }
437  }
438 
439  // ASSERT(ReceiveMsg.Header.u1.s1.TotalLength >= sizeof(PORT_MESSAGE));
440  // ASSERT(ReceiveMsg.Header.u1.s1.TotalLength < sizeof(ReceiveMsg));
441 
442  /* Use whatever Client ID we got */
443  Teb->RealClientId = ReceiveMsg.Header.ClientId;
444 
445  /* Get the Message Type */
446  MessageType = ReceiveMsg.Header.u2.s2.Type;
447 
448  /* Handle connection requests */
449  if (MessageType == LPC_CONNECTION_REQUEST)
450  {
451  /* Handle the Connection Request */
452  CsrApiHandleConnectionRequest(&ReceiveMsg);
453 
454  ReplyMsg = NULL;
455  ReplyPort = CsrApiPort;
456  continue;
457  }
458 
459  /* It's some other kind of request. Get the lock for the lookup */
461 
462  /* Now do the lookup to get the CSR_THREAD */
464  &ReceiveMsg.Header.ClientId);
465 
466  /* Did we find a thread? */
467  if (!CsrThread)
468  {
469  /* This wasn't a CSR Thread, release lock */
471 
472  /* If this was an exception, handle it */
473  if (MessageType == LPC_EXCEPTION)
474  {
475  ReplyMsg = &ReceiveMsg;
476  ReplyPort = CsrApiPort;
477  ReplyMsg->Status = DBG_CONTINUE;
478  }
479  else if (MessageType == LPC_PORT_CLOSED ||
480  MessageType == LPC_CLIENT_DIED)
481  {
482  /* The Client or Port are gone, loop again */
483  ReplyMsg = NULL;
484  ReplyPort = CsrApiPort;
485  }
486  else if (MessageType == LPC_ERROR_EVENT)
487  {
488  /* If it's a hard error, handle this too */
489  HardErrorMsg = (PHARDERROR_MSG)&ReceiveMsg;
490 
491  /* Default it to unhandled */
492  HardErrorMsg->Response = ResponseNotHandled;
493 
494  /* Check if there are free api threads */
497  {
498  /* Loop every Server DLL */
499  for (i = 0; i < CSR_SERVER_DLL_MAX; i++)
500  {
501  /* Get the Server DLL */
502  ServerDll = CsrLoadedServerDll[i];
503 
504  /* Check if it's valid and if it has a Hard Error Callback */
505  if ((ServerDll) && (ServerDll->HardErrorCallback))
506  {
507  /* Call it */
508  ServerDll->HardErrorCallback(NULL /* == CsrThread */, HardErrorMsg);
509 
510  /* If it's handled, get out of here */
511  if (HardErrorMsg->Response != ResponseNotHandled) break;
512  }
513  }
514  }
515 
516  /* Increase the thread count */
518 
519  /* If the response was 0xFFFFFFFF, we'll ignore it */
520  if (HardErrorMsg->Response == 0xFFFFFFFF)
521  {
522  ReplyMsg = NULL;
523  ReplyPort = CsrApiPort;
524  }
525  else
526  {
527  ReplyMsg = &ReceiveMsg;
528  ReplyPort = CsrApiPort;
529  }
530  }
531  else if (MessageType == LPC_REQUEST)
532  {
533  /* This is an API Message coming from a non-CSR Thread */
534  ReplyMsg = &ReceiveMsg;
535  ReplyPort = CsrApiPort;
536  ReplyMsg->Status = STATUS_ILLEGAL_FUNCTION;
537  }
538  else if (MessageType == LPC_DATAGRAM)
539  {
540  /* This is an API call, get the Server ID */
541  ServerId = CSR_API_NUMBER_TO_SERVER_ID(ReceiveMsg.ApiNumber);
542 
543  /* Make sure that the ID is within limits, and the Server DLL loaded */
544  ServerDll = NULL;
545  if ((ServerId >= CSR_SERVER_DLL_MAX) ||
546  (!(ServerDll = CsrLoadedServerDll[ServerId])))
547  {
548  /* We are beyond the Maximum Server ID */
549 #ifdef CSR_DBG
550  DPRINT1("CSRSS: %lx is invalid ServerDllIndex (%08x)\n",
551  ServerId, ServerDll);
552  if (NtCurrentPeb()->BeingDebugged) DbgBreakPoint();
553 #endif
554  ReplyMsg = NULL;
555  ReplyPort = CsrApiPort;
556  continue;
557  }
558 
559  /* Get the API ID, normalized with our Base ID */
560  ApiId = CSR_API_NUMBER_TO_API_ID(ReceiveMsg.ApiNumber) - ServerDll->ApiBase;
561 
562  /* Make sure that the ID is within limits, and the entry exists */
563  if (ApiId >= ServerDll->HighestApiSupported)
564  {
565  /* We are beyond the Maximum API ID, or it doesn't exist */
566 #ifdef CSR_DBG
567  DPRINT1("CSRSS: %lx is invalid ApiTableIndex for %Z\n",
569  &ServerDll->Name);
570 #endif
571  ReplyPort = CsrApiPort;
572  ReplyMsg = NULL;
573  continue;
574  }
575 
576 #ifdef CSR_DBG
577  if (CsrDebug & 2)
578  {
579  DPRINT1("[%02x] CSRSS: [%02x,%02x] - %s Api called from %08x\n",
580  Teb->ClientId.UniqueThread,
581  ReceiveMsg.Header.ClientId.UniqueProcess,
582  ReceiveMsg.Header.ClientId.UniqueThread,
583  ServerDll->NameTable[ApiId],
584  NULL);
585  }
586 #endif
587 
588  /* Assume success */
589  ReceiveMsg.Status = STATUS_SUCCESS;
590 
591  /* Validation complete, start SEH */
592  _SEH2_TRY
593  {
594  /* Make sure we have enough threads */
596 
597  /* Call the API and get the reply code */
598  ReplyMsg = NULL;
599  ReplyPort = CsrApiPort;
600  ServerDll->DispatchTable[ApiId](&ReceiveMsg, &ReplyCode);
601 
602  /* Increase the static thread count */
604  }
606  {
607  ReplyMsg = NULL;
608  ReplyPort = CsrApiPort;
609  }
610  _SEH2_END;
611  }
612  else
613  {
614  /* Some other ignored message type */
615  ReplyMsg = NULL;
616  ReplyPort = CsrApiPort;
617  }
618 
619  /* Keep going */
620  continue;
621  }
622 
623  /* We have a valid thread, was this an LPC Request? */
624  if (MessageType != LPC_REQUEST)
625  {
626  /* It's not an API, check if the client died */
627  if (MessageType == LPC_CLIENT_DIED)
628  {
629  /* Get the information and check if it matches our thread */
630  ClientDiedMsg = (PCLIENT_DIED_MSG)&ReceiveMsg;
631  if (ClientDiedMsg->CreateTime.QuadPart == CsrThread->CreateTime.QuadPart)
632  {
633  /* Now we reply to the dying client */
634  ReplyPort = CsrThread->Process->ClientPort;
635 
636  /* Reference the thread */
637  CsrLockedReferenceThread(CsrThread);
638 
639  /* Destroy the thread in the API Message */
640  CsrDestroyThread(&ReceiveMsg.Header.ClientId);
641 
642  /* Check if the thread was actually ourselves */
643  if (CsrProcess->ThreadCount == 1)
644  {
645  /* Kill the process manually here */
646  CsrDestroyProcess(&CsrThread->ClientId, 0);
647  }
648 
649  /* Remove our extra reference */
650  CsrLockedDereferenceThread(CsrThread);
651  }
652 
653  /* Release the lock and keep looping */
655 
656  ReplyMsg = NULL;
657  ReplyPort = CsrApiPort;
658  continue;
659  }
660 
661  /* Reference the thread and release the lock */
662  CsrLockedReferenceThread(CsrThread);
664 
665  /* Check if this was an exception */
666  if (MessageType == LPC_EXCEPTION)
667  {
668  /* Kill the process */
670 
671  /* Destroy it from CSR */
673 
674  /* Return a Debug Message */
675  DebugMessage = (PDBGKM_MSG)&ReceiveMsg;
676  DebugMessage->ReturnedStatus = DBG_CONTINUE;
677  ReplyMsg = &ReceiveMsg;
678  ReplyPort = CsrApiPort;
679 
680  /* Remove our extra reference */
681  CsrDereferenceThread(CsrThread);
682  }
683  else if (MessageType == LPC_ERROR_EVENT)
684  {
685  /* If it's a hard error, handle this too */
686  HardErrorMsg = (PHARDERROR_MSG)&ReceiveMsg;
687 
688  /* Default it to unhandled */
689  HardErrorMsg->Response = ResponseNotHandled;
690 
691  /* Check if there are free api threads */
694  {
695  /* Loop every Server DLL */
696  for (i = 0; i < CSR_SERVER_DLL_MAX; i++)
697  {
698  /* Get the Server DLL */
699  ServerDll = CsrLoadedServerDll[i];
700 
701  /* Check if it's valid and if it has a Hard Error Callback */
702  if ((ServerDll) && (ServerDll->HardErrorCallback))
703  {
704  /* Call it */
705  ServerDll->HardErrorCallback(CsrThread, HardErrorMsg);
706 
707  /* If it's handled, get out of here */
708  if (HardErrorMsg->Response != ResponseNotHandled) break;
709  }
710  }
711  }
712 
713  /* Increase the thread count */
715 
716  /* If the response was 0xFFFFFFFF, we'll ignore it */
717  if (HardErrorMsg->Response == 0xFFFFFFFF)
718  {
719  ReplyMsg = NULL;
720  ReplyPort = CsrApiPort;
721  }
722  else
723  {
724  CsrDereferenceThread(CsrThread);
725  ReplyMsg = &ReceiveMsg;
726  ReplyPort = CsrApiPort;
727  }
728  }
729  else
730  {
731  /* Something else */
732  CsrDereferenceThread(CsrThread);
733  ReplyMsg = NULL;
734  }
735 
736  /* Keep looping */
737  continue;
738  }
739 
740  /* We got an API Request */
741  CsrLockedReferenceThread(CsrThread);
743 
744  /* This is an API call, get the Server ID */
745  ServerId = CSR_API_NUMBER_TO_SERVER_ID(ReceiveMsg.ApiNumber);
746 
747  /* Make sure that the ID is within limits, and the Server DLL loaded */
748  ServerDll = NULL;
749  if ((ServerId >= CSR_SERVER_DLL_MAX) ||
750  (!(ServerDll = CsrLoadedServerDll[ServerId])))
751  {
752  /* We are beyond the Maximum Server ID */
753 #ifdef CSR_DBG
754  DPRINT1("CSRSS: %lx is invalid ServerDllIndex (%08x)\n",
755  ServerId, ServerDll);
756  if (NtCurrentPeb()->BeingDebugged) DbgBreakPoint();
757 #endif
758  ReplyPort = CsrApiPort;
759  ReplyMsg = &ReceiveMsg;
760  ReplyMsg->Status = STATUS_ILLEGAL_FUNCTION;
761  CsrDereferenceThread(CsrThread);
762  continue;
763  }
764 
765  /* Get the API ID, normalized with our Base ID */
766  ApiId = CSR_API_NUMBER_TO_API_ID(ReceiveMsg.ApiNumber) - ServerDll->ApiBase;
767 
768  /* Make sure that the ID is within limits, and the entry exists */
769  if (ApiId >= ServerDll->HighestApiSupported)
770  {
771 #ifdef CSR_DBG
772  /* We are beyond the Maximum API ID, or it doesn't exist */
773  DPRINT1("CSRSS: %lx is invalid ApiTableIndex for %Z\n",
775  &ServerDll->Name);
776 #endif
777  ReplyPort = CsrApiPort;
778  ReplyMsg = &ReceiveMsg;
779  ReplyMsg->Status = STATUS_ILLEGAL_FUNCTION;
780  CsrDereferenceThread(CsrThread);
781  continue;
782  }
783 
784 #ifdef CSR_DBG
785  if (CsrDebug & 2)
786  {
787  DPRINT1("[%02x] CSRSS: [%02x,%02x] - %s Api called from %08x, Process %08x - %08x\n",
788  Teb->ClientId.UniqueThread,
789  ReceiveMsg.Header.ClientId.UniqueProcess,
790  ReceiveMsg.Header.ClientId.UniqueThread,
791  ServerDll->NameTable[ApiId],
792  CsrThread,
793  CsrThread->Process,
794  CsrProcess);
795  }
796 #endif
797 
798  /* Assume success */
799  ReplyMsg = &ReceiveMsg;
800  ReceiveMsg.Status = STATUS_SUCCESS;
801 
802  /* Now we reply to a particular client */
803  ReplyPort = CsrThread->Process->ClientPort;
804 
805  /* Check if there's a capture buffer */
806  if (ReceiveMsg.CsrCaptureData)
807  {
808  /* Capture the arguments */
809  if (!CsrCaptureArguments(CsrThread, &ReceiveMsg))
810  {
811  /* Ignore this message if we failed to get the arguments */
812  CsrDereferenceThread(CsrThread);
813  continue;
814  }
815  }
816 
817  /* Validation complete, start SEH */
818  _SEH2_TRY
819  {
820  /* Make sure we have enough threads */
822 
823  Teb->CsrClientThread = CsrThread;
824 
825  /* Call the API, get the reply code and return the result */
826  ReplyCode = CsrReplyImmediately;
827  ReplyMsg->Status = ServerDll->DispatchTable[ApiId](&ReceiveMsg, &ReplyCode);
828 
829  /* Increase the static thread count */
831 
832  Teb->CsrClientThread = CurrentThread;
833 
834  if (ReplyCode == CsrReplyAlreadySent)
835  {
836  if (ReceiveMsg.CsrCaptureData)
837  {
838  CsrReleaseCapturedArguments(&ReceiveMsg);
839  }
840  ReplyMsg = NULL;
841  ReplyPort = CsrApiPort;
842  CsrDereferenceThread(CsrThread);
843  }
844  else if (ReplyCode == CsrReplyDeadClient)
845  {
846  /* Reply to the death message */
847  NTSTATUS Status2;
848  Status2 = NtReplyPort(ReplyPort, &ReplyMsg->Header);
849  if (!NT_SUCCESS(Status2))
850  DPRINT1("CSRSS: Error while replying to the death message, Status 0x%lx\n", Status2);
851 
852  /* Reply back to the API port now */
853  ReplyMsg = NULL;
854  ReplyPort = CsrApiPort;
855  CsrDereferenceThread(CsrThread);
856  }
857  else if (ReplyCode == CsrReplyPending)
858  {
859  ReplyMsg = NULL;
860  ReplyPort = CsrApiPort;
861  }
862  else
863  {
864  if (ReceiveMsg.CsrCaptureData)
865  {
866  CsrReleaseCapturedArguments(&ReceiveMsg);
867  }
868  CsrDereferenceThread(CsrThread);
869  }
870  }
872  {
873  ReplyMsg = NULL;
874  ReplyPort = CsrApiPort;
875  }
876  _SEH2_END;
877  }
878 
879  /* We're out of the loop for some reason, terminate! */
881  return Status;
882 }
883 
884 /*++
885  * @name CsrApiPortInitialize
886  *
887  * The CsrApiPortInitialize routine initializes the LPC Port used for
888  * communications with the Client/Server Runtime (CSR) and initializes the
889  * static thread that will handle connection requests and APIs.
890  *
891  * @param None
892  *
893  * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
894  *
895  * @remarks None.
896  *
897  *--*/
898 NTSTATUS
899 NTAPI
901 {
902  ULONG Size;
905  HANDLE hRequestEvent, hThread;
907  PLIST_ENTRY ListHead, NextEntry;
909 
910  /* Calculate how much space we'll need for the Port Name */
911  Size = CsrDirectoryName.Length + sizeof(CSR_PORT_NAME) + sizeof(WCHAR);
912 
913  /* Create the buffer for it */
916 
917  /* Setup the rest of the empty string */
923  if (CsrDebug & 1)
924  {
925  DPRINT1("CSRSS: Creating %wZ port and associated threads\n", &CsrApiPortName);
926  DPRINT1("CSRSS: sizeof( CONNECTINFO ) == %ld sizeof( API_MSG ) == %ld\n",
927  sizeof(CSR_API_CONNECTINFO), sizeof(CSR_API_MESSAGE));
928  }
929 
930  /* FIXME: Create a Security Descriptor */
931 
932  /* Initialize the Attributes */
935  0,
936  NULL,
937  NULL /* FIXME: Use the Security Descriptor */);
938 
939  /* Create the Port Object */
942  sizeof(CSR_API_CONNECTINFO),
943  sizeof(CSR_API_MESSAGE),
944  16 * PAGE_SIZE);
945  if (NT_SUCCESS(Status))
946  {
947  /* Create the event the Port Thread will use */
948  Status = NtCreateEvent(&hRequestEvent,
950  NULL,
952  FALSE);
953  if (NT_SUCCESS(Status))
954  {
955  /* Create the Request Thread */
957  NULL,
958  TRUE,
959  0,
960  0,
961  0,
963  (PVOID)hRequestEvent,
964  &hThread,
965  &ClientId);
966  if (NT_SUCCESS(Status))
967  {
968  /* Add this as a static thread to CSRSRV */
970 
971  /* Get the Thread List Pointers */
972  ListHead = &CsrRootProcess->ThreadList;
973  NextEntry = ListHead->Flink;
974 
975  /* Start looping the list */
976  while (NextEntry != ListHead)
977  {
978  /* Get the Thread */
980 
981  /* Start it up */
982  Status = NtResumeThread(ServerThread->ThreadHandle, NULL);
983 
984  /* Is this a Server Thread? */
986  {
987  /* If so, then wait for it to initialize */
988  Status = NtWaitForSingleObject(hRequestEvent, FALSE, NULL);
990  }
991 
992  /* Next thread */
993  NextEntry = NextEntry->Flink;
994  }
995 
996  /* We don't need this anymore */
997  NtClose(hRequestEvent);
998  }
999  }
1000  }
1001 
1002  /* Return */
1003  return Status;
1004 }
1005 
1006 /*++
1007  * @name CsrConnectToUser
1008  * @implemented NT4
1009  *
1010  * The CsrConnectToUser connects to the User subsystem.
1011  *
1012  * @param None
1013  *
1014  * @return A pointer to the CSR Thread
1015  *
1016  * @remarks None.
1017  *
1018  *--*/
1020 NTAPI
1022 {
1023  NTSTATUS Status;
1024  ANSI_STRING DllName;
1025  UNICODE_STRING TempName;
1026  HANDLE hUser32;
1027  STRING StartupName;
1028  PTEB Teb = NtCurrentTeb();
1029  PCSR_THREAD CsrThread;
1030  BOOLEAN Connected;
1031 
1032  /* Check if we didn't already find it */
1033  if (!CsrClientThreadSetup)
1034  {
1035  /* Get the DLL Handle for user32.dll */
1036  RtlInitAnsiString(&DllName, "user32");
1037  RtlAnsiStringToUnicodeString(&TempName, &DllName, TRUE);
1039  NULL,
1040  &TempName,
1041  &hUser32);
1042  RtlFreeUnicodeString(&TempName);
1043 
1044  /* If we got the handle, get the Client Thread Startup Entrypoint */
1045  if (NT_SUCCESS(Status))
1046  {
1047  RtlInitAnsiString(&StartupName,"ClientThreadSetup");
1048  Status = LdrGetProcedureAddress(hUser32,
1049  &StartupName,
1050  0,
1052  }
1053  }
1054 
1055  /* Connect to user32 */
1056  _SEH2_TRY
1057  {
1058  Connected = CsrClientThreadSetup();
1059  }
1061  {
1062  Connected = FALSE;
1063  }
1064  _SEH2_END;
1065 
1066  if (!Connected)
1067  {
1068  DPRINT1("CSRSS: CsrConnectToUser failed\n");
1069  return NULL;
1070  }
1071 
1072  /* Save pointer to this thread in TEB */
1074  CsrThread = CsrLocateThreadInProcess(NULL, &Teb->ClientId);
1076  if (CsrThread) Teb->CsrClientThread = CsrThread;
1077 
1078  /* Return it */
1079  return CsrThread;
1080 }
1081 
1082 /*++
1083  * @name CsrQueryApiPort
1084  * @implemented NT4
1085  *
1086  * The CsrQueryApiPort routine returns a handle to the CSR API LPC port.
1087  *
1088  * @param None.
1089  *
1090  * @return A handle to the port.
1091  *
1092  * @remarks None.
1093  *
1094  *--*/
1095 HANDLE
1096 NTAPI
1098 {
1099  return CsrApiPort;
1100 }
1101 
1102 /*++
1103  * @name CsrCaptureArguments
1104  * @implemented NT5.1
1105  *
1106  * The CsrCaptureArguments routine validates a CSR Capture Buffer and
1107  * re-captures it into a server CSR Capture Buffer.
1108  *
1109  * @param CsrThread
1110  * Pointer to the CSR Thread performing the validation.
1111  *
1112  * @param ApiMessage
1113  * Pointer to the CSR API Message containing the Capture Buffer
1114  * that needs to be validated.
1115  *
1116  * @return TRUE if validation succeeded, FALSE otherwise.
1117  *
1118  * @remarks None.
1119  *
1120  *--*/
1121 BOOLEAN
1122 NTAPI
1124  IN PCSR_API_MESSAGE ApiMessage)
1125 {
1126  PCSR_PROCESS CsrProcess = CsrThread->Process;
1127  PCSR_CAPTURE_BUFFER ClientCaptureBuffer, ServerCaptureBuffer = NULL;
1128  ULONG_PTR EndOfClientBuffer;
1129  SIZE_T SizeOfBufferThroughOffsetsArray;
1130  SIZE_T BufferDistance;
1131  ULONG Length;
1132  ULONG PointerCount;
1133  PULONG_PTR OffsetPointer;
1134  ULONG_PTR CurrentOffset;
1135 
1136  /* Get the buffer we got from whoever called NTDLL */
1137  ClientCaptureBuffer = ApiMessage->CsrCaptureData;
1138 
1139  /* Use SEH to validate and capture the client buffer */
1140  _SEH2_TRY
1141  {
1142  /* Check whether at least the buffer's header is inside our mapped section */
1143  if ( ((ULONG_PTR)ClientCaptureBuffer < CsrProcess->ClientViewBase) ||
1144  (((ULONG_PTR)ClientCaptureBuffer + FIELD_OFFSET(CSR_CAPTURE_BUFFER, PointerOffsetsArray))
1145  >= CsrProcess->ClientViewBounds) )
1146  {
1147 #ifdef CSR_DBG
1148  DPRINT1("*** CSRSS: CaptureBuffer outside of ClientView 1\n");
1149  if (NtCurrentPeb()->BeingDebugged) DbgBreakPoint();
1150 #endif
1151  /* Return failure */
1152  ApiMessage->Status = STATUS_INVALID_PARAMETER;
1153  _SEH2_YIELD(return FALSE);
1154  }
1155 
1156  /* Capture the buffer length */
1157  Length = ((volatile CSR_CAPTURE_BUFFER*)ClientCaptureBuffer)->Size;
1158 
1159  /*
1160  * Now check if the remaining of the buffer is inside our mapped section.
1161  * Take also care for any possible wrap-around of the buffer end-address.
1162  */
1163  EndOfClientBuffer = (ULONG_PTR)ClientCaptureBuffer + Length;
1164  if ( (EndOfClientBuffer < (ULONG_PTR)ClientCaptureBuffer) ||
1165  (EndOfClientBuffer >= CsrProcess->ClientViewBounds) )
1166  {
1167 #ifdef CSR_DBG
1168  DPRINT1("*** CSRSS: CaptureBuffer outside of ClientView 2\n");
1169  if (NtCurrentPeb()->BeingDebugged) DbgBreakPoint();
1170 #endif
1171  /* Return failure */
1172  ApiMessage->Status = STATUS_INVALID_PARAMETER;
1173  _SEH2_YIELD(return FALSE);
1174  }
1175 
1176  /* Capture the pointer count */
1177  PointerCount = ((volatile CSR_CAPTURE_BUFFER*)ClientCaptureBuffer)->PointerCount;
1178 
1179  /*
1180  * Check whether the total buffer size and the pointer count are consistent
1181  * -- the array of offsets must be contained inside the buffer.
1182  */
1183  SizeOfBufferThroughOffsetsArray =
1184  FIELD_OFFSET(CSR_CAPTURE_BUFFER, PointerOffsetsArray) +
1185  (PointerCount * sizeof(PVOID));
1186  if ( (PointerCount > MAXUSHORT) ||
1187  (SizeOfBufferThroughOffsetsArray > Length) )
1188  {
1189 #ifdef CSR_DBG
1190  DPRINT1("*** CSRSS: CaptureBuffer %p has bad length\n", ClientCaptureBuffer);
1191  if (NtCurrentPeb()->BeingDebugged) DbgBreakPoint();
1192 #endif
1193  /* Return failure */
1194  ApiMessage->Status = STATUS_INVALID_PARAMETER;
1195  _SEH2_YIELD(return FALSE);
1196  }
1197  }
1199  {
1200 #ifdef CSR_DBG
1201  DPRINT1("*** CSRSS: Took exception during capture %x\n", _SEH2_GetExceptionCode());
1202  if (NtCurrentPeb()->BeingDebugged) DbgBreakPoint();
1203 #endif
1204  /* Return failure */
1205  ApiMessage->Status = STATUS_INVALID_PARAMETER;
1206  _SEH2_YIELD(return FALSE);
1207  }
1208  _SEH2_END;
1209 
1210  /* We validated the client buffer, now allocate the server buffer */
1211  ServerCaptureBuffer = RtlAllocateHeap(CsrHeap, HEAP_ZERO_MEMORY, Length);
1212  if (!ServerCaptureBuffer)
1213  {
1214  /* We're out of memory */
1215  ApiMessage->Status = STATUS_NO_MEMORY;
1216  return FALSE;
1217  }
1218 
1219  /*
1220  * Copy the client's buffer and ensure we use the correct buffer length
1221  * and pointer count we captured and used for validation earlier on.
1222  */
1223  _SEH2_TRY
1224  {
1225  RtlMoveMemory(ServerCaptureBuffer, ClientCaptureBuffer, Length);
1226  }
1228  {
1229 #ifdef CSR_DBG
1230  DPRINT1("*** CSRSS: Took exception during capture %x\n", _SEH2_GetExceptionCode());
1231  if (NtCurrentPeb()->BeingDebugged) DbgBreakPoint();
1232 #endif
1233  /* Failure, free the buffer and return */
1234  RtlFreeHeap(CsrHeap, 0, ServerCaptureBuffer);
1235  ApiMessage->Status = STATUS_INVALID_PARAMETER;
1236  _SEH2_YIELD(return FALSE);
1237  }
1238  _SEH2_END;
1239 
1240  ServerCaptureBuffer->Size = Length;
1241  ServerCaptureBuffer->PointerCount = PointerCount;
1242 
1243  /* Calculate the difference between our buffer and the client's */
1244  BufferDistance = (ULONG_PTR)ServerCaptureBuffer - (ULONG_PTR)ClientCaptureBuffer;
1245 
1246  /*
1247  * All the pointer offsets correspond to pointers that point
1248  * to the server data buffer instead of the client one.
1249  */
1250  // PointerCount = ServerCaptureBuffer->PointerCount;
1251  OffsetPointer = ServerCaptureBuffer->PointerOffsetsArray;
1252  while (PointerCount--)
1253  {
1254  CurrentOffset = *OffsetPointer;
1255 
1256  if (CurrentOffset != 0)
1257  {
1258  /*
1259  * Check whether the offset is pointer-aligned and whether
1260  * it points inside CSR_API_MESSAGE::Data.ApiMessageData.
1261  */
1262  if ( ((CurrentOffset & (sizeof(PVOID)-1)) != 0) ||
1263  (CurrentOffset < FIELD_OFFSET(CSR_API_MESSAGE, Data.ApiMessageData)) ||
1264  (CurrentOffset >= sizeof(CSR_API_MESSAGE)) )
1265  {
1266 #ifdef CSR_DBG
1267  DPRINT1("*** CSRSS: CaptureBuffer MessagePointer outside of message\n");
1268  if (NtCurrentPeb()->BeingDebugged) DbgBreakPoint();
1269 #endif
1270  /* Invalid pointer, fail */
1271  ApiMessage->Status = STATUS_INVALID_PARAMETER;
1272  break;
1273  }
1274 
1275  /* Get the pointer corresponding to the offset */
1276  CurrentOffset += (ULONG_PTR)ApiMessage;
1277 
1278  /* Validate the bounds of the current pointed pointer */
1279  if ( (*(PULONG_PTR)CurrentOffset >= ((ULONG_PTR)ClientCaptureBuffer +
1280  SizeOfBufferThroughOffsetsArray)) &&
1281  (*(PULONG_PTR)CurrentOffset <= (EndOfClientBuffer - sizeof(PVOID))) )
1282  {
1283  /* Modify the pointed pointer to take into account its new position */
1284  *(PULONG_PTR)CurrentOffset += BufferDistance;
1285  }
1286  else
1287  {
1288 #ifdef CSR_DBG
1289  DPRINT1("*** CSRSS: CaptureBuffer MessagePointer outside of ClientView\n");
1290  if (NtCurrentPeb()->BeingDebugged) DbgBreakPoint();
1291 #endif
1292  /* Invalid pointer, fail */
1293  ApiMessage->Status = STATUS_INVALID_PARAMETER;
1294  break;
1295  }
1296  }
1297 
1298  ++OffsetPointer;
1299  }
1300 
1301  /* Check if we got success */
1302  if (ApiMessage->Status != STATUS_SUCCESS)
1303  {
1304  /* Failure, free the buffer and return */
1305  RtlFreeHeap(CsrHeap, 0, ServerCaptureBuffer);
1306  return FALSE;
1307  }
1308  else
1309  {
1310  /* Success, save the previous buffer and use the server capture buffer */
1311  ServerCaptureBuffer->PreviousCaptureBuffer = ClientCaptureBuffer;
1312  ApiMessage->CsrCaptureData = ServerCaptureBuffer;
1313  }
1314 
1315  /* Success */
1316  return TRUE;
1317 }
1318 
1319 /*++
1320  * @name CsrReleaseCapturedArguments
1321  * @implemented NT5.1
1322  *
1323  * The CsrReleaseCapturedArguments routine releases a Capture Buffer
1324  * that was previously captured with CsrCaptureArguments.
1325  *
1326  * @param ApiMessage
1327  * Pointer to the CSR API Message containing the Capture Buffer
1328  * that needs to be released.
1329  *
1330  * @return None.
1331  *
1332  * @remarks None.
1333  *
1334  *--*/
1335 VOID
1336 NTAPI
1338 {
1339  PCSR_CAPTURE_BUFFER ServerCaptureBuffer, ClientCaptureBuffer;
1340  SIZE_T BufferDistance;
1341  ULONG PointerCount;
1342  PULONG_PTR OffsetPointer;
1343  ULONG_PTR CurrentOffset;
1344 
1345  /* Get the server capture buffer */
1346  ServerCaptureBuffer = ApiMessage->CsrCaptureData;
1347 
1348  /* Do not continue if there is no captured buffer */
1349  if (!ServerCaptureBuffer) return;
1350 
1351  /* If there is one, get the corresponding client capture buffer */
1352  ClientCaptureBuffer = ServerCaptureBuffer->PreviousCaptureBuffer;
1353 
1354  /* Free the previous one and use again the client capture buffer */
1355  ServerCaptureBuffer->PreviousCaptureBuffer = NULL;
1356  ApiMessage->CsrCaptureData = ClientCaptureBuffer;
1357 
1358  /* Calculate the difference between our buffer and the client's */
1359  BufferDistance = (ULONG_PTR)ServerCaptureBuffer - (ULONG_PTR)ClientCaptureBuffer;
1360 
1361  /*
1362  * All the pointer offsets correspond to pointers that point
1363  * to the client data buffer instead of the server one (reverse
1364  * the logic of CsrCaptureArguments()).
1365  */
1366  PointerCount = ServerCaptureBuffer->PointerCount;
1367  OffsetPointer = ServerCaptureBuffer->PointerOffsetsArray;
1368  while (PointerCount--)
1369  {
1370  CurrentOffset = *OffsetPointer;
1371 
1372  if (CurrentOffset != 0)
1373  {
1374  /* Get the pointer corresponding to the offset */
1375  CurrentOffset += (ULONG_PTR)ApiMessage;
1376 
1377  /* Modify the pointed pointer to take into account its new position */
1378  *(PULONG_PTR)CurrentOffset -= BufferDistance;
1379  }
1380 
1381  ++OffsetPointer;
1382  }
1383 
1384  /* Copy the data back into the client buffer */
1385  _SEH2_TRY
1386  {
1387  RtlMoveMemory(ClientCaptureBuffer, ServerCaptureBuffer, ServerCaptureBuffer->Size);
1388  }
1390  {
1391 #ifdef CSR_DBG
1392  DPRINT1("*** CSRSS: Took exception during release %x\n", _SEH2_GetExceptionCode());
1393  if (NtCurrentPeb()->BeingDebugged) DbgBreakPoint();
1394 #endif
1395  /* Return failure */
1396  ApiMessage->Status = _SEH2_GetExceptionCode();
1397  }
1398  _SEH2_END;
1399 
1400  /* Free our allocated buffer */
1401  RtlFreeHeap(CsrHeap, 0, ServerCaptureBuffer);
1402 }
1403 
1404 /*++
1405  * @name CsrValidateMessageBuffer
1406  * @implemented NT5.1
1407  *
1408  * The CsrValidateMessageBuffer routine validates a captured message buffer
1409  * present in the CSR Api Message
1410  *
1411  * @param ApiMessage
1412  * Pointer to the CSR API Message containing the CSR Capture Buffer.
1413  *
1414  * @param Buffer
1415  * Pointer to the message buffer to validate.
1416  *
1417  * @param ElementCount
1418  * Number of elements contained in the message buffer.
1419  *
1420  * @param ElementSize
1421  * Size of each element.
1422  *
1423  * @return TRUE if validation succeeded, FALSE otherwise.
1424  *
1425  * @remarks None.
1426  *
1427  *--*/
1428 BOOLEAN
1429 NTAPI
1431  IN PVOID *Buffer,
1432  IN ULONG ElementCount,
1433  IN ULONG ElementSize)
1434 {
1435  PCSR_CAPTURE_BUFFER CaptureBuffer = ApiMessage->CsrCaptureData;
1436  SIZE_T BufferDistance = (ULONG_PTR)Buffer - (ULONG_PTR)ApiMessage;
1437  ULONG PointerCount;
1438  PULONG_PTR OffsetPointer;
1439 
1440  /*
1441  * Check whether we have a valid buffer pointer, elements
1442  * of non-trivial size and that we don't overflow.
1443  */
1444  if (!Buffer || ElementSize == 0 ||
1445  (ULONGLONG)ElementCount * ElementSize > (ULONGLONG)MAXULONG)
1446  {
1447  return FALSE;
1448  }
1449 
1450  /* Check if didn't get a buffer and there aren't any arguments to check */
1451  // if (!*Buffer && (ElementCount * ElementSize == 0))
1452  if (!*Buffer && ElementCount == 0) // Here ElementSize != 0 therefore only ElementCount can be == 0
1453  return TRUE;
1454 
1455  /* Check if we have no capture buffer */
1456  if (!CaptureBuffer)
1457  {
1458  /* In this case, succeed only if the caller is CSRSS */
1459  if (NtCurrentTeb()->ClientId.UniqueProcess ==
1460  ApiMessage->Header.ClientId.UniqueProcess)
1461  {
1462  return TRUE;
1463  }
1464  }
1465  else
1466  {
1467  /* Make sure that there is still space left in the capture buffer */
1468  if ((CaptureBuffer->Size - (ULONG_PTR)*Buffer + (ULONG_PTR)CaptureBuffer) >=
1469  (ElementCount * ElementSize))
1470  {
1471  /* Perform the validation test */
1472  PointerCount = CaptureBuffer->PointerCount;
1473  OffsetPointer = CaptureBuffer->PointerOffsetsArray;
1474  while (PointerCount--)
1475  {
1476  /*
1477  * Find in the array, the pointer offset (from the
1478  * API message) that corresponds to the buffer.
1479  */
1480  if (*OffsetPointer == BufferDistance)
1481  {
1482  return TRUE;
1483  }
1484  ++OffsetPointer;
1485  }
1486  }
1487  }
1488 
1489  /* Failure */
1490 #ifdef CSR_DBG
1491  DPRINT1("CSRSRV: Bad message buffer %p\n", ApiMessage);
1492  if (NtCurrentPeb()->BeingDebugged) DbgBreakPoint();
1493 #endif
1494  return FALSE;
1495 }
1496 
1497 /*++
1498  * @name CsrValidateMessageString
1499  * @implemented NT5.1
1500  *
1501  * The CsrValidateMessageString validates a captured Wide-Character String
1502  * present in a CSR API Message.
1503  *
1504  * @param ApiMessage
1505  * Pointer to the CSR API Message containing the CSR Capture Buffer.
1506  *
1507  * @param MessageString
1508  * Pointer to the buffer containing the string to validate.
1509  *
1510  * @return TRUE if validation succeeded, FALSE otherwise.
1511  *
1512  * @remarks None.
1513  *
1514  *--*/
1515 BOOLEAN
1516 NTAPI
1518  IN PWSTR *MessageString)
1519 {
1520  if (MessageString)
1521  {
1522  return CsrValidateMessageBuffer(ApiMessage,
1523  (PVOID*)MessageString,
1524  wcslen(*MessageString) + 1,
1525  sizeof(WCHAR));
1526  }
1527  else
1528  {
1529  return FALSE;
1530  }
1531 }
1532 
1533 /* EOF */
ULONG HighestApiSupported
Definition: csrsrv.h:223
VOID NTAPI CsrLockedReferenceThread(IN PCSR_THREAD CsrThread)
Definition: thredsup.c:154
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
#define IN
Definition: typedefs.h:39
ULONG Win32ClientInfo[31]
Definition: compat.h:706
ULONG Response
Definition: extypes.h:670
NTSTATUS NTAPI LdrGetDllHandle(IN PWSTR DllPath OPTIONAL, IN PULONG DllCharacteristics OPTIONAL, IN PUNICODE_STRING DllName, OUT PVOID *DllHandle)
Definition: ldrapi.c:805
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
BOOLEAN NTAPI CsrCaptureArguments(IN PCSR_THREAD CsrThread, IN PCSR_API_MESSAGE ApiMessage)
Definition: api.c:1123
USHORT MaximumLength
Definition: env_spec_w32.h:370
LARGE_INTEGER CreateTime
Definition: lpctypes.h:270
#define TRUE
Definition: types.h:120
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
uint16_t * PWSTR
Definition: typedefs.h:56
NTSTATUS ReturnedStatus
Definition: dbgktypes.h:210
PVOID CsrClientThread
Definition: compat.h:704
_Must_inspect_result_ _Outptr_ PFLT_PORT * ServerPort
Definition: fltkernel.h:1872
BOOLEAN(* CsrClientThreadSetup)(VOID)
Definition: api.c:21
LONG NTSTATUS
Definition: precomp.h:26
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:606
#define NtCurrentThread()
NTSTATUS NTAPI NtCreateEvent(OUT PHANDLE EventHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN EVENT_TYPE EventType, IN BOOLEAN InitialState)
Definition: event.c:96
ULONG CsrDebug
Definition: init.c:23
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
NTSTATUS NTAPI CsrDestroyProcess(IN PCLIENT_ID Cid, IN NTSTATUS ExitStatus)
Definition: procsup.c:735
#define CSR_PORT_NAME
Definition: csrmsg.h:17
ANSI_STRING Name
Definition: csrsrv.h:218
PKPROCESS CsrProcess
Definition: videoprt.c:39
VOID NTAPI CsrDereferenceThread(IN PCSR_THREAD CsrThread)
Definition: thredsup.c:776
PCSR_CAPTURE_BUFFER CsrCaptureData
Definition: csrmsg.h:110
_In_ PVOID Parameter
Definition: ldrtypes.h:241
HANDLE UniqueProcess
Definition: compat.h:684
void DbgBreakPoint()
Definition: mach.c:553
#define CSR_SERVER_DLL_MAX
Definition: api.h:34
#define CsrReleaseProcessLock()
Definition: api.h:15
PCSR_THREAD NTAPI CsrConnectToUser(VOID)
Definition: api.c:1021
static int Link(const char **args)
Definition: vfdcmd.c:2414
#define DBG_CONTINUE
Definition: ntstatus.h:47
#define STATUS_INVALID_HANDLE
Definition: ntstatus.h:245
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264
_SEH2_TRY
Definition: create.c:4226
NTSTATUS NTAPI NtReplyPort(IN HANDLE PortHandle, IN PPORT_MESSAGE ReplyMessage)
Definition: reply.c:190
NTSYSAPI VOID NTAPI RtlInitAnsiString(PANSI_STRING DestinationString, PCSZ SourceString)
uint32_t ULONG_PTR
Definition: typedefs.h:65
CLIENT_ID ClientId
Definition: compat.h:698
PCSR_PROCESS CsrRootProcess
Definition: procsup.c:22
EXCEPTION_DISPOSITION NTAPI CsrUnhandledExceptionFilter(IN PEXCEPTION_POINTERS ExceptionInfo)
Definition: server.c:622
PCSR_PROCESS Process
Definition: csrsrv.h:69
struct _CLIENT_DIED_MSG * PCLIENT_DIED_MSG
NTSTATUS NTAPI CsrApiHandleConnectionRequest(IN PCSR_API_MESSAGE ApiMessage)
Definition: api.c:144
NTSTATUS Status
Definition: csrmsg.h:112
PCSR_THREAD NTAPI CsrAddStaticServerThread(IN HANDLE hThread, IN PCLIENT_ID ClientId, IN ULONG ThreadFlags)
Definition: thredsup.c:512
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
HANDLE ServerProcessId
Definition: csrmsg.h:57
#define FALSE
Definition: types.h:117
VOID NTAPI CsrReleaseCapturedArguments(IN PCSR_API_MESSAGE ApiMessage)
Definition: api.c:1337
#define STATUS_INVALID_CID
Definition: ntstatus.h:248
#define EVENT_ALL_ACCESS
Definition: isotest.c:82
ULONG CountOfOwnedCriticalSections
Definition: compat.h:703
VOID NTAPI CsrLockedDereferenceThread(IN PCSR_THREAD CsrThread)
Definition: thredsup.c:467
#define _SEH2_GetExceptionInformation()
Definition: pseh2_64.h:164
NTSTATUS NTAPI LdrGetProcedureAddress(IN PVOID BaseAddress, IN PANSI_STRING Name, IN ULONG Ordinal, OUT PVOID *ProcedureAddress)
Definition: ldrapi.c:823
NTSTATUS NTAPI CsrCallServerFromServer(IN PCSR_API_MESSAGE ReceiveMsg, IN OUT PCSR_API_MESSAGE ReplyMsg)
Definition: api.c:51
unsigned char BOOLEAN
UINT CALLBACK ServerThread(_Inout_ PVOID Parameter)
struct _REMOTE_PORT_VIEW REMOTE_PORT_VIEW
BOOLEAN NTAPI CsrValidateMessageBuffer(IN PCSR_API_MESSAGE ApiMessage, IN PVOID *Buffer, IN ULONG ElementCount, IN ULONG ElementSize)
Definition: api.c:1430
Definition: bufpool.h:45
CSR_API_NUMBER ApiNumber
Definition: csrmsg.h:111
void * PVOID
Definition: retypes.h:9
HANDLE NTAPI CsrQueryApiPort(VOID)
Definition: api.c:1097
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
#define UlongToPtr(u)
Definition: config.h:106
NTSTATUS NTAPI NtDelayExecution(IN BOOLEAN Alertable, IN PLARGE_INTEGER DelayInterval)
Definition: wait.c:876
#define NtCurrentProcess()
Definition: nt_native.h:1657
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:588
NTSTATUS NTAPI CsrSrvAttachSharedSection(IN PCSR_PROCESS CsrProcess OPTIONAL, OUT PCSR_API_CONNECTINFO ConnectInfo)
Definition: server.c:472
Status
Definition: gdiplustypes.h:24
NTSTATUS RtlAppendUnicodeToString(IN PUNICODE_STRING Str1, IN PWSTR Str2)
Definition: string_lib.cpp:62
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
NTSTATUS NtTerminateThread(IN HANDLE ThreadHandle OPTIONAL, IN NTSTATUS ExitStatus)
Definition: kill.c:1278
NTSTATUS NTAPI NtResumeThread(IN HANDLE ThreadHandle, OUT PULONG SuspendCount OPTIONAL)
Definition: state.c:290
NTSTATUS NTAPI NtAcceptConnectPort(OUT PHANDLE PortHandle, IN PVOID PortContext OPTIONAL, IN PPORT_MESSAGE ReplyMessage, IN BOOLEAN AcceptConnection, IN OUT PPORT_VIEW ServerView OPTIONAL, OUT PREMOTE_PORT_VIEW ClientView OPTIONAL)
Definition: complete.c:40
_Out_ PCLIENT_ID ClientId
Definition: kefuncs.h:1163
NTSTATUS NTAPI NtCreatePort(OUT PHANDLE PortHandle, IN POBJECT_ATTRIBUTES ObjectAttributes, IN ULONG MaxConnectInfoLength, IN ULONG MaxDataLength, IN ULONG MaxPoolUsage)
Definition: create.c:212
NTSTATUS NTAPI NtSetEvent(IN HANDLE EventHandle, OUT PLONG PreviousState OPTIONAL)
Definition: event.c:455
#define ASSERT(a)
Definition: mode.c:44
LARGE_INTEGER CreateTime
Definition: csrsrv.h:65
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
CLIENT_ID ClientId
Definition: csrsrv.h:68
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
uint64_t ULONGLONG
Definition: typedefs.h:67
ULONG CsrMaxApiRequestThreads
Definition: init.c:34
CLIENT_ID RealClientId
Definition: compat.h:720
struct _CSR_CAPTURE_BUFFER * PreviousCaptureBuffer
Definition: csrmsg.h:95
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
#define CSR_API_NUMBER_TO_SERVER_ID(ApiNumber)
Definition: csrmsg.h:40
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3398
HANDLE UniqueThread
Definition: compat.h:685
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
PCSR_HARDERROR_CALLBACK HardErrorCallback
Definition: csrsrv.h:237
std::wstring STRING
Definition: fontsub.cpp:33
#define CsrAcquireProcessLock()
Definition: api.h:12
NTSTATUS NTAPI NtReplyWaitReceivePort(IN HANDLE PortHandle, OUT PVOID *PortContext OPTIONAL, IN PPORT_MESSAGE ReplyMessage OPTIONAL, OUT PPORT_MESSAGE ReceiveMessage)
Definition: reply.c:743
#define CSR_API_NUMBER_TO_API_ID(ApiNumber)
Definition: csrmsg.h:43
NTSTATUS NTAPI CsrDestroyThread(IN PCLIENT_ID Cid)
Definition: thredsup.c:814
NTSTATUS NTAPI CsrApiRequestThread(IN PVOID Parameter)
Definition: api.c:336
#define VOID
Definition: acefi.h:82
#define InterlockedDecrementUL(Addend)
Definition: ex.h:1522
#define PAGE_SIZE
Definition: env_spec_w32.h:49
Definition: typedefs.h:119
UNICODE_STRING CsrDirectoryName
Definition: init.c:27
volatile ULONG CsrpStaticThreadCount
Definition: api.c:23
NTSYSAPI NTSTATUS NTAPI RtlCreateUserThread(_In_ PVOID ThreadContext, _Out_ HANDLE *OutThreadHandle, _Reserved_ PVOID Reserved1, _Reserved_ PVOID Reserved2, _Reserved_ PVOID Reserved3, _Reserved_ PVOID Reserved4, _Reserved_ PVOID Reserved5, _Reserved_ PVOID Reserved6, _Reserved_ PVOID Reserved7, _Reserved_ PVOID Reserved8)
PCSR_THREAD NTAPI CsrLocateThreadByClientId(OUT PCSR_PROCESS *Process OPTIONAL, IN PCLIENT_ID ClientId)
Definition: thredsup.c:182
PCSR_THREAD NTAPI CsrLocateThreadInProcess(IN PCSR_PROCESS CsrProcess OPTIONAL, IN PCLIENT_ID Cid)
Definition: thredsup.c:248
HANDLE CsrApiPort
Definition: connect.c:21
ULONG ApiBase
Definition: csrsrv.h:222
#define MAXULONG
Definition: typedefs.h:251
ULONG PointerCount
Definition: csrmsg.h:96
ULONG_PTR SIZE_T
Definition: typedefs.h:80
Definition: compat.h:694
HANDLE ClientPort
Definition: csrsrv.h:43
_SEH2_END
Definition: create.c:4400
FORCEINLINE struct _TEB * NtCurrentTeb(VOID)
Definition: psfuncs.h:420
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
struct _HARDERROR_MSG * PHARDERROR_MSG
#define NtCurrentPeb()
Definition: FLS.c:22
#define STATUS_ACCESS_VIOLATION
Definition: ntstatus.h:242
unsigned short USHORT
Definition: pedump.c:61
LIST_ENTRY ThreadList
Definition: csrsrv.h:40
NTSYSAPI NTSTATUS NTAPI RtlAnsiStringToUnicodeString(PUNICODE_STRING DestinationString, PANSI_STRING SourceString, BOOLEAN AllocateDestinationString)
#define InterlockedIncrementUL(Addend)
Definition: ex.h:1525
#define UNICODE_PATH_SEP
Definition: connect.c:33
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
NTSYSAPI NTSTATUS NTAPI RtlAppendUnicodeStringToString(PUNICODE_STRING Destination, PUNICODE_STRING Source)
struct _DBGKM_MSG * PDBGKM_MSG
volatile ULONG CsrpDynamicThreadTotal
Definition: api.c:24
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
enum _CSR_REPLY_CODE CSR_REPLY_CODE
#define NULL
Definition: types.h:112
CLIENT_ID ClientId
Definition: winternl.h:1751
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
HANDLE hThread
Definition: wizard.c:28
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define MAXUSHORT
Definition: typedefs.h:83
#define DPRINT1
Definition: precomp.h:8
PCSR_API_ROUTINE * DispatchTable
Definition: csrsrv.h:224
UNICODE_STRING CsrApiPortName
Definition: api.c:22
#define BOOLEAN
Definition: pedump.c:73
#define OUT
Definition: typedefs.h:40
NTSTATUS NTAPI NtCompleteConnectPort(IN HANDLE PortHandle)
Definition: complete.c:421
unsigned int ULONG
Definition: retypes.h:1
NTSTATUS NTAPI CsrpCheckRequestThreads(VOID)
Definition: api.c:259
NTSTATUS NTAPI CsrApiPortInitialize(VOID)
Definition: api.c:900
NTSTATUS NTAPI NtTerminateProcess(HANDLE ProcessHandle, LONG ExitStatus)
#define ULONG_PTR
Definition: config.h:101
uint32_t * PULONG_PTR
Definition: typedefs.h:65
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
VOID NTAPI CsrLockedReferenceProcess(IN PCSR_PROCESS CsrProcess)
Definition: procsup.c:233
BOOLEAN NTAPI CsrValidateMessageString(IN PCSR_API_MESSAGE ApiMessage, IN PWSTR *MessageString)
Definition: api.c:1517
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:40
#define STATUS_SUCCESS
Definition: shellext.h:65
HANDLE CsrHeap
Definition: init.c:25
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:165
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:168
PORT_MESSAGE Header
Definition: csrmsg.h:104
#define STATUS_ILLEGAL_FUNCTION
Definition: ntstatus.h:411
#define STATUS_ABANDONED
Definition: ntstatus.h:75
VOID NTAPI CsrLockedDereferenceProcess(PCSR_PROCESS CsrProcess)
Definition: procsup.c:159
ULONG_PTR PointerOffsetsArray[ANYSIZE_ARRAY]
Definition: csrmsg.h:98
PBOOLEAN ValidTable
Definition: csrsrv.h:225
PCSR_SERVER_DLL CsrLoadedServerDll[CSR_SERVER_DLL_MAX]
Definition: server.c:20
LONGLONG QuadPart
Definition: typedefs.h:114
NTSYSAPI NTSTATUS NTAPI NtWaitForSingleObject(IN HANDLE hObject, IN BOOLEAN bAlertable, IN PLARGE_INTEGER Timeout)