ReactOS  0.4.14-dev-98-gb0d4763
port.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS Kernel
3  * LICENSE: GPL - See COPYING in the top level directory
4  * FILE: ntoskrnl/lpc/port.c
5  * PURPOSE: Local Procedure Call: Port Management
6  * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7  */
8 
9 /* INCLUDES ******************************************************************/
10 
11 #include <ntoskrnl.h>
12 #define NDEBUG
13 #include <debug.h>
14 
15 /* GLOBALS *******************************************************************/
16 
23 
25 {
28  0,
30 };
31 
32 /* PRIVATE FUNCTIONS *********************************************************/
33 
34 INIT_FUNCTION
35 BOOLEAN
36 NTAPI
38 {
39  OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
41 
42  /* Setup the LPC Lock */
44 
45  /* Create the Port Object Type */
46  RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
47  RtlInitUnicodeString(&Name, L"Port");
48  ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
49  ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(LPCP_NONPAGED_PORT_QUEUE);
50  ObjectTypeInitializer.DefaultPagedPoolCharge = FIELD_OFFSET(LPCP_PORT_OBJECT, WaitEvent);
51  ObjectTypeInitializer.GenericMapping = LpcpPortMapping;
52  ObjectTypeInitializer.PoolType = PagedPool;
53  ObjectTypeInitializer.UseDefaultObject = TRUE;
54  ObjectTypeInitializer.CloseProcedure = LpcpClosePort;
55  ObjectTypeInitializer.DeleteProcedure = LpcpDeletePort;
56  ObjectTypeInitializer.ValidAccessMask = PORT_ALL_ACCESS;
59  &ObjectTypeInitializer,
60  NULL,
62 
63  /* Create the Waitable Port Object Type */
64  RtlInitUnicodeString(&Name, L"WaitablePort");
65  ObjectTypeInitializer.PoolType = NonPagedPool;
66  ObjectTypeInitializer.DefaultNonPagedPoolCharge += sizeof(LPCP_PORT_OBJECT);
67  ObjectTypeInitializer.DefaultPagedPoolCharge = 0;
68  ObjectTypeInitializer.UseDefaultObject = FALSE;
70  &ObjectTypeInitializer,
71  NULL,
73 
74  /* Allocate the LPC lookaside list */
77  NULL,
78  NULL,
79  0,
81  'McpL',
82  32);
83 
84  /* We're done */
85  return TRUE;
86 }
87 
88 BOOLEAN
89 NTAPI
93 {
94  PLPCP_PORT_OBJECT ThreadPort;
95 
96  /* Get the thread's port */
97  ThreadPort = LpcpGetPortFromThread(ClientThread);
98  if (ThreadPort == NULL)
99  {
100  return FALSE;
101  }
102 
103  /* Check if the port matches directly */
104  if ((Port == ThreadPort) ||
105  (Port == ThreadPort->ConnectionPort) ||
106  (Port == ThreadPort->ConnectedPort))
107  {
108  return TRUE;
109  }
110 
111  /* Check if this is a communication port and the connection port matches */
113  (Port->ConnectionPort == ThreadPort))
114  {
115  return TRUE;
116  }
117 
118  return FALSE;
119 }
120 
121 
122 /* PUBLIC FUNCTIONS **********************************************************/
123 
124 NTSTATUS
125 NTAPI
127  IN PPORT_MESSAGE ClientMessage)
128 {
132  ULONG MessageId;
133  PLPCP_PORT_OBJECT Port = NULL, ConnectedPort = NULL;
136 
137  PAGED_CODE();
138 
139  /* Check if the call comes from user mode */
140  if (PreviousMode != KernelMode)
141  {
142  _SEH2_TRY
143  {
144  ProbeForRead(ClientMessage, sizeof(*ClientMessage), sizeof(PVOID));
145  ClientId = ((volatile PORT_MESSAGE*)ClientMessage)->ClientId;
146  MessageId = ((volatile PORT_MESSAGE*)ClientMessage)->MessageId;
147  }
149  {
151  }
152  _SEH2_END;
153  }
154  else
155  {
156  ClientId = ClientMessage->ClientId;
157  MessageId = ClientMessage->MessageId;
158  }
159 
160  /* Reference the port handle */
161  Status = ObReferenceObjectByHandle(PortHandle,
164  PreviousMode,
165  (PVOID*)&Port,
166  NULL);
167  if (!NT_SUCCESS(Status))
168  {
169  DPRINT1("Failed to reference port handle: 0x%ls\n", Status);
170  return Status;
171  }
172 
173  /* Make sure this is a connection port */
175  {
176  /* It isn't, fail */
177  DPRINT1("Port is not a communication port\n");
179  goto Cleanup;
180  }
181 
182  /* Look up the client thread */
184  if (!NT_SUCCESS(Status))
185  {
186  DPRINT1("Failed to lookup client thread: 0x%ls\n", Status);
187  goto Cleanup;
188  }
189 
190  /* Acquire the lock */
192 
193  /* Get the connected port and try to reference it */
194  ConnectedPort = Port->ConnectedPort;
195  if ((ConnectedPort == NULL) || !ObReferenceObjectSafe(ConnectedPort))
196  {
197  DPRINT1("Failed to reference the connected port\n");
198  ConnectedPort = NULL;
200  goto CleanupWithLock;
201  }
202 
203  /* Check for no-impersonation flag */
205  {
206  DPRINT1("Reply message has no impersonation flag set\n");
208  goto CleanupWithLock;
209  }
210 
211  /* Check for message id mismatch */
212  if ((ClientThread->LpcReplyMessageId != MessageId) || (MessageId == 0))
213  {
214  DPRINT1("LpcReplyMessageId mismatch: 0x%lx/0x%lx.\n",
215  ClientThread->LpcReplyMessageId, MessageId);
217  goto CleanupWithLock;
218  }
219 
220  /* Validate the port */
222  {
223  DPRINT1("LpcpValidateClientPort failed\n");
225  goto CleanupWithLock;
226  }
227 
228  /* Release the lock */
230 
231  /* Check if security is static */
232  if (!(ConnectedPort->Flags & LPCP_SECURITY_DYNAMIC))
233  {
234  /* Use the static security for impersonation */
235  Status = SeImpersonateClientEx(&ConnectedPort->StaticSecurity, NULL);
236  goto Cleanup;
237  }
238 
239  /* Create new dynamic security */
241  &ConnectedPort->SecurityQos,
242  FALSE,
243  &ClientContext);
244  if (!NT_SUCCESS(Status))
245  {
246  DPRINT1("SeCreateClientSecurity failed\n");
247  goto Cleanup;
248  }
249 
250  /* Use dynamic security for impersonation */
252 
253  /* Get rid of the security context */
255 
256 Cleanup:
257 
258  if (ConnectedPort != NULL)
259  ObDereferenceObject(ConnectedPort);
260 
261  if (ClientThread != NULL)
263 
265 
266  return Status;
267 
268 CleanupWithLock:
269 
270  /* Release the lock */
272  goto Cleanup;
273 }
274 
275 NTSTATUS
276 NTAPI
278 {
279  /* This is all this function does */
280  return STATUS_UNSUCCESSFUL;
281 }
282 
283 NTSTATUS
284 NTAPI
290 {
292  return STATUS_NOT_IMPLEMENTED;
293 }
294 
295 /* EOF */
IN CINT OUT PVOID IN ULONG OUT PULONG ReturnLength
Definition: dumpinfo.c:39
CPPORT Port[4]
Definition: headless.c:34
#define IN
Definition: typedefs.h:38
NTSTATUS NTAPI ObCreateObjectType(IN PUNICODE_STRING TypeName, IN POBJECT_TYPE_INITIALIZER ObjectTypeInitializer, IN PVOID Reserved, OUT POBJECT_TYPE *ObjectType)
Definition: oblife.c:1048
#define TRUE
Definition: types.h:120
POBJECT_TYPE LpcPortObjectType
Definition: port.c:17
VOID NTAPI ExInitializePagedLookasideList(IN PPAGED_LOOKASIDE_LIST Lookaside, IN PALLOCATE_FUNCTION Allocate OPTIONAL, IN PFREE_FUNCTION Free OPTIONAL, IN ULONG Flags, IN SIZE_T Size, IN ULONG Tag, IN USHORT Depth)
Definition: lookas.c:274
struct _LPCP_PORT_OBJECT * ConnectedPort
Definition: lpctypes.h:212
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:225
VOID FASTCALL KeAcquireGuardedMutex(IN PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:42
#define KeGetPreviousMode()
Definition: ketypes.h:1107
LONG NTSTATUS
Definition: precomp.h:26
IN CINT OUT PVOID PortInformation
Definition: dumpinfo.c:39
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
#define LPCP_PORT_TYPE_MASK
Definition: lpctypes.h:58
#define PAGED_CODE()
Definition: video.h:57
static GENERIC_MAPPING LpcpPortMapping
Definition: port.c:24
#define LPCP_MAX_MESSAGE_SIZE
Definition: lpctypes.h:276
_SEH2_TRY
Definition: create.c:4250
BOOLEAN FASTCALL ObReferenceObjectSafe(IN PVOID Object)
Definition: obref.c:24
#define STATUS_INVALID_PORT_HANDLE
Definition: ntstatus.h:288
uint32_t ULONG_PTR
Definition: typedefs.h:63
IN CINT OUT PVOID IN ULONG PortInformationLength
Definition: dumpinfo.c:39
struct _LPCP_NONPAGED_PORT_QUEUE LPCP_NONPAGED_PORT_QUEUE
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:496
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define SeDeleteClientSecurity(C)
Definition: imports.h:320
USHORT Flags
Definition: cportlib.h:31
struct NameRec_ * Name
Definition: cdprocs.h:464
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
POBJECT_TYPE LpcWaitablePortObjectType
Definition: port.c:17
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
UINT CALLBACK ClientThread(_Inout_ PVOID Parameter)
#define STATUS_REPLY_MESSAGE_MISMATCH
Definition: ntstatus.h:661
NTKERNELAPI NTSTATUS NTAPI SeCreateClientSecurity(IN PETHREAD Thread, IN PSECURITY_QUALITY_OF_SERVICE QualityOfService, IN BOOLEAN RemoteClient, OUT PSECURITY_CLIENT_CONTEXT ClientContext)
Definition: access.c:506
OB_CLOSE_METHOD CloseProcedure
Definition: obtypes.h:368
FORCEINLINE PLPCP_PORT_OBJECT LpcpGetPortFromThread(IN PETHREAD Thread)
Definition: lpc_x.h:144
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103
#define PORT_CONNECT
Definition: lpctypes.h:46
_Out_ PCLIENT_ID ClientId
Definition: kefuncs.h:1176
#define _SEH2_YIELD(STMT_)
Definition: pseh2_64.h:8
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
VOID NTAPI LpcpDeletePort(IN PVOID ObjectBody)
Definition: close.c:302
_In_ PVOID ClientContext
Definition: netioddk.h:55
ULONG LpcpTraceLevel
Definition: port.c:21
NTSTATUS NTAPI NtQueryPortInformationProcess(VOID)
Definition: port.c:277
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
#define READ_CONTROL
Definition: nt_native.h:58
NTSTATUS NTAPI PsLookupProcessThreadByCid(IN PCLIENT_ID Cid, OUT PEPROCESS *Process OPTIONAL, OUT PETHREAD *Thread)
Definition: process.c:961
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
enum _PORT_INFORMATION_CLASS PORT_INFORMATION_CLASS
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
static const WCHAR L[]
Definition: oid.c:1250
static const WCHAR Cleanup[]
Definition: register.c:80
NTSTATUS NTAPI SeImpersonateClientEx(IN PSECURITY_CLIENT_CONTEXT ClientContext, IN PETHREAD ServerThread OPTIONAL)
Definition: access.c:589
Status
Definition: gdiplustypes.h:24
ULONG LpcpMaxMessageSize
Definition: port.c:18
NTSTATUS NTAPI NtImpersonateClientOfPort(IN HANDLE PortHandle, IN PPORT_MESSAGE ClientMessage)
Definition: port.c:126
_SEH2_END
Definition: create.c:4424
VOID FASTCALL KeInitializeGuardedMutex(OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:31
GENERIC_MAPPING GenericMapping
Definition: obtypes.h:358
KGUARDED_MUTEX LpcpLock
Definition: port.c:20
struct _LPCP_PORT_OBJECT LPCP_PORT_OBJECT
struct LOOKASIDE_ALIGN _PAGED_LOOKASIDE_LIST PAGED_LOOKASIDE_LIST
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
#define LPCP_THREAD_FLAG_NO_IMPERSONATION
Definition: lpc.h:56
unsigned int * PULONG
Definition: retypes.h:1
ULONG LpcpNextCallbackId
Definition: port.c:22
struct _LPCP_PORT_OBJECT * ConnectionPort
Definition: lpctypes.h:211
VOID FASTCALL KeReleaseGuardedMutex(IN OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:53
#define DPRINT1
Definition: precomp.h:8
#define OBJ_VALID_ATTRIBUTES
Definition: winternl.h:233
#define PORT_ALL_ACCESS
Definition: lpctypes.h:47
#define OUT
Definition: typedefs.h:39
#define LPCP_COMMUNICATION_PORT
Definition: lpctypes.h:56
#define STATUS_PORT_DISCONNECTED
Definition: ntstatus.h:277
INIT_FUNCTION BOOLEAN NTAPI LpcInitSystem(VOID)
Definition: port.c:37
unsigned int ULONG
Definition: retypes.h:1
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
ULONG LpcpNextMessageId
Definition: port.c:22
#define UNIMPLEMENTED
Definition: debug.h:114
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
#define LPCP_SECURITY_DYNAMIC
Definition: lpctypes.h:62
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
PAGED_LOOKASIDE_LIST LpcpMessagesLookaside
Definition: port.c:19
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
IN CINT PortInformationClass
Definition: dumpinfo.c:39
VOID NTAPI LpcpClosePort(IN PEPROCESS Process OPTIONAL, IN PVOID Object, IN ACCESS_MASK GrantedAccess, IN ULONG ProcessHandleCount, IN ULONG SystemHandleCount)
Definition: close.c:244
OB_DELETE_METHOD DeleteProcedure
Definition: obtypes.h:369
BOOLEAN NTAPI LpcpValidateClientPort(PETHREAD ClientThread, PLPCP_PORT_OBJECT Port)
Definition: port.c:90
ULONG DefaultNonPagedPoolCharge
Definition: obtypes.h:365
#define DELETE
Definition: nt_native.h:57
NTSTATUS NTAPI NtQueryInformationPort(IN HANDLE PortHandle, IN PORT_INFORMATION_CLASS PortInformationClass, OUT PVOID PortInformation, IN ULONG PortInformationLength, OUT PULONG ReturnLength)
Definition: port.c:285