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.

1288 lines
34 KiB

  1. /********************************************************************/
  2. /** Copyright(c) 1995 Microsoft Corporation. **/
  3. /********************************************************************/
  4. //***
  5. //
  6. // Filename: main.c
  7. //
  8. // Description: This module contains the main procedure of the Dynamic
  9. // Interface Manager server service. It will contain code to
  10. // initialize and install itself. It also contains
  11. // code to respond to the server controller. It will also
  12. // handle service shutdown.
  13. //
  14. // History: May 11,1995. NarenG Created original version.
  15. //
  16. #define _ALLOCATE_DIM_GLOBALS_
  17. #include "dimsvcp.h"
  18. #include <winsvc.h>
  19. #include <winuser.h>
  20. #include <dbt.h>
  21. #include <ndisguid.h>
  22. #include <wmium.h>
  23. #include <rpc.h>
  24. #include <iaspolcy.h>
  25. #include <iasext.h>
  26. #include <lmserver.h>
  27. #include <srvann.h>
  28. #include <ddmif.h>
  29. #define RAS_CONTROL_CONFIGURE 128
  30. //**
  31. //
  32. // Call: MediaSenseCallback
  33. //
  34. // Returns: None
  35. //
  36. // Description:
  37. //
  38. VOID
  39. WINAPI
  40. MediaSenseCallback(
  41. PWNODE_HEADER pWnodeHeader,
  42. UINT_PTR NotificationContext
  43. )
  44. {
  45. ROUTER_INTERFACE_OBJECT * pIfObject;
  46. PWNODE_SINGLE_INSTANCE pWnode = (PWNODE_SINGLE_INSTANCE)pWnodeHeader;
  47. LPWSTR lpwsName = (LPWSTR)RtlOffsetToPointer(
  48. pWnode,
  49. pWnode->OffsetInstanceName );
  50. if ( (gblDIMConfigInfo.ServiceStatus.dwCurrentState == SERVICE_STOP_PENDING)
  51. ||
  52. (gblDIMConfigInfo.ServiceStatus.dwCurrentState == SERVICE_STOPPED ))
  53. {
  54. return;
  55. }
  56. //
  57. // Get the information for the media disconnect.
  58. //
  59. if ( memcmp( &(pWnodeHeader->Guid),
  60. &GUID_NDIS_STATUS_MEDIA_DISCONNECT,
  61. sizeof( GUID ) ) == 0 )
  62. {
  63. DIMTRACE1("MediaSenseCallback for sense disconnect called for %ws",
  64. lpwsName );
  65. IfObjectNotifyOfMediaSenseChange();
  66. }
  67. else
  68. {
  69. //
  70. // Get the information for the media connect.
  71. //
  72. if ( memcmp( &(pWnodeHeader->Guid),
  73. &GUID_NDIS_STATUS_MEDIA_CONNECT,
  74. sizeof( GUID ) ) == 0 )
  75. {
  76. DIMTRACE1("MediaSenseCallback for sense connect called for %ws",
  77. lpwsName );
  78. IfObjectNotifyOfMediaSenseChange();
  79. }
  80. }
  81. }
  82. //**
  83. //
  84. // Call: MediaSenseRegister
  85. //
  86. // Returns: NO_ERROR - Success
  87. // Non-zero returns - Failure
  88. //
  89. // Description:
  90. //
  91. DWORD
  92. MediaSenseRegister(
  93. IN BOOL fRegister
  94. )
  95. {
  96. DWORD dwRetCode = NO_ERROR;
  97. PVOID pvDeliveryInfo = MediaSenseCallback;
  98. dwRetCode = WmiNotificationRegistration(
  99. (LPGUID)(&GUID_NDIS_STATUS_MEDIA_CONNECT),
  100. (BOOLEAN)fRegister,
  101. pvDeliveryInfo,
  102. (ULONG_PTR)NULL,
  103. NOTIFICATION_CALLBACK_DIRECT );
  104. if ( dwRetCode != NO_ERROR )
  105. {
  106. return( dwRetCode );
  107. }
  108. dwRetCode = WmiNotificationRegistration(
  109. (LPGUID)(&GUID_NDIS_STATUS_MEDIA_DISCONNECT),
  110. (BOOLEAN)fRegister,
  111. pvDeliveryInfo,
  112. (ULONG_PTR)NULL,
  113. NOTIFICATION_CALLBACK_DIRECT );
  114. if ( dwRetCode != NO_ERROR )
  115. {
  116. return( dwRetCode );
  117. }
  118. return( NO_ERROR );
  119. }
  120. //**
  121. //
  122. // Call: BindingsNotificationsCallback
  123. //
  124. // Returns: None
  125. //
  126. // Description:
  127. //
  128. VOID
  129. WINAPI
  130. BindingsNotificationsCallback(
  131. PWNODE_HEADER pWnodeHeader,
  132. UINT_PTR NotificationContext
  133. )
  134. {
  135. LPWSTR lpwszGUIDStart;
  136. LPWSTR lpwszGUIDEnd;
  137. LPWSTR lpwszGUID;
  138. WCHAR wchGUIDSaveLast;
  139. ROUTER_INTERFACE_OBJECT * pIfObject;
  140. PWNODE_SINGLE_INSTANCE pWnode = (PWNODE_SINGLE_INSTANCE)pWnodeHeader;
  141. LPWSTR lpwsName = (LPWSTR)RtlOffsetToPointer(
  142. pWnode,
  143. pWnode->OffsetInstanceName );
  144. LPWSTR lpwsTransportName = (LPWSTR)RtlOffsetToPointer(
  145. pWnode,
  146. pWnode->DataBlockOffset );
  147. if ( (gblDIMConfigInfo.ServiceStatus.dwCurrentState == SERVICE_STOP_PENDING)
  148. ||
  149. (gblDIMConfigInfo.ServiceStatus.dwCurrentState == SERVICE_STOPPED ))
  150. {
  151. return;
  152. }
  153. //
  154. // Extract GUID from the \device\GUID name
  155. //
  156. lpwszGUID = lpwsTransportName + wcslen( lpwsTransportName ) + 1;
  157. lpwszGUIDStart = wcsrchr( lpwszGUID, L'{' );
  158. lpwszGUIDEnd = wcsrchr( lpwszGUID, L'}' );
  159. if ( (lpwszGUIDStart != NULL )
  160. && (lpwszGUIDEnd != NULL ))
  161. {
  162. wchGUIDSaveLast = *(lpwszGUIDEnd+1);
  163. EnterCriticalSection( &(gblInterfaceTable.CriticalSection));
  164. *(lpwszGUIDEnd+1) = (WCHAR)NULL;
  165. pIfObject = IfObjectGetPointerByName( lpwszGUIDStart, FALSE );
  166. *(lpwszGUIDEnd+1) = wchGUIDSaveLast;
  167. //
  168. // If we got a bind notification
  169. //
  170. if ( memcmp( &(pWnodeHeader->Guid), &GUID_NDIS_NOTIFY_BIND, sizeof( GUID ) ) == 0)
  171. {
  172. DIMTRACE2("BindingsNotificationsCallback BIND for %ws,Transport=%ws",
  173. lpwsName, lpwsTransportName );
  174. //
  175. // If we have this interface loaded.
  176. //
  177. if ( pIfObject != NULL )
  178. {
  179. //
  180. // If this interface is being bound to IP
  181. //
  182. if ( _wcsicmp( L"TCPIP", lpwsTransportName ) == 0 )
  183. {
  184. DWORD dwTransportIndex = GetTransportIndex( PID_IP );
  185. //
  186. // If IP routermanager is loaded and this interface is not
  187. // already registered with it
  188. //
  189. if (( dwTransportIndex != -1 ) &&
  190. ( pIfObject->Transport[dwTransportIndex].hInterface
  191. == INVALID_HANDLE_VALUE ))
  192. {
  193. AddInterfacesToRouterManager( lpwszGUIDStart, PID_IP );
  194. }
  195. }
  196. //
  197. // If this interface is being bound to IPX
  198. //
  199. if ( _wcsicmp( L"NWLNKIPX", lpwsTransportName ) == 0 )
  200. {
  201. DWORD dwTransportIndex = GetTransportIndex( PID_IPX );
  202. //
  203. // If IPX routermanager is loaded and this interface is not
  204. // already registered with it
  205. //
  206. if (( dwTransportIndex != -1 ) &&
  207. ( pIfObject->Transport[dwTransportIndex].hInterface
  208. == INVALID_HANDLE_VALUE ))
  209. {
  210. AddInterfacesToRouterManager( lpwszGUIDStart, PID_IPX );
  211. }
  212. }
  213. }
  214. }
  215. else if (memcmp( &(pWnodeHeader->Guid),&GUID_NDIS_NOTIFY_UNBIND,sizeof(GUID))==0)
  216. {
  217. if ( pIfObject != NULL )
  218. {
  219. //
  220. // Get the information for the media connect.
  221. //
  222. DIMTRACE2("BindingsNotificationsCallback UNDBIND for %ws,Transport=%ws",
  223. lpwsName, lpwsTransportName );
  224. if ( _wcsicmp( L"TCPIP", lpwsTransportName ) == 0 )
  225. {
  226. IfObjectDeleteInterfaceFromTransport( pIfObject, PID_IP );
  227. }
  228. if ( _wcsicmp( L"NWLNKIPX", lpwsTransportName ) == 0 )
  229. {
  230. IfObjectDeleteInterfaceFromTransport( pIfObject, PID_IPX );
  231. }
  232. }
  233. }
  234. LeaveCriticalSection( &(gblInterfaceTable.CriticalSection) );
  235. }
  236. }
  237. //**
  238. //
  239. // Call: BindingsNotificationsRegister
  240. //
  241. // Returns: NO_ERROR - Success
  242. // Non-zero returns - Failure
  243. //
  244. // Description:
  245. //
  246. DWORD
  247. BindingsNotificationsRegister(
  248. IN BOOL fRegister
  249. )
  250. {
  251. DWORD dwRetCode = NO_ERROR;
  252. PVOID pvDeliveryInfo = BindingsNotificationsCallback;
  253. dwRetCode = WmiNotificationRegistration(
  254. (LPGUID)(&GUID_NDIS_NOTIFY_BIND),
  255. (BOOLEAN)fRegister,
  256. pvDeliveryInfo,
  257. (ULONG_PTR)NULL,
  258. NOTIFICATION_CALLBACK_DIRECT );
  259. if ( dwRetCode != NO_ERROR )
  260. {
  261. return( dwRetCode );
  262. }
  263. dwRetCode = WmiNotificationRegistration(
  264. (LPGUID)(&GUID_NDIS_NOTIFY_UNBIND),
  265. (BOOLEAN)fRegister,
  266. pvDeliveryInfo,
  267. (ULONG_PTR)NULL,
  268. NOTIFICATION_CALLBACK_DIRECT );
  269. if ( dwRetCode != NO_ERROR )
  270. {
  271. return( dwRetCode );
  272. }
  273. return( NO_ERROR );
  274. }
  275. //**
  276. //
  277. // Call: DimAnnounceServiceStatus
  278. //
  279. // Returns: none
  280. //
  281. // Description: Will simly call SetServiceStatus to inform the service
  282. // control manager of this service's current status.
  283. //
  284. VOID
  285. DimAnnounceServiceStatus(
  286. VOID
  287. )
  288. {
  289. BOOL dwRetCode;
  290. ASSERT (gblDIMConfigInfo.hServiceStatus);
  291. //
  292. // Increment the checkpoint in a pending state:
  293. //
  294. switch( gblDIMConfigInfo.ServiceStatus.dwCurrentState )
  295. {
  296. case SERVICE_START_PENDING:
  297. case SERVICE_STOP_PENDING:
  298. gblDIMConfigInfo.ServiceStatus.dwCheckPoint++;
  299. break;
  300. default:
  301. break;
  302. }
  303. dwRetCode = SetServiceStatus( gblDIMConfigInfo.hServiceStatus,
  304. &gblDIMConfigInfo.ServiceStatus );
  305. if ( dwRetCode == FALSE )
  306. {
  307. //TracePrintfExA( gblDIMConfigInfo.dwTraceId,
  308. // TRACE_DIM,
  309. // "SetServiceStatus returned %d", GetLastError() );
  310. }
  311. }
  312. //**
  313. //
  314. // Call: DimCleanUp
  315. //
  316. // Returns: none
  317. //
  318. // Description: Will free any allocated memory, deinitialize RPC, deinitialize
  319. // the kernel-mode server and unload it if it was loaded.
  320. // This could have been called due to an error on SERVICE_START
  321. // or normal termination.
  322. //
  323. VOID
  324. DimCleanUp(
  325. IN DWORD dwError
  326. )
  327. {
  328. DWORD dwIndex;
  329. //
  330. // Announce that we are stopping
  331. //
  332. gblDIMConfigInfo.ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
  333. gblDIMConfigInfo.ServiceStatus.dwControlsAccepted = 0;
  334. gblDIMConfigInfo.ServiceStatus.dwCheckPoint = 1;
  335. gblDIMConfigInfo.ServiceStatus.dwWaitHint = 200000;
  336. DimAnnounceServiceStatus();
  337. if ( gbldwDIMComponentsLoaded & DIM_RPC_LOADED )
  338. {
  339. DimTerminateRPC();
  340. }
  341. //
  342. // Stop the timer and delete the timer Q if there is one.
  343. //
  344. if ( gblDIMConfigInfo.hTimerQ != NULL )
  345. {
  346. RtlDeleteTimerQueueEx( gblDIMConfigInfo.hTimerQ, INVALID_HANDLE_VALUE );
  347. }
  348. EnterCriticalSection( &(gblDIMConfigInfo.CSRouterIdentity) );
  349. DeleteCriticalSection( &(gblDIMConfigInfo.CSRouterIdentity) );
  350. if ( gbldwDIMComponentsLoaded & DIM_DDM_LOADED )
  351. {
  352. //
  353. // If we are not in LANOnly mode then stop DDM
  354. //
  355. if ( gblDIMConfigInfo.dwRouterRole != ROUTER_ROLE_LAN )
  356. {
  357. if ( gblhEventDDMServiceState != NULL )
  358. {
  359. SetEvent( gblhEventDDMServiceState );
  360. }
  361. }
  362. //
  363. // Wait for all threads in use to stop
  364. //
  365. while( gblDIMConfigInfo.dwNumThreadsRunning > 0 )
  366. {
  367. Sleep( 1000 );
  368. }
  369. }
  370. DimAnnounceServiceStatus();
  371. //
  372. // Tear down and free everything
  373. //
  374. if ( gbldwDIMComponentsLoaded & DIM_RMS_LOADED )
  375. {
  376. DimUnloadRouterManagers();
  377. }
  378. //
  379. // Unregister for media sense
  380. //
  381. MediaSenseRegister( FALSE );
  382. //
  383. // Unregister for bind/unbind sense
  384. //
  385. BindingsNotificationsRegister( FALSE );
  386. //
  387. // Need to sleep to give the router managers a change to unload
  388. // bug# 78711
  389. //
  390. Sleep( 2000 );
  391. if ( gblhModuleDDM != NULL )
  392. {
  393. FreeLibrary( gblhModuleDDM );
  394. }
  395. //
  396. // If security object was created
  397. //
  398. if ( gbldwDIMComponentsLoaded & DIM_SECOBJ_LOADED )
  399. {
  400. DimSecObjDelete();
  401. }
  402. if ( gblDIMConfigInfo.hMprConfig != NULL )
  403. {
  404. MprConfigServerDisconnect( gblDIMConfigInfo.hMprConfig );
  405. }
  406. if ( gblhEventDDMTerminated != NULL )
  407. {
  408. CloseHandle( gblhEventDDMTerminated );
  409. }
  410. if ( gblhEventDDMServiceState != NULL )
  411. {
  412. CloseHandle( gblhEventDDMServiceState );
  413. }
  414. if ( gblhEventTerminateDIM != NULL )
  415. {
  416. CloseHandle( gblhEventTerminateDIM );
  417. }
  418. if ( gblhEventRMState != NULL )
  419. {
  420. CloseHandle( gblhEventRMState );
  421. }
  422. if ( gblDIMConfigInfo.hObjectRouterIdentity != NULL )
  423. {
  424. RouterIdentityObjectClose( gblDIMConfigInfo.hObjectRouterIdentity );
  425. }
  426. //
  427. // Wait for everybody to release this and then delete it
  428. //
  429. EnterCriticalSection( &(gblInterfaceTable.CriticalSection) );
  430. DeleteCriticalSection( &(gblInterfaceTable.CriticalSection) );
  431. gbldwDIMComponentsLoaded = 0;
  432. if ( gblDIMConfigInfo.dwTraceId != INVALID_TRACEID )
  433. {
  434. TraceDeregisterA( gblDIMConfigInfo.dwTraceId );
  435. }
  436. RouterLogDeregister( gblDIMConfigInfo.hLogEvents );
  437. //
  438. // Destroy private heap
  439. //
  440. if ( gblDIMConfigInfo.hHeap != NULL )
  441. {
  442. HeapDestroy( gblDIMConfigInfo.hHeap );
  443. }
  444. DIMTRACE1("DimCleanup completed for error %d", dwError );
  445. //
  446. // Zero init all the globals
  447. //
  448. gblRouterManagers = NULL;
  449. gbldwDIMComponentsLoaded = 0;
  450. gblhEventDDMTerminated = NULL;
  451. gblhEventRMState = NULL;
  452. gblhEventDDMServiceState = NULL;
  453. gblhModuleDDM = NULL;
  454. gblhEventTerminateDIM = NULL;
  455. ZeroMemory( &gblInterfaceTable, sizeof( gblInterfaceTable ) );
  456. {
  457. SERVICE_STATUS_HANDLE svchandle = gblDIMConfigInfo.hServiceStatus;
  458. ZeroMemory( &gblDIMConfigInfo, sizeof( gblDIMConfigInfo ) );
  459. gblDIMConfigInfo.hServiceStatus = svchandle;
  460. }
  461. //
  462. // Zero out only the procedure entrypoints. This is a side effect of
  463. // the merge into svchost.exe since svchost doesn't unload mprdim
  464. // anymore when router stops.
  465. //
  466. for ( dwIndex = 0;
  467. gblDDMFunctionTable[dwIndex].lpEntryPointName != NULL;
  468. dwIndex ++ )
  469. {
  470. gblDDMFunctionTable[dwIndex].pEntryPoint = NULL;
  471. }
  472. if ( dwError == NO_ERROR )
  473. {
  474. gblDIMConfigInfo.ServiceStatus.dwWin32ExitCode = NO_ERROR;
  475. }
  476. else
  477. {
  478. gblDIMConfigInfo.ServiceStatus.dwWin32ExitCode =
  479. ERROR_SERVICE_SPECIFIC_ERROR;
  480. }
  481. gblDIMConfigInfo.ServiceStatus.dwServiceType = SERVICE_WIN32_SHARE_PROCESS;
  482. gblDIMConfigInfo.ServiceStatus.dwCurrentState = SERVICE_STOPPED;
  483. gblDIMConfigInfo.ServiceStatus.dwControlsAccepted = 0;
  484. gblDIMConfigInfo.ServiceStatus.dwCheckPoint = 0;
  485. gblDIMConfigInfo.ServiceStatus.dwWaitHint = 0;
  486. gblDIMConfigInfo.ServiceStatus.dwServiceSpecificExitCode = dwError;
  487. DimAnnounceServiceStatus();
  488. }
  489. //**
  490. //
  491. // Call: ServiceHandlerEx
  492. //
  493. // Returns: none
  494. //
  495. // Description: Will respond to control requests from the service controller.
  496. //
  497. DWORD
  498. ServiceHandlerEx(
  499. IN DWORD dwControlCode,
  500. IN DWORD dwEventType,
  501. IN LPVOID lpEventData,
  502. IN LPVOID lpContext
  503. )
  504. {
  505. DWORD dwRetCode = NO_ERROR;
  506. switch( dwControlCode )
  507. {
  508. case SERVICE_CONTROL_STOP:
  509. case SERVICE_CONTROL_SHUTDOWN:
  510. if ( ( gblDIMConfigInfo.ServiceStatus.dwCurrentState ==
  511. SERVICE_STOP_PENDING)
  512. ||
  513. ( gblDIMConfigInfo.ServiceStatus.dwCurrentState ==
  514. SERVICE_STOPPED ))
  515. {
  516. break;
  517. }
  518. DIMTRACE("Service control stop or shutdown called");
  519. //
  520. // Announce that we are stopping
  521. //
  522. gblDIMConfigInfo.ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
  523. gblDIMConfigInfo.ServiceStatus.dwControlsAccepted = 0;
  524. gblDIMConfigInfo.ServiceStatus.dwCheckPoint = 1;
  525. gblDIMConfigInfo.ServiceStatus.dwWaitHint = 200000;
  526. DimAnnounceServiceStatus();
  527. //
  528. // Make sure serice is started before initiating a stop
  529. //
  530. while( !( gbldwDIMComponentsLoaded & DIM_SERVICE_STARTED ) )
  531. {
  532. Sleep( 1000 );
  533. }
  534. SetEvent( gblhEventTerminateDIM );
  535. return( NO_ERROR );
  536. case SERVICE_CONTROL_PAUSE:
  537. if ( ( gblDIMConfigInfo.ServiceStatus.dwCurrentState ==
  538. SERVICE_PAUSE_PENDING)
  539. ||
  540. ( gblDIMConfigInfo.ServiceStatus.dwCurrentState ==
  541. SERVICE_PAUSED ))
  542. break;
  543. gblDIMConfigInfo.ServiceStatus.dwCurrentState = SERVICE_PAUSED;
  544. gblDIMConfigInfo.ServiceStatus.dwControlsAccepted = 0;
  545. gblDIMConfigInfo.ServiceStatus.dwCheckPoint = 0;
  546. gblDIMConfigInfo.ServiceStatus.dwWaitHint = 200000;
  547. gblDIMConfigInfo.ServiceStatus.dwControlsAccepted =
  548. SERVICE_ACCEPT_STOP
  549. | SERVICE_ACCEPT_PAUSE_CONTINUE
  550. | SERVICE_ACCEPT_SHUTDOWN;
  551. SetEvent( gblhEventDDMServiceState );
  552. break;
  553. case SERVICE_CONTROL_CONTINUE:
  554. if ( ( gblDIMConfigInfo.ServiceStatus.dwCurrentState ==
  555. SERVICE_CONTINUE_PENDING )
  556. ||
  557. ( gblDIMConfigInfo.ServiceStatus.dwCurrentState ==
  558. SERVICE_RUNNING ) )
  559. break;
  560. gblDIMConfigInfo.ServiceStatus.dwCheckPoint = 0;
  561. gblDIMConfigInfo.ServiceStatus.dwWaitHint = 0;
  562. gblDIMConfigInfo.ServiceStatus.dwCurrentState = SERVICE_RUNNING;
  563. gblDIMConfigInfo.ServiceStatus.dwControlsAccepted =
  564. SERVICE_ACCEPT_STOP
  565. | SERVICE_ACCEPT_PAUSE_CONTINUE
  566. | SERVICE_ACCEPT_SHUTDOWN;
  567. SetEvent( gblhEventDDMServiceState );
  568. break;
  569. case SERVICE_CONTROL_DEVICEEVENT:
  570. if ( ( gblDIMConfigInfo.ServiceStatus.dwCurrentState ==
  571. SERVICE_STOP_PENDING)
  572. ||
  573. ( gblDIMConfigInfo.ServiceStatus.dwCurrentState ==
  574. SERVICE_STOPPED ))
  575. {
  576. break;
  577. }
  578. if ( lpEventData != NULL)
  579. {
  580. DEV_BROADCAST_DEVICEINTERFACE* pInfo =
  581. (DEV_BROADCAST_DEVICEINTERFACE*)lpEventData;
  582. if ( pInfo->dbcc_devicetype == DBT_DEVTYP_DEVICEINTERFACE )
  583. {
  584. ROUTER_INTERFACE_OBJECT * pIfObject = NULL;
  585. if ( ( dwEventType == DBT_DEVICEARRIVAL ) ||
  586. ( dwEventType == DBT_DEVICEREMOVECOMPLETE ) )
  587. {
  588. //
  589. // Extract GUID from the \device\GUID name
  590. //
  591. LPWSTR lpwszGUIDStart = wcsrchr( pInfo->dbcc_name, L'{' );
  592. LPWSTR lpwszGUIDEnd = wcsrchr( pInfo->dbcc_name, L'}' );
  593. if ( lpwszGUIDStart != NULL )
  594. {
  595. WCHAR wchGUIDSaveLast = *(lpwszGUIDEnd+1);
  596. EnterCriticalSection( &(gblInterfaceTable.CriticalSection));
  597. *(lpwszGUIDEnd+1) = (WCHAR)NULL;
  598. pIfObject = IfObjectGetPointerByName( lpwszGUIDStart, FALSE );
  599. *(lpwszGUIDEnd+1) = wchGUIDSaveLast;
  600. if ( dwEventType == DBT_DEVICEARRIVAL )
  601. {
  602. if ( pIfObject == NULL )
  603. {
  604. DIMTRACE1("Device arrival:[%ws]", lpwszGUIDStart );
  605. RegLoadInterfaces( lpwszGUIDStart, TRUE );
  606. }
  607. }
  608. else
  609. {
  610. if ( pIfObject != NULL )
  611. {
  612. DIMTRACE1("Device removed:[%ws]", lpwszGUIDStart );
  613. IfObjectDeleteInterfaceFromTransport( pIfObject, PID_IP );
  614. IfObjectDeleteInterfaceFromTransport( pIfObject, PID_IPX);
  615. IfObjectRemove( pIfObject->hDIMInterface );
  616. }
  617. }
  618. LeaveCriticalSection( &(gblInterfaceTable.CriticalSection) );
  619. }
  620. }
  621. }
  622. }
  623. break;
  624. case RAS_CONTROL_CONFIGURE:
  625. //
  626. // Code for dynamic configuration of RAP
  627. //
  628. DIMTRACE( "Received Remote Access Policy change control message" );
  629. {
  630. //
  631. // thread needs to be COM initialized
  632. //
  633. HRESULT hResult = CoInitializeEx( NULL, COINIT_MULTITHREADED );
  634. if ( SUCCEEDED( hResult ) )
  635. {
  636. //
  637. // configure, doesn't matter if the API call fails
  638. //
  639. ConfigureIas();
  640. CoUninitialize();
  641. }
  642. }
  643. break;
  644. case SERVICE_CONTROL_POWEREVENT:
  645. switch( dwEventType )
  646. {
  647. case PBT_APMQUERYSTANDBY:
  648. case PBT_APMQUERYSUSPEND:
  649. //
  650. // Fail only if we are in LAN only mode, otherwise defer
  651. // decision to RASMAN/NDISWAN
  652. //
  653. if ( gblDIMConfigInfo.dwRouterRole == ROUTER_ROLE_LAN )
  654. {
  655. dwRetCode = ERROR_ACTIVE_CONNECTIONS;
  656. }
  657. break;
  658. case PBT_APMRESUMECRITICAL:
  659. default:
  660. {
  661. break;
  662. }
  663. }
  664. break;
  665. case SERVICE_CONTROL_NETBINDADD:
  666. case SERVICE_CONTROL_NETBINDREMOVE:
  667. case SERVICE_CONTROL_NETBINDENABLE:
  668. case SERVICE_CONTROL_NETBINDDISABLE:
  669. break;
  670. default:
  671. return( ERROR_CALL_NOT_IMPLEMENTED );
  672. break;
  673. }
  674. DimAnnounceServiceStatus();
  675. return( dwRetCode );
  676. }
  677. //**
  678. //
  679. // Call: ServiceMain
  680. //
  681. // Returns: None
  682. //
  683. // Description: This is the main procedure for the DIM Server Service. It
  684. // will be called when the service is supposed to start itself.
  685. // It will do all service wide initialization.
  686. //
  687. VOID
  688. ServiceMain(
  689. IN DWORD argc, // Command line arguments. Will be ignored.
  690. IN LPWSTR * lpwsServiceArgs
  691. )
  692. {
  693. DIM_INFO DimInfo;
  694. DWORD dwRetCode;
  695. DWORD dwIndex;
  696. DWORD (*DDMServiceInitialize)( DIM_INFO * );
  697. VOID (*DDMServicePostListens)( VOID *);
  698. UNREFERENCED_PARAMETER( argc );
  699. UNREFERENCED_PARAMETER( lpwsServiceArgs );
  700. gblDIMConfigInfo.hServiceStatus = RegisterServiceCtrlHandlerEx(
  701. TEXT("remoteaccess"),
  702. ServiceHandlerEx,
  703. NULL );
  704. if ( !gblDIMConfigInfo.hServiceStatus )
  705. {
  706. return;
  707. }
  708. gblDIMConfigInfo.ServiceStatus.dwServiceType = SERVICE_WIN32_SHARE_PROCESS;
  709. gblDIMConfigInfo.ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
  710. DimAnnounceServiceStatus();
  711. gblDIMConfigInfo.dwTraceId = TraceRegisterA( "Router" );
  712. try {
  713. //
  714. // Mutex around the interface table
  715. //
  716. InitializeCriticalSection( &(gblInterfaceTable.CriticalSection) );
  717. //
  718. // Mutex around setting router identity attributes
  719. //
  720. InitializeCriticalSection( &(gblDIMConfigInfo.CSRouterIdentity) );
  721. }
  722. except (EXCEPTION_EXECUTE_HANDLER) {
  723. return;
  724. }
  725. gblDIMConfigInfo.hLogEvents = RouterLogRegister( DIM_SERVICE_NAME );
  726. /*
  727. if ( gblDIMConfigInfo.hLogEvents == NULL )
  728. {
  729. DimCleanUp( GetLastError() );
  730. return;
  731. }
  732. */
  733. //
  734. // Create DIM private heap
  735. //
  736. gblDIMConfigInfo.hHeap = HeapCreate( 0, DIM_HEAP_INITIAL_SIZE,
  737. DIM_HEAP_MAX_SIZE );
  738. if ( gblDIMConfigInfo.hHeap == NULL )
  739. {
  740. DimCleanUp( GetLastError() );
  741. return;
  742. }
  743. //
  744. // Lead DIM parameters from the registry
  745. //
  746. if ( ( dwRetCode = RegLoadDimParameters() ) != NO_ERROR )
  747. {
  748. DimCleanUp( dwRetCode );
  749. return;
  750. }
  751. DimAnnounceServiceStatus();
  752. //
  753. // Create event that will be used by DIM to make sure all the Router
  754. // Managers have shut down when DIM is stopping.
  755. //
  756. gblhEventRMState = CreateEvent( NULL, FALSE, FALSE, NULL );
  757. if ( gblhEventRMState == (HANDLE)NULL )
  758. {
  759. DimCleanUp( GetLastError() );
  760. return;
  761. }
  762. //
  763. // Announce that we have successfully started.
  764. //
  765. gblDIMConfigInfo.ServiceStatus.dwCurrentState = SERVICE_RUNNING;
  766. gblDIMConfigInfo.ServiceStatus.dwCheckPoint = 0;
  767. gblDIMConfigInfo.ServiceStatus.dwWaitHint = 0;
  768. gblDIMConfigInfo.ServiceStatus.dwControlsAccepted =
  769. SERVICE_ACCEPT_STOP
  770. | SERVICE_ACCEPT_PAUSE_CONTINUE
  771. | SERVICE_ACCEPT_SHUTDOWN;
  772. DimAnnounceServiceStatus();
  773. //
  774. // Load the router managers
  775. //
  776. gbldwDIMComponentsLoaded |= DIM_RMS_LOADED;
  777. if ( ( dwRetCode = RegLoadRouterManagers() ) != NO_ERROR )
  778. {
  779. DimCleanUp( dwRetCode );
  780. return;
  781. }
  782. //
  783. // Create event that will be used to shutdown the DIM service
  784. //
  785. gblhEventTerminateDIM = CreateEvent( NULL, TRUE, FALSE, NULL );
  786. if ( gblhEventTerminateDIM == (HANDLE)NULL )
  787. {
  788. DimCleanUp( GetLastError() );
  789. return;
  790. }
  791. //
  792. // If not in LAN only mode load the Demand Dial Manager DLL
  793. //
  794. if ( gblDIMConfigInfo.dwRouterRole != ROUTER_ROLE_LAN )
  795. {
  796. //
  797. // Create event that will be used by DDM to notify DIM that it has
  798. // terminated
  799. //
  800. gblhEventDDMTerminated = CreateEvent( NULL, TRUE, FALSE, NULL );
  801. if ( gblhEventDDMTerminated == (HANDLE)NULL )
  802. {
  803. DimCleanUp( GetLastError() );
  804. return;
  805. }
  806. //
  807. // Create event that will be used by DIM to notify DDM that there is
  808. // is a change is state of this service
  809. //
  810. gblhEventDDMServiceState = CreateEvent( NULL, FALSE, FALSE, NULL );
  811. if ( gblhEventDDMServiceState == (HANDLE)NULL )
  812. {
  813. DimCleanUp( GetLastError() );
  814. return;
  815. }
  816. if ( ( dwRetCode = RegLoadDDM() ) != NO_ERROR )
  817. {
  818. DimCleanUp( dwRetCode );
  819. return;
  820. }
  821. //
  822. // Initialize the DDM
  823. //
  824. DDMServiceInitialize = (DWORD(*)( DIM_INFO * ))
  825. GetDDMEntryPoint( "DDMServiceInitialize" );
  826. if ( DDMServiceInitialize == NULL )
  827. {
  828. DimCleanUp( ERROR_PROC_NOT_FOUND );
  829. return;
  830. }
  831. DDMServicePostListens = (VOID(*)( VOID *))
  832. GetDDMEntryPoint( "DDMServicePostListens" );
  833. if ( DDMServicePostListens == NULL )
  834. {
  835. DimCleanUp( ERROR_PROC_NOT_FOUND );
  836. return;
  837. }
  838. DimInfo.pInterfaceTable = &gblInterfaceTable;
  839. DimInfo.pRouterManagers = gblRouterManagers;
  840. DimInfo.dwNumRouterManagers = gblDIMConfigInfo.dwNumRouterManagers;
  841. DimInfo.pServiceStatus = &gblDIMConfigInfo.ServiceStatus;
  842. DimInfo.phEventDDMServiceState = &gblhEventDDMServiceState;
  843. DimInfo.phEventDDMTerminated = &gblhEventDDMTerminated;
  844. DimInfo.dwTraceId = gblDIMConfigInfo.dwTraceId;
  845. DimInfo.hLogEvents = gblDIMConfigInfo.hLogEvents;
  846. DimInfo.lpdwNumThreadsRunning =
  847. &(gblDIMConfigInfo.dwNumThreadsRunning);
  848. DimInfo.lpfnIfObjectAllocateAndInit = IfObjectAllocateAndInit;
  849. DimInfo.lpfnIfObjectGetPointerByName = IfObjectGetPointerByName;
  850. DimInfo.lpfnIfObjectGetPointer = IfObjectGetPointer;
  851. DimInfo.lpfnIfObjectRemove = IfObjectRemove;
  852. DimInfo.lpfnIfObjectInsertInTable = IfObjectInsertInTable;
  853. DimInfo.lpfnIfObjectWANDeviceInstalled = IfObjectWANDeviceInstalled;
  854. DimInfo.lpfnRouterIdentityObjectUpdate
  855. = RouterIdentityObjectUpdateDDMAttributes;
  856. if ( ( dwRetCode = DDMServiceInitialize( &DimInfo ) ) != NO_ERROR )
  857. {
  858. DimCleanUp( dwRetCode );
  859. return;
  860. }
  861. gbldwDIMComponentsLoaded |= DIM_DDM_LOADED;
  862. //
  863. // Initialize random number generator that is used by DDM
  864. //
  865. srand( GetTickCount() );
  866. }
  867. //
  868. // What is the platform
  869. //
  870. RtlGetNtProductType( &(gblDIMConfigInfo.NtProductType) );
  871. //
  872. // Need this to do GUID to friendly name mapping
  873. //
  874. MprConfigServerConnect( NULL, &gblDIMConfigInfo.hMprConfig );
  875. //
  876. // Add the various interfaces
  877. //
  878. dwRetCode = RegLoadInterfaces( NULL, gblDIMConfigInfo.dwNumRouterManagers );
  879. if ( dwRetCode != NO_ERROR )
  880. {
  881. DimCleanUp( dwRetCode );
  882. return;
  883. }
  884. if ( ( dwRetCode = DimSecObjCreate() ) != NO_ERROR )
  885. {
  886. DimCleanUp( dwRetCode );
  887. return;
  888. }
  889. gbldwDIMComponentsLoaded |= DIM_SECOBJ_LOADED;
  890. dwRetCode = DimInitializeRPC(
  891. gblDIMConfigInfo.dwRouterRole == ROUTER_ROLE_LAN );
  892. if ( dwRetCode != NO_ERROR )
  893. {
  894. DimCleanUp( dwRetCode );
  895. return;
  896. }
  897. gbldwDIMComponentsLoaded |= DIM_RPC_LOADED;
  898. //
  899. // Start a timer that when fired will go out and plumb the router attributes
  900. //
  901. if ( RtlCreateTimerQueue( &(gblDIMConfigInfo.hTimerQ) ) == STATUS_SUCCESS )
  902. {
  903. //
  904. // We wait 5 minutes in the case where we are the router providing
  905. // connectivity to the DC so we wait for all routing protocols to
  906. // stabalize and propagate.
  907. //
  908. gblDIMConfigInfo.dwRouterIdentityDueTime = 5*60*1000;
  909. RtlCreateTimer( gblDIMConfigInfo.hTimerQ,
  910. &(gblDIMConfigInfo.hTimer),
  911. RouterIdentityObjectUpdateAttributes,
  912. (PVOID)TRUE,
  913. gblDIMConfigInfo.dwRouterIdentityDueTime,
  914. 0,
  915. WT_EXECUTEDEFAULT );
  916. }
  917. GetSystemTimeAsFileTime( (FILETIME*)&gblDIMConfigInfo.qwStartTime );
  918. if ( gbldwDIMComponentsLoaded & DIM_DDM_LOADED )
  919. {
  920. DDMServicePostListens(NULL);
  921. }
  922. //
  923. // Set the RAS bit for NetServerEnum
  924. //
  925. if( I_ScSetServiceBits( gblDIMConfigInfo.hServiceStatus,
  926. SV_TYPE_DIALIN_SERVER,
  927. TRUE,
  928. TRUE,
  929. NULL) == FALSE )
  930. {
  931. DimCleanUp( GetLastError() );
  932. return;
  933. }
  934. //
  935. // Register for device notifications. Specifically, we're interested
  936. // in network adapters coming and going. If this fails, we proceed
  937. // anyway.
  938. //
  939. {
  940. DEV_BROADCAST_DEVICEINTERFACE PnpFilter;
  941. ZeroMemory( &PnpFilter, sizeof( PnpFilter ) );
  942. PnpFilter.dbcc_size = sizeof( PnpFilter );
  943. PnpFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
  944. PnpFilter.dbcc_classguid = GUID_NDIS_LAN_CLASS;
  945. gblDIMConfigInfo.hDeviceNotification =
  946. RegisterDeviceNotification(
  947. (HANDLE)gblDIMConfigInfo.hServiceStatus,
  948. &PnpFilter,
  949. DEVICE_NOTIFY_SERVICE_HANDLE );
  950. if ( gblDIMConfigInfo.hDeviceNotification == NULL )
  951. {
  952. dwRetCode = GetLastError();
  953. DIMTRACE1( "RegisterDeviceNotification failed with error %d",
  954. dwRetCode );
  955. DimCleanUp( dwRetCode );
  956. return;
  957. }
  958. }
  959. //
  960. // Register for media sense events
  961. //
  962. if ( ( dwRetCode = MediaSenseRegister( TRUE ) ) != NO_ERROR )
  963. {
  964. DIMTRACE1( "Registering for media sense failed with dwRetCode = %d",
  965. dwRetCode );
  966. dwRetCode = NO_ERROR;
  967. }
  968. //
  969. // Register for BIND/UNBIND notifications
  970. //
  971. if ( ( dwRetCode = BindingsNotificationsRegister( TRUE ) ) != NO_ERROR )
  972. {
  973. DIMTRACE1( "Registering for bindings notifications failed with dwRetCode = %d",
  974. dwRetCode );
  975. dwRetCode = NO_ERROR;
  976. }
  977. DIMTRACE( "Multi-Protocol Router started successfully" );
  978. gbldwDIMComponentsLoaded |= DIM_SERVICE_STARTED;
  979. //
  980. // Notify all router managers that all interfaces have been loaded at
  981. // service start.
  982. //
  983. for (dwIndex = 0; dwIndex < gblDIMConfigInfo.dwNumRouterManagers; dwIndex++)
  984. {
  985. gblRouterManagers[dwIndex].DdmRouterIf.RouterBootComplete();
  986. }
  987. //
  988. // If we are a demand dial router
  989. //
  990. if ( gblDIMConfigInfo.dwRouterRole & ROUTER_ROLE_WAN )
  991. {
  992. DWORD dwXportIndex = GetTransportIndex( PID_IP );
  993. //
  994. // Initate persistent demand dial conenctions
  995. //
  996. DWORD (*IfObjectInitiatePersistentConnections)() =
  997. (DWORD(*)())GetDDMEntryPoint("IfObjectInitiatePersistentConnections");
  998. IfObjectInitiatePersistentConnections();
  999. //
  1000. // If a WAN device is installed and IP is installed then we
  1001. // start advertizing on specific multicast address so as to make this
  1002. // router discoverable
  1003. //
  1004. IfObjectWANDeviceInstalled( DimInfo.fWANDeviceInstalled );
  1005. }
  1006. //
  1007. // Just wait here for DIM to terminate.
  1008. //
  1009. dwRetCode = WaitForSingleObject( gblhEventTerminateDIM, INFINITE );
  1010. if ( dwRetCode == WAIT_FAILED )
  1011. {
  1012. dwRetCode = GetLastError();
  1013. }
  1014. else
  1015. {
  1016. dwRetCode = NO_ERROR;
  1017. }
  1018. DimCleanUp( dwRetCode );
  1019. }