Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

lpcclose.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1989 Microsoft Corporation 00004 00005 Module Name: 00006 00007 lpcclose.c 00008 00009 Abstract: 00010 00011 Local Inter-Process Communication close procedures that are called when 00012 a connection port or a communications port is closed. 00013 00014 Author: 00015 00016 Steve Wood (stevewo) 15-May-1989 00017 00018 Revision History: 00019 00020 --*/ 00021 00022 #include "lpcp.h" 00023 00024 #ifdef ALLOC_PRAGMA 00025 #pragma alloc_text(PAGE,LpcpDeletePort) 00026 #pragma alloc_text(PAGE,LpcExitThread) 00027 #endif 00028 00029 00030 VOID 00031 LpcpClosePort ( 00032 IN PEPROCESS Process OPTIONAL, 00033 IN PVOID Object, 00034 IN ACCESS_MASK GrantedAccess, 00035 IN ULONG ProcessHandleCount, 00036 IN ULONG SystemHandleCount 00037 ) 00038 00039 /*++ 00040 00041 Routine Description: 00042 00043 This routine is the callback used for closing a port object. 00044 00045 Arguments: 00046 00047 Process - Supplies an optional pointer to the process whose port is being 00048 closed 00049 00050 Object - Supplies a pointer to the port object being closed 00051 00052 GrantedAccess - Supplies the access granted to the handle closing port 00053 object 00054 00055 ProcessHandleCount - Supplies the number of process handles remaining to 00056 the object 00057 00058 SystemHandleCount - Supplies the number of system handles remaining to 00059 the object 00060 00061 Return Value: 00062 00063 None. 00064 00065 --*/ 00066 00067 { 00068 // 00069 // Translate the object to what it really is, an LPCP port object 00070 // 00071 00072 PLPCP_PORT_OBJECT Port = Object; 00073 00074 // 00075 // We only have work to do if the object is a server communication port 00076 // 00077 00078 if ( (Port->Flags & PORT_TYPE) == SERVER_CONNECTION_PORT ) { 00079 00080 // 00081 // If this is a server commucation port without any system handles 00082 // then we can completely destroy the communication queue for the 00083 // port 00084 // 00085 00086 if ( SystemHandleCount == 0 ) { 00087 00088 LpcpDestroyPortQueue( Port, TRUE ); 00089 00090 // 00091 // If there is only one system handle left then we'll reset the 00092 // communication queue for the port 00093 // 00094 00095 } else if ( SystemHandleCount == 1 ) { 00096 00097 LpcpDestroyPortQueue( Port, FALSE ); 00098 } 00099 00100 // 00101 // Otherwise we do nothing 00102 // 00103 } 00104 00105 return; 00106 } 00107 00108 00109 VOID 00110 LpcpDeletePort ( 00111 IN PVOID Object 00112 ) 00113 00114 /*++ 00115 00116 Routine Description: 00117 00118 This routine is the callback used for deleting a port object. 00119 00120 Arguments: 00121 00122 Object - Supplies a pointer to the port object being deleted 00123 00124 Return Value: 00125 00126 None. 00127 00128 --*/ 00129 00130 { 00131 PLPCP_PORT_OBJECT Port = Object; 00132 PLPCP_PORT_OBJECT ConnectionPort; 00133 LPC_CLIENT_DIED_MSG ClientPortClosedDatagram; 00134 PLPCP_MESSAGE Msg; 00135 PLIST_ENTRY Head, Next; 00136 HANDLE CurrentProcessId; 00137 00138 PAGED_CODE(); 00139 00140 // 00141 // If the port is a server communication port then make sure that if 00142 // there is a dangling client thread that we get rid of it. This 00143 // handles the case of someone calling NtAcceptConnectPort and not 00144 // calling NtCompleteConnectPort 00145 // 00146 00147 LpcpPortExtraDataDestroy( Port ); 00148 00149 if ((Port->Flags & PORT_TYPE) == SERVER_COMMUNICATION_PORT) { 00150 00151 PETHREAD ClientThread; 00152 00153 LpcpAcquireLpcpLock(); 00154 00155 if ((ClientThread = Port->ClientThread) != NULL) { 00156 00157 Port->ClientThread = NULL; 00158 00159 LpcpReleaseLpcpLock(); 00160 00161 ObDereferenceObject( ClientThread ); 00162 00163 } else { 00164 00165 LpcpReleaseLpcpLock(); 00166 } 00167 } 00168 00169 // 00170 // Send an LPC_PORT_CLOSED datagram to whoever is connected 00171 // to this port so they know they are no longer connected. 00172 // 00173 00174 if ((Port->Flags & PORT_TYPE) == CLIENT_COMMUNICATION_PORT) { 00175 00176 ClientPortClosedDatagram.PortMsg.u1.s1.TotalLength = sizeof( ClientPortClosedDatagram ); 00177 ClientPortClosedDatagram.PortMsg.u1.s1.DataLength = sizeof( ClientPortClosedDatagram.CreateTime ); 00178 00179 ClientPortClosedDatagram.PortMsg.u2.s2.Type = LPC_PORT_CLOSED; 00180 ClientPortClosedDatagram.PortMsg.u2.s2.DataInfoOffset = 0; 00181 00182 ClientPortClosedDatagram.CreateTime = PsGetCurrentProcess()->CreateTime; 00183 00184 LpcRequestPort( Port, (PPORT_MESSAGE)&ClientPortClosedDatagram ); 00185 } 00186 00187 // 00188 // If connected, disconnect the port, and then scan the message queue 00189 // for this port and dereference any messages in the queue. 00190 // 00191 00192 LpcpDestroyPortQueue( Port, TRUE ); 00193 00194 // 00195 // If the client has a port memory view, then unmap it 00196 // 00197 00198 if (Port->ClientSectionBase != NULL) { 00199 00200 MmUnmapViewOfSection( PsGetCurrentProcess(), 00201 Port->ClientSectionBase ); 00202 00203 } 00204 00205 // 00206 // If the server has a port memory view, then unmap it 00207 // 00208 00209 if (Port->ServerSectionBase != NULL) { 00210 00211 MmUnmapViewOfSection( PsGetCurrentProcess(), 00212 Port->ServerSectionBase ); 00213 00214 } 00215 00216 // 00217 // Dereference the pointer to the connection port if it is not 00218 // this port. 00219 // 00220 00221 if (ConnectionPort = Port->ConnectionPort) { 00222 00223 CurrentProcessId = PsGetCurrentThread()->Cid.UniqueProcess; 00224 00225 LpcpAcquireLpcpLock(); 00226 00227 Head = &ConnectionPort->LpcDataInfoChainHead; 00228 Next = Head->Flink; 00229 00230 while (Next != Head) { 00231 00232 Msg = CONTAINING_RECORD( Next, LPCP_MESSAGE, Entry ); 00233 Next = Next->Flink; 00234 00235 if (Msg->Request.ClientId.UniqueProcess == CurrentProcessId) { 00236 00237 LpcpTrace(( "%s Freeing DataInfo Message %lx (%u.%u) Port: %lx\n", 00238 PsGetCurrentProcess()->ImageFileName, 00239 Msg, 00240 Msg->Request.MessageId, 00241 Msg->Request.CallbackId, 00242 ConnectionPort )); 00243 00244 RemoveEntryList( &Msg->Entry ); 00245 00246 LpcpFreeToPortZone( Msg, TRUE ); 00247 } 00248 } 00249 00250 LpcpReleaseLpcpLock(); 00251 00252 if (ConnectionPort != Port) { 00253 00254 ObDereferenceObject( ConnectionPort ); 00255 } 00256 } 00257 00258 if (((Port->Flags & PORT_TYPE) == SERVER_CONNECTION_PORT) && 00259 (ConnectionPort->ServerProcess != NULL)) { 00260 00261 ObDereferenceObject( ConnectionPort->ServerProcess ); 00262 00263 ConnectionPort->ServerProcess = NULL; 00264 } 00265 00266 // 00267 // Free any static client security context 00268 // 00269 00270 LpcpFreePortClientSecurity( Port ); 00271 00272 // 00273 // And return to our caller 00274 // 00275 00276 return; 00277 } 00278 00279 00280 VOID 00281 LpcExitThread ( 00282 PETHREAD Thread 00283 ) 00284 00285 /*++ 00286 00287 Routine Description: 00288 00289 This routine is called whenever a thread is exiting and need to cleanup the 00290 lpc port for the thread. 00291 00292 Arguments: 00293 00294 Thread - Supplies the thread being terminated 00295 00296 Return Value: 00297 00298 None. 00299 00300 --*/ 00301 00302 { 00303 PLPCP_MESSAGE Msg; 00304 00305 // 00306 // Acquire the mutex that protects the LpcReplyMessage field of 00307 // the thread. Zero the field so nobody else tries to process it 00308 // when we release the lock. 00309 // 00310 00311 LpcpAcquireLpcpLock(); 00312 00313 if (!IsListEmpty( &Thread->LpcReplyChain )) { 00314 00315 RemoveEntryList( &Thread->LpcReplyChain ); 00316 } 00317 00318 // 00319 // Indicate that this thread is exiting 00320 // 00321 00322 Thread->LpcExitThreadCalled = TRUE; 00323 Thread->LpcReplyMessageId = 0; 00324 00325 // 00326 // If we need to reply to a message then if the thread that we need to reply 00327 // to is still around we want to dereference the thread and free the message 00328 // 00329 00330 Msg = Thread->LpcReplyMessage; 00331 00332 if (Msg != NULL) { 00333 00334 Thread->LpcReplyMessage = NULL; 00335 00336 if (Msg->RepliedToThread != NULL) { 00337 00338 ObDereferenceObject( Msg->RepliedToThread ); 00339 00340 Msg->RepliedToThread = NULL; 00341 } 00342 00343 LpcpTrace(( "Cleanup Msg %lx (%d) for Thread %lx allocated\n", Msg, IsListEmpty( &Msg->Entry ), Thread )); 00344 00345 LpcpFreeToPortZone( Msg, TRUE ); 00346 } 00347 00348 // 00349 // Free the global lpc lock 00350 // 00351 00352 LpcpReleaseLpcpLock(); 00353 00354 // 00355 // And return to our caller 00356 // 00357 00358 return; 00359 }

Generated on Sat May 15 19:40:39 2004 for test by doxygen 1.3.7