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 } 174