/*++ Copyright (c) 1991 Microsoft Corporation Module Name: brdmmstr.c Abstract: This module contains the routines to manage a domain master browser server Author: Rita Wong (ritaw) 20-Feb-1991 Revision History: --*/ #include "precomp.h" #pragma hdrstop //-------------------------------------------------------------------// // // // Local structure definitions // // // //-------------------------------------------------------------------// //-------------------------------------------------------------------// // // // Local function prototypes // // // //-------------------------------------------------------------------// VOID GetMasterAnnouncementCompletion ( IN PVOID Ctx ); typedef struct _BROWSER_GET_MASTER_ANNOUNCEMENT_CONTEXT { PDOMAIN_INFO DomainInfo; HANDLE EventHandle; NET_API_STATUS NetStatus; } BROWSER_GET_MASTER_ANNOUNCEMENT_CONTEXT, *PBROWSER_GET_MASTER_ANNOUNCEMENT_CONTEXT; NET_API_STATUS PostGetMasterAnnouncement ( PNETWORK Network ) /*++ Routine Description: Ensure the GetMasterAnnouncement request is posted for a particular network. Arguments: None. Return Value: Status - The status of the operation. --*/ { NET_API_STATUS NetStatus = NERR_Success; #ifdef ENABLE_PSEUDO_BROWSER if ( BrInfo.PseudoServerLevel == BROWSER_PSEUDO ) { // No master announcement handling for a phase out server return NERR_Success; } #endif if (!LOCK_NETWORK(Network)) { return NERR_InternalError; } if ( (Network->Flags & NETWORK_PDC) != 0 && (Network->Flags & NETWORK_WANNISH) != 0 ) { if (!(Network->Flags & NETWORK_GET_MASTER_ANNOUNCE_POSTED)) { BrPrint(( BR_MASTER, "%ws: %ws: Doing PostGetMasterAnnouncement\n", Network->DomainInfo->DomUnicodeDomainName, Network->NetworkName.Buffer)); NetStatus = BrIssueAsyncBrowserIoControl(Network, IOCTL_LMDR_WAIT_FOR_MASTER_ANNOUNCE, GetMasterAnnouncementCompletion, NULL ); if ( NetStatus == NERR_Success ) { Network->Flags |= NETWORK_GET_MASTER_ANNOUNCE_POSTED; } } else { BrPrint(( BR_MASTER, "%ws: %ws: PostGetMasterAnnouncement already posted.\n", Network->DomainInfo->DomUnicodeDomainName, Network->NetworkName.Buffer)); } } UNLOCK_NETWORK(Network); return NetStatus; } VOID GetMasterAnnouncementCompletion ( IN PVOID Ctx ) /*++ Routine Description: This function is the completion routine for a master announcement. It is called whenever a master announcement is received for a particular network. Arguments: Ctx - Context block for request. Return Value: None. --*/ { PVOID ServerList = NULL; ULONG EntriesRead; ULONG TotalEntries; NET_API_STATUS Status = NERR_Success; PBROWSERASYNCCONTEXT Context = Ctx; PLMDR_REQUEST_PACKET MasterAnnouncement = Context->RequestPacket; PNETWORK Network = Context->Network; LPTSTR RemoteMasterName = NULL; BOOLEAN NetLocked = FALSE; BOOLEAN NetReferenced = FALSE; try { // // Ensure the network wasn't deleted from under us. // if ( BrReferenceNetwork( Network ) == NULL ) { try_return(NOTHING); } NetReferenced = TRUE; if (!LOCK_NETWORK(Network)){ try_return(NOTHING); } NetLocked = TRUE; Network->Flags &= ~NETWORK_GET_MASTER_ANNOUNCE_POSTED; // // The request failed for some reason - just return immediately. // if (!NT_SUCCESS(Context->IoStatusBlock.Status)) { try_return(NOTHING); } Status = PostGetMasterAnnouncement(Network); if (Status != NERR_Success) { BrPrint(( BR_CRITICAL, "%ws: %ws: Unable to re-issue GetMasterAnnouncement request: %lx\n", Network->DomainInfo->DomUnicodeDomainName, Network->NetworkName.Buffer, Status)); try_return(NOTHING); } RemoteMasterName = MIDL_user_allocate(MasterAnnouncement->Parameters.WaitForMasterAnnouncement.MasterNameLength+3*sizeof(TCHAR)); if (RemoteMasterName == NULL) { try_return(NOTHING); } RemoteMasterName[0] = TEXT('\\'); RemoteMasterName[1] = TEXT('\\'); STRNCPY(&RemoteMasterName[2], MasterAnnouncement->Parameters.WaitForMasterAnnouncement.Name, MasterAnnouncement->Parameters.WaitForMasterAnnouncement.MasterNameLength/sizeof(TCHAR)); RemoteMasterName[(MasterAnnouncement->Parameters.WaitForMasterAnnouncement.MasterNameLength/sizeof(TCHAR))+2] = UNICODE_NULL; BrPrint(( BR_MASTER, "%ws: %ws: GetMasterAnnouncement: Got a master browser announcement from %ws\n", Network->DomainInfo->DomUnicodeDomainName, Network->NetworkName.Buffer, RemoteMasterName)); UNLOCK_NETWORK(Network); NetLocked = FALSE; // // Remote the api and pull the browse list from the remote server. // Status = RxNetServerEnum(RemoteMasterName, Network->NetworkName.Buffer, 101, (LPBYTE *)&ServerList, 0xffffffff, &EntriesRead, &TotalEntries, SV_TYPE_LOCAL_LIST_ONLY, NULL, NULL ); if ((Status == NERR_Success) || (Status == ERROR_MORE_DATA)) { if (!LOCK_NETWORK(Network)) { try_return(NOTHING); } NetLocked = TRUE; Status = MergeServerList(&Network->BrowseTable, 101, ServerList, EntriesRead, TotalEntries ); UNLOCK_NETWORK(Network); NetLocked = FALSE; (void) NetApiBufferFree( ServerList ); ServerList = NULL; } else { BrPrint(( BR_MASTER, "%ws: %ws: GetMasterAnnouncement: Cannot get server list from %ws (%ld)\n", Network->DomainInfo->DomUnicodeDomainName, Network->NetworkName.Buffer, RemoteMasterName, Status )); } // // Remote the api and pull the browse list from the remote server. // Status = RxNetServerEnum(RemoteMasterName, Network->NetworkName.Buffer, 101, (LPBYTE *)&ServerList, 0xffffffff, &EntriesRead, &TotalEntries, SV_TYPE_LOCAL_LIST_ONLY | SV_TYPE_DOMAIN_ENUM, NULL, NULL ); if ((Status == NERR_Success) || (Status == ERROR_MORE_DATA)) { if (!LOCK_NETWORK(Network)) { try_return(NOTHING); } NetLocked = TRUE; Status = MergeServerList(&Network->DomainList, 101, ServerList, EntriesRead, TotalEntries ); } else { BrPrint(( BR_MASTER, "%ws: %ws: GetMasterAnnouncement: Cannot get domain list from %ws (%ld)\n", Network->DomainInfo->DomUnicodeDomainName, Network->NetworkName.Buffer, RemoteMasterName, Status )); } try_exit:NOTHING; } finally { if (NetLocked) { UNLOCK_NETWORK(Network); } if ( NetReferenced ) { BrDereferenceNetwork( Network ); } if (RemoteMasterName != NULL) { MIDL_user_free(RemoteMasterName); } MIDL_user_free(Context); if ( ServerList != NULL ) { (void) NetApiBufferFree( ServerList ); } } return; }