ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

close.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.