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.
263 lines
8.3 KiB
263 lines
8.3 KiB
/*++
|
|
|
|
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;
|
|
}
|