Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenclose.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS Kernel 00003 * LICENSE: GPL - See COPYING in the top level directory 00004 * FILE: ntoskrnl/lpc/close.c 00005 * PURPOSE: Local Procedure Call: Rundown, Cleanup, Deletion 00006 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 00007 */ 00008 00009 /* INCLUDES ******************************************************************/ 00010 00011 #include <ntoskrnl.h> 00012 #define NDEBUG 00013 #include <debug.h> 00014 00015 /* PRIVATE FUNCTIONS *********************************************************/ 00016 00017 VOID 00018 NTAPI 00019 LpcExitThread(IN PETHREAD Thread) 00020 { 00021 PLPCP_MESSAGE Message; 00022 ASSERT(Thread == PsGetCurrentThread()); 00023 00024 /* Acquire the lock */ 00025 KeAcquireGuardedMutex(&LpcpLock); 00026 00027 /* Make sure that the Reply Chain is empty */ 00028 if (!IsListEmpty(&Thread->LpcReplyChain)) 00029 { 00030 /* It's not, remove the entry */ 00031 RemoveEntryList(&Thread->LpcReplyChain); 00032 } 00033 00034 /* Set the thread in exit mode */ 00035 Thread->LpcExitThreadCalled = TRUE; 00036 Thread->LpcReplyMessageId = 0; 00037 00038 /* Check if there's a reply message */ 00039 Message = LpcpGetMessageFromThread(Thread); 00040 if (Message) 00041 { 00042 /* FIXME: TODO */ 00043 ASSERT(FALSE); 00044 } 00045 00046 /* Release the lock */ 00047 KeReleaseGuardedMutex(&LpcpLock); 00048 } 00049 00050 VOID 00051 NTAPI 00052 LpcpFreeToPortZone(IN PLPCP_MESSAGE Message, 00053 IN ULONG Flags) 00054 { 00055 PLPCP_CONNECTION_MESSAGE ConnectMessage; 00056 PLPCP_PORT_OBJECT ClientPort = NULL; 00057 PETHREAD Thread = NULL; 00058 BOOLEAN LockHeld = Flags & 1, ReleaseLock = Flags & 2; 00059 PAGED_CODE(); 00060 LPCTRACE(LPC_CLOSE_DEBUG, "Message: %p. Flags: %lx\n", Message, Flags); 00061 00062 /* Acquire the lock if not already */ 00063 if (!LockHeld) KeAcquireGuardedMutex(&LpcpLock); 00064 00065 /* Check if the queue list is empty */ 00066 if (!IsListEmpty(&Message->Entry)) 00067 { 00068 /* Remove and re-initialize */ 00069 RemoveEntryList(&Message->Entry); 00070 InitializeListHead(&Message->Entry); 00071 } 00072 00073 /* Check if we've already replied */ 00074 if (Message->RepliedToThread) 00075 { 00076 /* Set thread to dereference and clean up */ 00077 Thread = Message->RepliedToThread; 00078 Message->RepliedToThread = NULL; 00079 } 00080 00081 /* Check if this is a connection request */ 00082 if (Message->Request.u2.s2.Type == LPC_CONNECTION_REQUEST) 00083 { 00084 /* Get the connection message */ 00085 ConnectMessage = (PLPCP_CONNECTION_MESSAGE)(Message + 1); 00086 00087 /* Clear the client port */ 00088 ClientPort = ConnectMessage->ClientPort; 00089 if (ClientPort) ConnectMessage->ClientPort = NULL; 00090 } 00091 00092 /* Release the lock */ 00093 KeReleaseGuardedMutex(&LpcpLock); 00094 00095 /* Check if we had anything to dereference */ 00096 if (Thread) ObDereferenceObject(Thread); 00097 if (ClientPort) ObDereferenceObject(ClientPort); 00098 00099 /* Free the entry */ 00100 ExFreeToPagedLookasideList(&LpcpMessagesLookaside, Message); 00101 00102 /* Reacquire the lock if needed */ 00103 if ((LockHeld) && !(ReleaseLock)) KeAcquireGuardedMutex(&LpcpLock); 00104 } 00105 00106 VOID 00107 NTAPI 00108 LpcpDestroyPortQueue(IN PLPCP_PORT_OBJECT Port, 00109 IN BOOLEAN Destroy) 00110 { 00111 PLIST_ENTRY ListHead, NextEntry; 00112 PETHREAD Thread; 00113 PLPCP_MESSAGE Message; 00114 PLPCP_PORT_OBJECT ConnectionPort = NULL; 00115 PLPCP_CONNECTION_MESSAGE ConnectMessage; 00116 PAGED_CODE(); 00117 LPCTRACE(LPC_CLOSE_DEBUG, "Port: %p. Flags: %lx\n", Port, Port->Flags); 00118 00119 /* Hold the lock */ 00120 KeAcquireGuardedMutex(&LpcpLock); 00121 00122 /* Check if we have a connected port */ 00123 if (((Port->Flags & LPCP_PORT_TYPE_MASK) != LPCP_UNCONNECTED_PORT) && 00124 (Port->ConnectedPort)) 00125 { 00126 /* Disconnect it */ 00127 Port->ConnectedPort->ConnectedPort = NULL; 00128 ConnectionPort = Port->ConnectedPort->ConnectionPort; 00129 if (ConnectionPort) 00130 { 00131 /* Clear connection port */ 00132 Port->ConnectedPort->ConnectionPort = NULL; 00133 } 00134 } 00135 00136 /* Check if this is a connection port */ 00137 if ((Port->Flags & LPCP_PORT_TYPE_MASK) == LPCP_CONNECTION_PORT) 00138 { 00139 /* Delete the name */ 00140 Port->Flags |= LPCP_NAME_DELETED; 00141 } 00142 00143 /* Walk all the threads waiting and signal them */ 00144 ListHead = &Port->LpcReplyChainHead; 00145 NextEntry = ListHead->Flink; 00146 while ((NextEntry) && (NextEntry != ListHead)) 00147 { 00148 /* Get the Thread */ 00149 Thread = CONTAINING_RECORD(NextEntry, ETHREAD, LpcReplyChain); 00150 00151 /* Make sure we're not in exit */ 00152 if (Thread->LpcExitThreadCalled) break; 00153 00154 /* Move to the next entry */ 00155 NextEntry = NextEntry->Flink; 00156 00157 /* Remove and reinitialize the List */ 00158 RemoveEntryList(&Thread->LpcReplyChain); 00159 InitializeListHead(&Thread->LpcReplyChain); 00160 00161 /* Check if someone is waiting */ 00162 if (!KeReadStateSemaphore(&Thread->LpcReplySemaphore)) 00163 { 00164 /* Get the message */ 00165 Message = LpcpGetMessageFromThread(Thread); 00166 if (Message) 00167 { 00168 /* Check if it's a connection request */ 00169 if (Message->Request.u2.s2.Type == LPC_CONNECTION_REQUEST) 00170 { 00171 /* Get the connection message */ 00172 ConnectMessage = (PLPCP_CONNECTION_MESSAGE)(Message + 1); 00173 00174 /* Check if it had a section */ 00175 if (ConnectMessage->SectionToMap) 00176 { 00177 /* Dereference it */ 00178 ObDereferenceObject(ConnectMessage->SectionToMap); 00179 } 00180 } 00181 00182 /* Clear the reply message */ 00183 Thread->LpcReplyMessage = NULL; 00184 00185 /* And remove the message from the port zone */ 00186 LpcpFreeToPortZone(Message, 1); 00187 NextEntry = Port->LpcReplyChainHead.Flink; 00188 } 00189 00190 /* Release the semaphore and reset message id count */ 00191 Thread->LpcReplyMessageId = 0; 00192 KeReleaseSemaphore(&Thread->LpcReplySemaphore, 0, 1, FALSE); 00193 } 00194 } 00195 00196 /* Reinitialize the list head */ 00197 InitializeListHead(&Port->LpcReplyChainHead); 00198 00199 /* Loop queued messages */ 00200 while ((Port->MsgQueue.ReceiveHead.Flink) && 00201 !(IsListEmpty(&Port->MsgQueue.ReceiveHead))) 00202 { 00203 /* Get the message */ 00204 Message = CONTAINING_RECORD(Port->MsgQueue.ReceiveHead.Flink, 00205 LPCP_MESSAGE, 00206 Entry); 00207 00208 /* Free and reinitialize it's list head */ 00209 RemoveEntryList(&Message->Entry); 00210 InitializeListHead(&Message->Entry); 00211 00212 /* Remove it from the port zone */ 00213 LpcpFreeToPortZone(Message, 1); 00214 } 00215 00216 /* Release the lock */ 00217 KeReleaseGuardedMutex(&LpcpLock); 00218 00219 /* Dereference the connection port */ 00220 if (ConnectionPort) ObDereferenceObject(ConnectionPort); 00221 00222 /* Check if we have to free the port entirely */ 00223 if (Destroy) 00224 { 00225 /* Check if the semaphore exists */ 00226 if (Port->MsgQueue.Semaphore) 00227 { 00228 /* Use the semaphore to find the port queue and free it */ 00229 ExFreePool(CONTAINING_RECORD(Port->MsgQueue.Semaphore, 00230 LPCP_NONPAGED_PORT_QUEUE, 00231 Semaphore)); 00232 } 00233 } 00234 } 00235 00236 VOID 00237 NTAPI 00238 LpcpClosePort(IN PEPROCESS Process OPTIONAL, 00239 IN PVOID Object, 00240 IN ACCESS_MASK GrantedAccess, 00241 IN ULONG ProcessHandleCount, 00242 IN ULONG SystemHandleCount) 00243 { 00244 PLPCP_PORT_OBJECT Port = (PLPCP_PORT_OBJECT)Object; 00245 LPCTRACE(LPC_CLOSE_DEBUG, "Port: %p. Flags: %lx\n", Port, Port->Flags); 00246 00247 /* Only Server-side Connection Ports need clean up*/ 00248 if ((Port->Flags & LPCP_PORT_TYPE_MASK) == LPCP_CONNECTION_PORT) 00249 { 00250 /* Check the handle count */ 00251 switch (SystemHandleCount) 00252 { 00253 /* No handles left */ 00254 case 0: 00255 00256 /* Destroy the port queue */ 00257 LpcpDestroyPortQueue(Port, TRUE); 00258 break; 00259 00260 /* Last handle remaining */ 00261 case 1: 00262 00263 /* Reset the queue only */ 00264 LpcpDestroyPortQueue(Port, FALSE); 00265 00266 /* More handles remain, do nothing */ 00267 default: 00268 break; 00269 } 00270 } 00271 } 00272 00273 VOID 00274 NTAPI 00275 LpcpFreePortClientSecurity(IN PLPCP_PORT_OBJECT Port) 00276 { 00277 /* Check if this is a client port */ 00278 if ((Port->Flags & LPCP_PORT_TYPE_MASK) == LPCP_CLIENT_PORT) 00279 { 00280 /* Check if security is static */ 00281 if (!(Port->Flags & LPCP_SECURITY_DYNAMIC)) 00282 { 00283 /* Check if we have a token */ 00284 if (Port->StaticSecurity.ClientToken) 00285 { 00286 /* Free security */ 00287 SeDeleteClientSecurity(&Port->StaticSecurity); 00288 } 00289 } 00290 } 00291 } 00292 00293 VOID 00294 NTAPI 00295 LpcpDeletePort(IN PVOID ObjectBody) 00296 { 00297 LARGE_INTEGER Timeout; 00298 PETHREAD Thread; 00299 PLPCP_PORT_OBJECT Port = (PLPCP_PORT_OBJECT)ObjectBody; 00300 PLPCP_PORT_OBJECT ConnectionPort; 00301 PLPCP_MESSAGE Message; 00302 PLIST_ENTRY ListHead, NextEntry; 00303 HANDLE Pid; 00304 CLIENT_DIED_MSG ClientDiedMsg; 00305 Timeout.QuadPart = -1000000; 00306 PAGED_CODE(); 00307 LPCTRACE(LPC_CLOSE_DEBUG, "Port: %p. Flags: %lx\n", Port, Port->Flags); 00308 00309 /* Check if this is a communication port */ 00310 if ((Port->Flags & LPCP_PORT_TYPE_MASK) == LPCP_COMMUNICATION_PORT) 00311 { 00312 /* Acquire the lock */ 00313 KeAcquireGuardedMutex(&LpcpLock); 00314 00315 /* Get the thread */ 00316 Thread = Port->ClientThread; 00317 if (Thread) 00318 { 00319 /* Clear it */ 00320 Port->ClientThread = NULL; 00321 00322 /* Release the lock and dereference */ 00323 KeReleaseGuardedMutex(&LpcpLock); 00324 ObDereferenceObject(Thread); 00325 } 00326 else 00327 { 00328 /* Release the lock */ 00329 KeReleaseGuardedMutex(&LpcpLock); 00330 } 00331 } 00332 00333 /* Check if this is a client-side port */ 00334 if ((Port->Flags & LPCP_PORT_TYPE_MASK) == LPCP_CLIENT_PORT) 00335 { 00336 /* Setup the client died message */ 00337 ClientDiedMsg.h.u1.s1.TotalLength = sizeof(ClientDiedMsg); 00338 ClientDiedMsg.h.u1.s1.DataLength = sizeof(ClientDiedMsg.CreateTime); 00339 ClientDiedMsg.h.u2.ZeroInit = 0; 00340 ClientDiedMsg.h.u2.s2.Type = LPC_PORT_CLOSED; 00341 ClientDiedMsg.CreateTime = PsGetCurrentProcess()->CreateTime; 00342 00343 /* Send it */ 00344 for (;;) 00345 { 00346 /* Send the message */ 00347 if (LpcRequestPort(Port, 00348 &ClientDiedMsg.h) != STATUS_NO_MEMORY) break; 00349 00350 /* Wait until trying again */ 00351 KeDelayExecutionThread(KernelMode, FALSE, &Timeout); 00352 } 00353 } 00354 00355 /* Destroy the port queue */ 00356 LpcpDestroyPortQueue(Port, TRUE); 00357 00358 /* Check if we had views */ 00359 if ((Port->ClientSectionBase) || (Port->ServerSectionBase)) 00360 { 00361 /* Check if we had a client view */ 00362 if (Port->ClientSectionBase) 00363 { 00364 /* Unmap it */ 00365 MmUnmapViewOfSection(Port->MappingProcess, 00366 Port->ClientSectionBase); 00367 } 00368 00369 /* Check for a server view */ 00370 if (Port->ServerSectionBase) 00371 { 00372 /* Unmap it */ 00373 MmUnmapViewOfSection(Port->MappingProcess, 00374 Port->ServerSectionBase); 00375 } 00376 00377 /* Dereference the mapping process */ 00378 ObDereferenceObject(Port->MappingProcess); 00379 Port->MappingProcess = NULL; 00380 } 00381 00382 /* Acquire the lock */ 00383 KeAcquireGuardedMutex(&LpcpLock); 00384 00385 /* Get the connection port */ 00386 ConnectionPort = Port->ConnectionPort; 00387 if (ConnectionPort) 00388 { 00389 /* Get the PID */ 00390 Pid = PsGetCurrentProcessId(); 00391 00392 /* Loop the data lists */ 00393 ListHead = &ConnectionPort->LpcDataInfoChainHead; 00394 NextEntry = ListHead->Flink; 00395 while (NextEntry != ListHead) 00396 { 00397 /* Get the message */ 00398 Message = CONTAINING_RECORD(NextEntry, LPCP_MESSAGE, Entry); 00399 NextEntry = NextEntry->Flink; 00400 00401 /* Check if this is the connection port */ 00402 if (Port == ConnectionPort) 00403 { 00404 /* Free queued messages */ 00405 RemoveEntryList(&Message->Entry); 00406 InitializeListHead(&Message->Entry); 00407 LpcpFreeToPortZone(Message, 1); 00408 00409 /* Restart at the head */ 00410 NextEntry = ListHead->Flink; 00411 } 00412 else if ((Message->Request.ClientId.UniqueProcess == Pid) && 00413 ((Message->SenderPort == Port) || 00414 (Message->SenderPort == Port->ConnectedPort) || 00415 (Message->SenderPort == ConnectionPort))) 00416 { 00417 /* Remove it */ 00418 RemoveEntryList(&Message->Entry); 00419 InitializeListHead(&Message->Entry); 00420 LpcpFreeToPortZone(Message, 1); 00421 00422 /* Restart at the head */ 00423 NextEntry = ListHead->Flink; 00424 } 00425 } 00426 00427 /* Release the lock */ 00428 KeReleaseGuardedMutex(&LpcpLock); 00429 00430 /* Dereference the object unless it's the same port */ 00431 if (ConnectionPort != Port) ObDereferenceObject(ConnectionPort); 00432 } 00433 else 00434 { 00435 /* Release the lock */ 00436 KeReleaseGuardedMutex(&LpcpLock); 00437 } 00438 00439 /* Check if this is a connection port with a server process*/ 00440 if (((Port->Flags & LPCP_PORT_TYPE_MASK) == LPCP_CONNECTION_PORT) && 00441 (ConnectionPort->ServerProcess)) 00442 { 00443 /* Dereference the server process */ 00444 ObDereferenceObject(ConnectionPort->ServerProcess); 00445 ConnectionPort->ServerProcess = NULL; 00446 } 00447 00448 /* Free client security */ 00449 LpcpFreePortClientSecurity(Port); 00450 LPCTRACE(LPC_CLOSE_DEBUG, "Port: %p deleted\n", Port); 00451 } 00452 00453 /* EOF */ Generated on Sun May 27 2012 04:27:34 for ReactOS by
1.7.6.1
|