326 lines
9.1 KiB
C
326 lines
9.1 KiB
C
|
||
/*++
|
||
|
||
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;
|
||
|
||
}
|