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.

1364 lines
38 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. if(gblDIMConfigInfo.hTimer != NULL)
  347. {
  348. RtlDeleteTimer(gblDIMConfigInfo.hTimerQ,
  349. gblDIMConfigInfo.hTimer,
  350. NULL);
  351. gblDIMConfigInfo.hTimer = NULL;
  352. }
  353. RtlDeleteTimerQueueEx( gblDIMConfigInfo.hTimerQ, INVALID_HANDLE_VALUE );
  354. gblDIMConfigInfo.hTimerQ = NULL;
  355. }
  356. EnterCriticalSection( &(gblDIMConfigInfo.CSRouterIdentity) );
  357. DeleteCriticalSection( &(gblDIMConfigInfo.CSRouterIdentity) );
  358. if ( gbldwDIMComponentsLoaded & DIM_DDM_LOADED )
  359. {
  360. //
  361. // If we are not in LANOnly mode then stop DDM
  362. //
  363. if ( gblDIMConfigInfo.dwRouterRole != ROUTER_ROLE_LAN )
  364. {
  365. if ( gblhEventDDMServiceState != NULL )
  366. {
  367. SetEvent( gblhEventDDMServiceState );
  368. }
  369. }
  370. //
  371. // Wait for all threads in use to stop
  372. //
  373. while( gblDIMConfigInfo.dwNumThreadsRunning > 0 )
  374. {
  375. Sleep( 1000 );
  376. }
  377. }
  378. // just to increment checkpoints
  379. DimAnnounceServiceStatus();
  380. //
  381. // Tear down and free everything
  382. //
  383. if ( gbldwDIMComponentsLoaded & DIM_RMS_LOADED )
  384. {
  385. DimUnloadRouterManagers();
  386. }
  387. //
  388. // Unregister for media sense
  389. //
  390. MediaSenseRegister( FALSE );
  391. //
  392. // Unregister for bind/unbind sense
  393. //
  394. BindingsNotificationsRegister( FALSE );
  395. //
  396. // Need to sleep to give the router managers a change to unload
  397. // bug# 78711
  398. //
  399. Sleep( 2000 );
  400. if ( gblhModuleDDM != NULL )
  401. {
  402. VOID (*DDMPostCleanup)( VOID ) = NULL;
  403. DDMPostCleanup = (VOID(*)( VOID ))
  404. GetDDMEntryPoint("DDMPostCleanup");
  405. if(NULL != DDMPostCleanup)
  406. {
  407. //
  408. // Call DDM to cleanup.
  409. //
  410. DDMPostCleanup();
  411. }
  412. FreeLibrary( gblhModuleDDM );
  413. }
  414. //
  415. // If security object was created
  416. //
  417. if ( gbldwDIMComponentsLoaded & DIM_SECOBJ_LOADED )
  418. {
  419. DimSecObjDelete();
  420. }
  421. if ( gblDIMConfigInfo.hMprConfig != NULL )
  422. {
  423. MprConfigServerDisconnect( gblDIMConfigInfo.hMprConfig );
  424. }
  425. if ( gblhEventDDMTerminated != NULL )
  426. {
  427. CloseHandle( gblhEventDDMTerminated );
  428. }
  429. if ( gblhEventDDMServiceState != NULL )
  430. {
  431. CloseHandle( gblhEventDDMServiceState );
  432. }
  433. if ( gblhEventTerminateDIM != NULL )
  434. {
  435. CloseHandle( gblhEventTerminateDIM );
  436. }
  437. if ( gblhEventRMState != NULL )
  438. {
  439. CloseHandle( gblhEventRMState );
  440. }
  441. if ( gblDIMConfigInfo.hObjectRouterIdentity != NULL )
  442. {
  443. RouterIdentityObjectClose( gblDIMConfigInfo.hObjectRouterIdentity );
  444. }
  445. //
  446. // Wait for everybody to release this and then delete it
  447. //
  448. EnterCriticalSection( &(gblInterfaceTable.CriticalSection) );
  449. DeleteCriticalSection( &(gblInterfaceTable.CriticalSection) );
  450. gbldwDIMComponentsLoaded = 0;
  451. if ( gblDIMConfigInfo.dwTraceId != INVALID_TRACEID )
  452. {
  453. TraceDeregisterA( gblDIMConfigInfo.dwTraceId );
  454. }
  455. RouterLogDeregister( gblDIMConfigInfo.hLogEvents );
  456. //
  457. // Destroy private heap
  458. //
  459. if ( gblDIMConfigInfo.hHeap != NULL )
  460. {
  461. HeapDestroy( gblDIMConfigInfo.hHeap );
  462. }
  463. DIMTRACE1("DimCleanup completed for error %d", dwError );
  464. //
  465. // Zero init all the globals
  466. //
  467. gblRouterManagers = NULL;
  468. gbldwDIMComponentsLoaded = 0;
  469. gblhEventDDMTerminated = NULL;
  470. gblhEventRMState = NULL;
  471. gblhEventDDMServiceState = NULL;
  472. gblhModuleDDM = NULL;
  473. gblhEventTerminateDIM = NULL;
  474. ZeroMemory( &gblInterfaceTable, sizeof( gblInterfaceTable ) );
  475. {
  476. SERVICE_STATUS_HANDLE svchandle = gblDIMConfigInfo.hServiceStatus;
  477. ZeroMemory( &gblDIMConfigInfo, sizeof( gblDIMConfigInfo ) );
  478. gblDIMConfigInfo.hServiceStatus = svchandle;
  479. }
  480. //
  481. // Zero out only the procedure entrypoints. This is a side effect of
  482. // the merge into svchost.exe since svchost doesn't unload mprdim
  483. // anymore when router stops.
  484. //
  485. for ( dwIndex = 0;
  486. gblDDMFunctionTable[dwIndex].lpEntryPointName != NULL;
  487. dwIndex ++ )
  488. {
  489. gblDDMFunctionTable[dwIndex].pEntryPoint = NULL;
  490. }
  491. if ( dwError == NO_ERROR )
  492. {
  493. gblDIMConfigInfo.ServiceStatus.dwWin32ExitCode = NO_ERROR;
  494. }
  495. else
  496. {
  497. gblDIMConfigInfo.ServiceStatus.dwWin32ExitCode =
  498. ERROR_SERVICE_SPECIFIC_ERROR;
  499. }
  500. gblDIMConfigInfo.ServiceStatus.dwServiceType = SERVICE_WIN32_SHARE_PROCESS;
  501. gblDIMConfigInfo.ServiceStatus.dwCurrentState = SERVICE_STOPPED;
  502. gblDIMConfigInfo.ServiceStatus.dwControlsAccepted = 0;
  503. gblDIMConfigInfo.ServiceStatus.dwCheckPoint = 0;
  504. gblDIMConfigInfo.ServiceStatus.dwWaitHint = 0;
  505. gblDIMConfigInfo.ServiceStatus.dwServiceSpecificExitCode = dwError;
  506. gbldwDIMComponentsLoaded |= DIM_SERVICE_STOPPED;
  507. DimAnnounceServiceStatus();
  508. }
  509. //**
  510. //
  511. // Call: ServiceHandlerEx
  512. //
  513. // Returns: none
  514. //
  515. // Description: Will respond to control requests from the service controller.
  516. //
  517. DWORD
  518. ServiceHandlerEx(
  519. IN DWORD dwControlCode,
  520. IN DWORD dwEventType,
  521. IN LPVOID lpEventData,
  522. IN LPVOID lpContext
  523. )
  524. {
  525. DWORD dwRetCode = NO_ERROR;
  526. switch( dwControlCode )
  527. {
  528. case SERVICE_CONTROL_STOP:
  529. case SERVICE_CONTROL_SHUTDOWN:
  530. if ( ( gblDIMConfigInfo.ServiceStatus.dwCurrentState ==
  531. SERVICE_STOP_PENDING)
  532. ||
  533. ( gblDIMConfigInfo.ServiceStatus.dwCurrentState ==
  534. SERVICE_STOPPED ))
  535. {
  536. break;
  537. }
  538. DIMTRACE("Service control stop or shutdown called");
  539. //
  540. // Announce that we are stopping
  541. //
  542. gblDIMConfigInfo.ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
  543. gblDIMConfigInfo.ServiceStatus.dwControlsAccepted = 0;
  544. gblDIMConfigInfo.ServiceStatus.dwCheckPoint = 1;
  545. gblDIMConfigInfo.ServiceStatus.dwWaitHint = 200000;
  546. DimAnnounceServiceStatus();
  547. //
  548. // Make sure service is started before initiating a stop
  549. //
  550. while( !( gbldwDIMComponentsLoaded & DIM_SERVICE_STARTED ) )
  551. {
  552. //
  553. // Check to see if the we have already sent the
  554. // stopped status. If it did, then bail.
  555. //
  556. if(gbldwDIMComponentsLoaded & DIM_SERVICE_STOPPED)
  557. {
  558. return dwRetCode;
  559. }
  560. Sleep( 1000 );
  561. }
  562. SetEvent( gblhEventTerminateDIM );
  563. return( NO_ERROR );
  564. case SERVICE_CONTROL_PAUSE:
  565. if ( ( gblDIMConfigInfo.ServiceStatus.dwCurrentState ==
  566. SERVICE_PAUSE_PENDING)
  567. ||
  568. ( gblDIMConfigInfo.ServiceStatus.dwCurrentState ==
  569. SERVICE_PAUSED ))
  570. break;
  571. gblDIMConfigInfo.ServiceStatus.dwCurrentState = SERVICE_PAUSED;
  572. gblDIMConfigInfo.ServiceStatus.dwControlsAccepted = 0;
  573. gblDIMConfigInfo.ServiceStatus.dwCheckPoint = 0;
  574. gblDIMConfigInfo.ServiceStatus.dwWaitHint = 200000;
  575. gblDIMConfigInfo.ServiceStatus.dwControlsAccepted =
  576. SERVICE_ACCEPT_STOP
  577. | SERVICE_ACCEPT_PAUSE_CONTINUE
  578. | SERVICE_ACCEPT_SHUTDOWN;
  579. SetEvent( gblhEventDDMServiceState );
  580. break;
  581. case SERVICE_CONTROL_CONTINUE:
  582. if ( ( gblDIMConfigInfo.ServiceStatus.dwCurrentState ==
  583. SERVICE_CONTINUE_PENDING )
  584. ||
  585. ( gblDIMConfigInfo.ServiceStatus.dwCurrentState ==
  586. SERVICE_RUNNING ) )
  587. break;
  588. gblDIMConfigInfo.ServiceStatus.dwCheckPoint = 0;
  589. gblDIMConfigInfo.ServiceStatus.dwWaitHint = 0;
  590. gblDIMConfigInfo.ServiceStatus.dwCurrentState = SERVICE_RUNNING;
  591. gblDIMConfigInfo.ServiceStatus.dwControlsAccepted =
  592. SERVICE_ACCEPT_STOP
  593. | SERVICE_ACCEPT_PAUSE_CONTINUE
  594. | SERVICE_ACCEPT_SHUTDOWN;
  595. SetEvent( gblhEventDDMServiceState );
  596. break;
  597. case SERVICE_CONTROL_DEVICEEVENT:
  598. if ( ( gblDIMConfigInfo.ServiceStatus.dwCurrentState ==
  599. SERVICE_STOP_PENDING)
  600. ||
  601. ( gblDIMConfigInfo.ServiceStatus.dwCurrentState ==
  602. SERVICE_STOPPED ))
  603. {
  604. break;
  605. }
  606. if ( lpEventData != NULL)
  607. {
  608. DEV_BROADCAST_DEVICEINTERFACE* pInfo =
  609. (DEV_BROADCAST_DEVICEINTERFACE*)lpEventData;
  610. if ( pInfo->dbcc_devicetype == DBT_DEVTYP_DEVICEINTERFACE )
  611. {
  612. ROUTER_INTERFACE_OBJECT * pIfObject = NULL;
  613. if ( ( dwEventType == DBT_DEVICEARRIVAL ) ||
  614. ( dwEventType == DBT_DEVICEREMOVECOMPLETE ) )
  615. {
  616. //
  617. // Extract GUID from the \device\GUID name
  618. //
  619. LPWSTR lpwszGUIDStart = wcsrchr( pInfo->dbcc_name, L'{' );
  620. LPWSTR lpwszGUIDEnd = wcsrchr( pInfo->dbcc_name, L'}' );
  621. if ( lpwszGUIDStart != NULL )
  622. {
  623. WCHAR wchGUIDSaveLast = *(lpwszGUIDEnd+1);
  624. EnterCriticalSection( &(gblInterfaceTable.CriticalSection));
  625. *(lpwszGUIDEnd+1) = (WCHAR)NULL;
  626. pIfObject = IfObjectGetPointerByName( lpwszGUIDStart, FALSE );
  627. *(lpwszGUIDEnd+1) = wchGUIDSaveLast;
  628. if ( dwEventType == DBT_DEVICEARRIVAL )
  629. {
  630. if ( pIfObject == NULL )
  631. {
  632. DIMTRACE1("Device arrival:[%ws]", lpwszGUIDStart );
  633. RegLoadInterfaces( lpwszGUIDStart, TRUE );
  634. }
  635. }
  636. else
  637. {
  638. if ( pIfObject != NULL )
  639. {
  640. DIMTRACE1("Device removed:[%ws]", lpwszGUIDStart );
  641. IfObjectDeleteInterfaceFromTransport( pIfObject, PID_IP );
  642. IfObjectDeleteInterfaceFromTransport( pIfObject, PID_IPX);
  643. IfObjectRemove( pIfObject->hDIMInterface );
  644. }
  645. }
  646. LeaveCriticalSection( &(gblInterfaceTable.CriticalSection) );
  647. }
  648. }
  649. }
  650. }
  651. break;
  652. case RAS_CONTROL_CONFIGURE:
  653. //
  654. // Code for dynamic configuration of RAP
  655. //
  656. DIMTRACE( "Received Remote Access Policy change control message" );
  657. {
  658. //
  659. // thread needs to be COM initialized
  660. //
  661. HRESULT hResult = CoInitializeEx( NULL, COINIT_MULTITHREADED );
  662. if ( SUCCEEDED( hResult ) )
  663. {
  664. //
  665. // configure, doesn't matter if the API call fails
  666. //
  667. ConfigureIas();
  668. CoUninitialize();
  669. }
  670. }
  671. break;
  672. case SERVICE_CONTROL_POWEREVENT:
  673. switch( dwEventType )
  674. {
  675. case PBT_APMQUERYSTANDBY:
  676. case PBT_APMQUERYSUSPEND:
  677. //
  678. // Check if the this is running on a workstation
  679. //
  680. if (gblOsVersionInfo.wProductType == VER_NT_WORKSTATION)
  681. {
  682. //
  683. // DIM has no say in the hibernation process on a
  684. // workstation
  685. //
  686. break;
  687. }
  688. //
  689. // If we are running as an RRAS server, on a Server platform,
  690. // refuse the hibernate.
  691. //
  692. // This is not the best possible response, but given that
  693. // connectivity is liable to break if an RRAS server is
  694. // hibernated it is reasonable to prevent it (for now).
  695. //
  696. // In addition, the design of RTM currently (.net server)
  697. // causes a delayed deletion of routes from the TCP/IP stack
  698. // on a hibernate (routes deleted from IP Router Manager prior
  699. // to hibernate are deleted from the stack when coming out of
  700. // hibernate) leading to the loss of routes and hence
  701. // connectivity. Until the design of RTM is fixed rejecting
  702. // the hibernate query is the best solution.
  703. //
  704. if ( gblDIMConfigInfo.dwRouterRole &
  705. ( ROUTER_ROLE_LAN | ROUTER_ROLE_WAN | ROUTER_ROLE_RAS ) )
  706. {
  707. dwRetCode = ERROR_ACTIVE_CONNECTIONS;
  708. }
  709. break;
  710. case PBT_APMRESUMECRITICAL:
  711. default:
  712. {
  713. break;
  714. }
  715. }
  716. break;
  717. case SERVICE_CONTROL_NETBINDADD:
  718. case SERVICE_CONTROL_NETBINDREMOVE:
  719. case SERVICE_CONTROL_NETBINDENABLE:
  720. case SERVICE_CONTROL_NETBINDDISABLE:
  721. break;
  722. default:
  723. return( ERROR_CALL_NOT_IMPLEMENTED );
  724. break;
  725. }
  726. DimAnnounceServiceStatus();
  727. return( dwRetCode );
  728. }
  729. //**
  730. //
  731. // Call: ServiceMain
  732. //
  733. // Returns: None
  734. //
  735. // Description: This is the main procedure for the DIM Server Service. It
  736. // will be called when the service is supposed to start itself.
  737. // It will do all service wide initialization.
  738. //
  739. VOID
  740. ServiceMain(
  741. IN DWORD argc, // Command line arguments. Will be ignored.
  742. IN LPWSTR * lpwsServiceArgs
  743. )
  744. {
  745. DIM_INFO DimInfo;
  746. DWORD dwRetCode;
  747. DWORD dwIndex;
  748. DWORD (*DDMServiceInitialize)( DIM_INFO * );
  749. VOID (*DDMServicePostListens)( VOID *) = NULL;
  750. UNREFERENCED_PARAMETER( argc );
  751. UNREFERENCED_PARAMETER( lpwsServiceArgs );
  752. gbldwDIMComponentsLoaded &= ~(DIM_SERVICE_STOPPED);
  753. gblDIMConfigInfo.hServiceStatus = RegisterServiceCtrlHandlerEx(
  754. TEXT("remoteaccess"),
  755. ServiceHandlerEx,
  756. NULL );
  757. if ( !gblDIMConfigInfo.hServiceStatus )
  758. {
  759. return;
  760. }
  761. gblDIMConfigInfo.ServiceStatus.dwServiceType = SERVICE_WIN32_SHARE_PROCESS;
  762. gblDIMConfigInfo.ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
  763. DimAnnounceServiceStatus();
  764. gblDIMConfigInfo.dwTraceId = TraceRegisterA( "Router" );
  765. try {
  766. //
  767. // Mutex around the interface table
  768. //
  769. InitializeCriticalSection( &(gblInterfaceTable.CriticalSection) );
  770. //
  771. // Mutex around setting router identity attributes
  772. //
  773. InitializeCriticalSection( &(gblDIMConfigInfo.CSRouterIdentity) );
  774. }
  775. except (EXCEPTION_EXECUTE_HANDLER) {
  776. return;
  777. }
  778. gblDIMConfigInfo.hLogEvents = RouterLogRegister( DIM_SERVICE_NAME );
  779. /*
  780. if ( gblDIMConfigInfo.hLogEvents == NULL )
  781. {
  782. DimCleanUp( GetLastError() );
  783. return;
  784. }
  785. */
  786. //
  787. // Create DIM private heap
  788. //
  789. gblDIMConfigInfo.hHeap = HeapCreate( 0, DIM_HEAP_INITIAL_SIZE,
  790. DIM_HEAP_MAX_SIZE );
  791. if ( gblDIMConfigInfo.hHeap == NULL )
  792. {
  793. DimCleanUp( GetLastError() );
  794. return;
  795. }
  796. //
  797. // Lead DIM parameters from the registry
  798. //
  799. if ( ( dwRetCode = RegLoadDimParameters() ) != NO_ERROR )
  800. {
  801. DimCleanUp( dwRetCode );
  802. return;
  803. }
  804. DimAnnounceServiceStatus();
  805. //
  806. // Create event that will be used by DIM to make sure all the Router
  807. // Managers have shut down when DIM is stopping.
  808. //
  809. gblhEventRMState = CreateEvent( NULL, FALSE, FALSE, NULL );
  810. if ( gblhEventRMState == (HANDLE)NULL )
  811. {
  812. DimCleanUp( GetLastError() );
  813. return;
  814. }
  815. //
  816. // Announce that we have successfully started.
  817. //
  818. gblDIMConfigInfo.ServiceStatus.dwCurrentState = SERVICE_RUNNING;
  819. gblDIMConfigInfo.ServiceStatus.dwCheckPoint = 0;
  820. gblDIMConfigInfo.ServiceStatus.dwWaitHint = 0;
  821. gblDIMConfigInfo.ServiceStatus.dwControlsAccepted =
  822. SERVICE_ACCEPT_STOP
  823. | SERVICE_ACCEPT_POWEREVENT
  824. | SERVICE_ACCEPT_PAUSE_CONTINUE
  825. | SERVICE_ACCEPT_SHUTDOWN;
  826. DimAnnounceServiceStatus();
  827. //
  828. // Load the router managers
  829. //
  830. gbldwDIMComponentsLoaded |= DIM_RMS_LOADED;
  831. if ( ( dwRetCode = RegLoadRouterManagers() ) != NO_ERROR )
  832. {
  833. DimCleanUp( dwRetCode );
  834. return;
  835. }
  836. #if (WINVER >= 0x0501)
  837. if ( gblDIMConfigInfo.dwNumRouterManagers == 0)
  838. {
  839. DimCleanUp( ROUTERLOG_IPX_TRANSPORT_NOT_SUPPORTED );
  840. return;
  841. }
  842. #endif
  843. //
  844. // Create event that will be used to shutdown the DIM service
  845. //
  846. gblhEventTerminateDIM = CreateEvent( NULL, TRUE, FALSE, NULL );
  847. if ( gblhEventTerminateDIM == (HANDLE)NULL )
  848. {
  849. DimCleanUp( GetLastError() );
  850. return;
  851. }
  852. //
  853. // If not in LAN only mode load the Demand Dial Manager DLL
  854. //
  855. if ( gblDIMConfigInfo.dwRouterRole != ROUTER_ROLE_LAN )
  856. {
  857. //
  858. // Create event that will be used by DDM to notify DIM that it has
  859. // terminated
  860. //
  861. gblhEventDDMTerminated = CreateEvent( NULL, TRUE, FALSE, NULL );
  862. if ( gblhEventDDMTerminated == (HANDLE)NULL )
  863. {
  864. DimCleanUp( GetLastError() );
  865. return;
  866. }
  867. //
  868. // Create event that will be used by DIM to notify DDM that there is
  869. // is a change is state of this service
  870. //
  871. gblhEventDDMServiceState = CreateEvent( NULL, FALSE, FALSE, NULL );
  872. if ( gblhEventDDMServiceState == (HANDLE)NULL )
  873. {
  874. DimCleanUp( GetLastError() );
  875. return;
  876. }
  877. if ( ( dwRetCode = RegLoadDDM() ) != NO_ERROR )
  878. {
  879. DimCleanUp( dwRetCode );
  880. return;
  881. }
  882. //
  883. // Initialize the DDM
  884. //
  885. DDMServiceInitialize = (DWORD(*)( DIM_INFO * ))
  886. GetDDMEntryPoint( "DDMServiceInitialize" );
  887. if ( DDMServiceInitialize == NULL )
  888. {
  889. DimCleanUp( ERROR_PROC_NOT_FOUND );
  890. return;
  891. }
  892. DDMServicePostListens = (VOID(*)( VOID *))
  893. GetDDMEntryPoint( "DDMServicePostListens" );
  894. if ( DDMServicePostListens == NULL )
  895. {
  896. DimCleanUp( ERROR_PROC_NOT_FOUND );
  897. return;
  898. }
  899. DimInfo.pInterfaceTable = &gblInterfaceTable;
  900. DimInfo.pRouterManagers = gblRouterManagers;
  901. DimInfo.dwNumRouterManagers = gblDIMConfigInfo.dwNumRouterManagers;
  902. DimInfo.pServiceStatus = &gblDIMConfigInfo.ServiceStatus;
  903. DimInfo.phEventDDMServiceState = &gblhEventDDMServiceState;
  904. DimInfo.phEventDDMTerminated = &gblhEventDDMTerminated;
  905. DimInfo.dwTraceId = gblDIMConfigInfo.dwTraceId;
  906. DimInfo.hLogEvents = gblDIMConfigInfo.hLogEvents;
  907. DimInfo.lpdwNumThreadsRunning =
  908. &(gblDIMConfigInfo.dwNumThreadsRunning);
  909. DimInfo.lpfnIfObjectAllocateAndInit = IfObjectAllocateAndInit;
  910. DimInfo.lpfnIfObjectGetPointerByName = IfObjectGetPointerByName;
  911. DimInfo.lpfnIfObjectGetPointer = IfObjectGetPointer;
  912. DimInfo.lpfnIfObjectRemove = IfObjectRemove;
  913. DimInfo.lpfnIfObjectInsertInTable = IfObjectInsertInTable;
  914. DimInfo.lpfnIfObjectWANDeviceInstalled = IfObjectWANDeviceInstalled;
  915. DimInfo.lpfnRouterIdentityObjectUpdate
  916. = RouterIdentityObjectUpdateDDMAttributes;
  917. if ( ( dwRetCode = DDMServiceInitialize( &DimInfo ) ) != NO_ERROR )
  918. {
  919. DimCleanUp( dwRetCode );
  920. return;
  921. }
  922. gbldwDIMComponentsLoaded |= DIM_DDM_LOADED;
  923. //
  924. // Initialize random number generator that is used by DDM
  925. //
  926. srand( GetTickCount() );
  927. }
  928. //
  929. // What is the platform
  930. //
  931. RtlGetNtProductType( &(gblDIMConfigInfo.NtProductType) );
  932. //
  933. // Need this to do GUID to friendly name mapping
  934. //
  935. MprConfigServerConnect( NULL, &gblDIMConfigInfo.hMprConfig );
  936. //
  937. // Add the various interfaces
  938. //
  939. dwRetCode = RegLoadInterfaces( NULL, gblDIMConfigInfo.dwNumRouterManagers );
  940. if ( dwRetCode != NO_ERROR )
  941. {
  942. DimCleanUp( dwRetCode );
  943. return;
  944. }
  945. if ( ( dwRetCode = DimSecObjCreate() ) != NO_ERROR )
  946. {
  947. DimCleanUp( dwRetCode );
  948. return;
  949. }
  950. gbldwDIMComponentsLoaded |= DIM_SECOBJ_LOADED;
  951. dwRetCode = DimInitializeRPC(
  952. gblDIMConfigInfo.dwRouterRole == ROUTER_ROLE_LAN );
  953. if ( dwRetCode != NO_ERROR )
  954. {
  955. DimCleanUp( dwRetCode );
  956. return;
  957. }
  958. gbldwDIMComponentsLoaded |= DIM_RPC_LOADED;
  959. //
  960. // Start a timer that when fired will go out and plumb the router attributes
  961. //
  962. if ( RtlCreateTimerQueue( &(gblDIMConfigInfo.hTimerQ) ) == STATUS_SUCCESS )
  963. {
  964. //
  965. // We wait 5 minutes in the case where we are the router providing
  966. // connectivity to the DC so we wait for all routing protocols to
  967. // stabalize and propagate.
  968. //
  969. gblDIMConfigInfo.dwRouterIdentityDueTime = 5*60*1000;
  970. RtlCreateTimer( gblDIMConfigInfo.hTimerQ,
  971. &(gblDIMConfigInfo.hTimer),
  972. RouterIdentityObjectUpdateAttributes,
  973. (PVOID)TRUE,
  974. gblDIMConfigInfo.dwRouterIdentityDueTime,
  975. 0,
  976. WT_EXECUTEDEFAULT );
  977. }
  978. GetSystemTimeAsFileTime( (FILETIME*)&gblDIMConfigInfo.qwStartTime );
  979. if ( gbldwDIMComponentsLoaded & DIM_DDM_LOADED )
  980. {
  981. if (DDMServicePostListens) //to keep prefast happy
  982. DDMServicePostListens(NULL);
  983. }
  984. //
  985. // Set the RAS bit for NetServerEnum
  986. //
  987. if( I_ScSetServiceBits( gblDIMConfigInfo.hServiceStatus,
  988. SV_TYPE_DIALIN_SERVER,
  989. TRUE,
  990. TRUE,
  991. NULL) == FALSE )
  992. {
  993. DimCleanUp( GetLastError() );
  994. return;
  995. }
  996. //
  997. // Register for device notifications. Specifically, we're interested
  998. // in network adapters coming and going. If this fails, we proceed
  999. // anyway.
  1000. //
  1001. {
  1002. DEV_BROADCAST_DEVICEINTERFACE PnpFilter;
  1003. ZeroMemory( &PnpFilter, sizeof( PnpFilter ) );
  1004. PnpFilter.dbcc_size = sizeof( PnpFilter );
  1005. PnpFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
  1006. PnpFilter.dbcc_classguid = GUID_NDIS_LAN_CLASS;
  1007. gblDIMConfigInfo.hDeviceNotification =
  1008. RegisterDeviceNotification(
  1009. (HANDLE)gblDIMConfigInfo.hServiceStatus,
  1010. &PnpFilter,
  1011. DEVICE_NOTIFY_SERVICE_HANDLE );
  1012. if ( gblDIMConfigInfo.hDeviceNotification == NULL )
  1013. {
  1014. dwRetCode = GetLastError();
  1015. DIMTRACE1( "RegisterDeviceNotification failed with error %d",
  1016. dwRetCode );
  1017. DimCleanUp( dwRetCode );
  1018. return;
  1019. }
  1020. }
  1021. //
  1022. // Register for media sense events
  1023. //
  1024. if ( ( dwRetCode = MediaSenseRegister( TRUE ) ) != NO_ERROR )
  1025. {
  1026. DIMTRACE1( "Registering for media sense failed with dwRetCode = %d",
  1027. dwRetCode );
  1028. dwRetCode = NO_ERROR;
  1029. }
  1030. //
  1031. // Register for BIND/UNBIND notifications
  1032. //
  1033. if ( ( dwRetCode = BindingsNotificationsRegister( TRUE ) ) != NO_ERROR )
  1034. {
  1035. DIMTRACE1( "Registering for bindings notifications failed with dwRetCode = %d",
  1036. dwRetCode );
  1037. dwRetCode = NO_ERROR;
  1038. }
  1039. DIMTRACE( "Multi-Protocol Router started successfully" );
  1040. gbldwDIMComponentsLoaded |= DIM_SERVICE_STARTED;
  1041. //
  1042. // Notify all router managers that all interfaces have been loaded at
  1043. // service start.
  1044. //
  1045. for (dwIndex = 0; dwIndex < gblDIMConfigInfo.dwNumRouterManagers; dwIndex++)
  1046. {
  1047. gblRouterManagers[dwIndex].DdmRouterIf.RouterBootComplete();
  1048. }
  1049. //
  1050. // If we are a demand dial router
  1051. //
  1052. if ( gblDIMConfigInfo.dwRouterRole & ROUTER_ROLE_WAN )
  1053. {
  1054. DWORD dwXportIndex = GetTransportIndex( PID_IP );
  1055. //
  1056. // Initate persistent demand dial conenctions
  1057. //
  1058. DWORD (*IfObjectInitiatePersistentConnections)() =
  1059. (DWORD(*)())GetDDMEntryPoint("IfObjectInitiatePersistentConnections");
  1060. IfObjectInitiatePersistentConnections();
  1061. //
  1062. // If a WAN device is installed and IP is installed then we
  1063. // start advertizing on specific multicast address so as to make this
  1064. // router discoverable
  1065. //
  1066. IfObjectWANDeviceInstalled( DimInfo.fWANDeviceInstalled );
  1067. }
  1068. //
  1069. // Just wait here for DIM to terminate.
  1070. //
  1071. dwRetCode = WaitForSingleObject( gblhEventTerminateDIM, INFINITE );
  1072. if ( dwRetCode == WAIT_FAILED )
  1073. {
  1074. dwRetCode = GetLastError();
  1075. }
  1076. else
  1077. {
  1078. dwRetCode = NO_ERROR;
  1079. }
  1080. DimCleanUp( dwRetCode );
  1081. }