ReactOS 0.4.15-dev-8145-ga541a46
reply.c File Reference
#include <ntoskrnl.h>
#include <debug.h>
Include dependency graph for reply.c:

Go to the source code of this file.

Macros

#define NDEBUG
 

Functions

VOID NTAPI LpcpFreeDataInfoMessage (IN PLPCP_PORT_OBJECT Port, IN ULONG MessageId, IN ULONG CallbackId, IN CLIENT_ID ClientId)
 
VOID NTAPI LpcpSaveDataInfoMessage (IN PLPCP_PORT_OBJECT Port, IN PLPCP_MESSAGE Message, IN ULONG LockFlags)
 
PLPCP_MESSAGE NTAPI LpcpFindDataInfoMessage (IN PLPCP_PORT_OBJECT Port, IN ULONG MessageId, IN LPC_CLIENT_ID ClientId)
 
VOID NTAPI LpcpMoveMessage (IN PPORT_MESSAGE Destination, IN PPORT_MESSAGE Origin, IN PVOID Data, IN ULONG MessageType, IN PCLIENT_ID ClientId)
 
NTSTATUS NTAPI NtReplyPort (IN HANDLE PortHandle, IN PPORT_MESSAGE ReplyMessage)
 
NTSTATUS NTAPI NtReplyWaitReceivePortEx (IN HANDLE PortHandle, OUT PVOID *PortContext OPTIONAL, IN PPORT_MESSAGE ReplyMessage OPTIONAL, OUT PPORT_MESSAGE ReceiveMessage, IN PLARGE_INTEGER Timeout OPTIONAL)
 
NTSTATUS NTAPI NtReplyWaitReceivePort (IN HANDLE PortHandle, OUT PVOID *PortContext OPTIONAL, IN PPORT_MESSAGE ReplyMessage OPTIONAL, OUT PPORT_MESSAGE ReceiveMessage)
 
NTSTATUS NTAPI NtReplyWaitReplyPort (IN HANDLE PortHandle, IN PPORT_MESSAGE ReplyMessage)
 
NTSTATUS NTAPI LpcpCopyRequestData (IN BOOLEAN Write, IN HANDLE PortHandle, IN PPORT_MESSAGE Message, IN ULONG Index, IN PVOID Buffer, IN ULONG BufferLength, OUT PULONG ReturnLength)
 
NTSTATUS NTAPI NtReadRequestData (IN HANDLE PortHandle, IN PPORT_MESSAGE Message, IN ULONG Index, IN PVOID Buffer, IN ULONG BufferLength, OUT PULONG ReturnLength)
 
NTSTATUS NTAPI NtWriteRequestData (IN HANDLE PortHandle, IN PPORT_MESSAGE Message, IN ULONG Index, IN PVOID Buffer, IN ULONG BufferLength, OUT PULONG ReturnLength)
 

Macro Definition Documentation

◆ NDEBUG

#define NDEBUG

Definition at line 12 of file reply.c.

Function Documentation

◆ LpcpCopyRequestData()

NTSTATUS NTAPI LpcpCopyRequestData ( IN BOOLEAN  Write,
IN HANDLE  PortHandle,
IN PPORT_MESSAGE  Message,
IN ULONG  Index,
IN PVOID  Buffer,
IN ULONG  BufferLength,
OUT PULONG  ReturnLength 
)

Definition at line 770 of file reply.c.

778{
781 PORT_MESSAGE CapturedMessage;
784 SIZE_T LocalReturnLength;
785 PLPCP_MESSAGE InfoMessage;
786 PLPCP_DATA_INFO DataInfo;
787 PVOID DataInfoBaseAddress;
788
789 PAGED_CODE();
790
791 /* Check if the call comes from user mode */
793 {
795 {
796 ProbeForRead(Message, sizeof(*Message), sizeof(PVOID));
797 CapturedMessage = *(volatile PORT_MESSAGE*)Message;
798 }
800 {
802 }
803 _SEH2_END;
804 }
805 else
806 {
807 CapturedMessage = *Message;
808 }
809
810 /* Make sure there is any data to copy */
811 if (CapturedMessage.u2.s2.DataInfoOffset == 0)
812 {
814 }
815
816 /* Reference the port handle */
821 (PVOID*)&Port,
822 NULL);
823 if (!NT_SUCCESS(Status))
824 {
825 DPRINT1("Failed to reference port handle: 0x%ls\n", Status);
826 return Status;
827 }
828
829 /* Look up the client thread */
830 Status = PsLookupProcessThreadByCid(&CapturedMessage.ClientId,
831 NULL,
832 &ClientThread);
833 if (!NT_SUCCESS(Status))
834 {
835 DPRINT1("Failed to lookup client thread for [0x%lx:0x%lx]: 0x%ls\n",
836 CapturedMessage.ClientId.UniqueProcess,
837 CapturedMessage.ClientId.UniqueThread, Status);
838 goto Cleanup;
839 }
840
841 /* Acquire the global LPC lock */
843
844 /* Check for message id mismatch */
845 if ((ClientThread->LpcReplyMessageId != CapturedMessage.MessageId) ||
846 (CapturedMessage.MessageId == 0))
847 {
848 DPRINT1("LpcReplyMessageId mismatch: 0x%lx/0x%lx.\n",
849 ClientThread->LpcReplyMessageId, CapturedMessage.MessageId);
851 goto CleanupWithLock;
852 }
853
854 /* Validate the port */
856 {
857 DPRINT1("LpcpValidateClientPort failed\n");
859 goto CleanupWithLock;
860 }
861
862 /* Find the message with the data */
863 InfoMessage = LpcpFindDataInfoMessage(Port,
864 CapturedMessage.MessageId,
865 CapturedMessage.ClientId);
866 if (InfoMessage == NULL)
867 {
868 DPRINT1("LpcpFindDataInfoMessage failed\n");
870 goto CleanupWithLock;
871 }
872
873 /* Get the data info */
874 DataInfo = LpcpGetDataInfoFromMessage(&InfoMessage->Request);
875
876 /* Check if the index is within bounds */
877 if (Index >= DataInfo->NumberOfEntries)
878 {
879 DPRINT1("Message data index %lu out of bounds (%lu in msg)\n",
880 Index, DataInfo->NumberOfEntries);
882 goto CleanupWithLock;
883 }
884
885 /* Check if the caller wants to read/write more data than expected */
886 if (BufferLength > DataInfo->Entries[Index].DataLength)
887 {
888 DPRINT1("Trying to read more data (%lu) than available (%lu)\n",
889 BufferLength, DataInfo->Entries[Index].DataLength);
891 goto CleanupWithLock;
892 }
893
894 /* Get the data pointer */
895 DataInfoBaseAddress = DataInfo->Entries[Index].BaseAddress;
896
897 /* Release the lock */
899
900 if (Write)
901 {
902 /* Copy data from the caller to the message sender */
904 Buffer,
905 ClientThread->ThreadsProcess,
906 DataInfoBaseAddress,
909 &LocalReturnLength);
910 }
911 else
912 {
913 /* Copy data from the message sender to the caller */
914 Status = MmCopyVirtualMemory(ClientThread->ThreadsProcess,
915 DataInfoBaseAddress,
917 Buffer,
920 &LocalReturnLength);
921 }
922
923 if (!NT_SUCCESS(Status))
924 {
925 DPRINT1("MmCopyVirtualMemory failed: 0x%ls\n", Status);
926 goto Cleanup;
927 }
928
929 /* Check if the caller asked to return the copied length */
930 if (ReturnLength != NULL)
931 {
933 {
934 *ReturnLength = LocalReturnLength;
935 }
937 {
938 /* Ignore */
939 DPRINT1("Exception writing ReturnLength, ignoring\n");
940 }
941 _SEH2_END;
942 }
943
944Cleanup:
945
946 if (ClientThread != NULL)
948
950
951 return Status;
952
953CleanupWithLock:
954
955 /* Release the lock */
957 goto Cleanup;
958}
#define PAGED_CODE()
UINT CALLBACK ClientThread(_Inout_ PVOID Parameter)
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
Definition: bufpool.h:45
#define NULL
Definition: types.h:112
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
static const WCHAR Message[]
Definition: register.c:74
static const WCHAR Cleanup[]
Definition: register.c:80
IN CINT OUT PVOID IN ULONG OUT PULONG ReturnLength
Definition: dumpinfo.c:43
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
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
CPPORT Port[4]
Definition: headless.c:35
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
KGUARDED_MUTEX LpcpLock
Definition: port.c:20
POBJECT_TYPE LpcPortObjectType
Definition: port.c:17
BOOLEAN NTAPI LpcpValidateClientPort(PETHREAD ClientThread, PLPCP_PORT_OBJECT Port)
Definition: port.c:90
FORCEINLINE PLPCP_DATA_INFO LpcpGetDataInfoFromMessage(PPORT_MESSAGE Message)
Definition: lpc_x.h:170
#define PORT_ALL_ACCESS
Definition: lpctypes.h:47
#define KernelMode
Definition: asm.h:34
#define KeGetPreviousMode()
Definition: ketypes.h:1115
NTSTATUS NTAPI MmCopyVirtualMemory(IN PEPROCESS SourceProcess, IN PVOID SourceAddress, IN PEPROCESS TargetProcess, OUT PVOID TargetAddress, IN SIZE_T BufferSize, IN KPROCESSOR_MODE PreviousMode, OUT PSIZE_T ReturnSize)
Definition: virtual.c:1270
PLPCP_MESSAGE NTAPI LpcpFindDataInfoMessage(IN PLPCP_PORT_OBJECT Port, IN ULONG MessageId, IN LPC_CLIENT_ID ClientId)
Definition: reply.c:95
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 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 _SEH2_GetExceptionCode()
Definition: pseh2_64.h:165
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:66
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:168
HANDLE UniqueThread
Definition: compat.h:826
HANDLE UniqueProcess
Definition: compat.h:825
ULONG NumberOfEntries
Definition: lpc.h:69
struct _LPCP_DATA_INFO::@1796 Entries[1]
PORT_MESSAGE Request
Definition: lpctypes.h:251
CLIENT_ID ClientId
Definition: winternl.h:1751
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
static BOOL Write(PBYTE Address, PBYTE Data, SIZE_T Size)
Definition: vmhorizon.c:15
_In_ WDFCOLLECTION _In_ ULONG Index
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ ULONG BufferLength
Definition: wdfdevice.h:3771
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
#define ObDereferenceObject
Definition: obfuncs.h:203
#define PsGetCurrentProcess
Definition: psfuncs.h:17
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103

Referenced by NtReadRequestData(), and NtWriteRequestData().

◆ LpcpFindDataInfoMessage()

PLPCP_MESSAGE NTAPI LpcpFindDataInfoMessage ( IN PLPCP_PORT_OBJECT  Port,
IN ULONG  MessageId,
IN LPC_CLIENT_ID  ClientId 
)

Definition at line 95 of file reply.c.

99{
101 PLIST_ENTRY ListEntry;
102
103 PAGED_CODE();
104
105 /* Check if the port we want is the connection port */
107 {
108 /* Use it */
109 Port = Port->ConnectionPort;
110 if (!Port)
111 {
112 /* Return NULL */
113 return NULL;
114 }
115 }
116
117 /* Loop all entries in the list */
118 for (ListEntry = Port->LpcDataInfoChainHead.Flink;
119 ListEntry != &Port->LpcDataInfoChainHead;
120 ListEntry = ListEntry->Flink)
121 {
123
124 /* Check if this is the desired message */
125 if ((Message->Request.MessageId == MessageId) &&
126 (Message->Request.ClientId.UniqueProcess == ClientId.UniqueProcess) &&
127 (Message->Request.ClientId.UniqueThread == ClientId.UniqueThread))
128 {
129 /* It is, return it */
130 return Message;
131 }
132 }
133
134 return NULL;
135}
#define LPCP_PORT_TYPE_MASK
Definition: lpctypes.h:58
#define LPCP_UNCONNECTED_PORT
Definition: lpctypes.h:55
base of all file and directory entries
Definition: entries.h:83
USHORT Flags
Definition: cportlib.h:31
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
_Out_ PCLIENT_ID ClientId
Definition: kefuncs.h:1151

Referenced by LpcpCopyRequestData().

◆ LpcpFreeDataInfoMessage()

VOID NTAPI LpcpFreeDataInfoMessage ( IN PLPCP_PORT_OBJECT  Port,
IN ULONG  MessageId,
IN ULONG  CallbackId,
IN CLIENT_ID  ClientId 
)

Definition at line 19 of file reply.c.

23{
25 PLIST_ENTRY ListHead, NextEntry;
26
27 /* Check if the port we want is the connection port */
29 {
30 /* Use it */
31 Port = Port->ConnectionPort;
32 if (!Port) return;
33 }
34
35 /* Loop the list */
36 ListHead = &Port->LpcDataInfoChainHead;
37 NextEntry = ListHead->Flink;
38 while (ListHead != NextEntry)
39 {
40 /* Get the message */
42
43 /* Make sure it matches */
44 if ((Message->Request.MessageId == MessageId) &&
45 (Message->Request.ClientId.UniqueThread == ClientId.UniqueThread) &&
46 (Message->Request.ClientId.UniqueProcess == ClientId.UniqueProcess))
47 {
48 /* Unlink and free it */
49 RemoveEntryList(&Message->Entry);
52 break;
53 }
54
55 /* Go to the next entry */
56 NextEntry = NextEntry->Flink;
57 }
58}
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
VOID NTAPI LpcpFreeToPortZone(IN PLPCP_MESSAGE Message, IN ULONG LockFlags)
Definition: close.c:52
#define LPCP_LOCK_HELD
Definition: lpc.h:63

Referenced by NtReplyPort(), and NtReplyWaitReceivePortEx().

◆ LpcpMoveMessage()

VOID NTAPI LpcpMoveMessage ( IN PPORT_MESSAGE  Destination,
IN PPORT_MESSAGE  Origin,
IN PVOID  Data,
IN ULONG  MessageType,
IN PCLIENT_ID  ClientId 
)

Definition at line 139 of file reply.c.

144{
146 "Destination/Origin: %p/%p. Data: %p. Length: %lx\n",
148 Origin,
149 Data,
150 Origin->u1.Length);
151
152 /* Set the Message size */
153 Destination->u1.Length = Origin->u1.Length;
154
155 /* Set the Message Type */
156 Destination->u2.s2.Type = !MessageType ?
157 Origin->u2.s2.Type : MessageType & 0xFFFF;
158
159 /* Check if we have a Client ID */
160 if (ClientId)
161 {
162 /* Set the Client ID */
163 Destination->ClientId.UniqueProcess = ClientId->UniqueProcess;
164 Destination->ClientId.UniqueThread = ClientId->UniqueThread;
165 }
166 else
167 {
168 /* Otherwise, copy it */
169 Destination->ClientId.UniqueProcess = Origin->ClientId.UniqueProcess;
170 Destination->ClientId.UniqueThread = Origin->ClientId.UniqueThread;
171 }
172
173 /* Copy the MessageId and ClientViewSize */
174 Destination->MessageId = Origin->MessageId;
175 Destination->ClientViewSize = Origin->ClientViewSize;
176
177 /* Copy the Message Data */
179 Data,
180 ALIGN_UP_BY(Destination->u1.s1.DataLength, sizeof(ULONG)));
181}
#define ALIGN_UP_BY(size, align)
#define LPC_SEND_DEBUG
Definition: lpc.h:23
#define LPCTRACE(x, fmt,...)
Definition: lpc.h:49
#define LPC_REPLY_DEBUG
Definition: lpc.h:21
_In_ PUNICODE_STRING _Inout_ PUNICODE_STRING Destination
Definition: rtlfuncs.h:3004
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
uint32_t ULONG
Definition: typedefs.h:59

Referenced by LpcRequestPort(), LpcRequestWaitReplyPort(), NtReplyPort(), NtReplyWaitReceivePortEx(), NtRequestPort(), and NtRequestWaitReplyPort().

◆ LpcpSaveDataInfoMessage()

VOID NTAPI LpcpSaveDataInfoMessage ( IN PLPCP_PORT_OBJECT  Port,
IN PLPCP_MESSAGE  Message,
IN ULONG  LockFlags 
)

Definition at line 62 of file reply.c.

65{
66 BOOLEAN LockHeld = (LockFlags & LPCP_LOCK_HELD);
67
68 PAGED_CODE();
69
70 /* Acquire the lock */
71 if (!LockHeld) KeAcquireGuardedMutex(&LpcpLock);
72
73 /* Check if the port we want is the connection port */
75 {
76 /* Use it */
77 Port = Port->ConnectionPort;
78 if (!Port)
79 {
80 /* Release the lock and return */
81 if (!LockHeld) KeReleaseGuardedMutex(&LpcpLock);
82 return;
83 }
84 }
85
86 /* Link the message */
87 InsertTailList(&Port->LpcDataInfoChainHead, &Message->Entry);
88
89 /* Release the lock */
90 if (!LockHeld) KeReleaseGuardedMutex(&LpcpLock);
91}
unsigned char BOOLEAN
#define InsertTailList(ListHead, Entry)

Referenced by NtReplyWaitReceivePortEx(), and NtRequestWaitReplyPort().

◆ NtReadRequestData()

NTSTATUS NTAPI NtReadRequestData ( IN HANDLE  PortHandle,
IN PPORT_MESSAGE  Message,
IN ULONG  Index,
IN PVOID  Buffer,
IN ULONG  BufferLength,
OUT PULONG  ReturnLength 
)

Definition at line 965 of file reply.c.

971{
972 /* Call the internal function */
974 PortHandle,
975 Message,
976 Index,
977 Buffer,
980}
#define FALSE
Definition: types.h:117
NTSTATUS NTAPI LpcpCopyRequestData(IN BOOLEAN Write, IN HANDLE PortHandle, IN PPORT_MESSAGE Message, IN ULONG Index, IN PVOID Buffer, IN ULONG BufferLength, OUT PULONG ReturnLength)
Definition: reply.c:770

◆ NtReplyPort()

NTSTATUS NTAPI NtReplyPort ( IN HANDLE  PortHandle,
IN PPORT_MESSAGE  ReplyMessage 
)

Definition at line 190 of file reply.c.

192{
195 PORT_MESSAGE CapturedReplyMessage;
198 PETHREAD Thread = PsGetCurrentThread(), WakeupThread;
199
200 PAGED_CODE();
202 "Handle: %p. Message: %p.\n",
203 PortHandle,
205
206 /* Check if the call comes from user mode */
208 {
210 {
211 ProbeForRead(ReplyMessage, sizeof(*ReplyMessage), sizeof(ULONG));
212 CapturedReplyMessage = *(volatile PORT_MESSAGE*)ReplyMessage;
213 }
215 {
217 }
218 _SEH2_END;
219 }
220 else
221 {
222 CapturedReplyMessage = *ReplyMessage;
223 }
224
225 /* Validate its length */
226 if (((ULONG)CapturedReplyMessage.u1.s1.DataLength + sizeof(PORT_MESSAGE)) >
227 (ULONG)CapturedReplyMessage.u1.s1.TotalLength)
228 {
229 /* Fail */
231 }
232
233 /* Make sure it has a valid ID */
234 if (!CapturedReplyMessage.MessageId) return STATUS_INVALID_PARAMETER;
235
236 /* Get the Port object */
238 0,
241 (PVOID*)&Port,
242 NULL);
243 if (!NT_SUCCESS(Status)) return Status;
244
245 /* Validate its length in respect to the port object */
246 if (((ULONG)CapturedReplyMessage.u1.s1.TotalLength > Port->MaxMessageLength) ||
247 ((ULONG)CapturedReplyMessage.u1.s1.TotalLength <=
248 (ULONG)CapturedReplyMessage.u1.s1.DataLength))
249 {
250 /* Too large, fail */
253 }
254
255 /* Get the ETHREAD corresponding to it */
256 Status = PsLookupProcessThreadByCid(&CapturedReplyMessage.ClientId,
257 NULL,
258 &WakeupThread);
259 if (!NT_SUCCESS(Status))
260 {
261 /* No thread found, fail */
263 return Status;
264 }
265
266 /* Allocate a message from the port zone */
268 if (!Message)
269 {
270 /* Fail if we couldn't allocate a message */
271 ObDereferenceObject(WakeupThread);
273 return STATUS_NO_MEMORY;
274 }
275
276 /* Keep the lock acquired */
278
279 /* Make sure this is the reply the thread is waiting for */
280 if ((WakeupThread->LpcReplyMessageId != CapturedReplyMessage.MessageId) ||
281 ((LpcpGetMessageFromThread(WakeupThread)) &&
283 != LPC_REQUEST)))
284 {
285 /* It isn't, fail */
287 ObDereferenceObject(WakeupThread);
290 }
291
292 /* Copy the message */
294 {
295 LpcpMoveMessage(&Message->Request,
296 &CapturedReplyMessage,
297 ReplyMessage + 1,
298 LPC_REPLY,
299 NULL);
300 }
302 {
303 /* Cleanup and return the exception code */
305 ObDereferenceObject(WakeupThread);
308 }
309 _SEH2_END;
310
311 /* Reference the thread while we use it */
312 ObReferenceObject(WakeupThread);
313 Message->RepliedToThread = WakeupThread;
314
315 /* Set this as the reply message */
316 WakeupThread->LpcReplyMessageId = 0;
317 WakeupThread->LpcReplyMessage = (PVOID)Message;
318
319 /* Check if we have messages on the reply chain */
320 if (!(WakeupThread->LpcExitThreadCalled) &&
321 !(IsListEmpty(&WakeupThread->LpcReplyChain)))
322 {
323 /* Remove us from it and reinitialize it */
324 RemoveEntryList(&WakeupThread->LpcReplyChain);
325 InitializeListHead(&WakeupThread->LpcReplyChain);
326 }
327
328 /* Check if this is the message the thread had received */
330 (Thread->LpcReceivedMessageId == CapturedReplyMessage.MessageId))
331 {
332 /* Clear this data */
335 }
336
337 /* Free any data information */
339 CapturedReplyMessage.MessageId,
340 CapturedReplyMessage.CallbackId,
341 CapturedReplyMessage.ClientId);
342
343 /* Release the lock and release the LPC semaphore to wake up waiters */
345 LpcpCompleteWait(&WakeupThread->LpcReplySemaphore);
346
347 /* Now we can let go of the thread */
348 ObDereferenceObject(WakeupThread);
349
350 /* Dereference port object */
352 return Status;
353}
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
#define LPCP_LOCK_RELEASE
Definition: lpc.h:64
#define LpcpGetMessageType(x)
Definition: lpc_x.h:12
#define LpcpCompleteWait(s)
Definition: lpc_x.h:88
FORCEINLINE PLPCP_MESSAGE LpcpGetMessageFromThread(IN PETHREAD Thread)
Definition: lpc_x.h:129
static __inline PLPCP_MESSAGE LpcpAllocateFromPortZone(VOID)
Definition: lpc_x.h:100
#define LPC_REQUEST
Definition: port.c:93
#define LPC_REPLY
Definition: port.c:94
VOID NTAPI LpcpMoveMessage(IN PPORT_MESSAGE Destination, IN PPORT_MESSAGE Origin, IN PVOID Data, IN ULONG MessageType, IN PCLIENT_ID ClientId)
Definition: reply.c:139
VOID NTAPI LpcpFreeDataInfoMessage(IN PLPCP_PORT_OBJECT Port, IN ULONG MessageId, IN ULONG CallbackId, IN CLIENT_ID ClientId)
Definition: reply.c:19
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
#define STATUS_PORT_MESSAGE_TOO_LONG
Definition: ntstatus.h:284
ULONG LpcReceivedMsgIdValid
Definition: pstypes.h:1214
ULONG LpcReceivedMessageId
Definition: pstypes.h:1156
void * PVOID
Definition: typedefs.h:50
_In_ WDFREQUEST Request
Definition: wdfdevice.h:547
BOOL WINAPI ReplyMessage(_In_ LRESULT)
#define ObReferenceObject
Definition: obfuncs.h:204

Referenced by AuthPortThreadRoutine(), CsrApiRequestThread(), and CsrNotifyWaitBlock().

◆ NtReplyWaitReceivePort()

NTSTATUS NTAPI NtReplyWaitReceivePort ( IN HANDLE  PortHandle,
OUT PVOID *PortContext  OPTIONAL,
IN PPORT_MESSAGE ReplyMessage  OPTIONAL,
OUT PPORT_MESSAGE  ReceiveMessage 
)

Definition at line 743 of file reply.c.

747{
748 /* Call the newer API */
749 return NtReplyWaitReceivePortEx(PortHandle,
750 PortContext,
752 ReceiveMessage,
753 NULL);
754}
NTSTATUS NTAPI NtReplyWaitReceivePortEx(IN HANDLE PortHandle, OUT PVOID *PortContext OPTIONAL, IN PPORT_MESSAGE ReplyMessage OPTIONAL, OUT PPORT_MESSAGE ReceiveMessage, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: reply.c:360

Referenced by AuthPortThreadRoutine(), CsrApiRequestThread(), CsrSbApiRequestThread(), LsapRmServerThread(), main(), NtListenPort(), ProcessPortMessage(), ServerThread(), and SmpApiLoop().

◆ NtReplyWaitReceivePortEx()

NTSTATUS NTAPI NtReplyWaitReceivePortEx ( IN HANDLE  PortHandle,
OUT PVOID *PortContext  OPTIONAL,
IN PPORT_MESSAGE ReplyMessage  OPTIONAL,
OUT PPORT_MESSAGE  ReceiveMessage,
IN PLARGE_INTEGER Timeout  OPTIONAL 
)

Definition at line 360 of file reply.c.

365{
368 PORT_MESSAGE CapturedReplyMessage;
369 LARGE_INTEGER CapturedTimeout;
370 PLPCP_PORT_OBJECT Port, ReceivePort, ConnectionPort = NULL;
372 PETHREAD Thread = PsGetCurrentThread(), WakeupThread;
373 PLPCP_CONNECTION_MESSAGE ConnectMessage;
374 ULONG ConnectionInfoLength;
375
376 PAGED_CODE();
378 "Handle: %p. Messages: %p/%p. Context: %p\n",
379 PortHandle,
381 ReceiveMessage,
382 PortContext);
383
384 /* Check if the call comes from user mode */
386 {
388 {
389 if (PortContext != NULL)
390 ProbeForWritePointer(PortContext);
391
392 if (ReplyMessage != NULL)
393 {
394 ProbeForRead(ReplyMessage, sizeof(*ReplyMessage), sizeof(ULONG));
395 CapturedReplyMessage = *(volatile PORT_MESSAGE*)ReplyMessage;
396 }
397
398 if (Timeout != NULL)
399 {
401 CapturedTimeout = *(volatile LARGE_INTEGER*)Timeout;
402 Timeout = &CapturedTimeout;
403 }
404 }
406 {
408 }
409 _SEH2_END;
410 }
411 else
412 {
413 /* If this is a system thread, then let it page out its stack */
414 if (Thread->SystemThread) WaitMode = UserMode;
415
416 if (ReplyMessage != NULL)
417 CapturedReplyMessage = *ReplyMessage;
418 }
419
420 /* Check if caller has a reply message */
421 if (ReplyMessage)
422 {
423 /* Validate its length */
424 if (((ULONG)CapturedReplyMessage.u1.s1.DataLength + sizeof(PORT_MESSAGE)) >
425 (ULONG)CapturedReplyMessage.u1.s1.TotalLength)
426 {
427 /* Fail */
429 }
430
431 /* Make sure it has a valid ID */
432 if (!CapturedReplyMessage.MessageId) return STATUS_INVALID_PARAMETER;
433 }
434
435 /* Get the Port object */
437 0,
440 (PVOID*)&Port,
441 NULL);
442 if (!NT_SUCCESS(Status)) return Status;
443
444 /* Check if the caller has a reply message */
445 if (ReplyMessage)
446 {
447 /* Validate its length in respect to the port object */
448 if (((ULONG)CapturedReplyMessage.u1.s1.TotalLength > Port->MaxMessageLength) ||
449 ((ULONG)CapturedReplyMessage.u1.s1.TotalLength <=
450 (ULONG)CapturedReplyMessage.u1.s1.DataLength))
451 {
452 /* Too large, fail */
455 }
456 }
457
458 /* Check if this is anything but a client port */
460 {
461 /* Check if this is the connection port */
462 if (Port->ConnectionPort == Port)
463 {
464 /* Use this port */
465 ConnectionPort = ReceivePort = Port;
466 ObReferenceObject(ConnectionPort);
467 }
468 else
469 {
470 /* Acquire the lock */
472
473 /* Get the port */
474 ConnectionPort = ReceivePort = Port->ConnectionPort;
475 if (!ConnectionPort)
476 {
477 /* Fail */
481 }
482
483 /* Release lock and reference */
484 ObReferenceObject(ConnectionPort);
486 }
487 }
488 else
489 {
490 /* Otherwise, use the port itself */
491 ReceivePort = Port;
492 }
493
494 /* Check if the caller gave a reply message */
495 if (ReplyMessage)
496 {
497 /* Get the ETHREAD corresponding to it */
498 Status = PsLookupProcessThreadByCid(&CapturedReplyMessage.ClientId,
499 NULL,
500 &WakeupThread);
501 if (!NT_SUCCESS(Status))
502 {
503 /* No thread found, fail */
505 if (ConnectionPort) ObDereferenceObject(ConnectionPort);
506 return Status;
507 }
508
509 /* Allocate a message from the port zone */
511 if (!Message)
512 {
513 /* Fail if we couldn't allocate a message */
514 if (ConnectionPort) ObDereferenceObject(ConnectionPort);
515 ObDereferenceObject(WakeupThread);
517 return STATUS_NO_MEMORY;
518 }
519
520 /* Keep the lock acquired */
522
523 /* Make sure this is the reply the thread is waiting for */
524 if ((WakeupThread->LpcReplyMessageId != CapturedReplyMessage.MessageId) ||
525 ((LpcpGetMessageFromThread(WakeupThread)) &&
527 != LPC_REQUEST)))
528 {
529 /* It isn't, fail */
531 if (ConnectionPort) ObDereferenceObject(ConnectionPort);
532 ObDereferenceObject(WakeupThread);
535 }
536
537 /* Copy the message */
539 {
540 LpcpMoveMessage(&Message->Request,
541 &CapturedReplyMessage,
542 ReplyMessage + 1,
543 LPC_REPLY,
544 NULL);
545 }
547 {
548 /* Cleanup and return the exception code */
550 if (ConnectionPort) ObDereferenceObject(ConnectionPort);
551 ObDereferenceObject(WakeupThread);
554 }
555 _SEH2_END;
556
557 /* Reference the thread while we use it */
558 ObReferenceObject(WakeupThread);
559 Message->RepliedToThread = WakeupThread;
560
561 /* Set this as the reply message */
562 WakeupThread->LpcReplyMessageId = 0;
563 WakeupThread->LpcReplyMessage = (PVOID)Message;
564
565 /* Check if we have messages on the reply chain */
566 if (!(WakeupThread->LpcExitThreadCalled) &&
567 !(IsListEmpty(&WakeupThread->LpcReplyChain)))
568 {
569 /* Remove us from it and reinitialize it */
570 RemoveEntryList(&WakeupThread->LpcReplyChain);
571 InitializeListHead(&WakeupThread->LpcReplyChain);
572 }
573
574 /* Check if this is the message the thread had received */
576 (Thread->LpcReceivedMessageId == CapturedReplyMessage.MessageId))
577 {
578 /* Clear this data */
581 }
582
583 /* Free any data information */
585 CapturedReplyMessage.MessageId,
586 CapturedReplyMessage.CallbackId,
587 CapturedReplyMessage.ClientId);
588
589 /* Release the lock and release the LPC semaphore to wake up waiters */
591 LpcpCompleteWait(&WakeupThread->LpcReplySemaphore);
592
593 /* Now we can let go of the thread */
594 ObDereferenceObject(WakeupThread);
595 }
596
597 /* Now wait for someone to reply to us */
598 LpcpReceiveWait(ReceivePort->MsgQueue.Semaphore, WaitMode);
599 if (Status != STATUS_SUCCESS) goto Cleanup;
600
601 /* Wait done, get the LPC lock */
603
604 /* Check if we've received nothing */
605 if (IsListEmpty(&ReceivePort->MsgQueue.ReceiveHead))
606 {
607 /* Check if this was a waitable port and wake it */
608 if (ReceivePort->Flags & LPCP_WAITABLE_PORT)
609 {
610 /* Reset its event */
611 KeClearEvent(&ReceivePort->WaitEvent);
612 }
613
614 /* Release the lock and fail */
616 if (ConnectionPort) ObDereferenceObject(ConnectionPort);
618 return STATUS_UNSUCCESSFUL;
619 }
620
621 /* Get the message on the queue */
624 Entry);
625
626 /* Check if the queue is empty now */
627 if (IsListEmpty(&ReceivePort->MsgQueue.ReceiveHead))
628 {
629 /* Check if this was a waitable port */
630 if (ReceivePort->Flags & LPCP_WAITABLE_PORT)
631 {
632 /* Reset its event */
633 KeClearEvent(&ReceivePort->WaitEvent);
634 }
635 }
636
637 /* Re-initialize the message's list entry */
639
640 /* Set this as the received message */
641 Thread->LpcReceivedMessageId = Message->Request.MessageId;
643
645 {
646 /* Check if this was a connection request */
648 {
649 /* Get the connection message */
650 ConnectMessage = (PLPCP_CONNECTION_MESSAGE)(Message + 1);
652 "Request Messages: %p/%p\n",
653 Message,
654 ConnectMessage);
655
656 /* Get its length */
657 ConnectionInfoLength = Message->Request.u1.s1.DataLength -
659
660 /* Return it as the receive message */
661 *ReceiveMessage = Message->Request;
662
663 /* Clear our stack variable so the message doesn't get freed */
664 Message = NULL;
665
666 /* Setup the receive message */
667 ReceiveMessage->u1.s1.TotalLength = (CSHORT)(sizeof(PORT_MESSAGE) +
668 ConnectionInfoLength);
669 ReceiveMessage->u1.s1.DataLength = (CSHORT)ConnectionInfoLength;
670 RtlCopyMemory(ReceiveMessage + 1,
671 ConnectMessage + 1,
672 ConnectionInfoLength);
673
674 /* Clear the port context if the caller requested one */
675 if (PortContext) *PortContext = NULL;
676 }
677 else if (LpcpGetMessageType(&Message->Request) != LPC_REPLY)
678 {
679 /* Otherwise, this is a new message or event */
681 "Non-Reply Messages: %p/%p\n",
682 &Message->Request,
683 (&Message->Request) + 1);
684
685 /* Copy it */
686 LpcpMoveMessage(ReceiveMessage,
687 &Message->Request,
688 (&Message->Request) + 1,
689 0,
690 NULL);
691
692 /* Return its context */
693 if (PortContext) *PortContext = Message->PortContext;
694
695 /* And check if it has data information */
696 if (Message->Request.u2.s2.DataInfoOffset)
697 {
698 /* It does, save it, and don't free the message below */
700 Message = NULL;
701 }
702 }
703 else
704 {
705 /* This is a reply message, should never happen! */
706 ASSERT(FALSE);
707 }
708 }
710 {
712 }
713 _SEH2_END;
714
715 /* Check if we have a message pointer here */
716 if (Message)
717 {
718 /* Free it and release the lock */
720 }
721 else
722 {
723 /* Just release the lock */
725 }
726
727Cleanup:
728 /* All done, dereference the port and return the status */
730 "Port: %p. Status: %d\n",
731 Port,
732 Status);
733 if (ConnectionPort) ObDereferenceObject(ConnectionPort);
735 return Status;
736}
#define TRUE
Definition: types.h:120
#define RemoveHeadList(ListHead)
Definition: env_spec_w32.h:964
VOID NTAPI KeClearEvent(IN PKEVENT Event)
Definition: eventobj.c:22
#define LpcpReceiveWait(s, w)
Definition: lpc_x.h:18
#define LPCP_WAITABLE_PORT
Definition: lpctypes.h:60
#define LPCP_CLIENT_PORT
Definition: lpctypes.h:57
struct _LPCP_CONNECTION_MESSAGE * PLPCP_CONNECTION_MESSAGE
struct _LPCP_CONNECTION_MESSAGE LPCP_CONNECTION_MESSAGE
#define ASSERT(a)
Definition: mode.c:44
#define LPC_CONNECTION_REQUEST
Definition: port.c:102
#define UserMode
Definition: asm.h:35
VOID NTAPI LpcpSaveDataInfoMessage(IN PLPCP_PORT_OBJECT Port, IN PLPCP_MESSAGE Message, IN ULONG LockFlags)
Definition: reply.c:62
#define STATUS_PORT_DISCONNECTED
Definition: ntstatus.h:291
static ULONG Timeout
Definition: ping.c:61
#define ProbeForWritePointer(Ptr)
Definition: probe.h:42
#define ProbeForReadLargeInteger(Ptr)
Definition: probe.h:75
#define STATUS_SUCCESS
Definition: shellext.h:65
ULONG SystemThread
Definition: pstypes.h:1182
LPCP_PORT_QUEUE MsgQueue
Definition: lpctypes.h:213
KEVENT WaitEvent
Definition: lpctypes.h:231
LIST_ENTRY ReceiveHead
Definition: lpctypes.h:203
PKSEMAPHORE Semaphore
Definition: lpctypes.h:202
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
short CSHORT
Definition: umtypes.h:127

Referenced by NtReplyWaitReceivePort().

◆ NtReplyWaitReplyPort()

NTSTATUS NTAPI NtReplyWaitReplyPort ( IN HANDLE  PortHandle,
IN PPORT_MESSAGE  ReplyMessage 
)

Definition at line 761 of file reply.c.

763{
766}
#define UNIMPLEMENTED
Definition: debug.h:118
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:239

◆ NtWriteRequestData()

NTSTATUS NTAPI NtWriteRequestData ( IN HANDLE  PortHandle,
IN PPORT_MESSAGE  Message,
IN ULONG  Index,
IN PVOID  Buffer,
IN ULONG  BufferLength,
OUT PULONG  ReturnLength 
)

Definition at line 987 of file reply.c.

993{
994 /* Call the internal function */
996 PortHandle,
997 Message,
998 Index,
999 Buffer,
1001 ReturnLength);
1002}