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.

1305 lines
32 KiB

  1. /*++
  2. Copyright (c) 1990-1992 Microsoft Corporation
  3. Module Name:
  4. brmain.c
  5. Abstract:
  6. This is the main routine for the NT LAN Manager Browser service.
  7. Author:
  8. Larry Osterman (LarryO) 3-23-92
  9. Environment:
  10. User Mode - Win32
  11. Revision History:
  12. --*/
  13. #include "precomp.h"
  14. #pragma hdrstop
  15. #if DBG
  16. #endif
  17. //-------------------------------------------------------------------//
  18. // //
  19. // Local structure definitions //
  20. // //
  21. //-------------------------------------------------------------------//
  22. ULONG
  23. UpdateAnnouncementPeriodicity[] = {1*60*1000, 2*60*1000, 5*60*1000, 10*60*1000, 15*60*1000, 30*60*1000, 60*60*1000};
  24. ULONG
  25. UpdateAnnouncementMax = (sizeof(UpdateAnnouncementPeriodicity) / sizeof(ULONG)) - 1;
  26. //-------------------------------------------------------------------//
  27. // //
  28. // Global variables //
  29. // //
  30. //-------------------------------------------------------------------//
  31. BR_GLOBAL_DATA
  32. BrGlobalData = {0};
  33. ULONG
  34. BrDefaultRole = {0};
  35. PSVCHOST_GLOBAL_DATA BrLmsvcsGlobalData;
  36. HANDLE BrGlobalEventlogHandle;
  37. //-------------------------------------------------------------------//
  38. // //
  39. // Function prototypes //
  40. // //
  41. //-------------------------------------------------------------------//
  42. NET_API_STATUS
  43. BrInitializeBrowser(
  44. OUT LPDWORD BrInitState
  45. );
  46. NET_API_STATUS
  47. BrInitializeBrowserService(
  48. OUT LPDWORD BrInitState
  49. );
  50. VOID
  51. BrUninitializeBrowser(
  52. IN DWORD BrInitState
  53. );
  54. VOID
  55. BrShutdownBrowser(
  56. IN NET_API_STATUS ErrorCode,
  57. IN DWORD BrInitState
  58. );
  59. VOID
  60. BrowserControlHandler(
  61. IN DWORD Opcode
  62. );
  63. VOID
  64. SvchostPushServiceGlobals (
  65. PSVCHOST_GLOBAL_DATA pGlobals
  66. )
  67. {
  68. BrLmsvcsGlobalData = pGlobals;
  69. }
  70. VOID
  71. ServiceMain ( // (BROWSER_main)
  72. DWORD NumArgs,
  73. LPTSTR *ArgsArray
  74. )
  75. /*++
  76. Routine Description:
  77. This is the main routine of the Browser Service which registers
  78. itself as an RPC server and notifies the Service Controller of the
  79. Browser service control entry point.
  80. Arguments:
  81. NumArgs - Supplies the number of strings specified in ArgsArray.
  82. ArgsArray - Supplies string arguments that are specified in the
  83. StartService API call. This parameter is ignored by the
  84. Browser service.
  85. Return Value:
  86. None.
  87. --*/
  88. {
  89. NET_API_STATUS NetStatus;
  90. DWORD BrInitState = 0;
  91. BrGlobalBrowserSecurityDescriptor = NULL;
  92. UNREFERENCED_PARAMETER(NumArgs);
  93. UNREFERENCED_PARAMETER(ArgsArray);
  94. //
  95. // Make sure svchost.exe gave us the global data
  96. //
  97. ASSERT(BrLmsvcsGlobalData != NULL);
  98. NetStatus = BrInitializeBrowserService(&BrInitState);
  99. //
  100. // Process requests in this thread, and wait for termination.
  101. //
  102. if ( NetStatus == NERR_Success) {
  103. //
  104. // Set the browser threads to time critical priority.
  105. //
  106. SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
  107. BrWorkerThread((PVOID)-1);
  108. }
  109. BrShutdownBrowser(
  110. NetStatus,
  111. BrInitState
  112. );
  113. return;
  114. }
  115. NET_API_STATUS
  116. BrInitializeBrowserService(
  117. OUT LPDWORD BrInitState
  118. )
  119. /*++
  120. Routine Description:
  121. This function initializes the Browser service.
  122. Arguments:
  123. BrInitState - Returns a flag to indicate how far we got with initializing
  124. the Browser service before an error occured.
  125. Return Value:
  126. NET_API_STATUS - NERR_Success or reason for failure.
  127. --*/
  128. {
  129. NET_API_STATUS Status;
  130. NTSTATUS NtStatus;
  131. //
  132. // Initialize event logging
  133. //
  134. BrGlobalEventlogHandle = NetpEventlogOpen ( SERVICE_BROWSER,
  135. 2*60*60*1000 ); // 2 hours
  136. if ( BrGlobalEventlogHandle == NULL ) {
  137. BrPrint((BR_CRITICAL, "Cannot NetpEventlogOpen\n" ));
  138. return ERROR_NOT_ENOUGH_MEMORY;
  139. }
  140. //
  141. // Initialize all the status fields so that subsequent calls to
  142. // SetServiceStatus need to only update fields that changed.
  143. //
  144. BrGlobalData.Status.dwServiceType = SERVICE_WIN32;
  145. BrGlobalData.Status.dwCurrentState = SERVICE_START_PENDING;
  146. BrGlobalData.Status.dwControlsAccepted = 0;
  147. BrGlobalData.Status.dwCheckPoint = 0;
  148. BrGlobalData.Status.dwWaitHint = BR_WAIT_HINT_TIME;
  149. SET_SERVICE_EXITCODE(
  150. NO_ERROR,
  151. BrGlobalData.Status.dwWin32ExitCode,
  152. BrGlobalData.Status.dwServiceSpecificExitCode
  153. );
  154. BrInitializeTraceLog();
  155. BrPrint(( BR_INIT, "Browser starting\n"));
  156. //
  157. // Initialize Browser to receive service requests by registering the
  158. // control handler.
  159. //
  160. if ((BrGlobalData.StatusHandle = RegisterServiceCtrlHandler(
  161. SERVICE_BROWSER,
  162. BrowserControlHandler
  163. )) == (SERVICE_STATUS_HANDLE) 0) {
  164. Status = GetLastError();
  165. BrPrint(( BR_CRITICAL, "Cannot register control handler "
  166. FORMAT_API_STATUS "\n", Status));
  167. return Status;
  168. }
  169. //
  170. // Create an event which is used by the service control handler to notify
  171. // the Browser service that it is time to terminate.
  172. //
  173. if ((BrGlobalData.TerminateNowEvent =
  174. CreateEvent(
  175. NULL, // Event attributes
  176. TRUE, // Event must be manually reset
  177. FALSE,
  178. NULL // Initial state not signalled
  179. )) == NULL) {
  180. Status = GetLastError();
  181. BrPrint(( BR_CRITICAL, "Cannot create termination event "
  182. FORMAT_API_STATUS "\n", Status));
  183. return Status;
  184. }
  185. (*BrInitState) |= BR_TERMINATE_EVENT_CREATED;
  186. //
  187. // Notify the Service Controller for the first time that we are alive
  188. // and we are start pending
  189. //
  190. if ((Status = BrGiveInstallHints( SERVICE_START_PENDING )) != NERR_Success) {
  191. BrPrint(( BR_CRITICAL, "SetServiceStatus error "
  192. FORMAT_API_STATUS "\n", Status));
  193. return Status;
  194. }
  195. //
  196. // Create well known SIDs for browser.dll
  197. //
  198. NtStatus = NetpCreateWellKnownSids( NULL );
  199. if( !NT_SUCCESS( NtStatus ) ) {
  200. Status = NetpNtStatusToApiStatus( NtStatus );
  201. BrPrint(( BR_CRITICAL, "NetpCreateWellKnownSids error "
  202. FORMAT_API_STATUS "\n", Status));
  203. return Status;
  204. }
  205. //
  206. // Create the security descriptors we'll use for the APIs
  207. //
  208. NtStatus = BrCreateBrowserObjects();
  209. if( !NT_SUCCESS( NtStatus ) ) {
  210. Status = NetpNtStatusToApiStatus( NtStatus );
  211. BrPrint(( BR_CRITICAL, "BrCreateBrowserObjects error "
  212. FORMAT_API_STATUS "\n", Status));
  213. return Status;
  214. }
  215. //
  216. // Open a handle to the driver.
  217. //
  218. if ((Status = BrOpenDgReceiver()) != NERR_Success) {
  219. BrPrint(( BR_CRITICAL, "BrOpenDgReceiver error "
  220. FORMAT_API_STATUS "\n", Status));
  221. return Status;
  222. }
  223. BrPrint(( BR_INIT, "Devices initialized.\n"));
  224. (*BrInitState) |= BR_DEVICES_INITIALIZED;
  225. //
  226. // Enable PNP to start queueing PNP notifications in the bowser driver.
  227. // We won't actually get any notifications until we later call
  228. // PostWaitForPnp ().
  229. //
  230. if ((Status = BrEnablePnp( TRUE )) != NERR_Success) {
  231. BrPrint(( BR_CRITICAL, "BrEnablePnp error "
  232. FORMAT_API_STATUS "\n", Status));
  233. return Status;
  234. }
  235. BrPrint(( BR_INIT, "PNP initialized.\n"));
  236. //
  237. // Initialize NetBios synchronization with the service controller.
  238. //
  239. BrLmsvcsGlobalData->NetBiosOpen();
  240. (*BrInitState) |= BR_NETBIOS_INITIALIZED;
  241. //
  242. // Read the configuration information to initialize the browser service.
  243. //
  244. if ((Status = BrInitializeBrowser(BrInitState)) != NERR_Success) {
  245. BrPrint(( BR_CRITICAL, "Cannot start browser "
  246. FORMAT_API_STATUS "\n", Status));
  247. if (Status == NERR_ServiceInstalled) {
  248. Status = NERR_WkstaInconsistentState;
  249. }
  250. return Status;
  251. }
  252. BrPrint(( BR_INIT, "Browser initialized.\n"));
  253. (*BrInitState) |= BR_BROWSER_INITIALIZED;
  254. //
  255. // Service install still pending.
  256. //
  257. (void) BrGiveInstallHints( SERVICE_START_PENDING );
  258. //
  259. // Initialize the browser service to receive RPC requests
  260. //
  261. if ((Status = BrLmsvcsGlobalData->StartRpcServer(
  262. BROWSER_INTERFACE_NAME,
  263. browser_ServerIfHandle
  264. )) != NERR_Success) {
  265. BrPrint(( BR_CRITICAL, "Cannot start RPC server "
  266. FORMAT_API_STATUS "\n", Status));
  267. return Status;
  268. }
  269. (*BrInitState) |= BR_RPC_SERVER_STARTED;
  270. //
  271. // Update our announcement bits based on our current role.
  272. //
  273. // This will force the server to announce itself. It will also update
  274. // the browser information in the driver.
  275. //
  276. //
  277. if ((Status = BrUpdateAnnouncementBits( NULL, BR_PARANOID )) != NERR_Success) {
  278. BrPrint(( BR_CRITICAL, "BrUpdateAnnouncementBits error "
  279. FORMAT_API_STATUS "\n", Status));
  280. return Status;
  281. }
  282. BrPrint(( BR_INIT, "Network status updated.\n"));
  283. //
  284. // We are done with starting the browser service. Tell Service
  285. // Controller our new status.
  286. //
  287. if ((Status = BrGiveInstallHints( SERVICE_RUNNING )) != NERR_Success) {
  288. BrPrint(( BR_CRITICAL, "SetServiceStatus error "
  289. FORMAT_API_STATUS "\n", Status));
  290. return Status;
  291. }
  292. if ((Status = PostWaitForPnp()) != NERR_Success) {
  293. BrPrint(( BR_CRITICAL, "PostWaitForPnp error "
  294. FORMAT_API_STATUS "\n", Status));
  295. return Status;
  296. }
  297. BrPrint(( BR_MAIN, "Successful Initialization\n"));
  298. return NERR_Success;
  299. }
  300. NET_API_STATUS
  301. BrInitializeBrowser(
  302. OUT LPDWORD BrInitState
  303. )
  304. /*++
  305. Routine Description:
  306. This function shuts down the Browser service.
  307. Arguments:
  308. ErrorCode - Supplies the error code of the failure
  309. BrInitState - Supplies a flag to indicate how far we got with initializing
  310. the Browser service before an error occured, thus the amount of
  311. clean up needed.
  312. Return Value:
  313. None.
  314. --*/
  315. {
  316. NET_API_STATUS NetStatus;
  317. SERVICE_STATUS ServiceStatus;
  318. //
  319. // The browser depends on the following services being started:
  320. //
  321. // WORKSTATION (to initialize the bowser driver)
  322. // SERVER (to receive remote APIs)
  323. //
  324. // Check to make sure that the services are started.
  325. //
  326. try{
  327. if ((NetStatus = CheckForService(SERVICE_WORKSTATION, &ServiceStatus)) != NERR_Success) {
  328. LPWSTR SubStrings[2];
  329. CHAR ServiceStatusString[10];
  330. WCHAR ServiceStatusStringW[10];
  331. SubStrings[0] = SERVICE_WORKSTATION;
  332. _ultoa(ServiceStatus.dwCurrentState, ServiceStatusString, 10);
  333. mbstowcs(ServiceStatusStringW, ServiceStatusString, 10);
  334. SubStrings[1] = ServiceStatusStringW;
  335. BrLogEvent(EVENT_BROWSER_DEPENDANT_SERVICE_FAILED, NetStatus, 2, SubStrings);
  336. try_return ( NetStatus );
  337. }
  338. if ((NetStatus = CheckForService(SERVICE_SERVER, &ServiceStatus)) != NERR_Success) {
  339. LPWSTR SubStrings[2];
  340. CHAR ServiceStatusString[10];
  341. WCHAR ServiceStatusStringW[10];
  342. SubStrings[0] = SERVICE_SERVER;
  343. _ultoa(ServiceStatus.dwCurrentState, ServiceStatusString, 10);
  344. mbstowcs(ServiceStatusStringW, ServiceStatusString, 10);
  345. SubStrings[1] = ServiceStatusStringW;
  346. BrLogEvent(EVENT_BROWSER_DEPENDANT_SERVICE_FAILED, NetStatus, 2, SubStrings);
  347. try_return ( NetStatus );
  348. }
  349. BrPrint(( BR_INIT, "Dependant services are running.\n"));
  350. //
  351. // We now know that our dependant services are started.
  352. //
  353. // Look up our configuration information.
  354. //
  355. if ((NetStatus = BrGetBrowserConfiguration()) != NERR_Success) {
  356. try_return ( NetStatus );
  357. }
  358. BrPrint(( BR_INIT, "Configuration read.\n"));
  359. (*BrInitState) |= BR_CONFIG_INITIALIZED;
  360. //
  361. // Initialize the browser statistics now.
  362. //
  363. NumberOfServerEnumerations = 0;
  364. NumberOfDomainEnumerations = 0;
  365. NumberOfOtherEnumerations = 0;
  366. NumberOfMissedGetBrowserListRequests = 0;
  367. InitializeCriticalSection(&BrowserStatisticsLock);
  368. //
  369. // MaintainServerList == -1 means No
  370. //
  371. if (BrInfo.MaintainServerList == -1) {
  372. BrPrint(( BR_CRITICAL, "MaintainServerList value set to NO. Stopping\n"));
  373. try_return ( NetStatus = NERR_BrowserConfiguredToNotRun );
  374. }
  375. //
  376. // Initialize the worker threads.
  377. //
  378. (void) BrGiveInstallHints( SERVICE_START_PENDING );
  379. if ((NetStatus = BrWorkerInitialization()) != NERR_Success) {
  380. try_return ( NetStatus );
  381. }
  382. BrPrint(( BR_INIT, "Worker threads created.\n"));
  383. (*BrInitState) |= BR_THREADS_STARTED;
  384. //
  385. // Initialize the networks module
  386. //
  387. (void) BrGiveInstallHints( SERVICE_START_PENDING );
  388. BrInitializeNetworks();
  389. (*BrInitState) |= BR_NETWORKS_INITIALIZED;
  390. //
  391. // Initialize the Domains module (and create networks for primary domain)
  392. //
  393. (void) BrGiveInstallHints( SERVICE_START_PENDING );
  394. NetStatus = BrInitializeDomains();
  395. if ( NetStatus != NERR_Success ) {
  396. try_return ( NetStatus );
  397. }
  398. (*BrInitState) |= BR_DOMAINS_INITIALIZED;
  399. NetStatus = NERR_Success;
  400. try_exit:NOTHING;
  401. } finally {
  402. #if DBG
  403. if ( NetStatus != NERR_Success ) {
  404. KdPrint( ("[Browser.dll]: Error <%lu>. Failed to initialize browser\n",
  405. NetStatus ) );
  406. }
  407. #endif
  408. }
  409. return NetStatus;
  410. }
  411. VOID
  412. BrUninitializeBrowser(
  413. IN DWORD BrInitState
  414. )
  415. /*++
  416. Routine Description:
  417. This function shuts down the parts of the browser service started by
  418. BrInitializeBrowser.
  419. Arguments:
  420. BrInitState - Supplies a flag to indicate how far we got with initializing
  421. the Browser service before an error occured, thus the amount of
  422. clean up needed.
  423. Return Value:
  424. None.
  425. --*/
  426. {
  427. if (BrInitState & BR_CONFIG_INITIALIZED) {
  428. BrDeleteConfiguration(BrInitState);
  429. }
  430. if (BrInitState & BR_DOMAINS_INITIALIZED) {
  431. BrUninitializeDomains();
  432. }
  433. if (BrInitState & BR_NETWORKS_INITIALIZED) {
  434. BrUninitializeNetworks(BrInitState);
  435. }
  436. DeleteCriticalSection(&BrowserStatisticsLock);
  437. }
  438. NET_API_STATUS
  439. BrElectMasterOnNet(
  440. IN PNETWORK Network,
  441. IN PVOID Context
  442. )
  443. {
  444. DWORD Event = PtrToUlong(Context);
  445. PWSTR SubString[1];
  446. REQUEST_ELECTION ElectionRequest;
  447. if (!LOCK_NETWORK(Network)) {
  448. return NERR_InternalError;
  449. }
  450. if (!(Network->Flags & NETWORK_RAS)) {
  451. //
  452. // Indicate we're forcing an election in the event log.
  453. //
  454. SubString[0] = Network->NetworkName.Buffer;
  455. BrLogEvent(Event,
  456. STATUS_SUCCESS,
  457. 1 | NETP_ALLOW_DUPLICATE_EVENTS,
  458. SubString);
  459. //
  460. // Force an election on this net.
  461. //
  462. ElectionRequest.Type = Election;
  463. ElectionRequest.ElectionRequest.Version = 0;
  464. ElectionRequest.ElectionRequest.Criteria = 0;
  465. ElectionRequest.ElectionRequest.TimeUp = 0;
  466. ElectionRequest.ElectionRequest.MustBeZero = 0;
  467. ElectionRequest.ElectionRequest.ServerName[0] = '\0';
  468. SendDatagram( BrDgReceiverDeviceHandle,
  469. &Network->NetworkName,
  470. &Network->DomainInfo->DomUnicodeDomainNameString,
  471. Network->DomainInfo->DomUnicodeDomainName,
  472. BrowserElection,
  473. &ElectionRequest,
  474. sizeof(ElectionRequest));
  475. }
  476. UNLOCK_NETWORK(Network);
  477. return NERR_Success;
  478. }
  479. NET_API_STATUS
  480. BrShutdownBrowserForNet(
  481. IN PNETWORK Network,
  482. IN PVOID Context
  483. )
  484. {
  485. NET_API_STATUS NetStatus;
  486. if (!LOCK_NETWORK(Network)) {
  487. return NERR_InternalError;
  488. }
  489. NetStatus = BrUpdateNetworkAnnouncementBits(Network, (PVOID)BR_SHUTDOWN );
  490. if ( NetStatus != NERR_Success ) {
  491. BrPrint(( BR_CRITICAL,
  492. "%ws: %ws: BrShutdownBrowserForNet: Cannot BrUpdateNetworkAnnouncementBits %ld\n",
  493. Network->DomainInfo->DomUnicodeDomainName,
  494. Network->NetworkName.Buffer,
  495. NetStatus ));
  496. }
  497. //
  498. // Force an election if we are the master for this network - this will
  499. // cause someone else to become master.
  500. //
  501. if ( Network->Role & ROLE_MASTER ) {
  502. BrElectMasterOnNet(Network, (PVOID)EVENT_BROWSER_ELECTION_SENT_LANMAN_NT_STOPPED);
  503. }
  504. UNLOCK_NETWORK(Network);
  505. //
  506. // Continue with next network regardless of success or failure of this one.
  507. //
  508. return NERR_Success;
  509. }
  510. VOID
  511. BrShutdownBrowser (
  512. IN NET_API_STATUS ErrorCode,
  513. IN DWORD BrInitState
  514. )
  515. /*++
  516. Routine Description:
  517. This function shuts down the Browser service.
  518. Arguments:
  519. ErrorCode - Supplies the error code of the failure
  520. BrInitState - Supplies a flag to indicate how far we got with initializing
  521. the Browser service before an error occured, thus the amount of
  522. clean up needed.
  523. Return Value:
  524. None.
  525. --*/
  526. {
  527. if (BrInitState & BR_RPC_SERVER_STARTED) {
  528. //
  529. // Stop the RPC server
  530. //
  531. BrLmsvcsGlobalData->StopRpcServer(browser_ServerIfHandle);
  532. }
  533. //
  534. // Don't need to ask redirector to unbind from its transports when
  535. // cleaning up because the redirector will tear down the bindings when
  536. // it stops.
  537. //
  538. if (BrInitState & BR_DEVICES_INITIALIZED) {
  539. //
  540. // Disable PNP to prevent any new networks from being created.
  541. //
  542. BrEnablePnp( FALSE );
  543. //
  544. // Delete any networks.
  545. //
  546. if (BrInitState & BR_NETWORKS_INITIALIZED) {
  547. BrEnumerateNetworks(BrShutdownBrowserForNet, NULL );
  548. }
  549. //
  550. // Shut down the datagram receiver.
  551. //
  552. // This will cancel all I/O outstanding on the browser for this
  553. // handle.
  554. //
  555. BrShutdownDgReceiver();
  556. }
  557. //
  558. // Clean up the browser threads.
  559. //
  560. // This will guarantee that there are no operations outstanding in
  561. // the browser when it is shut down.
  562. //
  563. if (BrInitState & BR_THREADS_STARTED) {
  564. BrWorkerKillThreads();
  565. }
  566. if (BrInitState & BR_BROWSER_INITIALIZED) {
  567. //
  568. // Shut down the browser (including removing networks).
  569. //
  570. BrUninitializeBrowser(BrInitState);
  571. }
  572. //
  573. // Now that we're sure no one will try to use the worker threads,
  574. // Unitialize the subsystem.
  575. //
  576. if (BrInitState & BR_THREADS_STARTED) {
  577. BrWorkerTermination();
  578. }
  579. if (BrInitState & BR_TERMINATE_EVENT_CREATED) {
  580. //
  581. // Close handle to termination event
  582. //
  583. CloseHandle(BrGlobalData.TerminateNowEvent);
  584. }
  585. if (BrInitState & BR_DEVICES_INITIALIZED) {
  586. NtClose(BrDgReceiverDeviceHandle);
  587. BrDgReceiverDeviceHandle = NULL;
  588. }
  589. //
  590. // Tell service controller we are done using NetBios.
  591. //
  592. if (BrInitState & BR_NETBIOS_INITIALIZED) {
  593. BrLmsvcsGlobalData->NetBiosClose();
  594. }
  595. //
  596. // Delete well known SIDs if they are allocated already.
  597. //
  598. NetpFreeWellKnownSids();
  599. if ( BrGlobalBrowserSecurityDescriptor != NULL ) {
  600. NetpDeleteSecurityObject( &BrGlobalBrowserSecurityDescriptor );
  601. BrGlobalBrowserSecurityDescriptor = NULL;
  602. }
  603. BrUninitializeTraceLog();
  604. //
  605. // Free the list of events that have already been logged.
  606. //
  607. NetpEventlogClose ( BrGlobalEventlogHandle );
  608. BrGlobalEventlogHandle = NULL;
  609. //
  610. // We are done with cleaning up. Tell Service Controller that we are
  611. // stopped.
  612. //
  613. SET_SERVICE_EXITCODE(
  614. ErrorCode,
  615. BrGlobalData.Status.dwWin32ExitCode,
  616. BrGlobalData.Status.dwServiceSpecificExitCode
  617. );
  618. (void) BrGiveInstallHints( SERVICE_STOPPED );
  619. }
  620. NET_API_STATUS
  621. BrGiveInstallHints(
  622. DWORD NewState
  623. )
  624. /*++
  625. Routine Description:
  626. This function updates the Browser service status with the Service
  627. Controller.
  628. Arguments:
  629. NewState - State to tell the service contoller
  630. Return Value:
  631. NET_API_STATUS - NERR_Success or reason for failure.
  632. --*/
  633. {
  634. NET_API_STATUS status = NERR_Success;
  635. //
  636. // If we're not starting,
  637. // we don't need this install hint.
  638. //
  639. if ( BrGlobalData.Status.dwCurrentState != SERVICE_START_PENDING &&
  640. NewState == SERVICE_START_PENDING ) {
  641. return NERR_Success;
  642. }
  643. //
  644. // Update our state for the service controller.
  645. //
  646. BrGlobalData.Status.dwCurrentState = NewState;
  647. switch ( NewState ) {
  648. case SERVICE_RUNNING:
  649. BrGlobalData.Status.dwControlsAccepted = SERVICE_ACCEPT_STOP;
  650. //
  651. // On DCs, shut down cleanly.
  652. //
  653. if (BrInfo.IsLanmanNt) {
  654. BrGlobalData.Status.dwControlsAccepted |= SERVICE_ACCEPT_SHUTDOWN;
  655. }
  656. BrGlobalData.Status.dwCheckPoint = 0;
  657. BrGlobalData.Status.dwWaitHint = 0;
  658. break;
  659. case SERVICE_START_PENDING:
  660. BrGlobalData.Status.dwCheckPoint++;
  661. break;
  662. case SERVICE_STOPPED:
  663. BrGlobalData.Status.dwCurrentState = SERVICE_STOPPED;
  664. BrGlobalData.Status.dwControlsAccepted = 0;
  665. BrGlobalData.Status.dwCheckPoint = 0;
  666. BrGlobalData.Status.dwWaitHint = 0;
  667. break;
  668. case SERVICE_STOP_PENDING:
  669. BrGlobalData.Status.dwCurrentState = SERVICE_STOP_PENDING;
  670. BrGlobalData.Status.dwCheckPoint = 1;
  671. BrGlobalData.Status.dwWaitHint = BR_WAIT_HINT_TIME;
  672. break;
  673. }
  674. //
  675. // Tell the service controller our current state.
  676. //
  677. if (BrGlobalData.StatusHandle == (SERVICE_STATUS_HANDLE) 0) {
  678. BrPrint(( BR_CRITICAL,
  679. "Cannot call SetServiceStatus, no status handle.\n"
  680. ));
  681. return ERROR_INVALID_HANDLE;
  682. }
  683. if (! SetServiceStatus(BrGlobalData.StatusHandle, &BrGlobalData.Status)) {
  684. status = GetLastError();
  685. BrPrint(( BR_CRITICAL, "SetServiceStatus error %lu\n", status));
  686. }
  687. return status;
  688. }
  689. NET_API_STATUS
  690. BrUpdateAnnouncementBits(
  691. IN PDOMAIN_INFO DomainInfo OPTIONAL,
  692. IN ULONG Flags
  693. )
  694. /*++
  695. Routine Description:
  696. This will update the service announcement bits appropriately depending on
  697. the role of the browser server.
  698. Arguments:
  699. DomainInfo - Domain the announcement is to be made for
  700. NULL implies the primary domain.
  701. Flags - Control flags to pass to BrUpdateNetworkAnnouncement
  702. Return Value:
  703. Status - Status of the update..
  704. --*/
  705. {
  706. NET_API_STATUS Status;
  707. Status = BrEnumerateNetworksForDomain(DomainInfo, BrUpdateNetworkAnnouncementBits, ULongToPtr(Flags));
  708. return Status;
  709. }
  710. ULONG
  711. BrGetBrowserServiceBits(
  712. IN PNETWORK Network
  713. )
  714. {
  715. DWORD ServiceBits = 0;
  716. if (Network->Role & ROLE_POTENTIAL_BACKUP) {
  717. ServiceBits |= SV_TYPE_POTENTIAL_BROWSER;
  718. }
  719. if (Network->Role & ROLE_BACKUP) {
  720. ServiceBits |= SV_TYPE_BACKUP_BROWSER;
  721. }
  722. if (Network->Role & ROLE_MASTER) {
  723. ServiceBits |= SV_TYPE_MASTER_BROWSER;
  724. }
  725. if (Network->Role & ROLE_DOMAINMASTER) {
  726. ServiceBits |= SV_TYPE_DOMAIN_MASTER;
  727. ASSERT (ServiceBits & SV_TYPE_BACKUP_BROWSER);
  728. }
  729. return ServiceBits;
  730. }
  731. VOID
  732. BrUpdateAnnouncementTimerRoutine(
  733. IN PVOID TimerContext
  734. )
  735. /*++
  736. Routine Description:
  737. This routine is called periodically until we've successfully updated
  738. our announcement status.
  739. Arguments:
  740. None.
  741. Return Value:
  742. None
  743. --*/
  744. {
  745. PNETWORK Network = TimerContext;
  746. ULONG Periodicity;
  747. NET_API_STATUS Status;
  748. //
  749. // Prevent the network from being deleted while we're in this timer routine.
  750. //
  751. if ( BrReferenceNetwork( Network ) == NULL ) {
  752. return;
  753. }
  754. if (!LOCK_NETWORK(Network)) {
  755. return;
  756. }
  757. BrPrint(( BR_NETWORK,
  758. "%ws: %ws: Periodic try to BrUpdateNetworkAnnouncementBits\n",
  759. Network->DomainInfo->DomUnicodeDomainName,
  760. Network->NetworkName.Buffer ));
  761. //
  762. // If we still need an announcement,
  763. // do it now.
  764. //
  765. if ( Network->Flags & NETWORK_ANNOUNCE_NEEDED ) {
  766. (VOID) BrUpdateNetworkAnnouncementBits( Network, (PVOID) BR_PARANOID );
  767. }
  768. UNLOCK_NETWORK(Network);
  769. BrDereferenceNetwork( Network );
  770. }
  771. NET_API_STATUS
  772. BrUpdateNetworkAnnouncementBits(
  773. IN PNETWORK Network,
  774. IN PVOID Context
  775. )
  776. /*++
  777. Routine Description:
  778. This is the informs the bowser driver and the SMB server the current status
  779. of this transport.
  780. Arguments:
  781. Network - Network being updated
  782. Context - Flags describing the circumstance of the call.
  783. BR_SHUTDOWN - Transport is being shutdown.
  784. BR_PARANOID - This is a superfluous call ensuring the services are
  785. in sync with us.
  786. Return Value:
  787. None.
  788. --*/
  789. {
  790. NET_API_STATUS NetStatus;
  791. NET_API_STATUS NetStatusToReturn = NERR_Success;
  792. ULONG Flags = PtrToUlong(Context);
  793. ULONG Periodicity;
  794. BOOL fUpdateNow;
  795. ULONG ServiceBits;
  796. if (!LOCK_NETWORK(Network)) {
  797. return NERR_InternalError;
  798. }
  799. ServiceBits = BrGetBrowserServiceBits(Network);
  800. //
  801. // Have the browser update it's information.
  802. //
  803. //
  804. // Don't ever tell the browser to turn off the potential bit - this
  805. // has the side effect of turning off the election name.
  806. //
  807. NetStatus = BrUpdateBrowserStatus(
  808. Network,
  809. (Flags & BR_SHUTDOWN) ? 0 : ServiceBits | SV_TYPE_POTENTIAL_BROWSER);
  810. if (NetStatus != NERR_Success) {
  811. BrPrint(( BR_CRITICAL,
  812. "%ws: %ws: BrUpdateNetworkAnnouncementBits: Cannot BrUpdateBrowserStatus %ld\n",
  813. Network->DomainInfo->DomUnicodeDomainName,
  814. Network->NetworkName.Buffer,
  815. NetStatus ));
  816. NetStatusToReturn = NetStatus;
  817. }
  818. #if DBG
  819. BrUpdateDebugInformation(L"LastServiceStatus", L"LastServiceBits", Network->NetworkName.Buffer, NULL, ServiceBits);
  820. #endif
  821. //
  822. // Tell the SMB server what the status is.
  823. //
  824. // On shutdown, tell it that we have no services.
  825. // When paranoid (or pseudo), don't force an announcement.
  826. //
  827. #ifdef ENABLE_PSEUDO_BROWSER
  828. if ( (Flags & BR_PARANOID) &&
  829. BrInfo.PseudoServerLevel != BROWSER_PSEUDO ) {
  830. fUpdateNow = TRUE;
  831. }
  832. else {
  833. fUpdateNow = FALSE;
  834. }
  835. #else
  836. fUpdateNow = (Flags & BR_PARANOID) ? TRUE : FALSE;
  837. #endif
  838. NetStatus = I_NetServerSetServiceBitsEx(
  839. NULL,
  840. Network->DomainInfo->DomUnicodeComputerName,
  841. Network->NetworkName.Buffer,
  842. BROWSER_SERVICE_BITS_OF_INTEREST,
  843. ( Flags & BR_SHUTDOWN) ? 0 : ServiceBits,
  844. fUpdateNow );
  845. if ( NetStatus != NERR_Success) {
  846. BrPrint(( BR_CRITICAL,
  847. "%ws: %ws: BrUpdateNetworkAnnouncementBits: Cannot I_NetServerSetServiceBitsEx %ld\n",
  848. Network->DomainInfo->DomUnicodeDomainName,
  849. Network->NetworkName.Buffer,
  850. NetStatus ));
  851. //
  852. // If the only problem is that the transport doesn't exist in
  853. // the SMB server, don't even bother reporting the problem.
  854. // Or if it's a shutdown, filter out log failures. In some cases the
  855. // smb svr is already unavailable & we get unexpected failures. Reporting
  856. // to event log can mislead the admin.
  857. //
  858. if ( NetStatus != ERROR_PATH_NOT_FOUND &&
  859. NetStatus != NERR_NetNameNotFound &&
  860. !(Flags & BR_SHUTDOWN) ) {
  861. BrLogEvent(EVENT_BROWSER_STATUS_BITS_UPDATE_FAILED, NetStatus, 0, NULL);
  862. NetStatusToReturn = NetStatus;
  863. #if 0
  864. // debugging when we get service update bit failures
  865. OutputDebugStringA("\nBrowser.dll: Update service bits tracing.\n");
  866. ASSERT( NetStatus != NERR_Success );
  867. #endif
  868. }
  869. //
  870. // Either way. Mark that we need to announce again later.
  871. //
  872. Network->Flags |= NETWORK_ANNOUNCE_NEEDED;
  873. Periodicity = UpdateAnnouncementPeriodicity[Network->UpdateAnnouncementIndex];
  874. BrSetTimer(&Network->UpdateAnnouncementTimer, Periodicity, BrUpdateAnnouncementTimerRoutine, Network);
  875. if (Network->UpdateAnnouncementIndex != UpdateAnnouncementMax) {
  876. Network->UpdateAnnouncementIndex += 1;
  877. }
  878. //
  879. // If we successfully informed the server,
  880. // mark it.
  881. //
  882. } else {
  883. Network->Flags &= ~NETWORK_ANNOUNCE_NEEDED;
  884. Network->UpdateAnnouncementIndex = 0;
  885. }
  886. UNLOCK_NETWORK(Network);
  887. return NetStatusToReturn;
  888. }
  889. VOID
  890. BrowserControlHandler(
  891. IN DWORD Opcode
  892. )
  893. /*++
  894. Routine Description:
  895. This is the service control handler of the Browser service.
  896. Arguments:
  897. Opcode - Supplies a value which specifies the action for the Browser
  898. service to perform.
  899. Arg - Supplies a value which tells a service specifically what to do
  900. for an operation specified by Opcode.
  901. Return Value:
  902. None.
  903. --*/
  904. {
  905. BrPrint(( BR_MAIN, "In Control Handler\n"));
  906. switch (Opcode) {
  907. case SERVICE_CONTROL_STOP:
  908. case SERVICE_CONTROL_SHUTDOWN:
  909. if (BrGlobalData.Status.dwCurrentState != SERVICE_STOP_PENDING) {
  910. BrPrint(( BR_MAIN, "Stopping Browser...\n"));
  911. if (! SetEvent(BrGlobalData.TerminateNowEvent)) {
  912. //
  913. // Problem with setting event to terminate Browser
  914. // service.
  915. //
  916. BrPrint(( BR_CRITICAL, "Error setting TerminateNowEvent "
  917. FORMAT_API_STATUS "\n", GetLastError()));
  918. NetpAssert(FALSE);
  919. }
  920. }
  921. //
  922. // Send the status response.
  923. //
  924. (void) BrGiveInstallHints( SERVICE_STOP_PENDING );
  925. return;
  926. case SERVICE_CONTROL_INTERROGATE:
  927. break;
  928. default:
  929. BrPrint(( BR_CRITICAL, "Unknown Browser opcode " FORMAT_HEX_DWORD
  930. "\n", Opcode));
  931. }
  932. //
  933. // Send the status response.
  934. //
  935. (void) BrGiveInstallHints( SERVICE_START_PENDING );
  936. }