ReactOS 0.4.15-dev-5875-g7c755d9
complete.c File Reference
#include <ntoskrnl.h>
#include <debug.h>
Include dependency graph for complete.c:

Go to the source code of this file.

Macros

#define NDEBUG
 

Functions

VOID NTAPI LpcpPrepareToWakeClient (IN PETHREAD Thread)
 
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)
 
NTSTATUS NTAPI NtCompleteConnectPort (IN HANDLE PortHandle)
 

Macro Definition Documentation

◆ NDEBUG

#define NDEBUG

Definition at line 12 of file complete.c.

Function Documentation

◆ LpcpPrepareToWakeClient()

VOID NTAPI LpcpPrepareToWakeClient ( IN PETHREAD  Thread)

Definition at line 19 of file complete.c.

20{
21 PAGED_CODE();
22
23 /* Make sure the thread isn't dying and it has a valid chain */
26 {
27 /* Remove it from the list and reinitialize it */
30 }
31}
#define PAGED_CODE()
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
ULONG LpcExitThreadCalled
Definition: pstypes.h:1215
LIST_ENTRY LpcReplyChain
Definition: pstypes.h:1108

Referenced by NtCompleteConnectPort().

◆ NtAcceptConnectPort()

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 at line 40 of file complete.c.

46{
49 PORT_VIEW CapturedServerView;
50 PORT_MESSAGE CapturedReplyMessage;
51 ULONG ConnectionInfoLength;
53 PLPCP_CONNECTION_MESSAGE ConnectMessage;
55 PVOID ClientSectionToMap = NULL;
57 PEPROCESS ClientProcess;
60
61 PAGED_CODE();
63 "Context: %p. Message: %p. Accept: %lx. Views: %p/%p\n",
64 PortContext,
66 AcceptConnection,
67 ClientView,
68 ServerView);
69
70 /* Check if the call comes from user mode */
72 {
74 {
75 /* Probe the PortHandle */
76 ProbeForWriteHandle(PortHandle);
77
78 /* Probe the basic ReplyMessage structure */
79 ProbeForRead(ReplyMessage, sizeof(*ReplyMessage), sizeof(ULONG));
80 CapturedReplyMessage = *(volatile PORT_MESSAGE*)ReplyMessage;
81 ConnectionInfoLength = CapturedReplyMessage.u1.s1.DataLength;
82
83 /* Probe the connection info */
84 ProbeForRead(ReplyMessage + 1, ConnectionInfoLength, 1);
85
86 /* The following parameters are optional */
87
88 /* Capture the server view */
89 if (ServerView)
90 {
91 ProbeForWrite(ServerView, sizeof(*ServerView), sizeof(ULONG));
92 CapturedServerView = *(volatile PORT_VIEW*)ServerView;
93
94 /* Validate the size of the server view */
95 if (CapturedServerView.Length != sizeof(CapturedServerView))
96 {
97 /* Invalid size */
99 }
100 }
101
102 /* Capture the client view */
103 if (ClientView)
104 {
105 ProbeForWrite(ClientView, sizeof(*ClientView), sizeof(ULONG));
106
107 /* Validate the size of the client view */
108 if (((volatile REMOTE_PORT_VIEW*)ClientView)->Length != sizeof(*ClientView))
109 {
110 /* Invalid size */
112 }
113 }
114 }
116 {
117 /* There was an exception, return the exception code */
119 }
120 _SEH2_END;
121 }
122 else
123 {
124 CapturedReplyMessage = *ReplyMessage;
125 ConnectionInfoLength = CapturedReplyMessage.u1.s1.DataLength;
126
127 /* Capture the server view */
128 if (ServerView)
129 {
130 /* Validate the size of the server view */
131 if (ServerView->Length != sizeof(*ServerView))
132 {
133 /* Invalid size */
135 }
136 CapturedServerView = *ServerView;
137 }
138
139 /* Capture the client view */
140 if (ClientView)
141 {
142 /* Validate the size of the client view */
143 if (ClientView->Length != sizeof(*ClientView))
144 {
145 /* Invalid size */
147 }
148 }
149 }
150
151 /* Get the client process and thread */
152 Status = PsLookupProcessThreadByCid(&CapturedReplyMessage.ClientId,
153 &ClientProcess,
154 &ClientThread);
155 if (!NT_SUCCESS(Status)) return Status;
156
157 /* Acquire the LPC Lock */
159
160 /* Make sure that the client wants a reply, and this is the right one */
162 !(CapturedReplyMessage.MessageId) ||
163 (ClientThread->LpcReplyMessageId != CapturedReplyMessage.MessageId))
164 {
165 /* Not the reply asked for, or no reply wanted, fail */
167 ObDereferenceObject(ClientProcess);
170 }
171
172 /* Now get the message and connection message */
174 ConnectMessage = (PLPCP_CONNECTION_MESSAGE)(Message + 1);
175
176 /* Get the client and connection port as well */
177 ClientPort = ConnectMessage->ClientPort;
178 ConnectionPort = ClientPort->ConnectionPort;
179
180 /* Make sure that the reply is being sent to the proper server process */
181 if (ConnectionPort->ServerProcess != PsGetCurrentProcess())
182 {
183 /* It's not, so fail */
185 ObDereferenceObject(ClientProcess);
188 }
189
190 /* At this point, don't let other accept attempts happen */
191 ClientThread->LpcReplyMessage = NULL;
192 ClientThread->LpcReplyMessageId = 0;
193
194 /* Clear the client port for now as well, then release the lock */
195 ConnectMessage->ClientPort = NULL;
197
198 /* Check the connection information length */
199 if (ConnectionInfoLength > ConnectionPort->MaxConnectionInfoLength)
200 {
201 /* Normalize it since it's too large */
202 ConnectionInfoLength = ConnectionPort->MaxConnectionInfoLength;
203 }
204
205 /* Set the sizes of our reply message */
206 Message->Request.u1.s1.DataLength = (CSHORT)ConnectionInfoLength +
208 Message->Request.u1.s1.TotalLength = sizeof(LPCP_MESSAGE) +
209 Message->Request.u1.s1.DataLength;
210
211 /* Setup the reply message */
212 Message->Request.u2.s2.Type = LPC_REPLY;
213 Message->Request.u2.s2.DataInfoOffset = 0;
214 Message->Request.ClientId = CapturedReplyMessage.ClientId;
215 Message->Request.MessageId = CapturedReplyMessage.MessageId;
216 Message->Request.ClientViewSize = 0;
217
219 {
220 RtlCopyMemory(ConnectMessage + 1, ReplyMessage + 1, ConnectionInfoLength);
221 }
223 {
225 _SEH2_YIELD(goto Cleanup);
226 }
227 _SEH2_END;
228
229 /* At this point, if the caller refused the connection, go to cleanup */
230 if (!AcceptConnection)
231 {
232 DPRINT1("LPC connection was refused\n");
233 goto Cleanup;
234 }
235
236 /* Otherwise, create the actual port */
239 NULL,
241 NULL,
242 sizeof(LPCP_PORT_OBJECT),
243 0,
244 0,
245 (PVOID*)&ServerPort);
246 if (!NT_SUCCESS(Status)) goto Cleanup;
247
248 /* Set it up */
250 ServerPort->PortContext = PortContext;
252 ServerPort->MaxMessageLength = ConnectionPort->MaxMessageLength;
253 InitializeListHead(&ServerPort->LpcReplyChainHead);
254 InitializeListHead(&ServerPort->LpcDataInfoChainHead);
255
256 /* Reference the connection port until we're fully setup */
257 ObReferenceObject(ConnectionPort);
258
259 /* Link the ports together */
260 ServerPort->ConnectionPort = ConnectionPort;
261 ServerPort->ConnectedPort = ClientPort;
262 ClientPort->ConnectedPort = ServerPort;
263
264 /* Also set the creator CID */
265 ServerPort->Creator = PsGetCurrentThread()->Cid;
266 ClientPort->Creator = Message->Request.ClientId;
267
268 /* Get the section associated and then clear it, while inside the lock */
270 ClientSectionToMap = ConnectMessage->SectionToMap;
271 ConnectMessage->SectionToMap = NULL;
273
274 /* Now check if there's a client section */
275 if (ClientSectionToMap)
276 {
277 /* Setup the offset */
278 SectionOffset.QuadPart = ConnectMessage->ClientView.SectionOffset;
279
280 /* Map the section */
281 Status = MmMapViewOfSection(ClientSectionToMap,
283 &ServerPort->ClientSectionBase,
284 0,
285 0,
287 &ConnectMessage->ClientView.ViewSize,
288 ViewUnmap,
289 0,
291
292 /* Update the offset and check for mapping status */
293 ConnectMessage->ClientView.SectionOffset = SectionOffset.LowPart;
294 if (NT_SUCCESS(Status))
295 {
296 /* Set the view base */
297 ConnectMessage->ClientView.ViewRemoteBase = ServerPort->
298 ClientSectionBase;
299
300 /* Save and reference the mapping process */
301 ServerPort->MappingProcess = PsGetCurrentProcess();
302 ObReferenceObject(ServerPort->MappingProcess);
303 }
304 else
305 {
306 /* Otherwise, quit */
308 DPRINT1("Client section mapping failed: %lx\n", Status);
309 DPRINT1("View base, offset, size: %p %lx %p\n",
310 ServerPort->ClientSectionBase,
311 ConnectMessage->ClientView.ViewSize,
313 goto Cleanup;
314 }
315 }
316
317 /* Check if there's a server section */
318 if (ServerView)
319 {
320 /* FIXME: TODO */
321 UNREFERENCED_PARAMETER(CapturedServerView);
322 ASSERT(FALSE);
323 }
324
325 /* Reference the server port until it's fully inserted */
327
328 /* Insert the server port in the namespace */
330 NULL,
332 0,
333 NULL,
334 &Handle);
335 if (!NT_SUCCESS(Status))
336 {
337 /* We failed, remove the extra reference and cleanup */
339 goto Cleanup;
340 }
341
342 /* Enter SEH to write back the results */
344 {
345 /* Check if the caller gave a client view */
346 if (ClientView)
347 {
348 /* Fill it out */
349 ClientView->ViewBase = ConnectMessage->ClientView.ViewRemoteBase;
350 ClientView->ViewSize = ConnectMessage->ClientView.ViewSize;
351 }
352
353 /* Return the handle to user mode */
354 *PortHandle = Handle;
355 }
357 {
358 /* Cleanup and return the exception code */
362 _SEH2_YIELD(goto Cleanup);
363 }
364 _SEH2_END;
365
367 "Handle: %p. Messages: %p/%p. Ports: %p/%p/%p\n",
368 Handle,
369 Message,
370 ConnectMessage,
373 ConnectionPort);
374
375 /* If there was no port context, use the handle by default */
376 if (!PortContext) ServerPort->PortContext = Handle;
377 ServerPort->ClientThread = ClientThread;
378
379 /* Set this message as the LPC Reply message while holding the lock */
381 ClientThread->LpcReplyMessage = Message;
383
384 /* Clear the thread pointer so it doesn't get cleaned later */
386
387 /* Remove the extra reference we had added */
389
390Cleanup:
391 /* If there was a section, dereference it */
392 if (ClientSectionToMap) ObDereferenceObject(ClientSectionToMap);
393
394 /* Check if we got here while still having a client thread */
395 if (ClientThread)
396 {
398 ClientThread->LpcReplyMessage = Message;
401 LpcpCompleteWait(&ClientThread->LpcReplySemaphore);
403 }
404
405 /* Dereference the client port if we have one, and the process */
407 "Status: %lx. Thread: %p. Process: [%.16s]\n",
408 Status,
410 ClientProcess->ImageFileName);
412 ObDereferenceObject(ClientProcess);
413 return Status;
414}
static const INTERNET_PORT ServerPort
Definition: CWebService.cpp:11
UINT CALLBACK ClientThread(_Inout_ PVOID Parameter)
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
VOID NTAPI LpcpPrepareToWakeClient(IN PETHREAD Thread)
Definition: complete.c:19
#define NULL
Definition: types.h:112
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
static const WCHAR Message[]
Definition: register.c:74
static const WCHAR Cleanup[]
Definition: register.c:80
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
VOID NTAPI ProbeForWrite(IN PVOID Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:143
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
_Outptr_ PFLT_PORT * ClientPort
Definition: fltkernel.h:1891
ULONG Handle
Definition: gdb_input.c:15
Status
Definition: gdiplustypes.h:25
VOID FASTCALL KeReleaseGuardedMutex(IN OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:53
VOID FASTCALL KeAcquireGuardedMutex(IN PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:42
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
KGUARDED_MUTEX LpcpLock
Definition: port.c:20
POBJECT_TYPE LpcPortObjectType
Definition: port.c:17
#define LPCTRACE(x, fmt,...)
Definition: lpc.h:49
#define LPC_COMPLETE_DEBUG
Definition: lpc.h:22
#define LpcpCompleteWait(s)
Definition: lpc_x.h:88
FORCEINLINE PLPCP_MESSAGE LpcpGetMessageFromThread(IN PETHREAD Thread)
Definition: lpc_x.h:129
#define LPCP_COMMUNICATION_PORT
Definition: lpctypes.h:56
#define PORT_ALL_ACCESS
Definition: lpctypes.h:47
struct _LPCP_MESSAGE LPCP_MESSAGE
struct _LPCP_CONNECTION_MESSAGE * PLPCP_CONNECTION_MESSAGE
#define ASSERT(a)
Definition: mode.c:44
#define LPC_REPLY
Definition: port.c:94
#define KernelMode
Definition: asm.h:34
#define KeGetPreviousMode()
Definition: ketypes.h:1108
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR _In_ SIZE_T _Inout_opt_ PLARGE_INTEGER SectionOffset
Definition: mmfuncs.h:407
#define PAGE_READWRITE
Definition: nt_native.h:1304
@ ViewUnmap
Definition: nt_native.h:1279
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
NTSTATUS NTAPI PsLookupProcessThreadByCid(IN PCLIENT_ID Cid, OUT PEPROCESS *Process OPTIONAL, OUT PETHREAD *Thread)
Definition: process.c:961
#define STATUS_REPLY_MESSAGE_MISMATCH
Definition: ntstatus.h:675
NTSTATUS NTAPI ObCloseHandle(IN HANDLE Handle, IN KPROCESSOR_MODE AccessMode)
Definition: obhandle.c:3379
NTSTATUS NTAPI ObInsertObject(IN PVOID Object, IN PACCESS_STATE AccessState OPTIONAL, IN ACCESS_MASK DesiredAccess, IN ULONG ObjectPointerBias, OUT PVOID *NewObject OPTIONAL, OUT PHANDLE Handle)
Definition: obhandle.c:2935
NTSTATUS NTAPI ObCreateObject(IN KPROCESSOR_MODE ProbeMode OPTIONAL, IN POBJECT_TYPE Type, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN KPROCESSOR_MODE AccessMode, IN OUT PVOID ParseContext OPTIONAL, IN ULONG ObjectSize, IN ULONG PagedPoolCharge OPTIONAL, IN ULONG NonPagedPoolCharge OPTIONAL, OUT PVOID *Object)
Definition: oblife.c:1024
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:159
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:34
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:162
#define ProbeForWriteHandle(Ptr)
Definition: probe.h:43
NTSTATUS NTAPI MmMapViewOfSection(IN PVOID SectionObject, IN PEPROCESS Process, IN OUT PVOID *BaseAddress, IN ULONG_PTR ZeroBits, IN SIZE_T CommitSize, IN OUT PLARGE_INTEGER SectionOffset OPTIONAL, IN OUT PSIZE_T ViewSize, IN SECTION_INHERIT InheritDisposition, IN ULONG AllocationType, IN ULONG Protect)
Definition: section.c:3918
CHAR ImageFileName[16]
Definition: pstypes.h:1326
PLPCP_PORT_OBJECT ClientPort
Definition: lpctypes.h:257
ULONG MaxMessageLength
Definition: lpctypes.h:228
PEPROCESS ServerProcess
Definition: lpctypes.h:225
ULONG MaxConnectionInfoLength
Definition: lpctypes.h:229
CLIENT_ID ClientId
Definition: winternl.h:1751
LPC_PVOID ViewRemoteBase
ULONG SectionOffset
LPC_SIZE_T ViewSize
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
short CSHORT
Definition: umtypes.h:127
BOOL WINAPI ReplyMessage(_In_ LRESULT)
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
#define ObDereferenceObject
Definition: obfuncs.h:203
#define ObReferenceObject
Definition: obfuncs.h:204
#define PsGetCurrentProcess
Definition: psfuncs.h:17
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103

Referenced by CsrApiHandleConnectionRequest(), CsrSbApiHandleConnectionRequest(), InitLogPort(), LsapHandlePortConnection(), LsapRmServerThread(), main(), ServerThread(), and SmpHandleConnectionRequest().

◆ NtCompleteConnectPort()

NTSTATUS NTAPI NtCompleteConnectPort ( IN HANDLE  PortHandle)

Definition at line 421 of file complete.c.

422{
427
428 PAGED_CODE();
429 LPCTRACE(LPC_COMPLETE_DEBUG, "Handle: %p\n", PortHandle);
430
431 /* Get the Port Object */
436 (PVOID*)&Port,
437 NULL);
438 if (!NT_SUCCESS(Status)) return Status;
439
440 /* Make sure this is a connection port */
442 {
443 /* It isn't, fail */
446 }
447
448 /* Acquire the lock */
450
451 /* Make sure we have a client thread */
452 if (!Port->ClientThread)
453 {
454 /* We don't, fail */
458 }
459
460 /* Get the thread */
461 Thread = Port->ClientThread;
462
463 /* Make sure it has a reply message */
465 {
466 /* It doesn't, quit */
469 return STATUS_SUCCESS;
470 }
471
472 /* Clear the client thread and wake it up */
473 Port->ClientThread = NULL;
475
476 /* Release the lock and wait for an answer */
478 LpcpCompleteWait(&Thread->LpcReplySemaphore);
479
480 /* Dereference the Thread and Port and return */
483 LPCTRACE(LPC_COMPLETE_DEBUG, "Port: %p. Thread: %p\n", Port, Thread);
484 return Status;
485}
CPPORT Port[4]
Definition: headless.c:35
#define LPCP_PORT_TYPE_MASK
Definition: lpctypes.h:58
#define STATUS_INVALID_PORT_HANDLE
Definition: ntstatus.h:302
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:494
#define STATUS_SUCCESS
Definition: shellext.h:65
USHORT Flags
Definition: cportlib.h:31

Referenced by CsrApiHandleConnectionRequest(), CsrSbApiHandleConnectionRequest(), InitLogPort(), LsapHandlePortConnection(), LsapRmServerThread(), main(), ServerThread(), and SmpHandleConnectionRequest().