Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

444 lines
12 KiB

  1. /*******************************************************************/
  2. /* Copyright(c) 1992 Microsoft Corporation */
  3. /*******************************************************************/
  4. //***
  5. //
  6. // Filename: closehnd.c
  7. //
  8. // Description: This module contains auxiliary procedures for the
  9. // supervisor's procedure-driven state machine that
  10. // handles device closing events.
  11. //
  12. // Author: Stefan Solomon (stefans) June 1, 1992.
  13. //
  14. //***
  15. #include "ddm.h"
  16. #include "handlers.h"
  17. #include "objects.h"
  18. #include <raserror.h>
  19. #include <ddmif.h>
  20. #include <util.h>
  21. #include "rasmanif.h"
  22. #include "isdn.h"
  23. #include "timer.h"
  24. #include <ntlsapi.h>
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. //***
  28. //
  29. // Function: DevStartClosing
  30. //
  31. // Descr:
  32. //
  33. //***
  34. VOID
  35. DevStartClosing(
  36. IN PDEVICE_OBJECT pDeviceObj
  37. )
  38. {
  39. PCONNECTION_OBJECT pConnObj;
  40. DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM,
  41. "DevStartClosing: Entered, hPort=%d", pDeviceObj->hPort);
  42. //
  43. // Was this a failure for a BAP callback?
  44. //
  45. if ( pDeviceObj->fFlags & DEV_OBJ_BAP_CALLBACK )
  46. {
  47. PppDdmBapCallbackResult( pDeviceObj->hBapConnection,
  48. ERROR_PORT_DISCONNECTED );
  49. pDeviceObj->fFlags &= ~DEV_OBJ_BAP_CALLBACK;
  50. }
  51. //
  52. // If not disconnected, disconnect the line.
  53. //
  54. if( pDeviceObj->ConnectionState != DISCONNECTED )
  55. {
  56. if(( gblDDMConfigInfo.pServiceStatus->dwCurrentState ==
  57. SERVICE_STOP_PENDING) &&
  58. (!IsPortOwned(pDeviceObj)))
  59. {
  60. //
  61. // RAS service is stopping and we do not own the port
  62. // so just mark the state as DISCONNECTED
  63. //
  64. pDeviceObj->ConnectionState = DISCONNECTED;
  65. DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM,
  66. "DevStartClosing:Disconnect not posted for biplx port%d",
  67. pDeviceObj->hPort);
  68. }
  69. else
  70. {
  71. RmDisconnect( pDeviceObj );
  72. }
  73. }
  74. //
  75. // If we are doing security dialog.
  76. //
  77. if ( pDeviceObj->SecurityState == DEV_OBJ_SECURITY_DIALOG_ACTIVE )
  78. {
  79. DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM,
  80. "DevStartClosing:Notifying sec. dll to Disconnect");
  81. //
  82. // If this fails then we assume that this port has been cleaned up
  83. //
  84. if ( (*gblDDMConfigInfo.lpfnRasEndSecurityDialog)( pDeviceObj->hPort )
  85. != NO_ERROR )
  86. {
  87. pDeviceObj->SecurityState = DEV_OBJ_SECURITY_DIALOG_INACTIVE;
  88. }
  89. else
  90. {
  91. pDeviceObj->SecurityState = DEV_OBJ_SECURITY_DIALOG_STOPPING;
  92. }
  93. }
  94. //
  95. // If authentication is active, stop it
  96. //
  97. pDeviceObj->fFlags &= (~DEV_OBJ_AUTH_ACTIVE);
  98. if ( ( pConnObj = ConnObjGetPointer( pDeviceObj->hConnection ) ) != NULL )
  99. {
  100. //
  101. // If our previous state has been active, get the time the user has been
  102. // active and log the result.
  103. //
  104. if (pDeviceObj->DeviceState == DEV_OBJ_ACTIVE)
  105. {
  106. LogConnectionEvent( pConnObj, pDeviceObj );
  107. }
  108. }
  109. //
  110. // If receive frame was active, stop it.
  111. //
  112. if ( pDeviceObj->fFlags & DEV_OBJ_RECEIVE_ACTIVE )
  113. {
  114. pDeviceObj->fFlags &= (~DEV_OBJ_RECEIVE_ACTIVE );
  115. }
  116. //
  117. // Stop timers. If no timer active, StopTimer still returns OK
  118. //
  119. TimerQRemove( (HANDLE)pDeviceObj->hPort, SvDiscTimeout );
  120. TimerQRemove( (HANDLE)pDeviceObj->hPort, SvAuthTimeout );
  121. TimerQRemove( (HANDLE)pDeviceObj->hPort, SvSecurityTimeout );
  122. //
  123. // Finally, change the state to closing
  124. //
  125. pDeviceObj->DeviceState = DEV_OBJ_CLOSING;
  126. //
  127. // If any any resources are still active, closing will have to wait
  128. // until all resources are released.
  129. // Check if everything has closed
  130. //
  131. DevCloseComplete( pDeviceObj );
  132. }
  133. //***
  134. //
  135. // Function: DevCloseComplete
  136. //
  137. // Description: Checks if there are still resources allocated.
  138. // If all cleaned up goes to next state
  139. //
  140. //***
  141. VOID
  142. DevCloseComplete(
  143. IN PDEVICE_OBJECT pDeviceObj
  144. )
  145. {
  146. BOOL fAuthClosed = FALSE;
  147. BOOL fRecvClosed = FALSE;
  148. BOOL fConnClosed = FALSE;
  149. BOOL fSecurityClosed = FALSE;
  150. BOOL fPppClosed = FALSE;
  151. PCONNECTION_OBJECT pConnObj = ConnObjGetPointer( pDeviceObj->hConnection );
  152. if ( !( pDeviceObj->fFlags & DEV_OBJ_AUTH_ACTIVE ) )
  153. {
  154. fAuthClosed = TRUE;
  155. }
  156. if ( !( pDeviceObj->fFlags & DEV_OBJ_RECEIVE_ACTIVE ) )
  157. {
  158. fRecvClosed = TRUE;
  159. }
  160. if ( !( pDeviceObj->fFlags & DEV_OBJ_PPP_IS_ACTIVE ) )
  161. {
  162. fPppClosed = TRUE;
  163. }
  164. //
  165. // Was this is the last link in the connection
  166. //
  167. if (pDeviceObj->ConnectionState == DISCONNECTED )
  168. {
  169. fConnClosed = TRUE;
  170. }
  171. if (pDeviceObj->SecurityState == DEV_OBJ_SECURITY_DIALOG_INACTIVE )
  172. {
  173. fSecurityClosed = TRUE;
  174. }
  175. DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM,
  176. "DevCloseComplete:hPort=%d,Auth=%d,Rcv=%d,Conn=%d %d,Sec=%d %d,Ppp=%d",
  177. pDeviceObj->hPort,
  178. !fAuthClosed,
  179. !fRecvClosed,
  180. pConnObj ? 0 : 1,
  181. !fConnClosed,
  182. pDeviceObj->ConnectionState,
  183. pDeviceObj->SecurityState,
  184. !fPppClosed );
  185. if ( fAuthClosed &&
  186. fRecvClosed &&
  187. fConnClosed &&
  188. fSecurityClosed &&
  189. fPppClosed )
  190. {
  191. //
  192. // Was this the last link in the bundle? If it was we clean up
  193. //
  194. if ( pConnObj != NULL )
  195. {
  196. HPORT hPortConnected;
  197. //
  198. // Remove this link from the connection
  199. //
  200. ConnObjRemoveLink( pDeviceObj->hConnection, pDeviceObj );
  201. //
  202. // If admin module is loaded, notify it of a link disconnection
  203. //
  204. if ( ( pDeviceObj->fFlags & DEV_OBJ_NOTIFY_OF_DISCONNECTION ) &&
  205. ( gblDDMConfigInfo.lpfnRasAdminLinkHangupNotification != NULL))
  206. {
  207. RAS_PORT_0 RasPort0;
  208. RAS_PORT_1 RasPort1;
  209. VOID (*MprAdminLinkHangupNotification)(RAS_PORT_0 *,
  210. RAS_PORT_1*);
  211. if ((GetRasPort0Data(pDeviceObj,&RasPort0) == NO_ERROR)
  212. &&
  213. (GetRasPort1Data(pDeviceObj,&RasPort1) == NO_ERROR))
  214. {
  215. MprAdminLinkHangupNotification =
  216. (VOID (*)( RAS_PORT_0 *, RAS_PORT_1 * ))
  217. gblDDMConfigInfo.lpfnRasAdminLinkHangupNotification;
  218. MprAdminLinkHangupNotification( &RasPort0, &RasPort1 );
  219. }
  220. }
  221. //
  222. // Confirm with RASMAN that there are no more ports in this
  223. // bundle. It may be that there is one but DDM has not gotten
  224. // a NewLink message from PPP yet.
  225. //
  226. if ( ( RasBundleGetPort( NULL, pConnObj->hConnection,
  227. &hPortConnected ) != NO_ERROR ) &&
  228. ( pConnObj->cActiveDevices == 0 ) )
  229. {
  230. //
  231. // If admin module is loaded, notify it of disconnection
  232. //
  233. if ( pConnObj->fFlags & CONN_OBJ_NOTIFY_OF_DISCONNECTION )
  234. {
  235. ConnectionHangupNotification( pConnObj );
  236. }
  237. //
  238. // Remove the interface object if it is not a full router.
  239. //
  240. if ( pConnObj->hDIMInterface != INVALID_HANDLE_VALUE )
  241. {
  242. ROUTER_INTERFACE_OBJECT * pIfObject;
  243. EnterCriticalSection(
  244. &(gblpInterfaceTable->CriticalSection));
  245. pIfObject = IfObjectGetPointer( pConnObj->hDIMInterface );
  246. if ( pIfObject != NULL )
  247. {
  248. IfObjectDisconnected( pIfObject );
  249. if ( pIfObject->IfType != ROUTER_IF_TYPE_FULL_ROUTER )
  250. {
  251. IfObjectDeleteInterface( pIfObject );
  252. IfObjectRemove( pConnObj->hDIMInterface );
  253. }
  254. }
  255. LeaveCriticalSection(
  256. &(gblpInterfaceTable->CriticalSection));
  257. }
  258. //
  259. // Remove the Connection Object
  260. //
  261. ConnObjRemoveAndDeAllocate( pDeviceObj->hConnection );
  262. }
  263. }
  264. //
  265. // Release the media (if any) used by this port
  266. //
  267. if ( pDeviceObj->fFlags & DEV_OBJ_MARKED_AS_INUSE )
  268. {
  269. pDeviceObj->fFlags &= ~DEV_OBJ_MARKED_AS_INUSE;
  270. gblDeviceTable.NumDevicesInUse--;
  271. //
  272. // Increase media count for this device
  273. //
  274. if ( pDeviceObj->fFlags & DEV_OBJ_ALLOW_ROUTERS )
  275. {
  276. MediaObjAddToTable( pDeviceObj->wchDeviceType );
  277. }
  278. //
  279. // Possibly need to notify router managers of reachability
  280. // change
  281. //
  282. EnterCriticalSection( &(gblpInterfaceTable->CriticalSection) );
  283. IfObjectNotifyAllOfReachabilityChange( TRUE,
  284. INTERFACE_OUT_OF_RESOURCES );
  285. LeaveCriticalSection( &(gblpInterfaceTable->CriticalSection) );
  286. }
  287. //
  288. // Release any RasMan buffers if we have allocated them
  289. //
  290. if ( pDeviceObj->pRasmanSendBuffer != NULL )
  291. {
  292. RasFreeBuffer( pDeviceObj->pRasmanSendBuffer );
  293. pDeviceObj->pRasmanSendBuffer = NULL;
  294. }
  295. if ( pDeviceObj->pRasmanRecvBuffer != NULL )
  296. {
  297. RasFreeBuffer( pDeviceObj->pRasmanRecvBuffer );
  298. pDeviceObj->pRasmanRecvBuffer = NULL;
  299. }
  300. RasSetRouterUsage( pDeviceObj->hPort, FALSE );
  301. //
  302. // If we have gotten a PnP remove message, then discard this port
  303. //
  304. if ( pDeviceObj->fFlags & DEV_OBJ_PNP_DELETE )
  305. {
  306. //
  307. // We do this in a worker thread since this thread may be
  308. // walking the device list, hence we cannot modify it here.
  309. //
  310. RtlQueueWorkItem( DeviceObjRemoveFromTable,
  311. pDeviceObj->hPort,
  312. WT_EXECUTEDEFAULT );
  313. return;
  314. }
  315. else
  316. {
  317. //
  318. // Reset fields in this port device
  319. //
  320. pDeviceObj->hConnection = (HCONN)INVALID_HANDLE_VALUE;
  321. pDeviceObj->wchUserName[0] = (WCHAR)NULL;
  322. pDeviceObj->wchDomainName[0] = (WCHAR)NULL;
  323. pDeviceObj->wchCallbackNumber[0] = (WCHAR)NULL;
  324. pDeviceObj->fFlags &= (~DEV_OBJ_IS_PPP);
  325. }
  326. //
  327. // switch to next state (based on the present service state)
  328. //
  329. switch ( gblDDMConfigInfo.pServiceStatus->dwCurrentState )
  330. {
  331. case SERVICE_RUNNING:
  332. case SERVICE_START_PENDING:
  333. //
  334. // post a listen on the device
  335. //
  336. pDeviceObj->DeviceState = DEV_OBJ_LISTENING;
  337. RmListen(pDeviceObj);
  338. break;
  339. case SERVICE_PAUSED:
  340. //
  341. // wait for the service to be running again
  342. //
  343. pDeviceObj->DeviceState = DEV_OBJ_CLOSED;
  344. break;
  345. case SERVICE_STOP_PENDING:
  346. //
  347. // this device has terminated. Announce the closure to
  348. // the central stop service coordinator
  349. //
  350. pDeviceObj->DeviceState = DEV_OBJ_CLOSED;
  351. DDMServiceStopComplete();
  352. break;
  353. default:
  354. RTASSERT(FALSE);
  355. break;
  356. }
  357. }
  358. }
  359.