/*++ Copyright (c) 1990 Microsoft Corporation Module Name: bowbackp.c Abstract: This module implements all of the backup 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 typedef struct _BECOME_BACKUP_CONTEXT { WORK_QUEUE_ITEM WorkHeader; PTRANSPORT_NAME TransportName; PBECOME_BACKUP_1 BecomeBackupRequest; ULONG BytesAvailable; } BECOME_BACKUP_CONTEXT, *PBECOME_BACKUP_CONTEXT; VOID BowserBecomeBackupWorker( IN PVOID WorkItem ); #ifdef ALLOC_PRAGMA #pragma alloc_text(PAGE, BowserBecomeBackupWorker) #endif DATAGRAM_HANDLER( BowserHandleBecomeBackup ) /*++ Routine Description: Indicate that a machine should become a backup browser server. This routine is called on receipt of a BecomeBackup frame. 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. --*/ { PTA_NETBIOS_ADDRESS Address = SourceAddress; return BowserPostDatagramToWorkerThread( TransportName, Buffer, BytesAvailable, BytesTaken, SourceAddress, SourceAddressLength, SourceName, SourceNameLength, BowserBecomeBackupWorker, NonPagedPool, DelayedWorkQueue, ReceiveFlags, FALSE // No response will be sent ); } VOID BowserBecomeBackupWorker( IN PVOID WorkItem ) { PPOST_DATAGRAM_CONTEXT Context = WorkItem; PIRP Irp = NULL; PTRANSPORT Transport = Context->TransportName->Transport; UNICODE_STRING UPromoteeName; OEM_STRING APromoteeName; PPAGED_TRANSPORT PagedTransport = Transport->PagedTransport; PBECOME_BACKUP_1 BecomeBackupRequest = Context->Buffer; PAGED_CODE(); UPromoteeName.Buffer = NULL; LOCK_TRANSPORT(Transport); try { NTSTATUS Status; RtlInitAnsiString(&APromoteeName, BecomeBackupRequest->BrowserToPromote); Status = RtlOemStringToUnicodeString(&UPromoteeName, &APromoteeName, TRUE); if (!NT_SUCCESS(Status)) { BowserWriteErrorLogEntry(EVENT_BOWSER_NAME_CONVERSION_FAILED, Status, APromoteeName.Buffer, APromoteeName.Length, 0); try_return(NOTHING); } if (RtlEqualUnicodeString(&UPromoteeName, &Transport->ComputerName->PagedTransportName->Name->Name, TRUE)) { if (PagedTransport->Role == Master) { BowserWriteErrorLogEntry(EVENT_BOWSER_PROMOTED_WHILE_ALREADY_MASTER, STATUS_UNSUCCESSFUL, NULL, 0, 0); try_return(NOTHING); } // // Ignore become backup requests on point-to-point (RAS) links and // transports which are actually duplicates of others. // if (PagedTransport->DisabledTransport) { try_return(NOTHING); } // // Complete any the first become backup request outstanding against this // workstation. // Irp = BowserDequeueQueuedIrp(&Transport->BecomeBackupQueue); if (Irp != NULL) { Irp->IoStatus.Information = 0; BowserCompleteRequest(Irp, STATUS_SUCCESS); } } try_exit:NOTHING; } finally { UNLOCK_TRANSPORT(Transport); BowserDereferenceTransportName(Context->TransportName); BowserDereferenceTransport(Transport); if (UPromoteeName.Buffer != NULL) { RtlFreeUnicodeString(&UPromoteeName); } InterlockedDecrement( &BowserPostedDatagramCount ); FREE_POOL(Context); } } VOID BowserResetStateForTransport( IN PTRANSPORT Transport, IN UCHAR NewState ) { PIRP Irp = NULL; PIO_STACK_LOCATION IrpSp; NTSTATUS Status; // // Complete a reset state IRP outstanding on this transport. // Irp = BowserDequeueQueuedIrp(&Transport->ChangeRoleQueue); if (Irp != NULL) { PLMDR_REQUEST_PACKET RequestPacket = Irp->AssociatedIrp.SystemBuffer; IrpSp = IoGetCurrentIrpStackLocation(Irp); if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(LMDR_REQUEST_PACKET)) { Status = STATUS_INSUFFICIENT_RESOURCES; } else { RequestPacket->Parameters.ChangeRole.RoleModification = NewState; Irp->IoStatus.Information = sizeof(LMDR_REQUEST_PACKET); Status = STATUS_SUCCESS; } BowserCompleteRequest(Irp, Status); } } DATAGRAM_HANDLER( BowserResetState ) { PTRANSPORT Transport = TransportName->Transport; UCHAR NewState = (UCHAR)((PRESET_STATE_1)(Buffer))->Options; BowserResetStateForTransport(Transport, NewState); return STATUS_SUCCESS; }