745 lines
21 KiB
C
745 lines
21 KiB
C
/*++
|
||
|
||
Copyright (c) 1990 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
bowmastr.c
|
||
|
||
Abstract:
|
||
|
||
This module implements all of the master browser related routines for the
|
||
NT browser
|
||
|
||
Author:
|
||
|
||
Larry Osterman (LarryO) 21-Jun-1990
|
||
|
||
Revision History:
|
||
|
||
21-Jun-1990 LarryO
|
||
|
||
Created
|
||
|
||
--*/
|
||
|
||
|
||
#include "precomp.h"
|
||
#pragma hdrstop
|
||
|
||
#define INCLUDE_SMB_TRANSACTION
|
||
|
||
NTSTATUS
|
||
StartProcessingAnnouncements(
|
||
IN PTRANSPORT_NAME TransportName,
|
||
IN PVOID Context
|
||
);
|
||
|
||
VOID
|
||
BowserMasterAnnouncementWorker(
|
||
IN PVOID Ctx
|
||
);
|
||
|
||
NTSTATUS
|
||
TimeoutFindMasterRequests(
|
||
IN PTRANSPORT Transport,
|
||
IN PVOID Context
|
||
|
||
);
|
||
NTSTATUS
|
||
BowserPrimeDomainTableWithOtherDomains(
|
||
IN PTRANSPORT_NAME TransportName,
|
||
IN PVOID Context
|
||
);
|
||
|
||
#ifdef ALLOC_PRAGMA
|
||
#pragma alloc_text(PAGE, BowserBecomeMaster)
|
||
#pragma alloc_text(PAGE, StartProcessingAnnouncements)
|
||
#pragma alloc_text(PAGE, BowserPrimeDomainTableWithOtherDomains)
|
||
#pragma alloc_text(PAGE, BowserNewMaster)
|
||
#pragma alloc_text(PAGE, BowserCompleteFindMasterRequests)
|
||
#pragma alloc_text(PAGE, BowserTimeoutFindMasterRequests)
|
||
#pragma alloc_text(PAGE, TimeoutFindMasterRequests)
|
||
#pragma alloc_text(PAGE, BowserMasterAnnouncementWorker)
|
||
#endif
|
||
|
||
|
||
NTSTATUS
|
||
BowserBecomeMaster(
|
||
IN PTRANSPORT Transport
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
Make this machine a master browser.
|
||
|
||
This routine is called when we are changing the state of a machine from
|
||
backup to master browser.
|
||
|
||
Arguments:
|
||
Transport - The transport on which to become a master.
|
||
|
||
Return Value
|
||
NTSTATUS - The status of the upgrade operation.
|
||
|
||
--*/
|
||
{
|
||
NTSTATUS Status;
|
||
PPAGED_TRANSPORT PagedTransport = Transport->PagedTransport;
|
||
|
||
PAGED_CODE();
|
||
|
||
try {
|
||
|
||
LOCK_TRANSPORT(Transport);
|
||
|
||
BowserReferenceDiscardableCode( BowserDiscardableCodeSection );
|
||
|
||
//
|
||
// Post the addname on this transport for the master name..
|
||
//
|
||
|
||
Status = BowserAllocateName(
|
||
&Transport->DomainInfo->DomUnicodeDomainName,
|
||
MasterBrowser,
|
||
Transport,
|
||
Transport->DomainInfo );
|
||
|
||
if (NT_SUCCESS(Status)) {
|
||
|
||
//
|
||
// Post the addname on this transport for the domain announcement.
|
||
//
|
||
|
||
Status = BowserAllocateName(&Transport->DomainInfo->DomUnicodeDomainName,
|
||
DomainAnnouncement,
|
||
Transport,
|
||
Transport->DomainInfo );
|
||
}
|
||
|
||
//
|
||
// The addition of the name failed - we can't be a master any
|
||
// more.
|
||
//
|
||
|
||
if (!NT_SUCCESS(Status)) {
|
||
|
||
try_return(Status);
|
||
|
||
}
|
||
|
||
PagedTransport->Role = Master;
|
||
|
||
//
|
||
// Start processing host announcements on each of
|
||
// the names associated with the server.
|
||
//
|
||
|
||
BowserForEachTransportName(Transport, StartProcessingAnnouncements, NULL);
|
||
|
||
//
|
||
// If we don't have any elements in our announcement table,
|
||
// send a request announcement packet to all the servers to
|
||
// allow ourselves to populate the table as quickly as possible.
|
||
//
|
||
|
||
|
||
#ifdef ENABLE_PSEUDO_BROWSER
|
||
if ((RtlNumberGenericTableElements(&PagedTransport->AnnouncementTable) == 0) &&
|
||
PagedTransport->NumberOfServersInTable == 0 &&
|
||
BowserData.PseudoServerLevel != BROWSER_PSEUDO) {
|
||
#else
|
||
if ((RtlNumberGenericTableElements(&PagedTransport->AnnouncementTable) == 0) &&
|
||
PagedTransport->NumberOfServersInTable == 0) {
|
||
#endif
|
||
BowserSendRequestAnnouncement(&Transport->DomainInfo->DomUnicodeDomainName,
|
||
PrimaryDomain,
|
||
Transport);
|
||
|
||
}
|
||
|
||
|
||
//
|
||
// If we don't have any elements in our domain table,
|
||
// send a request announcement packet to all the servers to
|
||
// allow ourselves to populate the table as quickly as possible.
|
||
//
|
||
|
||
#ifdef ENABLE_PSEUDO_BROWSER
|
||
if ((RtlNumberGenericTableElements(&PagedTransport->DomainTable) == 0) &&
|
||
PagedTransport->NumberOfServersInTable == 0 &&
|
||
BowserData.PseudoServerLevel != BROWSER_PSEUDO) {
|
||
#else
|
||
if ((RtlNumberGenericTableElements(&PagedTransport->DomainTable) == 0) &&
|
||
PagedTransport->NumberOfServersInTable == 0) {
|
||
#endif
|
||
BowserSendRequestAnnouncement(&Transport->DomainInfo->DomUnicodeDomainName,
|
||
DomainAnnouncement,
|
||
Transport);
|
||
}
|
||
|
||
PagedTransport->TimeMaster = BowserTimeUp();
|
||
|
||
|
||
//
|
||
// Now walk the transport names associated with this transport and
|
||
// seed all the "otherdomains" into the browse list.
|
||
//
|
||
|
||
BowserForEachTransportName(
|
||
Transport,
|
||
BowserPrimeDomainTableWithOtherDomains,
|
||
NULL);
|
||
|
||
//
|
||
// Now complete any and all find master requests outstanding on this
|
||
// transport.
|
||
//
|
||
|
||
BowserCompleteFindMasterRequests(Transport, &Transport->DomainInfo->DomUnicodeComputerName, STATUS_REQUEST_NOT_ACCEPTED);
|
||
|
||
try_return(Status = STATUS_SUCCESS);
|
||
|
||
try_exit:NOTHING;
|
||
} finally {
|
||
|
||
if (!NT_SUCCESS(Status)) {
|
||
|
||
dlog(DPRT_ELECT|DPRT_MASTER,
|
||
("%s: %ws: There's already a master on this net - we need to find who it is",
|
||
Transport->DomainInfo->DomOemDomainName,
|
||
PagedTransport->TransportName.Buffer ));
|
||
|
||
//
|
||
// We couldn't become a master. Reset our state and fail the
|
||
// promotion request.
|
||
//
|
||
|
||
PagedTransport->Role = PotentialBackup;
|
||
|
||
PagedTransport->ElectionCount = ELECTION_COUNT;
|
||
|
||
PagedTransport->Uptime = BowserTimeUp();
|
||
|
||
Transport->ElectionState = Idle;
|
||
|
||
//
|
||
// Stop processing host announcements on each of
|
||
// the names associated with the server.
|
||
//
|
||
|
||
BowserForEachTransportName(Transport, BowserStopProcessingAnnouncements, NULL);
|
||
|
||
//
|
||
// Stop any timers that are running (ie. if there's an election
|
||
// in progress)
|
||
//
|
||
|
||
BowserStopTimer(&Transport->ElectionTimer);
|
||
|
||
//
|
||
// Delete the names we added above.
|
||
//
|
||
|
||
BowserDeleteTransportNameByName(Transport,
|
||
NULL,
|
||
MasterBrowser);
|
||
|
||
BowserDeleteTransportNameByName(Transport,
|
||
NULL,
|
||
DomainAnnouncement);
|
||
|
||
|
||
BowserDereferenceDiscardableCode( BowserDiscardableCodeSection );
|
||
}
|
||
|
||
UNLOCK_TRANSPORT(Transport);
|
||
}
|
||
|
||
return Status;
|
||
}
|
||
NTSTATUS
|
||
StartProcessingAnnouncements(
|
||
IN PTRANSPORT_NAME TransportName,
|
||
IN PVOID Context
|
||
)
|
||
{
|
||
PAGED_CODE();
|
||
|
||
ASSERT (TransportName->Signature == STRUCTURE_SIGNATURE_TRANSPORTNAME);
|
||
|
||
ASSERT (TransportName->NameType == TransportName->PagedTransportName->Name->NameType);
|
||
|
||
if ((TransportName->NameType == OtherDomain) ||
|
||
(TransportName->NameType == MasterBrowser) ||
|
||
(TransportName->NameType == PrimaryDomain) ||
|
||
(TransportName->NameType == BrowserElection) ||
|
||
(TransportName->NameType == DomainAnnouncement)) {
|
||
|
||
if (!TransportName->ProcessHostAnnouncements) {
|
||
BowserReferenceDiscardableCode( BowserDiscardableCodeSection );
|
||
|
||
DISCARDABLE_CODE( BowserDiscardableCodeSection );
|
||
|
||
TransportName->ProcessHostAnnouncements = TRUE;
|
||
}
|
||
|
||
}
|
||
|
||
return(STATUS_SUCCESS);
|
||
|
||
UNREFERENCED_PARAMETER(Context);
|
||
}
|
||
|
||
NTSTATUS
|
||
BowserPrimeDomainTableWithOtherDomains(
|
||
IN PTRANSPORT_NAME TransportName,
|
||
IN PVOID Context
|
||
)
|
||
{
|
||
PAGED_CODE();
|
||
|
||
if (TransportName->NameType == OtherDomain) {
|
||
PPAGED_TRANSPORT PagedTransport = TransportName->Transport->PagedTransport;
|
||
PTRANSPORT Transport = TransportName->Transport;
|
||
ANNOUNCE_ENTRY OtherDomainPrototype;
|
||
PANNOUNCE_ENTRY Announcement;
|
||
BOOLEAN NewElement;
|
||
|
||
RtlZeroMemory( &OtherDomainPrototype, sizeof(OtherDomainPrototype) );
|
||
OtherDomainPrototype.Signature = STRUCTURE_SIGNATURE_ANNOUNCE_ENTRY;
|
||
OtherDomainPrototype.Size = sizeof(OtherDomainPrototype) -
|
||
sizeof(OtherDomainPrototype.ServerComment) +
|
||
Transport->DomainInfo->DomUnicodeComputerName.Length + sizeof(WCHAR);
|
||
|
||
RtlCopyMemory(OtherDomainPrototype.ServerName, TransportName->PagedTransportName->Name->Name.Buffer, TransportName->PagedTransportName->Name->Name.Length);
|
||
OtherDomainPrototype.ServerName[TransportName->PagedTransportName->Name->Name.Length / sizeof(WCHAR)] = UNICODE_NULL;
|
||
|
||
RtlCopyMemory(OtherDomainPrototype.ServerComment, Transport->DomainInfo->DomUnicodeComputerName.Buffer, Transport->DomainInfo->DomUnicodeComputerName.Length);
|
||
|
||
OtherDomainPrototype.ServerComment[Transport->DomainInfo->DomUnicodeComputerName.Length / sizeof(WCHAR)] = UNICODE_NULL;
|
||
|
||
OtherDomainPrototype.ServerType = SV_TYPE_DOMAIN_ENUM;
|
||
|
||
OtherDomainPrototype.ServerVersionMajor = 2;
|
||
|
||
OtherDomainPrototype.ServerVersionMinor = 0;
|
||
|
||
OtherDomainPrototype.ServerPeriodicity = 0xffff;
|
||
OtherDomainPrototype.ExpirationTime = 0xffffffff;
|
||
|
||
OtherDomainPrototype.SerialId = 0;
|
||
|
||
OtherDomainPrototype.Name = TransportName->PagedTransportName->Name;
|
||
|
||
//
|
||
// Make sure that no-one else is messing with the domain list.
|
||
//
|
||
|
||
LOCK_ANNOUNCE_DATABASE(Transport);
|
||
|
||
Announcement = RtlInsertElementGenericTable(&PagedTransport->DomainTable,
|
||
&OtherDomainPrototype, OtherDomainPrototype.Size, &NewElement);
|
||
|
||
if (Announcement != NULL && NewElement ) {
|
||
// Indicate the name is referenced by the announce entry we just inserted.
|
||
BowserReferenceName( OtherDomainPrototype.Name );
|
||
}
|
||
|
||
UNLOCK_ANNOUNCE_DATABASE(Transport);
|
||
|
||
}
|
||
|
||
return(STATUS_SUCCESS);
|
||
}
|
||
VOID
|
||
BowserNewMaster(
|
||
IN PTRANSPORT Transport,
|
||
IN PUCHAR MasterName
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
Flag that a machine is the new master browser server.
|
||
|
||
This routine is called to register a new master browser server.
|
||
|
||
Arguments:
|
||
IN PTRANSPORT Transport - The transport for the net we're on.
|
||
IN PUCHAR MasterName - The name of the new master browser server.
|
||
|
||
Return Value
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
PIRP Irp = NULL;
|
||
WCHAR MasterNameBuffer[LM20_CNLEN+1];
|
||
|
||
UNICODE_STRING UMasterName;
|
||
OEM_STRING OMasterName;
|
||
NTSTATUS Status;
|
||
PPAGED_TRANSPORT PagedTransport = Transport->PagedTransport;
|
||
|
||
PAGED_CODE();
|
||
|
||
UMasterName.Buffer = MasterNameBuffer;
|
||
UMasterName.MaximumLength = (LM20_CNLEN+1)*sizeof(WCHAR);
|
||
|
||
RtlInitAnsiString(&OMasterName, MasterName);
|
||
|
||
Status = RtlOemStringToUnicodeString(&UMasterName, &OMasterName, FALSE);
|
||
|
||
if (!NT_SUCCESS(Status)) {
|
||
BowserLogIllegalName( Status, OMasterName.Buffer, OMasterName.Length );
|
||
return;
|
||
}
|
||
|
||
LOCK_TRANSPORT(Transport);
|
||
|
||
try {
|
||
|
||
//
|
||
// There's a new master, we can stop our election timers.
|
||
//
|
||
|
||
PagedTransport->ElectionCount = 0;
|
||
|
||
Transport->ElectionState = Idle;
|
||
|
||
BowserStopTimer(&Transport->ElectionTimer);
|
||
|
||
//
|
||
// Check to see if we are the winner of the election. If we are
|
||
// we want to complete any BecomeMaster requests that are outstanding.
|
||
//
|
||
|
||
if (RtlEqualUnicodeString(&UMasterName, &Transport->DomainInfo->DomUnicodeComputerName, TRUE)) {
|
||
|
||
//
|
||
// We're the new master for this domain. Complete any BecomeMaster
|
||
// requests.
|
||
//
|
||
|
||
Irp = BowserDequeueQueuedIrp(&Transport->BecomeMasterQueue);
|
||
|
||
if (Irp != NULL) {
|
||
|
||
//
|
||
// Don't copy anything into the users buffer.
|
||
//
|
||
|
||
Irp->IoStatus.Information = 0;
|
||
|
||
BowserCompleteRequest(Irp, STATUS_SUCCESS);
|
||
} else {
|
||
|
||
//
|
||
// Go deaf to elections until we can become a master.
|
||
//
|
||
|
||
Transport->ElectionState = DeafToElections;
|
||
|
||
//
|
||
// If we're the master browser, stop being a master browser.
|
||
//
|
||
//
|
||
|
||
if (PagedTransport->Role == MasterBrowser) {
|
||
|
||
//
|
||
// Delete the names that make us a master.
|
||
//
|
||
|
||
BowserDeleteTransportNameByName(Transport,
|
||
NULL,
|
||
MasterBrowser);
|
||
|
||
BowserDeleteTransportNameByName(Transport,
|
||
NULL,
|
||
DomainAnnouncement);
|
||
|
||
}
|
||
|
||
dlog(DPRT_MASTER,
|
||
("%s: %ws: Unable to find a BecomeMasterIrp\n",
|
||
Transport->DomainInfo->DomOemDomainName,
|
||
PagedTransport->TransportName.Buffer ));
|
||
}
|
||
|
||
//
|
||
// Complete any outstanding find master requests with the special error MORE_PROCESSING_REQUIRED.
|
||
//
|
||
// This will cause the browser service to promote itself.
|
||
//
|
||
|
||
BowserCompleteFindMasterRequests(Transport, &UMasterName, STATUS_MORE_PROCESSING_REQUIRED);
|
||
|
||
} else {
|
||
|
||
BowserCompleteFindMasterRequests(Transport, &UMasterName, STATUS_SUCCESS);
|
||
|
||
}
|
||
|
||
} finally {
|
||
UNLOCK_TRANSPORT(Transport);
|
||
}
|
||
}
|
||
|
||
VOID
|
||
BowserCompleteFindMasterRequests(
|
||
IN PTRANSPORT Transport,
|
||
IN PUNICODE_STRING MasterName,
|
||
IN NTSTATUS Status
|
||
)
|
||
{
|
||
PIO_STACK_LOCATION IrpSp;
|
||
PIRP Irp = NULL;
|
||
BOOLEAN MasterNameChanged;
|
||
WCHAR MasterNameBuffer[CNLEN+1];
|
||
UNICODE_STRING MasterNameCopy;
|
||
NTSTATUS UcaseStatus;
|
||
PPAGED_TRANSPORT PagedTransport = Transport->PagedTransport;
|
||
|
||
PAGED_CODE();
|
||
|
||
MasterNameCopy.Buffer = MasterNameBuffer;
|
||
MasterNameCopy.MaximumLength = sizeof(MasterNameBuffer);
|
||
|
||
UcaseStatus = RtlUpcaseUnicodeString(&MasterNameCopy, MasterName, FALSE);
|
||
|
||
if (!NT_SUCCESS(UcaseStatus)) {
|
||
BowserLogIllegalName( UcaseStatus, MasterName->Buffer, MasterName->Length );
|
||
|
||
return;
|
||
}
|
||
|
||
LOCK_TRANSPORT(Transport);
|
||
|
||
MasterNameChanged = !RtlEqualUnicodeString(&MasterNameCopy, &PagedTransport->MasterName, FALSE);
|
||
|
||
if (MasterNameChanged) {
|
||
//
|
||
// If the master name changed, update the masters name in
|
||
// the transport structure.
|
||
//
|
||
|
||
RtlCopyUnicodeString(&PagedTransport->MasterName, &MasterNameCopy);
|
||
|
||
}
|
||
|
||
UNLOCK_TRANSPORT(Transport);
|
||
|
||
do {
|
||
|
||
//
|
||
// Complete any the find master requests outstanding against this
|
||
// workstation.
|
||
//
|
||
|
||
Irp = BowserDequeueQueuedIrp(&Transport->FindMasterQueue);
|
||
|
||
if (MasterNameChanged &&
|
||
(Irp == NULL)) {
|
||
|
||
Irp = BowserDequeueQueuedIrp(&Transport->WaitForNewMasterNameQueue);
|
||
|
||
}
|
||
|
||
if (Irp != NULL) {
|
||
PLMDR_REQUEST_PACKET RequestPacket = Irp->AssociatedIrp.SystemBuffer;
|
||
|
||
if (NT_SUCCESS(Status)) {
|
||
|
||
IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||
|
||
if (MasterName->Length > (USHORT)(IrpSp->Parameters.DeviceIoControl.OutputBufferLength-
|
||
(FIELD_OFFSET(LMDR_REQUEST_PACKET, Parameters.GetMasterName.Name))+3*sizeof(WCHAR)) ) {
|
||
Status = STATUS_BUFFER_TOO_SMALL;
|
||
} else {
|
||
RequestPacket->Parameters.GetMasterName.Name[0] = L'\\';
|
||
RequestPacket->Parameters.GetMasterName.Name[1] = L'\\';
|
||
RtlCopyMemory(&RequestPacket->Parameters.GetMasterName.Name[2], MasterName->Buffer, MasterName->Length);
|
||
RequestPacket->Parameters.GetMasterName.Name[2+(MasterName->Length/sizeof(WCHAR))] = UNICODE_NULL;
|
||
}
|
||
|
||
dlog(DPRT_MASTER,
|
||
("%s: %ws: Completing a find master request with new master %ws\n",
|
||
Transport->DomainInfo->DomOemDomainName,
|
||
PagedTransport->TransportName.Buffer,
|
||
RequestPacket->Parameters.GetMasterName.Name));
|
||
|
||
RequestPacket->Parameters.GetMasterName.MasterNameLength = MasterName->Length+2*sizeof(WCHAR);
|
||
|
||
Irp->IoStatus.Information = FIELD_OFFSET(LMDR_REQUEST_PACKET, Parameters.GetMasterName.Name)+MasterName->Length+3*sizeof(WCHAR);
|
||
|
||
}
|
||
|
||
BowserCompleteRequest(Irp, Status);
|
||
}
|
||
|
||
} while ( Irp != NULL );
|
||
}
|
||
|
||
|
||
DATAGRAM_HANDLER(BowserMasterAnnouncement)
|
||
{
|
||
PUCHAR MasterName = ((PMASTER_ANNOUNCEMENT_1)Buffer)->MasterName;
|
||
ULONG i;
|
||
|
||
//
|
||
// We need to make sure that the incoming packet contains a properly
|
||
// terminated ASCII string.
|
||
//
|
||
|
||
for (i = 0; i < BytesAvailable; i++) {
|
||
if (MasterName[i] == '\0') {
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (i == BytesAvailable) {
|
||
return(STATUS_REQUEST_NOT_ACCEPTED);
|
||
}
|
||
|
||
return BowserPostDatagramToWorkerThread(
|
||
TransportName,
|
||
Buffer,
|
||
BytesAvailable,
|
||
BytesTaken,
|
||
SourceAddress,
|
||
SourceAddressLength,
|
||
SourceName,
|
||
SourceNameLength,
|
||
BowserMasterAnnouncementWorker,
|
||
NonPagedPool,
|
||
DelayedWorkQueue,
|
||
ReceiveFlags,
|
||
FALSE // No response will be sent.
|
||
);
|
||
}
|
||
|
||
VOID
|
||
BowserMasterAnnouncementWorker(
|
||
IN PVOID Ctx
|
||
)
|
||
{
|
||
PPOST_DATAGRAM_CONTEXT Context = Ctx;
|
||
PTRANSPORT Transport = Context->TransportName->Transport;
|
||
PCHAR LocalMasterName = (PCHAR)((PMASTER_ANNOUNCEMENT_1)Context->Buffer)->MasterName;
|
||
size_t cbLocalMasterName;
|
||
PIRP Irp;
|
||
NTSTATUS Status;
|
||
|
||
PAGED_CODE();
|
||
|
||
Irp = BowserDequeueQueuedIrp(&Transport->WaitForMasterAnnounceQueue);
|
||
|
||
if (Irp != NULL) {
|
||
PIO_STACK_LOCATION IrpSp;
|
||
PLMDR_REQUEST_PACKET RequestPacket = Irp->AssociatedIrp.SystemBuffer;
|
||
|
||
IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||
|
||
cbLocalMasterName = strlen(LocalMasterName);
|
||
|
||
if (0 == cbLocalMasterName) {
|
||
|
||
// ensure we didn't get an invalid NULL announcement
|
||
// see bug 440813
|
||
// The request completed successfully, but the data is trash.
|
||
// - we won't fail the IRP (another one is posted immediately
|
||
// upon completion anyway), but not process further this one.
|
||
|
||
Irp->IoStatus.Information = 0;
|
||
Status = STATUS_SUCCESS;
|
||
}
|
||
else if ((cbLocalMasterName + 1) * sizeof(WCHAR) >
|
||
(IrpSp->Parameters.DeviceIoControl.OutputBufferLength -
|
||
FIELD_OFFSET(LMDR_REQUEST_PACKET, Parameters.WaitForMasterAnnouncement.Name))) {
|
||
//
|
||
// ensure there's enough buffer space to return name. If not,
|
||
// return error.
|
||
//
|
||
|
||
Irp->IoStatus.Information = 0;
|
||
|
||
Status = STATUS_BUFFER_TOO_SMALL;
|
||
} else {
|
||
|
||
//
|
||
// All is well. Fill info.
|
||
//
|
||
|
||
OEM_STRING MasterName;
|
||
UNICODE_STRING MasterNameU;
|
||
|
||
RtlInitString(&MasterName, LocalMasterName);
|
||
|
||
Status = RtlOemStringToUnicodeString(&MasterNameU, &MasterName, TRUE);
|
||
|
||
if ( NT_SUCCESS(Status) ) {
|
||
RequestPacket->Parameters.WaitForMasterAnnouncement.MasterNameLength = MasterNameU.Length;
|
||
|
||
RtlCopyMemory(RequestPacket->Parameters.WaitForMasterAnnouncement.Name, MasterNameU.Buffer, MasterNameU.Length);
|
||
|
||
RequestPacket->Parameters.WaitForMasterAnnouncement.Name[MasterNameU.Length/sizeof(WCHAR)] = UNICODE_NULL;
|
||
|
||
Irp->IoStatus.Information = FIELD_OFFSET(LMDR_REQUEST_PACKET, Parameters.WaitForMasterAnnouncement.Name)+MasterNameU.Length + sizeof(UNICODE_NULL);
|
||
|
||
RtlFreeUnicodeString(&MasterNameU);
|
||
|
||
Status = STATUS_SUCCESS;
|
||
}
|
||
}
|
||
|
||
BowserCompleteRequest(Irp, Status);
|
||
|
||
}
|
||
|
||
BowserDereferenceTransportName(Context->TransportName);
|
||
BowserDereferenceTransport(Transport);
|
||
|
||
InterlockedDecrement( &BowserPostedDatagramCount );
|
||
FREE_POOL(Context);
|
||
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
TimeoutFindMasterRequests(
|
||
IN PTRANSPORT Transport,
|
||
IN PVOID Context
|
||
)
|
||
{
|
||
|
||
PAGED_CODE();
|
||
|
||
//
|
||
// Perform an unprotected early out to prevent our calling into
|
||
// discardable code section during the scavenger. Since the discardable
|
||
// code section is <4K, touching the code would have the effect of
|
||
// bringing the entire page into memory, which is a waste - since the
|
||
// scavenger runs every 30 seconds, this would cause the discardable
|
||
// code section to be a part of the browsers working set.
|
||
//
|
||
|
||
if (BowserIsIrpQueueEmpty(&Transport->FindMasterQueue)) {
|
||
return STATUS_SUCCESS;
|
||
}
|
||
|
||
BowserTimeoutQueuedIrp(&Transport->FindMasterQueue, BowserFindMasterTimeout);
|
||
|
||
return STATUS_SUCCESS;
|
||
}
|
||
|
||
VOID
|
||
BowserTimeoutFindMasterRequests(
|
||
VOID
|
||
)
|
||
{
|
||
PAGED_CODE();
|
||
|
||
BowserForEachTransport(TimeoutFindMasterRequests, NULL);
|
||
}
|