[NTOSKRNL]
[reactos.git] / reactos / ntoskrnl / include / internal / lpc_x.h
1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/include/internal/lpc_x.h
5 * PURPOSE: Internal Inlined Functions for Local Procedure Call
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 */
8
9 //
10 // Gets the message type, removing the kernel-mode flag
11 //
12 #define LpcpGetMessageType(x) \
13 ((x)->u2.s2.Type &~ LPC_KERNELMODE_MESSAGE)
14
15 //
16 // Waits on an LPC semaphore for a receive operation
17 //
18 #define LpcpReceiveWait(s, w) \
19 { \
20 LPCTRACE(LPC_REPLY_DEBUG, "Wait: %p\n", s); \
21 Status = KeWaitForSingleObject(s, \
22 WrLpcReceive, \
23 w, \
24 FALSE, \
25 NULL); \
26 LPCTRACE(LPC_REPLY_DEBUG, "Wait done: %lx\n", Status); \
27 }
28
29 //
30 // Waits on an LPC semaphore for a reply operation
31 //
32 #define LpcpReplyWait(s, w) \
33 { \
34 LPCTRACE(LPC_SEND_DEBUG, "Wait: %p\n", s); \
35 Status = KeWaitForSingleObject(s, \
36 WrLpcReply, \
37 w, \
38 FALSE, \
39 NULL); \
40 LPCTRACE(LPC_SEND_DEBUG, "Wait done: %lx\n", Status); \
41 if (Status == STATUS_USER_APC) \
42 { \
43 /* We were preempted by an APC */ \
44 if (KeReadStateSemaphore(s)) \
45 { \
46 /* It's still signaled, so wait on it */ \
47 KeWaitForSingleObject(s, \
48 WrExecutive, \
49 KernelMode, \
50 FALSE, \
51 NULL); \
52 Status = STATUS_SUCCESS; \
53 } \
54 } \
55 }
56
57 //
58 // Waits on an LPC semaphore for a connect operation
59 //
60 #define LpcpConnectWait(s, w) \
61 { \
62 LPCTRACE(LPC_CONNECT_DEBUG, "Wait: %p\n", s); \
63 Status = KeWaitForSingleObject(s, \
64 Executive, \
65 w, \
66 FALSE, \
67 NULL); \
68 LPCTRACE(LPC_CONNECT_DEBUG, "Wait done: %lx\n", Status);\
69 if (Status == STATUS_USER_APC) \
70 { \
71 /* We were preempted by an APC */ \
72 if (KeReadStateSemaphore(s)) \
73 { \
74 /* It's still signaled, so wait on it */ \
75 KeWaitForSingleObject(s, \
76 WrExecutive, \
77 KernelMode, \
78 FALSE, \
79 NULL); \
80 Status = STATUS_SUCCESS; \
81 } \
82 } \
83 }
84
85 //
86 // Releases an LPC Semaphore to complete a wait
87 //
88 #define LpcpCompleteWait(s) \
89 { \
90 /* Release the semaphore */ \
91 LPCTRACE(LPC_SEND_DEBUG, "Release: %p\n", s); \
92 KeReleaseSemaphore(s, 1, 1, FALSE); \
93 }
94
95 //
96 // Allocates a new message
97 //
98 static __inline
99 PLPCP_MESSAGE
100 LpcpAllocateFromPortZone(VOID)
101 {
102 PLPCP_MESSAGE Message;
103
104 /* Allocate a message from the port zone while holding the lock */
105 KeAcquireGuardedMutex(&LpcpLock);
106 Message = (PLPCP_MESSAGE)ExAllocateFromPagedLookasideList(&LpcpMessagesLookaside);
107 if (!Message)
108 {
109 /* Fail, and let caller cleanup */
110 KeReleaseGuardedMutex(&LpcpLock);
111 return NULL;
112 }
113
114 /* Initialize it */
115 InitializeListHead(&Message->Entry);
116 Message->RepliedToThread = NULL;
117 Message->Request.u2.ZeroInit = 0;
118
119 /* Release the lock */
120 KeReleaseGuardedMutex(&LpcpLock);
121 return Message;
122 }
123
124 //
125 // Get the LPC Message associated to the Thread
126 //
127 FORCEINLINE
128 PLPCP_MESSAGE
129 LpcpGetMessageFromThread(IN PETHREAD Thread)
130 {
131 /* Check if the port flag is set */
132 if (((ULONG_PTR)Thread->LpcReplyMessage) & LPCP_THREAD_FLAG_IS_PORT)
133 {
134 /* The pointer is actually a port, not a message, so return NULL */
135 return NULL;
136 }
137
138 /* Otherwise, this is a message. Return the pointer */
139 return (PLPCP_MESSAGE)((ULONG_PTR)Thread->LpcReplyMessage & ~LPCP_THREAD_FLAGS);
140 }
141
142 FORCEINLINE
143 PLPCP_PORT_OBJECT
144 LpcpGetPortFromThread(IN PETHREAD Thread)
145 {
146 /* Check if the port flag is set */
147 if (((ULONG_PTR)Thread->LpcReplyMessage) & LPCP_THREAD_FLAG_IS_PORT)
148 {
149 /* The pointer is actually a port, return it */
150 return (PLPCP_PORT_OBJECT)((ULONG_PTR)Thread->LpcWaitingOnPort &
151 ~LPCP_THREAD_FLAGS);
152 }
153
154 /* Otherwise, this is a message. There is nothing to return */
155 return NULL;
156 }
157
158 FORCEINLINE
159 VOID
160 LpcpSetPortToThread(IN PETHREAD Thread,
161 IN PLPCP_PORT_OBJECT Port)
162 {
163 /* Set the port object */
164 Thread->LpcWaitingOnPort = (PVOID)(((ULONG_PTR)Port) |
165 LPCP_THREAD_FLAG_IS_PORT);
166 }
167
168 FORCEINLINE
169 PLPCP_DATA_INFO
170 LpcpGetDataInfoFromMessage(PPORT_MESSAGE Message)
171 {
172 return (PLPCP_DATA_INFO)((PUCHAR)Message + Message->u2.s2.DataInfoOffset);
173 }