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.

1070 lines
26 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. brdomain.c
  5. Abstract:
  6. Code to manage primary and emulated networks.
  7. Author:
  8. Cliff Van Dyke (CliffV) 11-Jan-1995
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. //
  14. // Module specific globals
  15. //
  16. // Serialized by NetworkCritSect
  17. LIST_ENTRY ServicedDomains = {0};
  18. //
  19. // Local procedure forwards.
  20. //
  21. NET_API_STATUS
  22. BrCreateDomain(
  23. LPWSTR DomainName,
  24. LPWSTR ComputerName,
  25. BOOLEAN IsEmulatedDomain
  26. );
  27. VOID
  28. BrCreateDomainWorker(
  29. IN PVOID Ctx
  30. );
  31. NET_API_STATUS
  32. BrInitializeDomains(
  33. VOID
  34. )
  35. /*++
  36. Routine Description:
  37. Initialize brdomain.c and create the primary domain.
  38. Arguments:
  39. None
  40. Return Value:
  41. Status of operation.
  42. --*/
  43. {
  44. NET_API_STATUS NetStatus;
  45. LPWSTR ComputerName = NULL;
  46. LPWSTR DomainName = NULL;
  47. //
  48. // Initialize globals
  49. //
  50. InitializeListHead(&ServicedDomains);
  51. //
  52. // Initialize actual domain of this machine.
  53. //
  54. // Get the configured computer name. NetpGetComputerName allocates
  55. // the memory to hold the computername string using LocalAlloc.
  56. //
  57. NetStatus = NetpGetComputerName( &ComputerName );
  58. if ( NetStatus != NERR_Success ) {
  59. goto Cleanup;
  60. }
  61. NetStatus = NetpGetDomainName( &DomainName );
  62. if ( NetStatus != NERR_Success ) {
  63. goto Cleanup;
  64. }
  65. NetStatus = BrCreateDomain( DomainName,
  66. ComputerName,
  67. FALSE );
  68. if ( NetStatus != NERR_Success ) {
  69. goto Cleanup;
  70. }
  71. NetStatus = NERR_Success;
  72. //
  73. // Free locally used resources
  74. //
  75. Cleanup:
  76. if ( ComputerName != NULL ) {
  77. (VOID)LocalFree( ComputerName );
  78. }
  79. if ( DomainName != NULL ) {
  80. (VOID)LocalFree( DomainName );
  81. }
  82. return NetStatus;
  83. }
  84. NET_API_STATUS
  85. BrCreateDomain(
  86. LPWSTR DomainName,
  87. LPWSTR ComputerName,
  88. BOOLEAN IsEmulatedDomain
  89. )
  90. /*++
  91. Routine Description:
  92. Create a new domain to browse on.
  93. Arguments:
  94. DomainName - Name of the domain to browse on
  95. ComputerName - Name of this computer in the specified domain.
  96. IsEmulatedDomain - TRUE iff this domain is an emulated domain of this machine.
  97. Return Value:
  98. Status of operation.
  99. --*/
  100. {
  101. NTSTATUS Status;
  102. NET_API_STATUS NetStatus;
  103. BOOLEAN CanCallBrDeleteDomain = FALSE;
  104. PDOMAIN_INFO DomainInfo = NULL;
  105. ULONG AComputerNameLength;
  106. BrPrint(( BR_DOMAIN, "%ws: Added new domain and computer: %ws\n",
  107. DomainName,
  108. ComputerName ));
  109. //
  110. // Allocate a structure describing the new domain.
  111. //
  112. DomainInfo = LocalAlloc( LMEM_ZEROINIT, sizeof(DOMAIN_INFO) );
  113. if ( DomainInfo == NULL ) {
  114. NetStatus = GetLastError();
  115. goto Cleanup;
  116. }
  117. //
  118. // Create an interim reference count for this domain.
  119. //
  120. DomainInfo->ReferenceCount = 1;
  121. DomainInfo->IsEmulatedDomain = IsEmulatedDomain;
  122. //
  123. // Copy the computer name into the structure.
  124. //
  125. NetStatus = I_NetNameCanonicalize(
  126. NULL,
  127. ComputerName,
  128. DomainInfo->DomUnicodeComputerName,
  129. sizeof(DomainInfo->DomUnicodeComputerName),
  130. NAMETYPE_COMPUTER,
  131. 0 );
  132. if ( NetStatus != NERR_Success ) {
  133. BrPrint(( BR_CRITICAL,
  134. "ComputerName " FORMAT_LPWSTR " is invalid\n",
  135. ComputerName ));
  136. goto Cleanup;
  137. }
  138. DomainInfo->DomUnicodeComputerNameLength = wcslen(DomainInfo->DomUnicodeComputerName);
  139. Status = RtlUpcaseUnicodeToOemN( DomainInfo->DomOemComputerName,
  140. sizeof(DomainInfo->DomOemComputerName),
  141. &DomainInfo->DomOemComputerNameLength,
  142. DomainInfo->DomUnicodeComputerName,
  143. DomainInfo->DomUnicodeComputerNameLength*sizeof(WCHAR));
  144. if (!NT_SUCCESS(Status)) {
  145. BrPrint(( BR_CRITICAL, "Unable to convert computer name to OEM %ws %lx\n", ComputerName, Status ));
  146. NetStatus = ERROR_NOT_ENOUGH_MEMORY;
  147. goto Cleanup;
  148. }
  149. DomainInfo->DomOemComputerName[DomainInfo->DomOemComputerNameLength] = '\0';
  150. //
  151. // Copy the domain name into the structure
  152. // Note: Use workgroup type rather then domain since
  153. // we have no notion of domain/workgroup in the browser (all are "groups")
  154. // an workgroup is less restrictive (see bug 348606)
  155. //
  156. NetStatus = I_NetNameCanonicalize(
  157. NULL,
  158. DomainName,
  159. DomainInfo->DomUnicodeDomainName,
  160. sizeof(DomainInfo->DomUnicodeDomainName),
  161. NAMETYPE_WORKGROUP,
  162. 0 );
  163. if ( NetStatus != NERR_Success ) {
  164. BrPrint(( BR_CRITICAL, "%ws: DomainName is invalid\n", DomainName ));
  165. goto Cleanup;
  166. }
  167. RtlInitUnicodeString( &DomainInfo->DomUnicodeDomainNameString,
  168. DomainInfo->DomUnicodeDomainName );
  169. Status = RtlUpcaseUnicodeToOemN( DomainInfo->DomOemDomainName,
  170. sizeof(DomainInfo->DomOemDomainName),
  171. &DomainInfo->DomOemDomainNameLength,
  172. DomainInfo->DomUnicodeDomainNameString.Buffer,
  173. DomainInfo->DomUnicodeDomainNameString.Length);
  174. if (!NT_SUCCESS(Status)) {
  175. BrPrint(( BR_CRITICAL, "%ws: Unable to convert Domain name to OEM\n", DomainName ));
  176. NetStatus = ERROR_NOT_ENOUGH_MEMORY;
  177. goto Cleanup;
  178. }
  179. DomainInfo->DomOemDomainName[DomainInfo->DomOemDomainNameLength] = '\0';
  180. //
  181. // Create the domain rename timer
  182. //
  183. NetStatus = BrCreateTimer( &DomainInfo->DomainRenameTimer );
  184. if ( NetStatus != NERR_Success ) {
  185. BrPrint(( BR_CRITICAL, "%ws: Cannot create domain rename timer %ld\n", DomainName, NetStatus ));
  186. goto Cleanup;
  187. }
  188. //
  189. // Link the domain into the list of domains
  190. // (And mark that any future cleanup can be done by calling BrDeleteDomain)
  191. EnterCriticalSection(&NetworkCritSect);
  192. InsertTailList(&ServicedDomains, &DomainInfo->Next);
  193. LeaveCriticalSection(&NetworkCritSect);
  194. CanCallBrDeleteDomain = TRUE;
  195. //
  196. // Create the various networks for this domain.
  197. //
  198. NetStatus = BrCreateNetworks( DomainInfo );
  199. if ( NetStatus != NERR_Success ) {
  200. goto Cleanup;
  201. }
  202. //
  203. // Free Locally used resources
  204. //
  205. Cleanup:
  206. if (NetStatus != NERR_Success) {
  207. if (DomainInfo != NULL) {
  208. //
  209. // If we've initialized to the point where we can call
  210. // we can call BrDeleteDomain, do so.
  211. //
  212. if ( CanCallBrDeleteDomain ) {
  213. (VOID) BrDeleteDomain( DomainInfo );
  214. //
  215. // Otherwise, just delete what we've created.
  216. //
  217. } else {
  218. (VOID) LocalFree(DomainInfo);
  219. }
  220. }
  221. }
  222. return NetStatus;
  223. }
  224. typedef struct _BROWSER_CREATE_DOMAIN_CONTEXT {
  225. LPWSTR DomainName;
  226. LPWSTR ComputerName;
  227. BOOLEAN IsEmulatedDomain;
  228. HANDLE EventHandle;
  229. NET_API_STATUS NetStatus;
  230. } BROWSER_CREATE_DOMAIN_CONTEXT, *PBROWSER_CREATE_DOMAIN_CONTEXT;
  231. NET_API_STATUS
  232. BrCreateDomainInWorker(
  233. LPWSTR DomainName,
  234. LPWSTR ComputerName,
  235. BOOLEAN IsEmulatedDomain
  236. )
  237. /*++
  238. Routine Description:
  239. Wrapper for BrCreateDomain. Since BrCreateDomain starts several pending
  240. IO's to the browser driver, the thread that calls BrCreateDomain must
  241. remain around forever. This wrapper can be called by any transient thread
  242. (e.g., an RPC thread). It simply causes BrCreateDomain to be called in a
  243. worker thread.
  244. Arguments:
  245. DomainName - Name of the domain to browse on
  246. ComputerName - Name of this computer in the specified domain.
  247. IsEmulatedDomain - TRUE iff this domain is an emulated domain of this machine.
  248. Return Value:
  249. Status of operation.
  250. --*/
  251. {
  252. NET_API_STATUS NetStatus;
  253. DWORD WaitStatus;
  254. WORKER_ITEM WorkItem;
  255. BROWSER_CREATE_DOMAIN_CONTEXT Context;
  256. //
  257. // Copy our arguments into a context block for the worker thread
  258. //
  259. Context.DomainName = DomainName;
  260. Context.ComputerName = ComputerName;
  261. Context.IsEmulatedDomain = IsEmulatedDomain;
  262. //
  263. // Create an event which we use to wait on the worker thread.
  264. //
  265. Context.EventHandle = CreateEvent(
  266. NULL, // Event attributes
  267. TRUE, // Event must be manually reset
  268. FALSE, // Initial state not signalled
  269. NULL ); // Event name
  270. if ( Context.EventHandle == NULL ) {
  271. NetStatus = GetLastError();
  272. return NetStatus;
  273. }
  274. //
  275. // Queue the request to the worker thread.
  276. //
  277. BrInitializeWorkItem( &WorkItem,
  278. BrCreateDomainWorker,
  279. &Context );
  280. BrQueueWorkItem( &WorkItem );
  281. //
  282. // Wait for the worker thread to finish
  283. //
  284. WaitStatus = WaitForSingleObject( Context.EventHandle, INFINITE );
  285. if ( WaitStatus == WAIT_OBJECT_0 ) {
  286. NetStatus = Context.NetStatus;
  287. } else {
  288. NetStatus = GetLastError();
  289. }
  290. CloseHandle( Context.EventHandle );
  291. return NetStatus;
  292. }
  293. VOID
  294. BrCreateDomainWorker(
  295. IN PVOID Ctx
  296. )
  297. /*++
  298. Routine Description:
  299. Worker routine for BrCreateDomainInWorker.
  300. This routine executes in the context of a worker thread.
  301. Arguments:
  302. Context - Context containing the workitem and the description of the
  303. domain to create.
  304. Return Value:
  305. None
  306. --*/
  307. {
  308. PBROWSER_CREATE_DOMAIN_CONTEXT Context = (PBROWSER_CREATE_DOMAIN_CONTEXT) Ctx;
  309. //
  310. // Create the domain.
  311. //
  312. Context->NetStatus = BrCreateDomain(
  313. Context->DomainName,
  314. Context->ComputerName,
  315. Context->IsEmulatedDomain );
  316. //
  317. // Let the caller know we're done.
  318. //
  319. SetEvent( Context->EventHandle );
  320. }
  321. PDOMAIN_INFO
  322. BrFindDomain(
  323. LPWSTR DomainName,
  324. BOOLEAN DefaultToPrimary
  325. )
  326. /*++
  327. Routine Description:
  328. This routine will look up a domain given a name.
  329. Arguments:
  330. DomainName - The name of the domain to look up.
  331. DefaultToPrimary - Return the primary domain if DomainName is NULL or
  332. can't be found.
  333. Return Value:
  334. NULL - No such domain exists
  335. A pointer to the domain found. The found domain should be dereferenced
  336. using BrDereferenceDomain.
  337. --*/
  338. {
  339. NTSTATUS Status;
  340. PLIST_ENTRY DomainEntry;
  341. PDOMAIN_INFO DomainInfo = NULL;
  342. CHAR OemDomainName[DNLEN+1];
  343. DWORD OemDomainNameLength;
  344. EnterCriticalSection(&NetworkCritSect);
  345. //
  346. // If domain was specified,
  347. // try to return primary domain.
  348. //
  349. if ( DomainName != NULL ) {
  350. //
  351. // Convert the domain name to OEM for faster comparison
  352. //
  353. Status = RtlUpcaseUnicodeToOemN( OemDomainName,
  354. sizeof(OemDomainName),
  355. &OemDomainNameLength,
  356. DomainName,
  357. wcslen(DomainName)*sizeof(WCHAR));
  358. if (!NT_SUCCESS(Status)) {
  359. BrPrint(( BR_CRITICAL, "%ws: Unable to convert Domain name to OEM\n", DomainName ));
  360. DomainInfo = NULL;
  361. goto Cleanup;
  362. }
  363. //
  364. // Loop trying to find this domain name.
  365. //
  366. for (DomainEntry = ServicedDomains.Flink ;
  367. DomainEntry != &ServicedDomains;
  368. DomainEntry = DomainEntry->Flink ) {
  369. DomainInfo = CONTAINING_RECORD(DomainEntry, DOMAIN_INFO, Next);
  370. if ( DomainInfo->DomOemDomainNameLength == OemDomainNameLength &&
  371. RtlCompareMemory( DomainInfo->DomOemDomainName,
  372. OemDomainName,
  373. OemDomainNameLength ) == OemDomainNameLength ) {
  374. break;
  375. }
  376. DomainInfo = NULL;
  377. }
  378. }
  379. //
  380. // If we're to default to the primary domain,
  381. // do so.
  382. //
  383. if ( DefaultToPrimary && DomainInfo == NULL ) {
  384. if ( !IsListEmpty( &ServicedDomains ) ) {
  385. DomainInfo = CONTAINING_RECORD(ServicedDomains.Flink, DOMAIN_INFO, Next);
  386. }
  387. }
  388. //
  389. // Reference the domain.
  390. //
  391. if ( DomainInfo != NULL ) {
  392. DomainInfo->ReferenceCount ++;
  393. }
  394. Cleanup:
  395. LeaveCriticalSection(&NetworkCritSect);
  396. return DomainInfo;
  397. }
  398. PDOMAIN_INFO
  399. BrReferenceDomain(
  400. PDOMAIN_INFO PotentialDomainInfo
  401. )
  402. /*++
  403. Routine Description:
  404. This routine will look up a domain given a potential pointer to the domain
  405. This routine is useful if a caller has a pointer to a domain but
  406. hasn't incremented the reference count. For instance,
  407. a timer completion routine has such a pointer.
  408. Arguments:
  409. PotentialDomainInfo - Pointer to the DomainInfo to be verified.
  410. Return Value:
  411. NULL - No such domain exists
  412. A pointer to the domain found. The found domain should be dereferenced
  413. using BrDereferenceDomain.
  414. --*/
  415. {
  416. NTSTATUS Status;
  417. PLIST_ENTRY ListEntry;
  418. EnterCriticalSection(&NetworkCritSect);
  419. for (ListEntry = ServicedDomains.Flink ;
  420. ListEntry != &ServicedDomains;
  421. ListEntry = ListEntry->Flink ) {
  422. PDOMAIN_INFO DomainInfo = CONTAINING_RECORD(ListEntry, DOMAIN_INFO, Next);
  423. if ( PotentialDomainInfo == DomainInfo ) {
  424. DomainInfo->ReferenceCount ++;
  425. BrPrint(( BR_LOCKS,
  426. "%ws: reference domain: %ld\n",
  427. DomainInfo->DomUnicodeDomainName,
  428. DomainInfo->ReferenceCount ));
  429. LeaveCriticalSection(&NetworkCritSect);
  430. return DomainInfo;
  431. }
  432. }
  433. LeaveCriticalSection(&NetworkCritSect);
  434. return NULL;
  435. }
  436. VOID
  437. BrDereferenceDomain(
  438. IN PDOMAIN_INFO DomainInfo
  439. )
  440. /*++
  441. Routine Description:
  442. Decrement the reference count on a domain.
  443. If the reference count goes to 0, remove the domain.
  444. On entry, the global NetworkCritSect may not be locked
  445. Arguments:
  446. DomainInfo - The domain to dereference
  447. Return Value:
  448. None
  449. --*/
  450. {
  451. NTSTATUS Status;
  452. ULONG ReferenceCount;
  453. //
  454. // Decrement the reference count
  455. //
  456. EnterCriticalSection(&NetworkCritSect);
  457. ReferenceCount = -- DomainInfo->ReferenceCount;
  458. LeaveCriticalSection(&NetworkCritSect);
  459. if ( ReferenceCount != 0 ) {
  460. return;
  461. }
  462. //
  463. // Ditch the rename timer
  464. //
  465. BrDestroyTimer( &DomainInfo->DomainRenameTimer );
  466. //
  467. // Free the Domain Info structure.
  468. //
  469. (VOID) LocalFree( DomainInfo );
  470. }
  471. NET_API_STATUS
  472. BrRenameDomainForNetwork(
  473. PNETWORK Network,
  474. PVOID Context
  475. )
  476. /*++
  477. Routine Description:
  478. Handle domain rename for a particular network.
  479. Reset the network indicating this machine plays no special role.
  480. Then, re-enable any role we're currently playing.
  481. Arguments:
  482. Network - Network to reset (Referenced)
  483. Return Value:
  484. Status - The status of the operation.
  485. --*/
  486. {
  487. NET_API_STATUS NetStatus;
  488. //
  489. // Lock the network
  490. //
  491. if (LOCK_NETWORK(Network)) {
  492. //
  493. // Stop it from being a master.
  494. //
  495. if (Network->Role & ROLE_MASTER) {
  496. NetStatus = BrStopMaster(Network);
  497. if ( NetStatus != NERR_Success ) {
  498. BrPrint(( BR_CRITICAL,
  499. "%ws: %ws: BrRenameDomainForNetwork: Cannot BrStopMaster %ld\n",
  500. Network->DomainInfo->DomUnicodeDomainName,
  501. Network->NetworkName.Buffer,
  502. NetStatus ));
  503. }
  504. }
  505. //
  506. // Stop being a backup as well.
  507. //
  508. NetStatus = BrStopBackup(Network);
  509. if ( NetStatus != NERR_Success ) {
  510. BrPrint(( BR_CRITICAL,
  511. "%ws: %ws: BrRenameDomainForNetwork: Cannot BrStopBackup %ld\n",
  512. Network->DomainInfo->DomUnicodeDomainName,
  513. Network->NetworkName.Buffer,
  514. NetStatus ));
  515. }
  516. //
  517. // Stop even being a potential browser.
  518. // Close the <DomainName>[1E] name
  519. //
  520. NetStatus = BrUpdateNetworkAnnouncementBits(Network, (PVOID)(BR_SHUTDOWN|BR_PARANOID) );
  521. if ( NetStatus != NERR_Success ) {
  522. BrPrint(( BR_CRITICAL,
  523. "%ws: %ws: BrRenameDomainForNetwork: Cannot BrUpdateNetworkAnnouncementBits %ld\n",
  524. Network->DomainInfo->DomUnicodeDomainName,
  525. Network->NetworkName.Buffer,
  526. NetStatus ));
  527. }
  528. //
  529. // Register the new <DomainName>[1E] name
  530. //
  531. NetStatus = BrUpdateNetworkAnnouncementBits(Network, (PVOID)BR_PARANOID );
  532. if ( NetStatus != NERR_Success ) {
  533. BrPrint(( BR_CRITICAL,
  534. "%ws: %ws: BrRenameDomainForNetwork: Cannot BrUpdateNetworkAnnouncementBits %ld\n",
  535. Network->DomainInfo->DomUnicodeDomainName,
  536. Network->NetworkName.Buffer,
  537. NetStatus ));
  538. }
  539. //
  540. // If we are on either a domain master, or on a lanman/NT machine,
  541. // force an election on all our transports to make sure that we're
  542. // the master
  543. //
  544. if ( (Network->Flags & NETWORK_PDC) != 0 || BrInfo.IsLanmanNt) {
  545. NetStatus = BrElectMasterOnNet( Network, (PVOID)EVENT_BROWSER_ELECTION_SENT_LANMAN_NT_STARTED );
  546. if (NetStatus != NERR_Success) {
  547. BrPrint(( BR_CRITICAL,
  548. "%ws: %ws: BrRenameDomainForNetwork: Can't Elect Master.\n",
  549. Network->DomainInfo->DomUnicodeDomainName,
  550. Network->NetworkName.Buffer,
  551. NetStatus ));
  552. // This isn't fatal.
  553. } else {
  554. BrPrint(( BR_NETWORK, "%ws: %ws: Election forced on domain rename.\n",
  555. Network->DomainInfo->DomUnicodeDomainName,
  556. Network->NetworkName.Buffer ));
  557. }
  558. }
  559. //
  560. // If forced to MaintainServerList, become a backup again
  561. //
  562. EnterCriticalSection(&BrInfo.ConfigCritSect);
  563. if (BrInfo.MaintainServerList == 1){
  564. //
  565. // Become a backup server now.
  566. //
  567. NetStatus = BrBecomeBackup( Network );
  568. if (NetStatus != NERR_Success) {
  569. BrPrint(( BR_CRITICAL,
  570. "%ws: %ws: BrRenameDomainForNetwork: Can't BecomeBackup.\n",
  571. Network->DomainInfo->DomUnicodeDomainName,
  572. Network->NetworkName.Buffer,
  573. NetStatus ));
  574. // This isn't fatal.
  575. } else {
  576. BrPrint(( BR_NETWORK, "%ws: %ws: Became Backup.\n",
  577. Network->DomainInfo->DomUnicodeDomainName,
  578. Network->NetworkName.Buffer ));
  579. }
  580. }
  581. LeaveCriticalSection(&BrInfo.ConfigCritSect);
  582. UNLOCK_NETWORK(Network);
  583. }
  584. //
  585. // Always return success so allow the caller to continue to the next network.
  586. //
  587. return NERR_Success;
  588. }
  589. VOID
  590. BrRenameDomain(
  591. IN PVOID Context
  592. )
  593. /*++
  594. Routine Description:
  595. Rename the domain from the specified name to the currently register named
  596. for the domain.
  597. Arguments:
  598. OldDomainName - Name that the domain is currently known by.
  599. Return Value:
  600. None
  601. --*/
  602. {
  603. NET_API_STATUS NetStatus;
  604. NTSTATUS Status;
  605. PDOMAIN_INFO DomainInfo = NULL;
  606. LPWSTR NewDomainName = NULL;
  607. //
  608. // Reference the domain.
  609. // This routine can be called as a timer routine. In that case, the
  610. // domain might not exist any more.
  611. //
  612. DomainInfo = BrReferenceDomain( Context );
  613. if ( DomainInfo == NULL ) {
  614. BrPrint(( BR_CRITICAL, "%lx: Renamed domain no longer exists\n", Context ));
  615. NetStatus = ERROR_INTERNAL_ERROR;
  616. goto Cleanup;
  617. }
  618. BrPrint(( BR_DOMAIN, "%ws: BrRenameDomain called\n",
  619. DomainInfo->DomUnicodeDomainName ));
  620. //
  621. // Determine the new domain name
  622. //
  623. NetStatus = NetpGetDomainName( &NewDomainName );
  624. if ( NetStatus != NERR_Success ) {
  625. BrPrint(( BR_CRITICAL, "%ws: Cannot determine the new domain name %ld\n",
  626. DomainInfo->DomUnicodeDomainName,
  627. NetStatus ));
  628. goto Cleanup;
  629. }
  630. //
  631. // Put the new domain name into the domain structure
  632. // Note: Use workgroup type rather then domain since
  633. // we have no notion of domain/workgroup in the browser (all are "groups")
  634. // an workgroup is less restrictive (see bug 348606)
  635. //
  636. EnterCriticalSection(&NetworkCritSect);
  637. NetStatus = I_NetNameCanonicalize(
  638. NULL,
  639. NewDomainName,
  640. DomainInfo->DomUnicodeDomainName,
  641. sizeof(DomainInfo->DomUnicodeDomainName),
  642. NAMETYPE_WORKGROUP,
  643. 0 );
  644. if ( NetStatus != NERR_Success ) {
  645. LeaveCriticalSection(&NetworkCritSect);
  646. BrPrint(( BR_CRITICAL, "%ws: DomainName is invalid %ld\n",
  647. NewDomainName,
  648. NetStatus ));
  649. goto Cleanup;
  650. }
  651. RtlInitUnicodeString( &DomainInfo->DomUnicodeDomainNameString,
  652. DomainInfo->DomUnicodeDomainName );
  653. Status = RtlUpcaseUnicodeToOemN( DomainInfo->DomOemDomainName,
  654. sizeof(DomainInfo->DomOemDomainName),
  655. &DomainInfo->DomOemDomainNameLength,
  656. DomainInfo->DomUnicodeDomainNameString.Buffer,
  657. DomainInfo->DomUnicodeDomainNameString.Length);
  658. if (!NT_SUCCESS(Status)) {
  659. LeaveCriticalSection(&NetworkCritSect);
  660. BrPrint(( BR_CRITICAL, "%ws: Unable to convert Domain name to OEM\n", DomainName ));
  661. NetStatus = ERROR_NOT_ENOUGH_MEMORY;
  662. goto Cleanup;
  663. }
  664. DomainInfo->DomOemDomainName[DomainInfo->DomOemDomainNameLength] = '\0';
  665. LeaveCriticalSection(&NetworkCritSect);
  666. //
  667. // Reset all of the networks telling them of the new domain name
  668. //
  669. NetStatus = BrEnumerateNetworksForDomain(DomainInfo, BrRenameDomainForNetwork, NULL);
  670. if ( NetStatus != NERR_Success ) {
  671. BrPrint(( BR_CRITICAL, "%ws: Cannot do rename on all networks %ld\n",
  672. NewDomainName,
  673. NetStatus ));
  674. goto Cleanup;
  675. }
  676. NetStatus = NERR_Success;
  677. //
  678. // Free locally used resources
  679. //
  680. Cleanup:
  681. if ( NewDomainName != NULL ) {
  682. (VOID)LocalFree( NewDomainName );
  683. }
  684. if ( DomainInfo != NULL ) {
  685. //
  686. // If the domain rename failed,
  687. // try it again in 15 minutes.
  688. //
  689. if ( NetStatus != NERR_Success ) {
  690. BrSetTimer(&DomainInfo->DomainRenameTimer, 15 * 1000 * 60, BrRenameDomain, DomainInfo);
  691. }
  692. BrDereferenceDomain( DomainInfo );
  693. }
  694. return;
  695. }
  696. VOID
  697. BrDeleteDomain(
  698. IN PDOMAIN_INFO DomainInfo
  699. )
  700. /*++
  701. Routine Description:
  702. Force a domain to be deleted.
  703. Arguments:
  704. DomainInfo - The domain to delete
  705. Return Value:
  706. None
  707. --*/
  708. {
  709. //
  710. // Delete each of the networks for this domain.
  711. //
  712. BrEnumerateNetworksForDomain(DomainInfo, BrDeleteNetwork, NULL );
  713. //
  714. // Delink the domain from the global list and remove the final reference.
  715. //
  716. EnterCriticalSection(&NetworkCritSect);
  717. RemoveEntryList(&DomainInfo->Next);
  718. LeaveCriticalSection(&NetworkCritSect);
  719. BrDereferenceDomain( DomainInfo );
  720. }
  721. VOID
  722. BrUninitializeDomains(
  723. VOID
  724. )
  725. /*++
  726. Routine Description:
  727. Delete all of the domains.
  728. Arguments:
  729. None.
  730. Return Value:
  731. None
  732. --*/
  733. {
  734. //
  735. // Loop through the domains deleting each of them
  736. //
  737. EnterCriticalSection(&NetworkCritSect);
  738. while (!IsListEmpty(&ServicedDomains)) {
  739. PDOMAIN_INFO DomainInfo = CONTAINING_RECORD(ServicedDomains.Flink, DOMAIN_INFO, Next);
  740. DomainInfo->ReferenceCount ++;
  741. LeaveCriticalSection(&NetworkCritSect);
  742. //
  743. // Clean up the domain.
  744. //
  745. BrDeleteDomain( DomainInfo );
  746. //
  747. // Actually delete the delinked structure by removing the last reference
  748. //
  749. ASSERT( DomainInfo->ReferenceCount == 1 );
  750. BrDereferenceDomain( DomainInfo );
  751. EnterCriticalSection(&NetworkCritSect);
  752. }
  753. LeaveCriticalSection(&NetworkCritSect);
  754. }