ReactOS 0.4.16-dev-401-g45b008d
close.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/close.c
5 * PURPOSE: Local Procedure Call: Rundown, Cleanup, Deletion
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/* PRIVATE FUNCTIONS *********************************************************/
16
17VOID
20{
23
24 /* Acquire the lock */
26
27 /* Make sure that the Reply Chain is empty */
29 {
30 /* It's not, remove the entry */
32 }
33
34 /* Set the thread in exit mode */
36 Thread->LpcReplyMessageId = 0;
37
38 /* Check if there's a reply message */
40 if (Message)
41 {
42 /* FIXME: TODO */
44 }
45
46 /* Release the lock */
48}
49
50VOID
53 IN ULONG LockFlags)
54{
55 PLPCP_CONNECTION_MESSAGE ConnectMessage;
58 BOOLEAN LockHeld = (LockFlags & LPCP_LOCK_HELD);
60
61 PAGED_CODE();
62
63 LPCTRACE(LPC_CLOSE_DEBUG, "Message: %p. LockFlags: %lx\n", Message, LockFlags);
64
65 /* Acquire the lock if not already */
66 if (!LockHeld) KeAcquireGuardedMutex(&LpcpLock);
67
68 /* Check if the queue list is empty */
69 if (!IsListEmpty(&Message->Entry))
70 {
71 /* Remove and re-initialize */
72 RemoveEntryList(&Message->Entry);
74 }
75
76 /* Check if we've already replied */
77 if (Message->RepliedToThread)
78 {
79 /* Set thread to dereference and clean up */
80 Thread = Message->RepliedToThread;
81 Message->RepliedToThread = NULL;
82 }
83
84 /* Check if this is a connection request */
85 if (Message->Request.u2.s2.Type == LPC_CONNECTION_REQUEST)
86 {
87 /* Get the connection message */
88 ConnectMessage = (PLPCP_CONNECTION_MESSAGE)(Message + 1);
89
90 /* Clear the client port */
91 ClientPort = ConnectMessage->ClientPort;
92 if (ClientPort) ConnectMessage->ClientPort = NULL;
93 }
94
95 /* Release the lock */
97
98 /* Check if we had anything to dereference */
101
102 /* Free the entry */
103 ExFreeToPagedLookasideList(&LpcpMessagesLookaside, Message);
104
105 /* Reacquire the lock if needed */
106 if ((LockHeld) && !(ReleaseLock)) KeAcquireGuardedMutex(&LpcpLock);
107}
108
109VOID
110NTAPI
112 IN BOOLEAN Destroy)
113{
114 PLIST_ENTRY ListHead, NextEntry;
117 PLPCP_PORT_OBJECT ConnectionPort = NULL;
118 PLPCP_CONNECTION_MESSAGE ConnectMessage;
119 PLPCP_NONPAGED_PORT_QUEUE MessageQueue;
120
121 PAGED_CODE();
122 LPCTRACE(LPC_CLOSE_DEBUG, "Port: %p. Flags: %lx\n", Port, Port->Flags);
123
124 /* Hold the lock */
126
127 /* Check if we have a connected port */
129 (Port->ConnectedPort))
130 {
131 /* Disconnect it */
132 Port->ConnectedPort->ConnectedPort = NULL;
133 ConnectionPort = Port->ConnectedPort->ConnectionPort;
134 if (ConnectionPort)
135 {
136 /* Clear connection port */
137 Port->ConnectedPort->ConnectionPort = NULL;
138 }
139 }
140
141 /* Check if this is a connection port */
143 {
144 /* Delete the name */
146 }
147
148 /* Walk all the threads waiting and signal them */
149 ListHead = &Port->LpcReplyChainHead;
150 NextEntry = ListHead->Flink;
151 while ((NextEntry) && (NextEntry != ListHead))
152 {
153 /* Get the Thread */
154 Thread = CONTAINING_RECORD(NextEntry, ETHREAD, LpcReplyChain);
155
156 /* Make sure we're not in exit */
157 if (Thread->LpcExitThreadCalled) break;
158
159 /* Move to the next entry */
160 NextEntry = NextEntry->Flink;
161
162 /* Remove and reinitialize the List */
165
166 /* Check if someone is waiting */
167 if (!KeReadStateSemaphore(&Thread->LpcReplySemaphore))
168 {
169 /* Get the message */
171 if (Message)
172 {
173 /* Check if it's a connection request */
174 if (Message->Request.u2.s2.Type == LPC_CONNECTION_REQUEST)
175 {
176 /* Get the connection message */
177 ConnectMessage = (PLPCP_CONNECTION_MESSAGE)(Message + 1);
178
179 /* Check if it had a section */
180 if (ConnectMessage->SectionToMap)
181 {
182 /* Dereference it */
183 ObDereferenceObject(ConnectMessage->SectionToMap);
184 }
185 }
186
187 /* Clear the reply message */
188 Thread->LpcReplyMessage = NULL;
189
190 /* And remove the message from the port zone */
192 NextEntry = Port->LpcReplyChainHead.Flink;
193 }
194
195 /* Release the semaphore and reset message id count */
196 Thread->LpcReplyMessageId = 0;
197 KeReleaseSemaphore(&Thread->LpcReplySemaphore, 0, 1, FALSE);
198 }
199 }
200
201 /* Reinitialize the list head */
202 InitializeListHead(&Port->LpcReplyChainHead);
203
204 /* Loop queued messages */
205 while ((Port->MsgQueue.ReceiveHead.Flink) &&
206 !(IsListEmpty(&Port->MsgQueue.ReceiveHead)))
207 {
208 /* Get the message */
209 Message = CONTAINING_RECORD(Port->MsgQueue.ReceiveHead.Flink,
211 Entry);
212
213 /* Free and reinitialize it's list head */
214 RemoveEntryList(&Message->Entry);
216
217 /* Remove it from the port zone */
219 }
220
221 /* Release the lock */
223
224 /* Dereference the connection port */
225 if (ConnectionPort) ObDereferenceObject(ConnectionPort);
226
227 /* Check if we have to free the port entirely */
228 if (Destroy)
229 {
230 /* Check if the semaphore exists */
231 if (Port->MsgQueue.Semaphore)
232 {
233 /* Use the semaphore to find the port queue and free it */
234 MessageQueue = CONTAINING_RECORD(Port->MsgQueue.Semaphore,
236 Semaphore);
237 ExFreePoolWithTag(MessageQueue, 'troP');
238 }
239 }
240}
241
242VOID
243NTAPI
248 IN ULONG SystemHandleCount)
249{
251
252 LPCTRACE(LPC_CLOSE_DEBUG, "Port: %p. Flags: %lx\n", Port, Port->Flags);
253
254 /* Only Server-side Connection Ports need clean up*/
256 {
257 /* Check the handle count */
258 switch (SystemHandleCount)
259 {
260 /* No handles left */
261 case 0:
262
263 /* Destroy the port queue */
265 break;
266
267 /* Last handle remaining */
268 case 1:
269
270 /* Reset the queue only */
272
273 /* More handles remain, do nothing */
274 default:
275 break;
276 }
277 }
278}
279
280VOID
281NTAPI
283{
284 /* Check if this is a client port */
286 {
287 /* Check if security is static */
289 {
290 /* Check if we have a token */
291 if (Port->StaticSecurity.ClientToken)
292 {
293 /* Free security */
294 SeDeleteClientSecurity(&Port->StaticSecurity);
295 }
296 }
297 }
298}
299
300VOID
301NTAPI
303{
307 PLPCP_PORT_OBJECT ConnectionPort;
309 PLIST_ENTRY ListHead, NextEntry;
310 HANDLE Pid;
311 CLIENT_DIED_MSG ClientDiedMsg;
312
313 PAGED_CODE();
314 LPCTRACE(LPC_CLOSE_DEBUG, "Port: %p. Flags: %lx\n", Port, Port->Flags);
315
316 Timeout.QuadPart = -1000000;
317
318 /* Check if this is a communication port */
320 {
321 /* Acquire the lock */
323
324 /* Get the thread */
325 Thread = Port->ClientThread;
326 if (Thread)
327 {
328 /* Clear it */
329 Port->ClientThread = NULL;
330
331 /* Release the lock and dereference */
334 }
335 else
336 {
337 /* Release the lock */
339 }
340 }
341
342 /* Check if this is a client-side port */
344 {
345 /* Setup the client died message */
346 ClientDiedMsg.h.u1.s1.TotalLength = sizeof(ClientDiedMsg);
347 ClientDiedMsg.h.u1.s1.DataLength = sizeof(ClientDiedMsg.CreateTime);
348 ClientDiedMsg.h.u2.ZeroInit = 0;
349 ClientDiedMsg.h.u2.s2.Type = LPC_PORT_CLOSED;
350 ClientDiedMsg.CreateTime = PsGetCurrentProcess()->CreateTime;
351
352 /* Send it */
353 for (;;)
354 {
355 /* Send the message */
356 if (LpcRequestPort(Port, &ClientDiedMsg.h) != STATUS_NO_MEMORY)
357 break;
358
359 /* Wait until trying again */
361 }
362 }
363
364 /* Destroy the port queue */
366
367 /* Check if we had views */
368 if ((Port->ClientSectionBase) || (Port->ServerSectionBase))
369 {
370 /* Check if we had a client view */
371 if (Port->ClientSectionBase)
372 {
373 /* Unmap it */
374 MmUnmapViewOfSection(Port->MappingProcess,
375 Port->ClientSectionBase);
376 }
377
378 /* Check for a server view */
379 if (Port->ServerSectionBase)
380 {
381 /* Unmap it */
382 MmUnmapViewOfSection(Port->MappingProcess,
383 Port->ServerSectionBase);
384 }
385
386 /* Dereference the mapping process */
387 ObDereferenceObject(Port->MappingProcess);
388 Port->MappingProcess = NULL;
389 }
390
391 /* Acquire the lock */
393
394 /* Get the connection port */
395 ConnectionPort = Port->ConnectionPort;
396 if (ConnectionPort)
397 {
398 /* Get the PID */
399 Pid = PsGetCurrentProcessId();
400
401 /* Loop the data lists */
402 ListHead = &ConnectionPort->LpcDataInfoChainHead;
403 NextEntry = ListHead->Flink;
404 while (NextEntry != ListHead)
405 {
406 /* Get the message */
408 NextEntry = NextEntry->Flink;
409
410 /* Check if this is the connection port */
411 if (Port == ConnectionPort)
412 {
413 /* Free queued messages */
414 RemoveEntryList(&Message->Entry);
417
418 /* Restart at the head */
419 NextEntry = ListHead->Flink;
420 }
421 else if ((Message->Request.ClientId.UniqueProcess == Pid) &&
422 ((Message->SenderPort == Port) ||
423 (Message->SenderPort == Port->ConnectedPort) ||
424 (Message->SenderPort == ConnectionPort)))
425 {
426 /* Remove it */
427 RemoveEntryList(&Message->Entry);
430
431 /* Restart at the head */
432 NextEntry = ListHead->Flink;
433 }
434 }
435
436 /* Release the lock */
438
439 /* Dereference the object unless it's the same port */
440 if (ConnectionPort != Port) ObDereferenceObject(ConnectionPort);
441
442 /* Check if this is a connection port with a server process */
444 (ConnectionPort->ServerProcess))
445 {
446 /* Dereference the server process */
447 ObDereferenceObject(ConnectionPort->ServerProcess);
448 ConnectionPort->ServerProcess = NULL;
449 }
450 }
451 else
452 {
453 /* Release the lock */
455 }
456
457 /* Free client security */
459 LPCTRACE(LPC_CLOSE_DEBUG, "Port: %p deleted\n", Port);
460}
461
462/* EOF */
NTSTATUS NTAPI MmUnmapViewOfSection(IN PEPROCESS Process, IN PVOID BaseAddress)
Definition: section.c:2750
#define PAGED_CODE()
unsigned char BOOLEAN
#define STATUS_NO_MEMORY
Definition: d3dkmdt.h:51
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
static const WCHAR Message[]
Definition: register.c:74
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define KeDelayExecutionThread(mode, foo, t)
Definition: env_spec_w32.h:484
_Outptr_ PFLT_PORT * ClientPort
Definition: fltkernel.h:1891
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:223
pPkgPnp m_DeviceInterfaceLock ReleaseLock(pFxDriverGlobals)
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
@ ProcessHandleCount
Definition: winternl.h:876
#define LPC_CLOSE_DEBUG
Definition: lpc.h:18
KGUARDED_MUTEX LpcpLock
Definition: port.c:20
#define LPCP_LOCK_HELD
Definition: lpc.h:63
#define LPCTRACE(x, fmt,...)
Definition: lpc.h:49
PAGED_LOOKASIDE_LIST LpcpMessagesLookaside
Definition: port.c:19
#define LPCP_LOCK_RELEASE
Definition: lpc.h:64
FORCEINLINE PLPCP_MESSAGE LpcpGetMessageFromThread(IN PETHREAD Thread)
Definition: lpc_x.h:129
#define LPCP_SECURITY_DYNAMIC
Definition: lpctypes.h:62
#define LPCP_COMMUNICATION_PORT
Definition: lpctypes.h:56
#define LPCP_CONNECTION_PORT
Definition: lpctypes.h:54
struct _LPCP_PORT_OBJECT * PLPCP_PORT_OBJECT
#define LPCP_NAME_DELETED
Definition: lpctypes.h:61
#define LPCP_CLIENT_PORT
Definition: lpctypes.h:57
#define LPCP_PORT_TYPE_MASK
Definition: lpctypes.h:58
struct _LPCP_CONNECTION_MESSAGE * PLPCP_CONNECTION_MESSAGE
#define LPCP_UNCONNECTED_PORT
Definition: lpctypes.h:55
#define ASSERT(a)
Definition: mode.c:44
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
#define SeDeleteClientSecurity(C)
Definition: imports.h:320
#define LPC_CONNECTION_REQUEST
Definition: port.c:102
#define LPC_PORT_CLOSED
Definition: port.c:97
#define KernelMode
Definition: asm.h:38
ULONG ACCESS_MASK
Definition: nt_native.h:40
VOID NTAPI LpcpFreeToPortZone(IN PLPCP_MESSAGE Message, IN ULONG LockFlags)
Definition: close.c:52
VOID NTAPI LpcpDestroyPortQueue(IN PLPCP_PORT_OBJECT Port, IN BOOLEAN Destroy)
Definition: close.c:111
VOID NTAPI LpcpDeletePort(IN PVOID ObjectBody)
Definition: close.c:302
VOID NTAPI LpcpFreePortClientSecurity(IN PLPCP_PORT_OBJECT Port)
Definition: close.c:282
VOID NTAPI LpcExitThread(IN PETHREAD Thread)
Definition: close.c:19
VOID NTAPI LpcpClosePort(IN PEPROCESS Process OPTIONAL, IN PVOID Object, IN ACCESS_MASK GrantedAccess, IN ULONG ProcessHandleCount, IN ULONG SystemHandleCount)
Definition: close.c:244
NTSTATUS NTAPI LpcRequestPort(IN PVOID PortObject, IN PPORT_MESSAGE LpcMessage)
Definition: send.c:22
HANDLE NTAPI PsGetCurrentProcessId(VOID)
Definition: process.c:1123
static ULONG Timeout
Definition: ping.c:61
LONG NTAPI KeReadStateSemaphore(IN PKSEMAPHORE Semaphore)
Definition: semphobj.c:41
LONG NTAPI KeReleaseSemaphore(IN PKSEMAPHORE Semaphore, IN KPRIORITY Increment, IN LONG Adjustment, IN BOOLEAN Wait)
Definition: semphobj.c:54
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
base of all file and directory entries
Definition: entries.h:83
PORT_MESSAGE h
Definition: lpctypes.h:269
LARGE_INTEGER CreateTime
Definition: lpctypes.h:270
USHORT Flags
Definition: cportlib.h:31
ULONG LpcExitThreadCalled
Definition: pstypes.h:1216
LIST_ENTRY LpcReplyChain
Definition: pstypes.h:1109
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
PLPCP_PORT_OBJECT ClientPort
Definition: lpctypes.h:257
LIST_ENTRY LpcDataInfoChainHead
Definition: lpctypes.h:222
PEPROCESS ServerProcess
Definition: lpctypes.h:225
#define NTAPI
Definition: typedefs.h:36
#define IN
Definition: typedefs.h:39
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
_Must_inspect_result_ _In_ WDFCOLLECTION _In_ WDFOBJECT Object
#define ObDereferenceObject
Definition: obfuncs.h:203
#define PsGetCurrentProcess
Definition: psfuncs.h:17
_In_ PSECURITY_SUBJECT_CONTEXT _In_ BOOLEAN _In_ ACCESS_MASK _In_ ACCESS_MASK _Outptr_opt_ PPRIVILEGE_SET _In_ PGENERIC_MAPPING _In_ KPROCESSOR_MODE _Out_ PACCESS_MASK GrantedAccess
Definition: sefuncs.h:20