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.

295 lines
7.6 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997.
  5. //
  6. // File: A I C . C P P
  7. //
  8. // Contents: Notification support for active inbound ras connections.
  9. //
  10. // Notes:
  11. //
  12. // Author: shaunco 24 Feb 1998
  13. //
  14. //----------------------------------------------------------------------------
  15. #include "pch.h"
  16. #pragma hdrstop
  17. #include "aic.h"
  18. #include "conman.h"
  19. #include "mprapi.h"
  20. #include "ncmisc.h"
  21. #include "nmbase.h"
  22. #include <raserror.h>
  23. ASSERTDATA;
  24. // This is the global data representing active inbound ras connections.
  25. //
  26. struct ACTIVE_INBOUND_RAS_CONNECTIONS
  27. {
  28. // This is set after calling AicInitialize.
  29. //
  30. BOOL fInitialized;
  31. // This critical section protects reading and writing to members of
  32. // this structure.
  33. //
  34. CRITICAL_SECTION critsec;
  35. // This is the array and count of active ras connections.
  36. //
  37. // Note: (shaunco) 28 Apr 1998: RASSRVCONN is too big to keep an
  38. // array off. We'll have to roll our own structure and keep what's
  39. // important.
  40. // RASSRVCONN* aRasConn;
  41. // DWORD cRasConn;
  42. // This is the event handle that is signled when a connection is
  43. // connected or disconnected.
  44. //
  45. HANDLE hEvent;
  46. // This is the wait handle returned from RtlRegisterWait.
  47. //
  48. HANDLE hWait;
  49. // This is set after the first call to HrAicEnsureCachedAndListening.
  50. //
  51. BOOL fCachedAndListening;
  52. };
  53. ACTIVE_INBOUND_RAS_CONNECTIONS g_Aic = { 0 };
  54. //+---------------------------------------------------------------------------
  55. //
  56. // Function: AicInitialize
  57. //
  58. // Purpose: Initialize this module for use.
  59. //
  60. // Arguments:
  61. // (none)
  62. //
  63. // Returns: nothing
  64. //
  65. // Author: shaunco 24 Feb 1998
  66. //
  67. // Notes: This can only be called once. It must be called before
  68. // any other Aic* API can be called.
  69. //
  70. VOID
  71. AicInitialize ()
  72. {
  73. Assert (!g_Aic.fInitialized);
  74. InitializeCriticalSection (&g_Aic.critsec);
  75. g_Aic.fInitialized = TRUE;
  76. }
  77. //+---------------------------------------------------------------------------
  78. //
  79. // Function: AicUninitialize
  80. //
  81. // Purpose: Uninitialize this module.
  82. //
  83. // Arguments:
  84. // (none)
  85. //
  86. // Returns: nothing
  87. //
  88. // Author: shaunco 24 Feb 1998
  89. //
  90. // Notes: This can only be called once. It must be called after the
  91. // last call to any other Aic* API.
  92. //
  93. VOID
  94. AicUninitialize ()
  95. {
  96. Assert (g_Aic.fInitialized);
  97. if (g_Aic.fCachedAndListening)
  98. {
  99. CExceptionSafeLock EsLock (&g_Aic.critsec);
  100. if (g_Aic.hWait)
  101. {
  102. TraceTag (ttidWanCon, "AicUninitialize: calling RtlDeregisterWait");
  103. RtlDeregisterWait (g_Aic.hWait);
  104. g_Aic.hWait = NULL;
  105. }
  106. TraceTag (ttidWanCon, "AicUninitialize: closing event handle");
  107. CloseHandle (g_Aic.hEvent);
  108. g_Aic.hEvent = NULL;
  109. // MemFree (g_Aic.aRasConn);
  110. // g_Aic.aRasConn = NULL;
  111. // g_Aic.cRasConn = 0;
  112. g_Aic.fCachedAndListening = FALSE;
  113. }
  114. // We can't delete the critical section unless we can guarantee
  115. // that no other API (like HrAicFindRasConnFromGuidId)
  116. // will be called. (This is assumed.)
  117. //
  118. DeleteCriticalSection (&g_Aic.critsec);
  119. g_Aic.fInitialized = FALSE;
  120. }
  121. //+---------------------------------------------------------------------------
  122. //
  123. // Function: AicWaitCallback
  124. //
  125. // Purpose: Called by the RTL thread pool for this process when
  126. // g_Aic.hEvent is signaled. This event will be signaled by
  127. // the RemoteAccess service when the state of an incoming
  128. // connection changes.
  129. //
  130. // Arguments:
  131. // pvContext [in] Our user data. (Not used here.)
  132. // fTimeout [in] TRUE if we were called because of a timeout.
  133. //
  134. // Returns: nothing
  135. //
  136. // Author: shaunco 24 Feb 1998
  137. //
  138. // Notes: Be quick about this. We're being called on a thread provided
  139. // by the system.
  140. //
  141. VOID
  142. NTAPI
  143. AicWaitCallback (
  144. PVOID pvContext,
  145. BOOLEAN fTimeout)
  146. {
  147. Assert (g_Aic.fInitialized);
  148. Assert (g_Aic.fCachedAndListening);
  149. // Let's be sure we only do work if the service state is still running.
  150. // If we have a stop pending for example, we don't need to do anything.
  151. //
  152. if (SERVICE_RUNNING != _Module.DwServiceStatus ())
  153. {
  154. TraceTag (ttidWanCon, "AicWaitCallback called while service is not "
  155. "in SERVICE_RUNNING state. Ignoring.");
  156. return;
  157. }
  158. TraceTag (ttidWanCon, "AicWaitCallback called");
  159. HRESULT hr = S_OK;
  160. // Lock scope
  161. {
  162. // Prevent other threads from reading the data we are about to update.
  163. //
  164. /*
  165. DWORD cRasConnOld = g_Arc.cRasConn;
  166. MemFree (g_Arc.aRasConn);
  167. hr = HrRasEnumAllActiveConnections (&g_Arc.aRasConn, &g_Arc.cRasConn);
  168. TraceTag (ttidWanCon,
  169. "ArcWaitCallback called: connection count: %u -> %u",
  170. cRasConnOld,
  171. g_Arc.cRasConn);
  172. */
  173. }
  174. // Tell the connection manager to advise it's clients that a change
  175. // occured and re-enumeration is neccessary.
  176. //
  177. CConnectionManager::NotifyClientsOfChange ();
  178. TraceHr (ttidError, FAL, hr, FALSE, "AicWaitCallback");
  179. }
  180. HRESULT
  181. HrAicEnsureCachedAndListening ()
  182. {
  183. Assert (g_Aic.fInitialized);
  184. if (g_Aic.fCachedAndListening)
  185. {
  186. return S_OK;
  187. }
  188. g_Aic.fCachedAndListening = TRUE;
  189. TraceTag (ttidWanCon, "Initializing active incoming ras "
  190. "connections cache...");
  191. HRESULT hr = E_FAIL;
  192. CExceptionSafeLock EsLock (&g_Aic.critsec);
  193. // Create a auto-reset event and register it with
  194. // MprAdminConnectionNotification.
  195. //
  196. g_Aic.hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
  197. if (g_Aic.hEvent)
  198. {
  199. HANDLE hMprAdmin;
  200. DWORD dwErr = MprAdminServerConnect (NULL, &hMprAdmin);
  201. hr = HRESULT_FROM_WIN32 (dwErr);
  202. TraceHr (ttidError, FAL, hr, FALSE, "MprAdminServerConnect", hr);
  203. if (SUCCEEDED(hr))
  204. {
  205. dwErr = MprAdminRegisterConnectionNotification (
  206. hMprAdmin, g_Aic.hEvent);
  207. hr = HRESULT_FROM_WIN32 (dwErr);
  208. TraceHr (ttidError, FAL, hr, FALSE,
  209. "MprAdminRegisterConnectionNotification", hr);
  210. if (SUCCEEDED(hr))
  211. {
  212. NTSTATUS status;
  213. status = RtlRegisterWait (&g_Aic.hWait, g_Aic.hEvent,
  214. AicWaitCallback, NULL, INFINITE, WT_EXECUTEDEFAULT);
  215. if (!NT_SUCCESS(status))
  216. {
  217. hr = HRESULT_FROM_NT (status);
  218. TraceHr (ttidError, FAL, hr, FALSE,
  219. "RtlRegisterWait", hr);
  220. }
  221. else
  222. {
  223. TraceTag (ttidWanCon, "Cached and listening for "
  224. "incoming ras connection state changes...");
  225. hr = S_OK;
  226. }
  227. if (FAILED(hr))
  228. {
  229. MprAdminDeregisterConnectionNotification (hMprAdmin,
  230. g_Aic.hEvent);
  231. }
  232. }
  233. MprAdminServerDisconnect (hMprAdmin);
  234. }
  235. if (FAILED(hr))
  236. {
  237. CloseHandle (g_Aic.hEvent);
  238. g_Aic.hEvent = NULL;
  239. }
  240. }
  241. else
  242. {
  243. hr = HrFromLastWin32Error ();
  244. TraceHr (ttidError, FAL, hr, FALSE, "CreateEvent", hr);
  245. }
  246. TraceHr (ttidError, FAL, hr, FALSE, "HrAicEnsureCachedAndListening");
  247. return hr;
  248. }