mirror of https://github.com/lianthony/NT4.0
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.
420 lines
10 KiB
420 lines
10 KiB
|
|
/*++
|
|
|
|
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 //
|
|
// //
|
|
//-------------------------------------------------------------------//
|
|
|
|
NET_API_STATUS
|
|
PostGetMasterAnnouncement (
|
|
PNETWORK Network,
|
|
PVOID Ctx
|
|
);
|
|
|
|
VOID
|
|
BrPostGetMasterAnnouncementWorker(
|
|
IN PVOID Ctx
|
|
);
|
|
|
|
VOID
|
|
GetMasterAnnouncementCompletion (
|
|
IN PVOID Ctx
|
|
);
|
|
|
|
typedef struct _BROWSER_GET_MASTER_ANNOUNCEMENT_CONTEXT {
|
|
HANDLE EventHandle;
|
|
NET_API_STATUS NetStatus;
|
|
} BROWSER_GET_MASTER_ANNOUNCEMENT_CONTEXT, *PBROWSER_GET_MASTER_ANNOUNCEMENT_CONTEXT;
|
|
|
|
NET_API_STATUS
|
|
BrPostGetMasterAnnouncementInWorker(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
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:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
Status of operation.
|
|
|
|
--*/
|
|
{
|
|
NET_API_STATUS NetStatus;
|
|
DWORD WaitStatus;
|
|
|
|
WORKER_ITEM WorkItem;
|
|
BROWSER_GET_MASTER_ANNOUNCEMENT_CONTEXT Context;
|
|
|
|
//
|
|
// 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();
|
|
|
|
//
|
|
// Let the caller know we're done.
|
|
//
|
|
SetEvent( Context->EventHandle );
|
|
|
|
}
|
|
|
|
NET_API_STATUS
|
|
BrPostGetMasterAnnouncement (
|
|
VOID
|
|
)
|
|
{
|
|
dprintf(MASTER, ("BrPostGetMasterAnnouncement\n"));
|
|
|
|
return BrEnumerateNetworks(PostGetMasterAnnouncement, NULL);
|
|
}
|
|
|
|
|
|
NET_API_STATUS
|
|
PostGetMasterAnnouncement (
|
|
PNETWORK Network,
|
|
PVOID Context
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function is the worker routine called to actually issue a BecomeBackup
|
|
FsControl to the bowser driver on all the bound transports. It will
|
|
complete when the machine becomes a backup browser server.
|
|
|
|
Please note that this might never complete.
|
|
|
|
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->Flags & NETWORK_WANNISH) {
|
|
|
|
if (!(Network->Flags & NETWORK_GET_MASTER_ANNOUNCE_POSTED)) {
|
|
|
|
dprintf(MASTER, ("PostGetMasterAnnouncement on %ws\n", Network->NetworkName.Buffer));
|
|
|
|
NetStatus = BrIssueAsyncBrowserIoControl(Network,
|
|
IOCTL_LMDR_WAIT_FOR_MASTER_ANNOUNCE,
|
|
GetMasterAnnouncementCompletion
|
|
);
|
|
|
|
if ( NetStatus == NERR_Success ) {
|
|
Network->Flags |= NETWORK_GET_MASTER_ANNOUNCE_POSTED;
|
|
}
|
|
} else {
|
|
dprintf(MASTER, ("PostGetMasterAnnouncement already posted on %ws\n", 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;
|
|
|
|
if (!LOCK_NETWORK(Network)){
|
|
MIDL_user_free(Context->RequestPacket);
|
|
|
|
MIDL_user_free(Context);
|
|
|
|
return;
|
|
}
|
|
|
|
NetLocked = TRUE;
|
|
|
|
try {
|
|
|
|
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) {
|
|
InternalError(("Unable to re-issue GetMasterAnnouncement request: %lx\n", 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;
|
|
|
|
dprintf(MASTER, ("GetMasterAnnouncement: Got a master browser announcement from %ws\n", 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 (RemoteMasterName != NULL) {
|
|
MIDL_user_free(RemoteMasterName);
|
|
}
|
|
|
|
MIDL_user_free(Context->RequestPacket);
|
|
|
|
MIDL_user_free(Context);
|
|
|
|
if ( ServerList != NULL ) {
|
|
(void) NetApiBufferFree( ServerList );
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|