/*++ Copyright (c) 1989-2001 Microsoft Corporation Module Name: name.c Abstract: Local Address Author: Jiandong Ruan Revision History: --*/ #include "precomp.h" #include "name.tmh" //#pragma alloc_text(PAGE, SmbCreateClient) //#pragma alloc_text(PAGE, SmbCloseClient) #define TA_ADDRESS_HEADER_SIZE (FIELD_OFFSET(TA_ADDRESS,Address)) VOID SmbDeleteClient(PSMB_CLIENT_ELEMENT ob) { KIRQL Irql; SMB_ACQUIRE_SPINLOCK(ob->Device, Irql); ASSERT(EntryIsInList(&ob->Device->PendingDeleteClientList, &ob->Linkage)); RemoveEntryList(&ob->Linkage); SMB_RELEASE_SPINLOCK(ob->Device, Irql); ExFreePool(ob); SmbPrint(SMB_TRACE_CALL, ("SmbDeleteClient: free Client %p\n", ob)); } NTSTATUS SmbCreateClient( IN PSMB_DEVICE Device, IN PIRP Irp, PFILE_FULL_EA_INFORMATION ea ) { TRANSPORT_ADDRESS UNALIGNED *pTransportAddr; PTA_ADDRESS pAddress; PTDI_ADDRESS_NETBIOS pNetbiosAddr; PTDI_ADDRESS_NETBIOS_EX pNetbiosAddrEx; PTDI_ADDRESS_NETBIOS_UNICODE_EX pUnicodeEx; PSMB_CLIENT_ELEMENT ClientObject; PIO_STACK_LOCATION IrpSp; UNICODE_STRING ucName; int i; DWORD RemainingBufferLength; CHAR Name[NETBIOS_NAME_SIZE + 1]; USHORT NameType; OEM_STRING OemString; KIRQL Irql; PAGED_CODE(); SmbPrint(SMB_TRACE_CALL, ("Enter SmbCreateClient\n")); pTransportAddr = (PTRANSPORT_ADDRESS)(((PUCHAR)ea->EaName) + ea->EaNameLength + 1); RemainingBufferLength = ea->EaValueLength; if (RemainingBufferLength < sizeof(TA_NETBIOS_ADDRESS)) { return STATUS_INVALID_ADDRESS_COMPONENT; } RemainingBufferLength -= sizeof(pTransportAddr->TAAddressCount); pAddress = (PTA_ADDRESS)pTransportAddr->Address; for (i = 0; i < pTransportAddr->TAAddressCount; i++) { // // First, make sure we can safely access pAddress->AddressLength // if (RemainingBufferLength < TA_ADDRESS_HEADER_SIZE) { return STATUS_INVALID_ADDRESS_COMPONENT; } RemainingBufferLength -= TA_ADDRESS_HEADER_SIZE; if (RemainingBufferLength < pAddress->AddressLength) { return STATUS_INVALID_ADDRESS_COMPONENT; } if (TDI_ADDRESS_TYPE_NETBIOS == pAddress->AddressType) { if (pAddress->AddressLength < sizeof(TDI_ADDRESS_NETBIOS)) { return STATUS_INVALID_ADDRESS_COMPONENT; } pNetbiosAddr = (PTDI_ADDRESS_NETBIOS)pAddress->Address; RtlCopyMemory(Name, pNetbiosAddr->NetbiosName, NETBIOS_NAME_SIZE); NameType = pNetbiosAddr->NetbiosNameType; break; } else if (TDI_ADDRESS_TYPE_NETBIOS_EX == pAddress->AddressType) { if (pAddress->AddressLength < sizeof(TDI_ADDRESS_NETBIOS_EX)) { return STATUS_INVALID_ADDRESS_COMPONENT; } pNetbiosAddrEx = (PTDI_ADDRESS_NETBIOS_EX)pAddress->Address; RtlCopyMemory(Name, pNetbiosAddrEx->EndpointName, NETBIOS_NAME_SIZE); NameType = TDI_ADDRESS_NETBIOS_TYPE_QUICK_UNIQUE; break; } else if (TDI_ADDRESS_TYPE_NETBIOS_UNICODE_EX == pAddress->AddressType) { if (pAddress->AddressLength < sizeof(TDI_ADDRESS_NETBIOS_UNICODE_EX)) { return STATUS_INVALID_ADDRESS_COMPONENT; } pUnicodeEx = (PTDI_ADDRESS_NETBIOS_UNICODE_EX)pAddress->Address; OemString.Buffer = Name; OemString.Length = 0; OemString.MaximumLength = sizeof(Name); ucName = pUnicodeEx->EndpointName; RtlUpcaseUnicodeStringToOemString(&OemString, &ucName, FALSE); NameType = TDI_ADDRESS_NETBIOS_TYPE_QUICK_UNIQUE; break; } RemainingBufferLength -= pAddress->AddressLength; pAddress = (PTA_ADDRESS)(((PUCHAR)pAddress) + pAddress->AddressLength + TA_ADDRESS_HEADER_SIZE); } if (i >= pTransportAddr->TAAddressCount) { return STATUS_INVALID_ADDRESS_COMPONENT; } // // We have the name and name type // Name[NETBIOS_NAME_SIZE] = 0; ClientObject = ExAllocatePoolWithTag(NonPagedPool, sizeof(ClientObject[0]), CLIENT_OBJECT_POOL_TAG); if (NULL == ClientObject) { return STATUS_NO_MEMORY; } SmbInitializeObject((PSMB_OBJECT)ClientObject, TAG_CLIENT_OBJECT, (PSMB_OBJECT_CLEANUP)SmbDeleteClient); ClientObject->Device = Device; RtlCopyMemory(ClientObject->EndpointName, Name, NETBIOS_NAME_SIZE); KeInitializeSpinLock(&ClientObject->Lock); InitializeListHead(&ClientObject->ListenHead); InitializeListHead(&ClientObject->AssociatedConnection); InitializeListHead(&ClientObject->ActiveConnection); InitializeListHead(&ClientObject->PendingAcceptConnection); ClientObject->PendingAcceptNumber = 0; ClientObject->evConnect = NULL; ClientObject->ConEvContext = NULL; ClientObject->evDisconnect = NULL; ClientObject->DiscEvContext = NULL; ClientObject->evError = NULL; ClientObject->ErrorEvContext = NULL; ClientObject->evReceive = NULL; ClientObject->RcvEvContext = NULL; SMB_ACQUIRE_SPINLOCK(Device, Irql); if (RtlEqualMemory(Device->EndpointName, ClientObject->EndpointName, NETBIOS_NAME_SIZE)) { if (Device->SmbServer) { ExFreePool(ClientObject); SMB_RELEASE_SPINLOCK(Device, Irql); SmbPrint(SMB_TRACE_CALL, ("SmbCreateClient: Duplicate server\n")); return STATUS_ACCESS_DENIED; } SmbPrint(SMB_TRACE_CALL, ("SmbCreateClient: Server comes in\n")); Device->SmbServer = ClientObject; } InsertTailList(&Device->ClientList, &ClientObject->Linkage); SMB_RELEASE_SPINLOCK(Device, Irql); IrpSp = IoGetCurrentIrpStackLocation(Irp); IrpSp->FileObject->FsContext = ClientObject; IrpSp->FileObject->FsContext2 = UlongToPtr(SMB_TDI_CLIENT); SmbPrint(SMB_TRACE_CALL, ("SmbCreateClient: new Client %p\n", ClientObject)); return STATUS_SUCCESS; } NTSTATUS SmbCloseClient( IN PSMB_DEVICE Device, IN PIRP Irp ) { PIO_STACK_LOCATION IrpSp; KIRQL Irql; PSMB_CLIENT_ELEMENT ClientObject; IrpSp = IoGetCurrentIrpStackLocation(Irp); if (IrpSp->FileObject->FsContext2 != UlongToPtr(SMB_TDI_CLIENT)) { ASSERT(0); return STATUS_INVALID_PARAMETER; } SMB_ACQUIRE_SPINLOCK(&SmbCfg, Irql); IrpSp->FileObject->FsContext2 = UlongToPtr(SMB_TDI_INVALID); SMB_RELEASE_SPINLOCK(&SmbCfg, Irql); if (NULL == IrpSp->FileObject->FsContext) { ASSERT(0); return STATUS_INVALID_PARAMETER; } ClientObject = (PSMB_CLIENT_ELEMENT)IrpSp->FileObject->FsContext; SMB_ACQUIRE_SPINLOCK(Device, Irql); ASSERT(EntryIsInList(&Device->ClientList, &ClientObject->Linkage)); if (RtlEqualMemory(Device->EndpointName, ClientObject->EndpointName, NETBIOS_NAME_SIZE)) { ASSERT(Device->SmbServer); Device->SmbServer = NULL; SmbPrint(SMB_TRACE_CALL, ("SmbCloseClient: Server leaves\n")); } RemoveEntryList(&ClientObject->Linkage); InsertTailList(&Device->PendingDeleteClientList, &ClientObject->Linkage); SMB_RELEASE_SPINLOCK(Device, Irql); SmbDereferenceClient(ClientObject, SMB_REF_CREATE); IrpSp->FileObject->FsContext = NULL; SmbPrint(SMB_TRACE_CALL, ("SmbCloseClient: close Client %p\n", ClientObject)); return STATUS_SUCCESS; } PSMB_CLIENT_ELEMENT SmbVerifyAndReferenceClient( PFILE_OBJECT FileObject, SMB_REF_CONTEXT ctx ) { PSMB_CLIENT_ELEMENT ClientObject; KIRQL Irql; SMB_ACQUIRE_SPINLOCK(&SmbCfg, Irql); if (FileObject->FsContext2 != UlongToPtr(SMB_TDI_CLIENT)) { ClientObject = NULL; } else { ClientObject = (PSMB_CLIENT_ELEMENT)FileObject->FsContext; SmbReferenceClient(ClientObject, ctx); } SMB_RELEASE_SPINLOCK(&SmbCfg, Irql); return ClientObject; }