diff options
Diffstat (limited to 'private/net/svcdlls/browser2/server/brdmmstr.c')
-rw-r--r-- | private/net/svcdlls/browser2/server/brdmmstr.c | 456 |
1 files changed, 456 insertions, 0 deletions
diff --git a/private/net/svcdlls/browser2/server/brdmmstr.c b/private/net/svcdlls/browser2/server/brdmmstr.c new file mode 100644 index 000000000..d9e0d73d3 --- /dev/null +++ b/private/net/svcdlls/browser2/server/brdmmstr.c @@ -0,0 +1,456 @@ + +/*++ + +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 +BrPostGetMasterAnnouncementWorker( + IN PVOID Ctx + ); + +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 +BrPostGetMasterAnnouncementInWorker( + PDOMAIN_INFO DomainInfo + ) + +/*++ + +Routine Description: + + Wrapper for BrPostGetMasterAnnouncement. Since BrPostGetMasterAnnouncement + starts a pending IO to the browser driver, the thread that calls + BrPostGetMasterAnnouncement must remain around forever. This wrapper can + be called by any transient thread (e.g., an RPC thread). It simply causes + BrPostGetMasterAnnouncement to be called in a worker thread. + +Arguments: + + DomainInfo - Domain the get master announcement is to be posted for + +Return Value: + + Status of operation. + +--*/ +{ + NET_API_STATUS NetStatus; + DWORD WaitStatus; + + WORKER_ITEM WorkItem; + BROWSER_GET_MASTER_ANNOUNCEMENT_CONTEXT Context; + + // + // Copy the parameters into the context. + // + + Context.DomainInfo = DomainInfo; + + // + // Create an event which we use to wait on the worker thread. + // + + Context.EventHandle = CreateEvent( + NULL, // Event attributes + TRUE, // Event must be manually reset + FALSE, // Initial state not signalled + NULL ); // Event name + + if ( Context.EventHandle == NULL ) { + NetStatus = GetLastError(); + return NetStatus; + } + + // + // Queue the request to the worker thread. + // + + BrInitializeWorkItem( &WorkItem, + BrPostGetMasterAnnouncementWorker, + &Context ); + + BrQueueWorkItem( &WorkItem ); + + // + // Wait for the worker thread to finish + // + + WaitStatus = WaitForSingleObject( Context.EventHandle, INFINITE ); + + if ( WaitStatus == WAIT_OBJECT_0 ) { + NetStatus = Context.NetStatus; + } else { + NetStatus = GetLastError(); + } + + CloseHandle( Context.EventHandle ); + + return NetStatus; +} + +VOID +BrPostGetMasterAnnouncementWorker( + IN PVOID Ctx + ) +/*++ + +Routine Description: + + Worker routine for BrPostGetMasterAnnouncementInWorker. + + This routine executes in the context of a worker thread. + +Arguments: + + Context - Context describing the workitem. + +Return Value: + + None + +--*/ +{ + PBROWSER_GET_MASTER_ANNOUNCEMENT_CONTEXT Context = + (PBROWSER_GET_MASTER_ANNOUNCEMENT_CONTEXT) Ctx; + + // + // Create the domain. + // + + Context->NetStatus = BrPostGetMasterAnnouncement( Context->DomainInfo ); + + // + // Let the caller know we're done. + // + SetEvent( Context->EventHandle ); + +} + +NET_API_STATUS +BrPostGetMasterAnnouncement ( + PDOMAIN_INFO DomainInfo + ) +/*++ + +Routine Description: + + Ensure the GetMasterAnnouncement request is posted for all networks on + the specified domain. + +Arguments: + + DomainInfo - Domain this operation is to apply to + +Return Value: + + Status - The status of the operation. + +--*/ +{ + BrPrint(( BR_MASTER, "%ws: BrPostGetMasterAnnouncement\n", DomainInfo->DomUnicodeDomainName )); + + return BrEnumerateNetworksForDomain(DomainInfo, PostGetMasterAnnouncement, NULL); +} + + +NET_API_STATUS +PostGetMasterAnnouncement ( + PNETWORK Network, + PVOID Context + ) +/*++ + +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; + + if (!LOCK_NETWORK(Network)) { + return NERR_InternalError; + } + + if ( Network->DomainInfo->IsDomainMasterBrowser && + (Network->Flags & NETWORK_WANNISH)) { + + if (!(Network->Flags & NETWORK_GET_MASTER_ANNOUNCE_POSTED)) { + + BrPrint(( BR_MASTER, + "%ws: PostGetMasterAnnouncement on %ws\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: PostGetMasterAnnouncement already posted on %ws\n", + Network->DomainInfo->DomUnicodeDomainName, + Network->NetworkName.Buffer)); + } + } + + UNLOCK_NETWORK(Network); + return NetStatus; + + UNREFERENCED_PARAMETER(Context); +} + + +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, NULL); + + 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; + + } + + // + // 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 + ); + } + +try_exit:NOTHING; + } finally { + + if (NetLocked) { + UNLOCK_NETWORK(Network); + } + + if ( NetReferenced ) { + BrDereferenceNetwork( Network ); + } + + if (RemoteMasterName != NULL) { + MIDL_user_free(RemoteMasterName); + } + + MIDL_user_free(Context->RequestPacket); + + MIDL_user_free(Context); + + if ( ServerList != NULL ) { + (void) NetApiBufferFree( ServerList ); + } + + } + + return; + +} |