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.

462 lines
12 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997-2001.
  5. //
  6. // File: S V C M A I N . C P P
  7. //
  8. // Contents: Service main for netman.dll
  9. //
  10. // Notes:
  11. //
  12. // Author: shaunco 3 Apr 1998
  13. //
  14. //----------------------------------------------------------------------------
  15. #include "pch.h"
  16. #pragma hdrstop
  17. #include <dbt.h>
  18. #include "nmbase.h"
  19. #include "nminit.h"
  20. #include "nmres.h"
  21. #include "eapolfunc.h"
  22. #include "wsdpsvc.h"
  23. #undef EAPOL_LINKED
  24. // Includes for COM objects needed in the following object map.
  25. //
  26. // Connection Manager
  27. //
  28. #include "..\conman\conman.h"
  29. #include "..\conman\conman2.h"
  30. #include "..\conman\enum.h"
  31. // Connection Class Managers
  32. //
  33. #include "..\conman\conmani.h"
  34. #include "..\conman\conmanl.h"
  35. #include "..\conman\conmansa.h"
  36. #include "..\conman\conmanw.h"
  37. #include "..\conman\enumi.h"
  38. #include "..\conman\enuml.h"
  39. #include "..\conman\enumsa.h"
  40. #include "..\conman\enumw.h"
  41. // Connection Objects
  42. //
  43. #include "dialup.h"
  44. #include "inbound.h"
  45. #include "lan.h"
  46. #include "saconob.h"
  47. // Install queue
  48. //
  49. #include "ncqueue.h"
  50. // Home networking support
  51. //
  52. #include "nmhnet.h"
  53. // NetGroupPolicies
  54. #include "nmpolicy.h"
  55. #define INITGUID
  56. DEFINE_GUID(CLSID_InternetConnectionBeaconService,0x04df613a,0x5610,0x11d4,0x9e,0xc8,0x00,0xb0,0xd0,0x22,0xdd,0x1f);
  57. // TODO Remove this when we have proper idl
  58. CServiceModule _Module;
  59. BEGIN_OBJECT_MAP(ObjectMap)
  60. // Connection Manager
  61. //
  62. OBJECT_ENTRY(CLSID_ConnectionManager, CConnectionManager)
  63. OBJECT_ENTRY(CLSID_ConnectionManagerEnumConnection, CConnectionManagerEnumConnection)
  64. // Connection Manager2
  65. OBJECT_ENTRY(CLSID_ConnectionManager2, CConnectionManager2)
  66. // Connection Class Managers
  67. //
  68. OBJECT_ENTRY(CLSID_InboundConnectionManager, CInboundConnectionManager)
  69. OBJECT_ENTRY(CLSID_InboundConnectionManagerEnumConnection, CInboundConnectionManagerEnumConnection)
  70. OBJECT_ENTRY(CLSID_LanConnectionManager, CLanConnectionManager)
  71. OBJECT_ENTRY(CLSID_LanConnectionManagerEnumConnection, CLanConnectionManagerEnumConnection)
  72. OBJECT_ENTRY(CLSID_WanConnectionManager, CWanConnectionManager)
  73. OBJECT_ENTRY(CLSID_WanConnectionManagerEnumConnection, CWanConnectionManagerEnumConnection)
  74. OBJECT_ENTRY(CLSID_SharedAccessConnectionManager, CSharedAccessConnectionManager)
  75. OBJECT_ENTRY(CLSID_SharedAccessConnectionManagerEnumConnection, CSharedAccessConnectionManagerEnumConnection)
  76. // Connection Objects
  77. //
  78. OBJECT_ENTRY(CLSID_DialupConnection, CDialupConnection)
  79. OBJECT_ENTRY(CLSID_InboundConnection, CInboundConnection)
  80. OBJECT_ENTRY(CLSID_LanConnection, CLanConnection)
  81. OBJECT_ENTRY(CLSID_SharedAccessConnection, CSharedAccessConnection)
  82. // Install queue
  83. //
  84. OBJECT_ENTRY(CLSID_InstallQueue, CInstallQueue)
  85. // Home networking support
  86. //
  87. OBJECT_ENTRY(CLSID_NetConnectionHNetUtil, CNetConnectionHNetUtil)
  88. // NetGroupPolicies
  89. OBJECT_ENTRY(CLSID_NetGroupPolicies, CNetMachinePolicies)
  90. END_OBJECT_MAP()
  91. VOID
  92. CServiceModule::DllProcessAttach (
  93. HINSTANCE hinst)
  94. {
  95. CComModule::Init (ObjectMap, hinst);
  96. }
  97. VOID
  98. CServiceModule::DllProcessDetach (
  99. VOID)
  100. {
  101. CComModule::Term ();
  102. }
  103. DWORD
  104. CServiceModule::DwHandler (
  105. DWORD dwControl,
  106. DWORD dwEventType,
  107. PVOID pEventData,
  108. PVOID pContext)
  109. {
  110. if (SERVICE_CONTROL_STOP == dwControl)
  111. {
  112. HRESULT hr;
  113. TraceTag (ttidConman, "Received SERVICE_CONTROL_STOP request");
  114. SetServiceStatus (SERVICE_STOP_PENDING);
  115. hr = ServiceShutdown();
  116. }
  117. else if (SERVICE_CONTROL_INTERROGATE == dwControl)
  118. {
  119. TraceTag (ttidConman, "Received SERVICE_CONTROL_INTERROGATE request");
  120. UpdateServiceStatus (FALSE);
  121. }
  122. else if ((SERVICE_CONTROL_DEVICEEVENT == dwControl) && pEventData)
  123. {
  124. DEV_BROADCAST_DEVICEINTERFACE* pInfo =
  125. (DEV_BROADCAST_DEVICEINTERFACE*)pEventData;
  126. if (DBT_DEVTYP_DEVICEINTERFACE == pInfo->dbcc_devicetype)
  127. {
  128. if (DBT_DEVICEARRIVAL == dwEventType)
  129. {
  130. TraceTag (ttidConman, "Device arrival: [%S]",
  131. pInfo->dbcc_name);
  132. LanEventNotify (REFRESH_ALL, NULL, NULL, NULL);
  133. }
  134. else if (DBT_DEVICEREMOVECOMPLETE == dwEventType)
  135. {
  136. GUID guidAdapter = GUID_NULL;
  137. WCHAR szGuid[MAX_PATH];
  138. WCHAR szTempName[MAX_PATH];
  139. WCHAR* szFindGuid;
  140. TraceTag (ttidConman, "Device removed: [%S]",
  141. pInfo->dbcc_name);
  142. szFindGuid = wcsrchr(pInfo->dbcc_name, L'{');
  143. if (szFindGuid)
  144. {
  145. wcscpy(szGuid, szFindGuid);
  146. IIDFromString(szGuid, &guidAdapter);
  147. }
  148. if (!IsEqualGUID(guidAdapter, GUID_NULL))
  149. {
  150. CONMAN_EVENT* pEvent;
  151. pEvent = new CONMAN_EVENT;
  152. if (pEvent)
  153. {
  154. pEvent->ConnectionManager = CONMAN_LAN;
  155. pEvent->guidId = guidAdapter;
  156. pEvent->Type = CONNECTION_STATUS_CHANGE;
  157. pEvent->Status = NCS_DISCONNECTED;
  158. if (!QueueUserWorkItemInThread(LanEventWorkItem, reinterpret_cast<LPVOID>(pEvent), EVENTMGR_CONMAN))
  159. {
  160. FreeConmanEvent(pEvent);
  161. }
  162. }
  163. }
  164. else
  165. {
  166. LanEventNotify (REFRESH_ALL, NULL, NULL, NULL);
  167. }
  168. }
  169. }
  170. #ifdef EAPOL_LINKED
  171. TraceTag (ttidConman, "Calling EAPOL ElDeviceNotificationHandler");
  172. DWORD dwRetCode = NO_ERROR;
  173. if ((dwRetCode = ElDeviceNotificationHandler (
  174. pEventData, dwEventType)) != NO_ERROR)
  175. {
  176. TraceTag (ttidConman, "ElDeviceNotificationHandler failed with error %ld",
  177. dwRetCode);
  178. }
  179. TraceTag (ttidConman, "EAPOL ElDeviceNotificationHandler completed");
  180. #endif
  181. }
  182. return 1;
  183. }
  184. VOID
  185. CServiceModule::SetServiceStatus(DWORD dwState)
  186. {
  187. m_status.dwCurrentState = dwState;
  188. m_status.dwCheckPoint = 0;
  189. if (!::SetServiceStatus (m_hStatus, &m_status))
  190. {
  191. TraceHr (ttidError, FAL, HrFromLastWin32Error(), FALSE,
  192. "CServiceModule::SetServiceStatus");
  193. }
  194. }
  195. VOID CServiceModule::UpdateServiceStatus (
  196. BOOL fUpdateCheckpoint /* = TRUE */)
  197. {
  198. if (fUpdateCheckpoint)
  199. {
  200. m_status.dwCheckPoint++;
  201. }
  202. if (!::SetServiceStatus (m_hStatus, &m_status))
  203. {
  204. TraceHr (ttidError, FAL, HrFromLastWin32Error(), FALSE,
  205. "CServiceModule::UpdateServiceStatus");
  206. }
  207. }
  208. VOID
  209. CServiceModule::Run()
  210. {
  211. HRESULT hr = CoInitializeEx (NULL,
  212. COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE);
  213. TraceHr (ttidError, FAL, hr, FALSE, "CServiceModule::Run: "
  214. "CoInitializeEx failed");
  215. if (SUCCEEDED(hr))
  216. {
  217. TraceTag (ttidConman, "Calling RegisterClassObjects...");
  218. // Create the event to sychronize registering our class objects
  219. // with the connection manager which attempts to CoCreate
  220. // objects which are also registered here. I've seen cases
  221. // where the connection manager will be off and running before
  222. // this completes causing CoCreateInstance to fail.
  223. // The connection manager will wait on this event before
  224. // executing CoCreateInstance.
  225. //
  226. HANDLE hEvent;
  227. hr = HrNmCreateClassObjectRegistrationEvent (&hEvent);
  228. if (SUCCEEDED(hr))
  229. {
  230. hr = _Module.RegisterClassObjects (
  231. CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER,
  232. REGCLS_MULTIPLEUSE);
  233. TraceHr (ttidError, FAL, hr, FALSE, "CServiceModule::Run: "
  234. "_Module.RegisterClassObjects failed");
  235. // Signal the event and close it. If this delete's the
  236. // event, so be it. It's purpose is served as all
  237. // class objects have been registered.
  238. //
  239. SetEvent (hEvent);
  240. CloseHandle (hEvent);
  241. }
  242. if (SUCCEEDED(hr))
  243. {
  244. hr = ServiceStartup();
  245. }
  246. CoUninitialize();
  247. }
  248. }
  249. VOID
  250. CServiceModule::ServiceMain (
  251. DWORD argc,
  252. PWSTR argv[])
  253. {
  254. // Reset the version era for RAS phonebook entry modifications.
  255. //
  256. g_lRasEntryModifiedVersionEra = 0;
  257. m_fRasmanReferenced = FALSE;
  258. m_dwThreadID = GetCurrentThreadId ();
  259. ZeroMemory (&m_status, sizeof(m_status));
  260. m_status.dwServiceType = SERVICE_WIN32_SHARE_PROCESS;
  261. m_status.dwControlsAccepted = SERVICE_ACCEPT_STOP;
  262. // Register the service control handler.
  263. //
  264. m_hStatus = RegisterServiceCtrlHandlerEx (
  265. L"netman",
  266. _DwHandler,
  267. NULL);
  268. if (m_hStatus)
  269. {
  270. SetServiceStatus (SERVICE_START_PENDING);
  271. // When the Run function returns, the service is running.
  272. // We now handle shutdown from ServiceShutdown when our DwHandler
  273. // is called and is passed SERVICE_CONTROL_STOP as the dwControl
  274. // parameter. This allows us to terminate our message pump thread
  275. // which effectively reduces us to 0 threads that we own.
  276. Run ();
  277. }
  278. else
  279. {
  280. TraceHr (ttidError, FAL, HrFromLastWin32Error(), FALSE,
  281. "CServiceModule::ServiceMain - RegisterServiceCtrlHandler failed");
  282. }
  283. }
  284. // static
  285. DWORD
  286. WINAPI
  287. CServiceModule::_DwHandler (
  288. DWORD dwControl,
  289. DWORD dwEventType,
  290. PVOID pEventData,
  291. PVOID pContext)
  292. {
  293. return _Module.DwHandler (dwControl, dwEventType, pEventData, pContext);
  294. }
  295. VOID
  296. CServiceModule::ReferenceRasman (
  297. RASREFTYPE RefType)
  298. {
  299. BOOL fRef = (REF_REFERENCE == RefType);
  300. if (REF_INITIALIZE == RefType)
  301. {
  302. Assert (!fRef);
  303. // RasInitialize implicitly references rasman.
  304. //
  305. RasInitialize ();
  306. }
  307. // If we need to reference and we're not already,
  308. // or we need unreference and we're referenced, do the appropriate thing.
  309. // (This is logical xor. Quite different than bitwise xor when
  310. // the two arguments don't neccesarily have the same value for TRUE.)
  311. //
  312. else if ((fRef && !m_fRasmanReferenced) ||
  313. (!fRef && m_fRasmanReferenced))
  314. {
  315. RasReferenceRasman (fRef);
  316. m_fRasmanReferenced = fRef;
  317. }
  318. }
  319. HRESULT CServiceModule::ServiceStartup()
  320. {
  321. HRESULT hr = S_OK;
  322. #ifdef EAPOL_LINKED
  323. //
  324. // Start EAPOL
  325. //
  326. TraceTag (ttidConman, "Starting EAPOL");
  327. EAPOLServiceMain ( argc, NULL);
  328. TraceTag (ttidConman, "EAPOL started successfully");
  329. #endif
  330. StartWsdpService (); // Starts WSDP service on DTC/AdvServer build/
  331. // no-op otherwise
  332. InitializeHNetSupport();
  333. SetServiceStatus (SERVICE_RUNNING);
  334. TraceTag (ttidConman, "Netman is now running...");
  335. return hr;
  336. }
  337. HRESULT CServiceModule::ServiceShutdown()
  338. {
  339. HRESULT hr = S_OK;
  340. hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
  341. if (SUCCEEDED(hr))
  342. {
  343. hr = UninitializeEventHandler();
  344. if (SUCCEEDED(hr))
  345. {
  346. CleanupHNetSupport();
  347. StopWsdpService (); // Stops WSDP service if necessary
  348. // We must synchronize with the install queue's thread otherwise
  349. // RevokeClassObjects will kill the InstallQueue object and
  350. // CoUninitialize will free the NetCfg module before the thread
  351. // is finished.
  352. //
  353. WaitForInstallQueueToExit();
  354. _Module.RevokeClassObjects ();
  355. // Unreference rasman now that our service is about to stop.
  356. //
  357. _Module.ReferenceRasman (REF_UNREFERENCE);
  358. #ifdef EAPOL_LINKED
  359. TraceTag (ttidConman, "Stopping EAPOL");
  360. EAPOLCleanUp (NO_ERROR);
  361. TraceTag (ttidConman, "EAPOL stopped successfully");
  362. #endif
  363. SetServiceStatus(SERVICE_STOPPED);
  364. }
  365. CoUninitialize();
  366. }
  367. if (FAILED(hr))
  368. {
  369. SetServiceStatus(SERVICE_RUNNING);
  370. }
  371. return hr;
  372. }