Leaked source code of windows server 2003
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.

455 lines
13 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. {
  206. RAS_PORT_0 RasPort0;
  207. RAS_PORT_1 RasPort1;
  208. VOID (*MprAdminLinkHangupNotification)(RAS_PORT_0 *,
  209. RAS_PORT_1*);
  210. if ((GetRasPort0Data(pDeviceObj,&RasPort0) == NO_ERROR)
  211. &&
  212. (GetRasPort1Data(pDeviceObj,&RasPort1) == NO_ERROR))
  213. {
  214. DWORD i;
  215. for (i=0; i<gblDDMConfigInfo.NumAdminDlls; i++)
  216. {
  217. PADMIN_DLL_CALLBACKS AdminDllCallbacks = &gblDDMConfigInfo.AdminDllCallbacks[i];
  218. if (AdminDllCallbacks->lpfnRasAdminLinkHangupNotification != NULL)
  219. {
  220. MprAdminLinkHangupNotification =
  221. (VOID (*)( RAS_PORT_0 *, RAS_PORT_1 * ))
  222. AdminDllCallbacks->lpfnRasAdminLinkHangupNotification;
  223. MprAdminLinkHangupNotification( &RasPort0, &RasPort1 );
  224. }
  225. }
  226. }
  227. }
  228. //
  229. // Confirm with RASMAN that there are no more ports in this
  230. // bundle. It may be that there is one but DDM has not gotten
  231. // a NewLink message from PPP yet.
  232. //
  233. if ( ( RasBundleGetPort( NULL, pConnObj->hConnection,
  234. &hPortConnected ) != NO_ERROR ) &&
  235. ( pConnObj->cActiveDevices == 0 ) )
  236. {
  237. //
  238. // If admin module is loaded, notify it of disconnection
  239. //
  240. if ( pConnObj->fFlags & CONN_OBJ_NOTIFY_OF_DISCONNECTION )
  241. {
  242. ConnectionHangupNotification( pConnObj );
  243. }
  244. //
  245. // Remove the interface object if it is not a full router.
  246. //
  247. if ( pConnObj->hDIMInterface != INVALID_HANDLE_VALUE )
  248. {
  249. ROUTER_INTERFACE_OBJECT * pIfObject;
  250. EnterCriticalSection(
  251. &(gblpInterfaceTable->CriticalSection));
  252. pIfObject = IfObjectGetPointer( pConnObj->hDIMInterface );
  253. if ( pIfObject != NULL )
  254. {
  255. IfObjectDisconnected( pIfObject );
  256. if ( pIfObject->IfType != ROUTER_IF_TYPE_FULL_ROUTER )
  257. {
  258. IfObjectDeleteInterface( pIfObject );
  259. IfObjectRemove( pConnObj->hDIMInterface );
  260. }
  261. }
  262. LeaveCriticalSection(
  263. &(gblpInterfaceTable->CriticalSection));
  264. }
  265. //
  266. // Remove the Connection Object
  267. //
  268. ConnObjRemoveAndDeAllocate( pDeviceObj->hConnection );
  269. }
  270. }
  271. //
  272. // Release the media (if any) used by this port
  273. //
  274. if ( pDeviceObj->fFlags & DEV_OBJ_MARKED_AS_INUSE )
  275. {
  276. pDeviceObj->fFlags &= ~DEV_OBJ_MARKED_AS_INUSE;
  277. gblDeviceTable.NumDevicesInUse--;
  278. //
  279. // Increase media count for this device
  280. //
  281. if ( pDeviceObj->fFlags & DEV_OBJ_ALLOW_ROUTERS )
  282. {
  283. MediaObjAddToTable( pDeviceObj->wchDeviceType );
  284. }
  285. //
  286. // Possibly need to notify router managers of reachability
  287. // change
  288. //
  289. EnterCriticalSection( &(gblpInterfaceTable->CriticalSection) );
  290. IfObjectNotifyAllOfReachabilityChange( TRUE,
  291. INTERFACE_OUT_OF_RESOURCES );
  292. LeaveCriticalSection( &(gblpInterfaceTable->CriticalSection) );
  293. }
  294. //
  295. // Release any RasMan buffers if we have allocated them
  296. //
  297. if ( pDeviceObj->pRasmanSendBuffer != NULL )
  298. {
  299. RasFreeBuffer( pDeviceObj->pRasmanSendBuffer );
  300. pDeviceObj->pRasmanSendBuffer = NULL;
  301. }
  302. if ( pDeviceObj->pRasmanRecvBuffer != NULL )
  303. {
  304. RasFreeBuffer( pDeviceObj->pRasmanRecvBuffer );
  305. pDeviceObj->pRasmanRecvBuffer = NULL;
  306. }
  307. RasSetRouterUsage( pDeviceObj->hPort, FALSE );
  308. //
  309. // If we have gotten a PnP remove message, then discard this port
  310. //
  311. if ( pDeviceObj->fFlags & DEV_OBJ_PNP_DELETE )
  312. {
  313. //
  314. // We do this in a worker thread since this thread may be
  315. // walking the device list, hence we cannot modify it here.
  316. //
  317. RtlQueueWorkItem( DeviceObjRemoveFromTable,
  318. pDeviceObj->hPort,
  319. WT_EXECUTEDEFAULT );
  320. return;
  321. }
  322. else
  323. {
  324. //
  325. // Reset fields in this port device
  326. //
  327. pDeviceObj->hConnection = (HCONN)INVALID_HANDLE_VALUE;
  328. pDeviceObj->wchUserName[0] = (WCHAR)NULL;
  329. pDeviceObj->wchDomainName[0] = (WCHAR)NULL;
  330. pDeviceObj->wchCallbackNumber[0] = (WCHAR)NULL;
  331. pDeviceObj->fFlags &= (~DEV_OBJ_IS_PPP);
  332. pDeviceObj->dwDisconnectReason = 0;
  333. }
  334. //
  335. // switch to next state (based on the present service state)
  336. //
  337. switch ( gblDDMConfigInfo.pServiceStatus->dwCurrentState )
  338. {
  339. case SERVICE_RUNNING:
  340. case SERVICE_START_PENDING:
  341. //
  342. // post a listen on the device
  343. //
  344. pDeviceObj->DeviceState = DEV_OBJ_LISTENING;
  345. RmListen(pDeviceObj);
  346. break;
  347. case SERVICE_PAUSED:
  348. //
  349. // wait for the service to be running again
  350. //
  351. pDeviceObj->DeviceState = DEV_OBJ_CLOSED;
  352. break;
  353. case SERVICE_STOP_PENDING:
  354. //
  355. // this device has terminated. Announce the closure to
  356. // the central stop service coordinator
  357. //
  358. pDeviceObj->DeviceState = DEV_OBJ_CLOSED;
  359. DDMServiceStopComplete();
  360. break;
  361. default:
  362. RTASSERT(FALSE);
  363. break;
  364. }
  365. }
  366. }
  367.