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.

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