xref: /reactos/win32ss/user/ntuser/csr.c (revision cc439606)
1 /*
2  * COPYRIGHT:        See COPYING in the top level directory
3  * PROJECT:          ReactOS Win32k subsystem
4  * PURPOSE:          Interface between Win32k and USERSRV
5  * FILE:             win32ss/user/ntuser/csr.c
6  * PROGRAMMER:       Hermes Belusca-Maito (hermes.belusca@sfr.fr), based on
7  *                   the original code by Ge van Geldorp (ge@gse.nl) and by
8  *                   the CSR code in NTDLL.
9  */
10 
11 #include <win32k.h>
12 
13 DBG_DEFAULT_CHANNEL(UserCsr);
14 
15 PEPROCESS gpepCSRSS = NULL;
16 PVOID CsrApiPort = NULL;
17 
18 VOID
19 InitCsrProcess(VOID /*IN PEPROCESS CsrProcess*/)
20 {
21     /* Save the EPROCESS of CSRSS */
22     gpepCSRSS = PsGetCurrentProcess();
23     // gpepCSRSS = CsrProcess;
24     ObReferenceObject(gpepCSRSS);
25 }
26 
27 VOID
28 ResetCsrProcess(VOID)
29 {
30     if (gpepCSRSS)
31         ObDereferenceObject(gpepCSRSS);
32 
33     gpepCSRSS = NULL;
34 }
35 
36 NTSTATUS
37 InitCsrApiPort(IN HANDLE CsrPortHandle)
38 {
39     NTSTATUS Status;
40 
41     Status = ObReferenceObjectByHandle(CsrPortHandle,
42                                        0,
43                                        /* * */LpcPortObjectType, // or NULL,
44                                        UserMode,
45                                        &CsrApiPort,
46                                        NULL);
47     if (!NT_SUCCESS(Status))
48     {
49         CsrApiPort = NULL;
50         ERR("Failed to set CSR API Port.\n");
51     }
52 
53     return Status;
54 }
55 
56 VOID
57 ResetCsrApiPort(VOID)
58 {
59     if (CsrApiPort)
60         ObDereferenceObject(CsrApiPort);
61 
62     CsrApiPort = NULL;
63 }
64 
65 /*
66  * Function copied from ntdll/csr/connect.c::CsrClientCallServer
67  * and adapted for kernel-mode.
68  *
69  * NOTE: This is really a co_* function!
70  */
71 NTSTATUS
72 NTAPI
73 CsrClientCallServer(IN OUT PCSR_API_MESSAGE ApiMessage,
74                     IN OUT PCSR_CAPTURE_BUFFER CaptureBuffer OPTIONAL,
75                     IN CSR_API_NUMBER ApiNumber,
76                     IN ULONG DataLength)
77 {
78     NTSTATUS Status;
79 #if 0
80     ULONG PointerCount;
81     PULONG_PTR OffsetPointer;
82 #endif
83 
84     /* Do we have a connection to CSR yet? */
85     if (!CsrApiPort)
86         return STATUS_INVALID_PORT_HANDLE;
87 
88     /* Fill out the Port Message Header */
89     ApiMessage->Header.u2.ZeroInit = 0;
90     ApiMessage->Header.u1.s1.TotalLength = FIELD_OFFSET(CSR_API_MESSAGE, Data) + DataLength;
91     ApiMessage->Header.u1.s1.DataLength = ApiMessage->Header.u1.s1.TotalLength -
92         sizeof(ApiMessage->Header);
93 
94     /* Fill out the CSR Header */
95     ApiMessage->ApiNumber = ApiNumber;
96     ApiMessage->CsrCaptureData = NULL;
97 
98     TRACE("API: %lx, u1.s1.DataLength: %x, u1.s1.TotalLength: %x\n",
99           ApiNumber,
100           ApiMessage->Header.u1.s1.DataLength,
101           ApiMessage->Header.u1.s1.TotalLength);
102 
103 #if 0
104     /* Check if we got a Capture Buffer */
105     if (CaptureBuffer)
106     {
107         /*
108          * We have to convert from our local (client) view
109          * to the remote (server) view.
110          */
111         ApiMessage->CsrCaptureData = (PCSR_CAPTURE_BUFFER)
112             ((ULONG_PTR)CaptureBuffer + CsrPortMemoryDelta);
113 
114         /* Lock the buffer. */
115         CaptureBuffer->BufferEnd = NULL;
116 
117         /*
118          * Each client pointer inside the CSR message is converted into
119          * a server pointer, and each pointer to these message pointers
120          * is converted into an offset.
121          */
122         PointerCount  = CaptureBuffer->PointerCount;
123         OffsetPointer = CaptureBuffer->PointerOffsetsArray;
124         while (PointerCount--)
125         {
126             if (*OffsetPointer != 0)
127             {
128                 *(PULONG_PTR)*OffsetPointer += CsrPortMemoryDelta;
129                 *OffsetPointer -= (ULONG_PTR)ApiMessage;
130             }
131             ++OffsetPointer;
132         }
133     }
134 #endif
135 
136     UserLeaveCo();
137 
138     /* Send the LPC Message */
139 
140     // The wait logic below is subject to change in the future. One can
141     // imagine adding an external parameter to CsrClientCallServer, or write
142     // two versions of CsrClientCallServer, synchronous and asynchronous.
143     if (PsGetCurrentProcess() == gpepCSRSS)
144     {
145         Status = LpcRequestPort(CsrApiPort,
146                                 &ApiMessage->Header);
147     }
148     else
149     {
150         Status = LpcRequestWaitReplyPort(CsrApiPort,
151                                          &ApiMessage->Header,
152                                          &ApiMessage->Header);
153     }
154 
155     UserEnterCo();
156 
157 #if 0
158     /* Check if we got a Capture Buffer */
159     if (CaptureBuffer)
160     {
161         /*
162          * We have to convert back from the remote (server) view
163          * to our local (client) view.
164          */
165         ApiMessage->CsrCaptureData = (PCSR_CAPTURE_BUFFER)
166             ((ULONG_PTR)ApiMessage->CsrCaptureData - CsrPortMemoryDelta);
167 
168         /*
169          * Convert back the offsets into pointers to CSR message
170          * pointers, and convert back these message server pointers
171          * into client pointers.
172          */
173         PointerCount  = CaptureBuffer->PointerCount;
174         OffsetPointer = CaptureBuffer->PointerOffsetsArray;
175         while (PointerCount--)
176         {
177             if (*OffsetPointer != 0)
178             {
179                 *OffsetPointer += (ULONG_PTR)ApiMessage;
180                 *(PULONG_PTR)*OffsetPointer -= CsrPortMemoryDelta;
181             }
182             ++OffsetPointer;
183         }
184     }
185 #endif
186 
187     /* Check for success */
188     if (!NT_SUCCESS(Status))
189     {
190         /* We failed. Overwrite the return value with the failure. */
191         ERR("LPC Failed: %lx\n", Status);
192         ApiMessage->Status = Status;
193     }
194 
195     /* Return the CSR Result */
196     TRACE("Got back: 0x%lx\n", ApiMessage->Status);
197     return ApiMessage->Status;
198 }
199 
200 /* EOF */
201