windows-nt/Source/XPSP1/NT/ds/netapi/svcdlls/browser/server/brdmmstr.c

326 lines
9.1 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
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;
}