summaryrefslogtreecommitdiffstats
path: root/private/ntos/tdi/isnp/ipx/address.c
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/tdi/isnp/ipx/address.c
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/ntos/tdi/isnp/ipx/address.c')
-rw-r--r--private/ntos/tdi/isnp/ipx/address.c1843
1 files changed, 1843 insertions, 0 deletions
diff --git a/private/ntos/tdi/isnp/ipx/address.c b/private/ntos/tdi/isnp/ipx/address.c
new file mode 100644
index 000000000..1049bc8de
--- /dev/null
+++ b/private/ntos/tdi/isnp/ipx/address.c
@@ -0,0 +1,1843 @@
+/*++
+
+Copyright (c) 1989-1993 Microsoft Corporation
+
+Module Name:
+
+ address.c
+
+Abstract:
+
+ This module contains code which implements the ADDRESS object.
+ Routines are provided to create, destroy, reference, and dereference,
+ transport address objects.
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Sanjay Anand (SanjayAn) - 22-Sept-1995
+ BackFill optimization changes added under #if BACK_FILL
+
+ Sanjay Anand (SanjayAn) 3-Oct-1995
+ Changes to support transfer of buffer ownership to transports - tagged [CH]
+
+--*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+
+//
+// Map all generic accesses to the same one.
+//
+
+static GENERIC_MAPPING AddressGenericMapping =
+ { READ_CONTROL, READ_CONTROL, READ_CONTROL, READ_CONTROL };
+
+
+
+TDI_ADDRESS_IPX UNALIGNED *
+IpxParseTdiAddress(
+ IN TRANSPORT_ADDRESS UNALIGNED * TransportAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This routine scans a TRANSPORT_ADDRESS, looking for an address
+ of type TDI_ADDRESS_TYPE_IPX.
+
+Arguments:
+
+ Transport - The generic TDI address.
+
+Return Value:
+
+ A pointer to the IPX address, or NULL if none is found.
+
+--*/
+
+{
+ TA_ADDRESS UNALIGNED * addressName;
+ INT i;
+
+ addressName = &TransportAddress->Address[0];
+
+ //
+ // The name can be passed with multiple entries; we'll take and use only
+ // the IPX one.
+ //
+
+ for (i=0;i<TransportAddress->TAAddressCount;i++) {
+ if (addressName->AddressType == TDI_ADDRESS_TYPE_IPX) {
+ if (addressName->AddressLength >= sizeof(TDI_ADDRESS_IPX)) {
+ return ((TDI_ADDRESS_IPX UNALIGNED *)(addressName->Address));
+ }
+ }
+ addressName = (TA_ADDRESS UNALIGNED *)(addressName->Address +
+ addressName->AddressLength);
+ }
+ return NULL;
+
+} /* IpxParseTdiAddress */
+
+
+BOOLEAN
+IpxValidateTdiAddress(
+ IN TRANSPORT_ADDRESS UNALIGNED * TransportAddress,
+ IN ULONG TransportAddressLength
+ )
+
+/*++
+
+Routine Description:
+
+ This routine scans a TRANSPORT_ADDRESS, verifying that the
+ components of the address do not extend past the specified
+ length.
+
+Arguments:
+
+ TransportAddress - The generic TDI address.
+
+ TransportAddressLength - The specific length of TransportAddress.
+
+Return Value:
+
+ TRUE if the address is valid, FALSE otherwise.
+
+--*/
+
+{
+ PUCHAR AddressEnd = ((PUCHAR)TransportAddress) + TransportAddressLength;
+ TA_ADDRESS UNALIGNED * addressName;
+ INT i;
+
+ if (TransportAddressLength < sizeof(TransportAddress->TAAddressCount)) {
+ IpxPrint0 ("IpxValidateTdiAddress: runt address\n");
+ return FALSE;
+ }
+
+ addressName = &TransportAddress->Address[0];
+
+ for (i=0;i<TransportAddress->TAAddressCount;i++) {
+ if (addressName->Address > AddressEnd) {
+ IpxPrint0 ("IpxValidateTdiAddress: address too short\n");
+ return FALSE;
+ }
+ addressName = (TA_ADDRESS UNALIGNED *)(addressName->Address +
+ addressName->AddressLength);
+ }
+
+ if ((PUCHAR)addressName > AddressEnd) {
+ IpxPrint0 ("IpxValidateTdiAddress: address too short\n");
+ return FALSE;
+ }
+ return TRUE;
+
+} /* IpxValidateTdiAddress */
+
+#if DBG
+
+VOID
+IpxBuildTdiAddress(
+ IN PVOID AddressBuffer,
+ IN ULONG Network,
+ IN UCHAR Node[6],
+ IN USHORT Socket
+ )
+
+/*++
+
+Routine Description:
+
+ This routine fills in a TRANSPORT_ADDRESS in the specified
+ buffer, given the socket, network and node.
+
+Arguments:
+
+ AddressBuffer - The buffer that will hold the address.
+
+ Network - The network number.
+
+ Node - The node address.
+
+ Socket - The socket.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ TA_IPX_ADDRESS UNALIGNED * IpxAddress;
+
+ IpxAddress = (TA_IPX_ADDRESS UNALIGNED *)AddressBuffer;
+
+ IpxAddress->TAAddressCount = 1;
+ IpxAddress->Address[0].AddressLength = sizeof(TDI_ADDRESS_IPX);
+ IpxAddress->Address[0].AddressType = TDI_ADDRESS_TYPE_IPX;
+ IpxAddress->Address[0].Address[0].NetworkAddress = Network;
+ IpxAddress->Address[0].Address[0].Socket = Socket;
+ RtlCopyMemory(IpxAddress->Address[0].Address[0].NodeAddress, Node, 6);
+
+} /* IpxBuildTdiAddress */
+#endif
+
+
+NTSTATUS
+IpxOpenAddress(
+ IN PDEVICE Device,
+ IN PREQUEST Request
+ )
+
+/*++
+
+Routine Description:
+
+ This routine opens a file that points to an existing address object, or, if
+ the object doesn't exist, creates it (note that creation of the address
+ object includes registering the address, and may take many seconds to
+ complete, depending upon system configuration).
+
+ If the address already exists, and it has an ACL associated with it, the
+ ACL is checked for access rights before allowing creation of the address.
+
+Arguments:
+
+ Device - pointer to the device describing the IPX transport.
+
+ Request - a pointer to the request used for the creation of the address.
+
+Return Value:
+
+ NTSTATUS - status of operation.
+
+--*/
+
+{
+ NTSTATUS status;
+ PADDRESS Address;
+ PADDRESS_FILE AddressFile;
+ PFILE_FULL_EA_INFORMATION ea;
+ TRANSPORT_ADDRESS UNALIGNED *name;
+ TA_ADDRESS UNALIGNED *AddressName;
+ USHORT Socket;
+ ULONG DesiredShareAccess;
+ CTELockHandle LockHandle;
+ PACCESS_STATE AccessState;
+ ACCESS_MASK GrantedAccess;
+ BOOLEAN AccessAllowed;
+ int i;
+ BOOLEAN found = FALSE;
+#ifdef ISN_NT
+ PIRP Irp = (PIRP)Request;
+ PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
+#endif
+
+
+ //
+ // If we are a dedicated router, we cannot let addresses
+ // be opened.
+ //
+
+ if (Device->DedicatedRouter) {
+ return STATUS_NOT_SUPPORTED;
+ }
+
+ //
+ // The network name is in the EA, passed in the request.
+ //
+
+ ea = OPEN_REQUEST_EA_INFORMATION(Request);
+ if (ea == NULL) {
+ IpxPrint1("OpenAddress: REQUEST %lx has no EA\n", Request);
+ return STATUS_NONEXISTENT_EA_ENTRY;
+ }
+
+ //
+ // this may be a valid name; parse the name from the EA and use it if OK.
+ //
+
+ name = (PTRANSPORT_ADDRESS)&ea->EaName[ea->EaNameLength+1];
+ AddressName = (PTA_ADDRESS)&name->Address[0];
+
+ //
+ // The name can be passed with multiple entries; we'll take and use only
+ // the first one of type IPX.
+ //
+
+ for (i=0;i<name->TAAddressCount;i++) {
+ if (AddressName->AddressType == TDI_ADDRESS_TYPE_IPX) {
+ if (AddressName->AddressLength >= sizeof(TDI_ADDRESS_IPX)) {
+ Socket = ((TDI_ADDRESS_IPX UNALIGNED *)&AddressName->Address[0])->Socket;
+ found = TRUE;
+ }
+ break;
+
+ } else {
+
+ AddressName = (PTA_ADDRESS)(AddressName->Address +
+ AddressName->AddressLength);
+
+ }
+
+ }
+
+ if (!found) {
+ IPX_DEBUG (ADDRESS, ("OpenAddress, request %lx has no IPX Address\n", Request));
+ return STATUS_NONEXISTENT_EA_ENTRY;
+ }
+
+ if (Socket == 0) {
+
+ Socket = IpxAssignSocket (Device);
+
+ if (Socket == 0) {
+ IPX_DEBUG (ADDRESS, ("OpenAddress, no unique socket found\n"));
+ return STATUS_INSUFFICIENT_RESOURCES;
+ } else {
+ IPX_DEBUG (ADDRESS, ("OpenAddress, assigned socket %lx\n", REORDER_USHORT(Socket)));
+ }
+
+ } else {
+
+ IPX_DEBUG (ADDRESS, ("OpenAddress, socket %lx\n", REORDER_USHORT(Socket)));
+
+ }
+
+ //
+ // get an address file structure to represent this address.
+ //
+
+ AddressFile = IpxCreateAddressFile (Device);
+
+ if (AddressFile == (PADDRESS_FILE)NULL) {
+ return status;
+ }
+
+ //
+ // We mark this socket specially.
+ //
+
+ if (Socket == SAP_SOCKET) {
+ AddressFile->IsSapSocket = TRUE;
+ AddressFile->SpecialReceiveProcessing = TRUE;
+ }
+
+ //
+ // See if this address is already established. This call automatically
+ // increments the reference count on the address so that it won't disappear
+ // from underneath us after this call but before we have a chance to use it.
+ //
+ // To ensure that we don't create two address objects for the
+ // same address, we hold the device context addressResource until
+ // we have found the address or created a new one.
+ //
+
+ ExAcquireResourceExclusive (&Device->AddressResource, TRUE);
+
+ CTEGetLock (&Device->Lock, &LockHandle);
+
+ Address = IpxLookupAddress (Device, Socket);
+
+ if (Address == NULL) {
+
+ CTEFreeLock (&Device->Lock, LockHandle);
+
+ //
+ // This address doesn't exist. Create it.
+ // registering it.
+ //
+
+ Address = IpxCreateAddress (
+ Device,
+ Socket);
+
+ if (Address != (PADDRESS)NULL) {
+
+ //
+ // Set this now in case we have to deref.
+ //
+
+ AddressFile->AddressLock = &Address->Lock;
+
+#ifdef ISN_NT
+
+ //
+ // Initialize the shared access now. We use read access
+ // to control all access.
+ //
+
+ DesiredShareAccess = (ULONG)
+ (((IrpSp->Parameters.Create.ShareAccess & FILE_SHARE_READ) ||
+ (IrpSp->Parameters.Create.ShareAccess & FILE_SHARE_WRITE)) ?
+ FILE_SHARE_READ : 0);
+
+ IoSetShareAccess(
+ FILE_READ_DATA,
+ DesiredShareAccess,
+ IrpSp->FileObject,
+ &Address->u.ShareAccess);
+
+
+ //
+ // Assign the security descriptor (need to do this with
+ // the spinlock released because the descriptor is not
+ // mapped).
+ //
+
+ AccessState = IrpSp->Parameters.Create.SecurityContext->AccessState;
+
+ status = SeAssignSecurity(
+ NULL, // parent descriptor
+ AccessState->SecurityDescriptor,
+ &Address->SecurityDescriptor,
+ FALSE, // is directory
+ &AccessState->SubjectSecurityContext,
+ &AddressGenericMapping,
+ NonPagedPool);
+
+ if (!NT_SUCCESS(status)) {
+
+ //
+ // Error, return status.
+ //
+
+ IoRemoveShareAccess (IrpSp->FileObject, &Address->u.ShareAccess);
+ ExReleaseResource (&Device->AddressResource);
+ IpxDereferenceAddress (Address, AREF_ADDRESS_FILE);
+ IpxDereferenceAddressFile (AddressFile, AFREF_CREATE);
+ return status;
+
+ }
+
+#endif
+
+ ExReleaseResource (&Device->AddressResource);
+
+ //
+ // if the adapter isn't ready, we can't do any of this; get out
+ //
+
+ if (Device->State == DEVICE_STATE_STOPPING) {
+ IpxDereferenceAddress (Address, AREF_ADDRESS_FILE);
+ IpxDereferenceAddressFile (AddressFile, AFREF_CREATE);
+ status = STATUS_DEVICE_NOT_READY;
+
+ } else {
+
+ REQUEST_OPEN_CONTEXT(Request) = (PVOID)AddressFile;
+ REQUEST_OPEN_TYPE(Request) = (PVOID)TDI_TRANSPORT_ADDRESS_FILE;
+#ifdef ISN_NT
+ AddressFile->FileObject = IrpSp->FileObject;
+#endif
+ AddressFile->Request = Request;
+ AddressFile->Address = Address;
+
+ CTEGetLock (&Address->Lock, &LockHandle);
+ InsertTailList (&Address->AddressFileDatabase, &AddressFile->Linkage);
+ CTEFreeLock (&Address->Lock, LockHandle);
+
+ AddressFile->Request = NULL;
+ AddressFile->State = ADDRESSFILE_STATE_OPEN;
+ status = STATUS_SUCCESS;
+
+ }
+
+ } else {
+
+ ExReleaseResource (&Device->AddressResource);
+
+ //
+ // If the address could not be created, and is not in the
+ // process of being created, then we can't open up an address.
+ // Since we can't use the AddressLock to deref, we just destroy
+ // the address file.
+ //
+
+ IpxDestroyAddressFile (AddressFile);
+
+ }
+
+ } else {
+
+ CTEFreeLock (&Device->Lock, LockHandle);
+
+ IPX_DEBUG (ADDRESS, ("Add to address %lx\n", Address));
+
+ //
+ // Set this now in case we have to deref.
+ //
+
+ AddressFile->AddressLock = &Address->Lock;
+
+ //
+ // The address already exists. Check the ACL and see if we
+ // can access it. If so, simply use this address as our address.
+ //
+
+#ifdef ISN_NT
+
+ AccessState = IrpSp->Parameters.Create.SecurityContext->AccessState;
+
+ AccessAllowed = SeAccessCheck(
+ Address->SecurityDescriptor,
+ &AccessState->SubjectSecurityContext,
+ FALSE, // tokens locked
+ IrpSp->Parameters.Create.SecurityContext->DesiredAccess,
+ (ACCESS_MASK)0, // previously granted
+ NULL, // privileges
+ &AddressGenericMapping,
+ Irp->RequestorMode,
+ &GrantedAccess,
+ &status);
+
+#else // ISN_NT
+
+ AccessAllowed = TRUE;
+
+#endif // ISN_NT
+
+ if (!AccessAllowed) {
+
+ ExReleaseResource (&Device->AddressResource);
+
+ IpxDereferenceAddressFile (AddressFile, AFREF_CREATE);
+
+ } else {
+
+#ifdef ISN_NT
+
+ //
+ // Now check that we can obtain the desired share
+ // access. We use read access to control all access.
+ //
+
+ DesiredShareAccess = (ULONG)
+ (((IrpSp->Parameters.Create.ShareAccess & FILE_SHARE_READ) ||
+ (IrpSp->Parameters.Create.ShareAccess & FILE_SHARE_WRITE)) ?
+ FILE_SHARE_READ : 0);
+
+ status = IoCheckShareAccess(
+ FILE_READ_DATA,
+ DesiredShareAccess,
+ IrpSp->FileObject,
+ &Address->u.ShareAccess,
+ TRUE);
+
+#else // ISN_NT
+
+ status = STATUS_SUCCESS;
+
+#endif // ISN_NT
+
+ if (!NT_SUCCESS (status)) {
+
+ ExReleaseResource (&Device->AddressResource);
+
+ IpxDereferenceAddressFile (AddressFile, AFREF_CREATE);
+
+ } else {
+
+ ExReleaseResource (&Device->AddressResource);
+
+ CTEGetLock (&Address->Lock, &LockHandle);
+
+ InsertTailList (
+ &Address->AddressFileDatabase,
+ &AddressFile->Linkage);
+
+ AddressFile->Request = NULL;
+ AddressFile->Address = Address;
+#ifdef ISN_NT
+ AddressFile->FileObject = IrpSp->FileObject;
+#endif
+ AddressFile->State = ADDRESSFILE_STATE_OPEN;
+
+ IpxReferenceAddress (Address, AREF_ADDRESS_FILE);
+
+ REQUEST_OPEN_CONTEXT(Request) = (PVOID)AddressFile;
+ REQUEST_OPEN_TYPE(Request) = (PVOID)TDI_TRANSPORT_ADDRESS_FILE;
+
+ CTEFreeLock (&Address->Lock, LockHandle);
+
+ status = STATUS_SUCCESS;
+
+ }
+ }
+
+ //
+ // Remove the reference from IpxLookupAddress.
+ //
+
+ IpxDereferenceAddress (Address, AREF_LOOKUP);
+ }
+
+ return status;
+
+} /* IpxOpenAddress */
+
+
+USHORT
+IpxAssignSocket(
+ IN PDEVICE Device
+ )
+
+/*++
+
+Routine Description:
+
+ This routine assigns a socket that is unique within a range
+ of SocketUniqueness.
+
+Arguments:
+
+ Device - Pointer to the device context.
+
+Return Value:
+
+ The assigned socket number, or 0 if a unique one cannot
+ be found.
+
+--*/
+
+{
+ USHORT InitialSocket, CurrentSocket, AddressSocket;
+ ULONG CurrentHash;
+ BOOLEAN Conflict;
+ PLIST_ENTRY p;
+ PADDRESS Address;
+ CTELockHandle LockHandle;
+
+ //
+ // Loop through all possible sockets, starting at
+ // Device->CurrentSocket, looking for a suitable one.
+ // Device->CurrentSocket rotates through the possible
+ // sockets to improve the chances of finding one
+ // quickly.
+ //
+
+ CTEGetLock (&Device->Lock, &LockHandle);
+
+ InitialSocket = Device->CurrentSocket;
+ Device->CurrentSocket = (USHORT)(Device->CurrentSocket + Device->SocketUniqueness);
+ if ((USHORT)(Device->CurrentSocket+Device->SocketUniqueness) > Device->SocketEnd) {
+ Device->CurrentSocket = Device->SocketStart;
+ }
+
+ CurrentSocket = InitialSocket;
+
+ do {
+
+ //
+ // Scan all addresses; if we find one with a socket
+ // that conflicts with this one, we can't use it.
+ //
+ // NOTE: Device->Lock is acquired here.
+ //
+
+ Conflict = FALSE;
+
+ for (CurrentHash = 0; CurrentHash < IPX_ADDRESS_HASH_COUNT; CurrentHash++) {
+
+ for (p = Device->AddressDatabases[CurrentHash].Flink;
+ p != &Device->AddressDatabases[CurrentHash];
+ p = p->Flink) {
+
+ Address = CONTAINING_RECORD (p, ADDRESS, Linkage);
+ AddressSocket = REORDER_USHORT(Address->Socket);
+
+ if ((AddressSocket + Device->SocketUniqueness > CurrentSocket) &&
+ (AddressSocket < CurrentSocket + Device->SocketUniqueness)) {
+ Conflict = TRUE;
+ break;
+ }
+ }
+
+ //
+ // If we've found a conflict, no need to check the other
+ // queues.
+ //
+
+ if (Conflict) {
+ break;
+ }
+ }
+
+ CTEFreeLock (&Device->Lock, LockHandle);
+
+ //
+ // We intentionally free the lock here so that we
+ // never spend too much time with it held.
+ //
+
+ if (!Conflict) {
+
+ //
+ // We went through the address list without
+ // finding a conflict; use this socket.
+ //
+
+ return REORDER_USHORT(CurrentSocket);
+ }
+
+ CurrentSocket = (USHORT)(CurrentSocket + Device->SocketUniqueness);
+ if ((USHORT)(CurrentSocket+Device->SocketUniqueness) > Device->SocketEnd) {
+ CurrentSocket = Device->SocketStart;
+ }
+
+ CTEGetLock (&Device->Lock, &LockHandle);
+
+ } while (CurrentSocket != InitialSocket);
+
+ CTEFreeLock (&Device->Lock, LockHandle);
+
+ //
+ // Could not find one to assign.
+ //
+
+ return (USHORT)0;
+
+} /* IpxAssignSocket */
+
+
+PADDRESS
+IpxCreateAddress(
+ IN PDEVICE Device,
+ IN USHORT Socket
+ )
+
+/*++
+
+Routine Description:
+
+ This routine creates a transport address and associates it with
+ the specified transport device context. The reference count in the
+ address is automatically set to 1, and the reference count of the
+ device context is incremented.
+
+ NOTE: This routine must be called with the Device
+ spinlock held.
+
+Arguments:
+
+ Device - Pointer to the device context (which is really just
+ the device object with its extension) to be associated with the
+ address.
+
+ Socket - The socket to assign to this address.
+
+Return Value:
+
+ The newly created address, or NULL if none can be allocated.
+
+--*/
+
+{
+ PADDRESS Address;
+ PIPX_SEND_RESERVED SendReserved;
+ PIPX_RECEIVE_RESERVED ReceiveReserved;
+ NDIS_STATUS Status;
+ IPX_DEFINE_LOCK_HANDLE (LockHandle)
+
+ Address = (PADDRESS)IpxAllocateMemory (sizeof(ADDRESS), MEMORY_ADDRESS, "Address");
+ if (Address == NULL) {
+ IPX_DEBUG (ADDRESS, ("Create address %lx failed\n", REORDER_USHORT(Socket)));
+ return NULL;
+ }
+
+ IPX_DEBUG (ADDRESS, ("Create address %lx (%lx)\n", Address, REORDER_USHORT(Socket)));
+ RtlZeroMemory (Address, sizeof(ADDRESS));
+
+#ifndef IPX_OWN_PACKETS
+ IpxAllocateSingleSendPacket(Device, &Address->SendPacket, &Status);
+ if (Status != NDIS_STATUS_SUCCESS) {
+ goto Fail1;
+ }
+#endif
+
+ if (IpxInitializeSendPacket (Device, &Address->SendPacket, Address->SendPacketHeader) != STATUS_SUCCESS) {
+#ifndef IPX_OWN_PACKETS
+Fail1:
+#endif
+ Address->SendPacketInUse = TRUE;
+ } else {
+ SendReserved = SEND_RESERVED(&Address->SendPacket);
+ SendReserved->Address = Address;
+ SendReserved->OwnedByAddress = TRUE;
+ Address->SendPacketInUse = FALSE;
+#ifdef IPX_TRACK_POOL
+ SendReserved->Pool = NULL;
+#endif
+ }
+
+
+#if BACK_FILL
+ {
+ PIPX_SEND_RESERVED BackFillReserved;
+
+#ifndef IPX_OWN_PACKETS
+ IpxAllocateSingleSendPacket(Device, &Address->BackFillPacket, &Status);
+ if (Status != NDIS_STATUS_SUCCESS) {
+ goto Fail2;
+ }
+#endif
+ if (IpxInitializeBackFillPacket (Device, &Address->BackFillPacket, NULL) != STATUS_SUCCESS) {
+#ifndef IPX_OWN_PACKETS
+Fail2:
+#endif
+ Address->BackFillPacketInUse = TRUE;
+ } else {
+ BackFillReserved = SEND_RESERVED(&Address->BackFillPacket);
+ BackFillReserved->Address = Address;
+ Address->BackFillPacketInUse = FALSE;
+ BackFillReserved->OwnedByAddress = TRUE;
+#ifdef IPX_TRACK_POOL
+ BackFillReserved->Pool = NULL;
+#endif
+ }
+ }
+#endif
+
+#ifndef IPX_OWN_PACKETS
+ IpxAllocateSingleReceivePacket(Device, &Address->ReceivePacket, &Status);
+ if (Status != NDIS_STATUS_SUCCESS) {
+ goto Fail3;
+ }
+#endif
+ if (IpxInitializeReceivePacket (Device, &Address->ReceivePacket) != STATUS_SUCCESS) {
+#ifndef IPX_OWN_PACKETS
+Fail3:
+#endif
+ Address->ReceivePacketInUse = TRUE;
+ } else {
+ ReceiveReserved = RECEIVE_RESERVED(&Address->ReceivePacket);
+ ReceiveReserved->Address = Address;
+ ReceiveReserved->OwnedByAddress = TRUE;
+ Address->ReceivePacketInUse = FALSE;
+#ifdef IPX_TRACK_POOL
+ ReceiveReserved->Pool = NULL;
+#endif
+ }
+
+ Address->Type = IPX_ADDRESS_SIGNATURE;
+ Address->Size = sizeof (ADDRESS);
+
+ Address->Device = Device;
+ Address->DeviceLock = &Device->Lock;
+ CTEInitLock (&Address->Lock);
+
+ InitializeListHead (&Address->AddressFileDatabase);
+
+ Address->ReferenceCount = 1;
+#if DBG
+ Address->RefTypes[AREF_ADDRESS_FILE] = 1;
+#endif
+ Address->Socket = Socket;
+ Address->SendSourceSocket = Socket;
+
+ //
+ // Save our local address for building datagrams quickly.
+ //
+
+ RtlCopyMemory (&Address->LocalAddress, &Device->SourceAddress, FIELD_OFFSET(TDI_ADDRESS_IPX,Socket));
+ Address->LocalAddress.Socket = Socket;
+
+ //
+ // Now link this address into the specified device context's
+ // address database. To do this, we need to acquire the spin lock
+ // on the device context.
+ //
+
+ IPX_GET_LOCK (&Device->Lock, &LockHandle);
+ InsertTailList (&Device->AddressDatabases[IPX_HASH_SOCKET(Socket)], &Address->Linkage);
+ IPX_FREE_LOCK (&Device->Lock, LockHandle);
+
+ IpxReferenceDevice (Device, DREF_ADDRESS);
+
+ return Address;
+
+} /* IpxCreateAddress */
+
+
+NTSTATUS
+IpxVerifyAddressFile(
+ IN PADDRESS_FILE AddressFile
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is called to verify that the pointer given us in a file
+ object is in fact a valid address file object. We also verify that the
+ address object pointed to by it is a valid address object, and reference
+ it to keep it from disappearing while we use it.
+
+Arguments:
+
+ AddressFile - potential pointer to a ADDRESS_FILE object
+
+Return Value:
+
+ STATUS_SUCCESS if all is well; STATUS_INVALID_ADDRESS otherwise
+
+--*/
+
+{
+ CTELockHandle LockHandle;
+ NTSTATUS status = STATUS_SUCCESS;
+ PADDRESS Address;
+
+ //
+ // try to verify the address file signature. If the signature is valid,
+ // verify the address pointed to by it and get the address spinlock.
+ // check the address's state, and increment the reference count if it's
+ // ok to use it. Note that the only time we return an error for state is
+ // if the address is closing.
+ //
+
+ try {
+
+ if ((AddressFile->Size == sizeof (ADDRESS_FILE)) &&
+ (AddressFile->Type == IPX_ADDRESSFILE_SIGNATURE) ) {
+// (AddressFile->State != ADDRESSFILE_STATE_CLOSING) ) {
+
+ Address = AddressFile->Address;
+
+ if ((Address->Size == sizeof (ADDRESS)) &&
+ (Address->Type == IPX_ADDRESS_SIGNATURE) ) {
+
+ CTEGetLock (&Address->Lock, &LockHandle);
+
+ if (!Address->Stopping) {
+
+ IpxReferenceAddressFileLock (AddressFile, AFREF_VERIFY);
+
+ } else {
+
+ IpxPrint1("IpxVerifyAddressFile: A %lx closing\n", Address);
+ status = STATUS_INVALID_ADDRESS;
+ }
+
+ CTEFreeLock (&Address->Lock, LockHandle);
+
+ } else {
+
+ IpxPrint1("IpxVerifyAddressFile: A %lx bad signature\n", Address);
+ status = STATUS_INVALID_ADDRESS;
+ }
+
+ } else {
+
+ IpxPrint1("IpxVerifyAddressFile: AF %lx bad signature\n", AddressFile);
+ status = STATUS_INVALID_ADDRESS;
+ }
+
+ } except(EXCEPTION_EXECUTE_HANDLER) {
+
+ IpxPrint1("IpxVerifyAddressFile: AF %lx exception\n", Address);
+ return GetExceptionCode();
+ }
+
+ return status;
+
+} /* IpxVerifyAddressFile */
+
+
+VOID
+IpxDestroyAddress(
+ IN PVOID Parameter
+ )
+
+/*++
+
+Routine Description:
+
+ This routine destroys a transport address and removes all references
+ made by it to other objects in the transport. The address structure
+ is returned to nonpaged system pool. It is assumed
+ that the caller has already removed all addressfile structures associated
+ with this address.
+
+ It is called from a worker thread queue by IpxDerefAddress when
+ the reference count goes to 0.
+
+ This thread is only queued by IpxDerefAddress. The reason for
+ this is that there may be multiple streams of execution which are
+ simultaneously referencing the same address object, and it should
+ not be deleted out from under an interested stream of execution.
+
+Arguments:
+
+ Address - Pointer to a transport address structure to be destroyed.
+
+Return Value:
+
+ NTSTATUS - status of operation.
+
+--*/
+
+{
+ PADDRESS Address = (PADDRESS)Parameter;
+ PDEVICE Device = Address->Device;
+ CTELockHandle LockHandle;
+
+ IPX_DEBUG (ADDRESS, ("Destroy address %lx (%lx)\n", Address, REORDER_USHORT(Address->Socket)));
+
+ SeDeassignSecurity (&Address->SecurityDescriptor);
+
+ //
+ // Delink this address from its associated device context's address
+ // database. To do this we must spin lock on the device context object,
+ // not on the address.
+ //
+
+ CTEGetLock (&Device->Lock, &LockHandle);
+ RemoveEntryList (&Address->Linkage);
+ CTEFreeLock (&Device->Lock, LockHandle);
+
+ if (!Address->SendPacketInUse) {
+ IpxDeinitializeSendPacket (Device, &Address->SendPacket);
+#ifndef IPX_OWN_PACKETS
+ IpxFreeSingleSendPacket (Device, Address->SendPacket);
+#endif
+ }
+
+ if (!Address->ReceivePacketInUse) {
+ IpxDeinitializeReceivePacket (Device, &Address->ReceivePacket);
+#ifndef IPX_OWN_PACKETS
+ IpxFreeSingleReceivePacket (Device, Address->ReceivePacket);
+#endif
+ }
+
+#if BACK_FILL
+ if (!Address->BackFillPacketInUse) {
+ IpxDeinitializeBackFillPacket (Device, &Address->BackFillPacket);
+#ifndef IPX_OWN_PACKETS
+ IpxFreeSingleSendPacket (Device, Address->BackFillPacket);
+#endif
+ }
+#endif
+ IpxFreeMemory (Address, sizeof(ADDRESS), MEMORY_ADDRESS, "Address");
+
+ IpxDereferenceDevice (Device, DREF_ADDRESS);
+
+} /* IpxDestroyAddress */
+
+
+#if DBG
+VOID
+IpxRefAddress(
+ IN PADDRESS Address
+ )
+
+/*++
+
+Routine Description:
+
+ This routine increments the reference count on a transport address.
+
+Arguments:
+
+ Address - Pointer to a transport address object.
+
+Return Value:
+
+ none.
+
+--*/
+
+{
+
+ CTEAssert (Address->ReferenceCount > 0); // not perfect, but...
+
+ (VOID)InterlockedIncrement(&Address->ReferenceCount);
+
+} /* IpxRefAddress */
+
+
+VOID
+IpxRefAddressLock(
+ IN PADDRESS Address
+ )
+
+/*++
+
+Routine Description:
+
+ This routine increments the reference count on a transport address
+ when the device lock is already held.
+
+Arguments:
+
+ Address - Pointer to a transport address object.
+
+Return Value:
+
+ none.
+
+--*/
+
+{
+
+ CTEAssert (Address->ReferenceCount > 0); // not perfect, but...
+
+ // ++Address->ReferenceCount;
+ (VOID)InterlockedIncrement(&Address->ReferenceCount);
+
+} /* IpxRefAddressLock */
+#endif
+
+
+VOID
+IpxDerefAddress(
+ IN PADDRESS Address
+ )
+
+/*++
+
+Routine Description:
+
+ This routine dereferences a transport address by decrementing the
+ reference count contained in the structure. If, after being
+ decremented, the reference count is zero, then this routine calls
+ IpxDestroyAddress to remove it from the system.
+
+Arguments:
+
+ Address - Pointer to a transport address object.
+
+Return Value:
+
+ none.
+
+--*/
+
+{
+ ULONG oldvalue;
+
+ oldvalue = IPX_ADD_ULONG (
+ &Address->ReferenceCount,
+ (ULONG)-1,
+ Address->DeviceLock);
+
+ //
+ // If we have deleted all references to this address, then we can
+ // destroy the object. It is okay to have already released the spin
+ // lock at this point because there is no possible way that another
+ // stream of execution has access to the address any longer.
+ //
+
+ CTEAssert (oldvalue != 0);
+
+ if (oldvalue == 1) {
+
+#if ISN_NT
+ ExInitializeWorkItem(
+ &Address->u.DestroyAddressQueueItem,
+ IpxDestroyAddress,
+ (PVOID)Address);
+ ExQueueWorkItem(&Address->u.DestroyAddressQueueItem, DelayedWorkQueue);
+#else
+ IpxDestroyAddress(Address);
+#endif
+
+ }
+
+} /* IpxDerefAddress */
+
+
+VOID
+IpxDerefAddressSync(
+ IN PADDRESS Address
+ )
+
+/*++
+
+Routine Description:
+
+ This routine dereferences a transport address by decrementing the
+ reference count contained in the structure. If, after being
+ decremented, the reference count is zero, then this routine calls
+ IpxDestroyAddress to remove it from the system. This routine can
+ only be called when we are synchronized (inside an IPX_SYNC_START/
+ IPX_SYNC_END pair, with a lock held, or in an indication).
+
+Arguments:
+
+ Address - Pointer to a transport address object.
+
+Return Value:
+
+ none.
+
+--*/
+
+{
+ ULONG oldvalue;
+
+ oldvalue = IPX_ADD_ULONG (
+ &Address->ReferenceCount,
+ (ULONG)-1,
+ Address->DeviceLock);
+
+ //
+ // If we have deleted all references to this address, then we can
+ // destroy the object. It is okay to have already released the spin
+ // lock at this point because there is no possible way that another
+ // stream of execution has access to the address any longer.
+ //
+
+ CTEAssert (oldvalue != 0);
+
+ if (oldvalue == 1) {
+
+#if ISN_NT
+ ExInitializeWorkItem(
+ &Address->u.DestroyAddressQueueItem,
+ IpxDestroyAddress,
+ (PVOID)Address);
+ ExQueueWorkItem(&Address->u.DestroyAddressQueueItem, DelayedWorkQueue);
+#else
+ IpxDestroyAddress(Address);
+#endif
+
+ }
+
+} /* IpxDerefAddressSync */
+
+
+PADDRESS_FILE
+IpxCreateAddressFile(
+ IN PDEVICE Device
+ )
+
+/*++
+
+Routine Description:
+
+ This routine creates an address file from the pool of ther
+ specified device context. The reference count in the
+ address is automatically set to 1.
+
+Arguments:
+
+ Device - Pointer to the device context (which is really just
+ the device object with its extension) to be associated with the
+ address.
+
+Return Value:
+
+ The allocate address file or NULL.
+
+--*/
+
+{
+ CTELockHandle LockHandle;
+ PADDRESS_FILE AddressFile;
+
+ CTEGetLock (&Device->Lock, &LockHandle);
+
+ AddressFile = (PADDRESS_FILE)IpxAllocateMemory (sizeof(ADDRESS_FILE), MEMORY_ADDRESS, "AddressFile");
+ if (AddressFile == NULL) {
+ IPX_DEBUG (ADDRESS, ("Create address file failed\n"));
+ CTEFreeLock (&Device->Lock, LockHandle);
+ return NULL;
+ }
+
+ IPX_DEBUG (ADDRESS, ("Create address file %lx\n", AddressFile));
+
+ RtlZeroMemory (AddressFile, sizeof(ADDRESS_FILE));
+
+ AddressFile->Type = IPX_ADDRESSFILE_SIGNATURE;
+ AddressFile->Size = sizeof (ADDRESS_FILE);
+
+ InitializeListHead (&AddressFile->ReceiveDatagramQueue);
+
+ CTEFreeLock (&Device->Lock, LockHandle);
+
+#if 0
+ AddressFile->SpecialReceiveProcessing = FALSE;
+ AddressFile->ExtendedAddressing = FALSE;
+ AddressFile->ReceiveIpxHeader = FALSE;
+ AddressFile->FilterOnPacketType = FALSE;
+ AddressFile->DefaultPacketType = 0;
+ AddressFile->Address = NULL;
+#ifdef ISN_NT
+ AddressFile->FileObject = NULL;
+#endif
+#endif
+
+ AddressFile->Device = Device;
+ AddressFile->State = ADDRESSFILE_STATE_OPENING;
+ AddressFile->ReferenceCount = 1;
+#if DBG
+ AddressFile->RefTypes[AFREF_CREATE] = 1;
+#endif
+ AddressFile->CloseRequest = (PREQUEST)NULL;
+
+ //
+ // Initialize the request handlers.
+ //
+
+ AddressFile->RegisteredReceiveDatagramHandler = FALSE;
+ AddressFile->ReceiveDatagramHandler = TdiDefaultRcvDatagramHandler;
+ AddressFile->ReceiveDatagramHandlerContext = NULL;
+
+ //
+ // [CH] Added these handlers for chained buffer receives
+ //
+ AddressFile->RegisteredChainedReceiveDatagramHandler = FALSE;
+ AddressFile->ChainedReceiveDatagramHandler = TdiDefaultChainedRcvDatagramHandler;
+ AddressFile->ChainedReceiveDatagramHandlerContext = NULL;
+
+ AddressFile->RegisteredErrorHandler = FALSE;
+ AddressFile->ErrorHandler = TdiDefaultErrorHandler;
+ AddressFile->ErrorHandlerContext = NULL;
+
+ return AddressFile;
+
+} /* IpxCreateAddressFile */
+
+
+NTSTATUS
+IpxDestroyAddressFile(
+ IN PADDRESS_FILE AddressFile
+ )
+
+/*++
+
+Routine Description:
+
+ This routine destroys an address file and removes all references
+ made by it to other objects in the transport.
+
+ This routine is only called by IpxDereferenceAddressFile. The reason
+ for this is that there may be multiple streams of execution which are
+ simultaneously referencing the same address file object, and it should
+ not be deleted out from under an interested stream of execution.
+
+Arguments:
+
+ AddressFile Pointer to a transport address file structure to be destroyed.
+
+Return Value:
+
+ NTSTATUS - status of operation.
+
+--*/
+
+{
+ CTELockHandle LockHandle, LockHandle1;
+ PADDRESS Address;
+ PDEVICE Device;
+ PREQUEST CloseRequest;
+
+ IPX_DEBUG (ADDRESS, ("Destroy address file %lx\n", AddressFile));
+
+ Address = AddressFile->Address;
+ Device = AddressFile->Device;
+
+ if (Address) {
+
+ //
+ // This addressfile was associated with an address.
+ //
+
+ CTEGetLock (&Address->Lock, &LockHandle);
+
+ //
+ // remove this addressfile from the address list and disassociate it from
+ // the file handle.
+ //
+
+ RemoveEntryList (&AddressFile->Linkage);
+ InitializeListHead (&AddressFile->Linkage);
+
+ if (Address->AddressFileDatabase.Flink == &Address->AddressFileDatabase) {
+
+ //
+ // This is the last open of this address, it will close
+ // due to normal dereferencing but we have to set the
+ // CLOSING flag too to stop further references.
+ //
+
+ CTEGetLock (&Device->Lock, &LockHandle1);
+ Address->Stopping = TRUE;
+ if (Device->LastAddress == Address) {
+ Device->LastAddress = NULL;
+ }
+ CTEFreeLock (&Device->Lock, LockHandle1);
+
+ }
+
+ AddressFile->Address = NULL;
+
+#ifdef ISN_NT
+ AddressFile->FileObject->FsContext = NULL;
+ AddressFile->FileObject->FsContext2 = NULL;
+#endif
+
+ CTEFreeLock (&Address->Lock, LockHandle);
+
+ //
+ // We will already have been removed from the ShareAccess
+ // of the owning address.
+ //
+
+ //
+ // Now dereference the owning address.
+ //
+
+ IpxDereferenceAddress (Address, AREF_ADDRESS_FILE);
+
+ }
+
+ //
+ // Save this for later completion.
+ //
+
+ CloseRequest = AddressFile->CloseRequest;
+
+ //
+ // return the addressFile to the pool of address files
+ //
+
+ IpxFreeMemory (AddressFile, sizeof(ADDRESS_FILE), MEMORY_ADDRESS, "AddressFile");
+
+ if (CloseRequest != (PREQUEST)NULL) {
+ REQUEST_INFORMATION(CloseRequest) = 0;
+ REQUEST_STATUS(CloseRequest) = STATUS_SUCCESS;
+ IpxCompleteRequest (CloseRequest);
+ IpxFreeRequest (Device, CloseRequest);
+ }
+
+ return STATUS_SUCCESS;
+
+} /* IpxDestroyAddressFile */
+
+
+#if DBG
+VOID
+IpxRefAddressFile(
+ IN PADDRESS_FILE AddressFile
+ )
+
+/*++
+
+Routine Description:
+
+ This routine increments the reference count on an address file.
+
+Arguments:
+
+ AddressFile - Pointer to a transport address file object.
+
+Return Value:
+
+ none.
+
+--*/
+
+{
+
+ CTEAssert (AddressFile->ReferenceCount > 0); // not perfect, but...
+
+ (VOID)IPX_ADD_ULONG (
+ &AddressFile->ReferenceCount,
+ 1,
+ AddressFile->AddressLock);
+
+} /* IpxRefAddressFile */
+
+
+VOID
+IpxRefAddressFileLock(
+ IN PADDRESS_FILE AddressFile
+ )
+
+/*++
+
+Routine Description:
+
+ This routine increments the reference count on an address file.
+ IT IS CALLED WITH THE ADDRESS LOCK HELD.
+
+Arguments:
+
+ AddressFile - Pointer to a transport address file object.
+
+Return Value:
+
+ none.
+
+--*/
+
+{
+
+ CTEAssert (AddressFile->ReferenceCount > 0); // not perfect, but...
+
+ //++AddressFile->ReferenceCount;
+ (VOID)InterlockedIncrement(&AddressFile->ReferenceCount);
+
+} /* IpxRefAddressFileLock */
+
+
+VOID
+IpxRefAddressFileSync(
+ IN PADDRESS_FILE AddressFile
+ )
+
+/*++
+
+Routine Description:
+
+ This routine increments the reference count on an address file.
+
+Arguments:
+
+ AddressFile - Pointer to a transport address file object.
+
+Return Value:
+
+ none.
+
+--*/
+
+{
+
+ CTEAssert (AddressFile->ReferenceCount > 0); // not perfect, but...
+
+ (VOID)IPX_ADD_ULONG (
+ &AddressFile->ReferenceCount,
+ 1,
+ AddressFile->AddressLock);
+
+} /* IpxRefAddressFileSync */
+
+
+VOID
+IpxDerefAddressFile(
+ IN PADDRESS_FILE AddressFile
+ )
+
+/*++
+
+Routine Description:
+
+ This routine dereferences an address file by decrementing the
+ reference count contained in the structure. If, after being
+ decremented, the reference count is zero, then this routine calls
+ IpxDestroyAddressFile to remove it from the system.
+
+Arguments:
+
+ AddressFile - Pointer to a transport address file object.
+
+Return Value:
+
+ none.
+
+--*/
+
+{
+ ULONG oldvalue;
+
+ oldvalue = IPX_ADD_ULONG (
+ &AddressFile->ReferenceCount,
+ (ULONG)-1,
+ AddressFile->AddressLock);
+
+ //
+ // If we have deleted all references to this address file, then we can
+ // destroy the object. It is okay to have already released the spin
+ // lock at this point because there is no possible way that another
+ // stream of execution has access to the address any longer.
+ //
+
+ CTEAssert (oldvalue > 0);
+
+ if (oldvalue == 1) {
+ IpxDestroyAddressFile (AddressFile);
+ }
+
+} /* IpxDerefAddressFile */
+
+
+VOID
+IpxDerefAddressFileSync(
+ IN PADDRESS_FILE AddressFile
+ )
+
+/*++
+
+Routine Description:
+
+ This routine dereferences an address file by decrementing the
+ reference count contained in the structure. If, after being
+ decremented, the reference count is zero, then this routine calls
+ IpxDestroyAddressFile to remove it from the system. This routine
+ can only be called when we are synchronized (inside an IPX_SYNC_START/
+ IPX_SYNC_END pair, with a lock held, or in an indication).
+
+Arguments:
+
+ AddressFile - Pointer to a transport address file object.
+
+Return Value:
+
+ none.
+
+--*/
+
+{
+ ULONG oldvalue;
+
+ oldvalue = IPX_ADD_ULONG (
+ &AddressFile->ReferenceCount,
+ (ULONG)-1,
+ AddressFile->AddressLock);
+
+ //
+ // If we have deleted all references to this address file, then we can
+ // destroy the object. It is okay to have already released the spin
+ // lock at this point because there is no possible way that another
+ // stream of execution has access to the address any longer.
+ //
+
+ CTEAssert (oldvalue > 0);
+
+ if (oldvalue == 1) {
+ IpxDestroyAddressFile (AddressFile);
+ }
+
+} /* IpxDerefAddressFileSync */
+#endif
+
+
+PADDRESS
+IpxLookupAddress(
+ IN PDEVICE Device,
+ IN USHORT Socket
+ )
+
+/*++
+
+Routine Description:
+
+ This routine scans the transport addresses defined for the given
+ device context and compares them with the specified NETWORK
+ NAME values. If an exact match is found, then a pointer to the
+ ADDRESS object is returned, and as a side effect, the reference
+ count to the address object is incremented. If the address is not
+ found, then NULL is returned.
+
+ NOTE: This routine must be called with the Device
+ spinlock held.
+
+Arguments:
+
+ Device - Pointer to the device object and its extension.
+
+ Socket - The socket to look up.
+
+Return Value:
+
+ Pointer to the ADDRESS object found, or NULL if not found.
+
+--*/
+
+{
+ PADDRESS Address;
+ PLIST_ENTRY p;
+ ULONG Hash = IPX_HASH_SOCKET (Socket);
+
+ p = Device->AddressDatabases[Hash].Flink;
+
+ for (p = Device->AddressDatabases[Hash].Flink;
+ p != &Device->AddressDatabases[Hash];
+ p = p->Flink) {
+
+ Address = CONTAINING_RECORD (p, ADDRESS, Linkage);
+
+ if (Address->Stopping) {
+ continue;
+ }
+
+ if (Address->Socket == Socket) {
+
+ //
+ // We found the match. Bump the reference count on the address, and
+ // return a pointer to the address object for the caller to use.
+ //
+
+ IpxReferenceAddressLock (Address, AREF_LOOKUP);
+ return Address;
+
+ }
+
+ }
+
+ //
+ // The specified address was not found.
+ //
+
+ return NULL;
+
+} /* IpxLookupAddress */
+
+
+NTSTATUS
+IpxStopAddressFile(
+ IN PADDRESS_FILE AddressFile
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is called to terminate all activity on an AddressFile and
+ destroy the object. We remove every connection and datagram associated
+ with this addressfile from the address database and terminate their
+ activity. Then, if there are no other outstanding addressfiles open on
+ this address, the address will go away.
+
+Arguments:
+
+ AddressFile - pointer to the addressFile to be stopped
+
+Return Value:
+
+ STATUS_SUCCESS if all is well, STATUS_INVALID_HANDLE if the request
+ is not for a real address.
+
+--*/
+
+{
+ CTELockHandle LockHandle;
+ PREQUEST Request;
+ PADDRESS Address = AddressFile->Address;
+ PLIST_ENTRY p;
+ KIRQL irql;
+
+
+ IoAcquireCancelSpinLock( &irql );
+ CTEGetLock (&Address->Lock, &LockHandle);
+
+ if (AddressFile->State == ADDRESSFILE_STATE_CLOSING) {
+ CTEFreeLock (&Address->Lock, LockHandle);
+ IoReleaseCancelSpinLock( irql );
+ return STATUS_SUCCESS;
+ }
+
+
+ AddressFile->State = ADDRESSFILE_STATE_CLOSING;
+
+ while (!(IsListEmpty(&AddressFile->ReceiveDatagramQueue))) {
+
+ p = RemoveHeadList (&AddressFile->ReceiveDatagramQueue);
+ Request = LIST_ENTRY_TO_REQUEST (p);
+
+ REQUEST_INFORMATION(Request) = 0;
+ REQUEST_STATUS(Request) = STATUS_NETWORK_NAME_DELETED;
+ IoSetCancelRoutine (Request, (PDRIVER_CANCEL)NULL);
+
+ CTEFreeLock(&Address->Lock, LockHandle);
+ IoReleaseCancelSpinLock( irql );
+
+ IpxCompleteRequest (Request);
+ IpxFreeRequest (Device, Request);
+
+ IpxDereferenceAddressFile (AddressFile, AFREF_RCV_DGRAM);
+
+ IoAcquireCancelSpinLock( &irql );
+ CTEGetLock(&Address->Lock, &LockHandle);
+
+ }
+
+ CTEFreeLock(&Address->Lock, LockHandle);
+ IoReleaseCancelSpinLock( irql );
+
+} /* IpxStopAddressFile */
+
+
+NTSTATUS
+IpxCloseAddressFile(
+ IN PDEVICE Device,
+ IN PREQUEST Request
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is called to close the addressfile pointed to by a file
+ object. If there is any activity to be run down, we will run it down
+ before we terminate the addressfile. We remove every connection and
+ datagram associated with this addressfile from the address database
+ and terminate their activity. Then, if there are no other outstanding
+ addressfiles open on this address, the address will go away.
+
+Arguments:
+
+ Request - the close request.
+
+Return Value:
+
+ STATUS_SUCCESS if all is well, STATUS_INVALID_HANDLE if the
+ request does not point to a real address.
+
+--*/
+
+{
+ PADDRESS Address;
+ PADDRESS_FILE AddressFile;
+ CTELockHandle LockHandle;
+
+ AddressFile = (PADDRESS_FILE)REQUEST_OPEN_CONTEXT(Request);
+ AddressFile->CloseRequest = Request;
+
+ //
+ // We assume that addressFile has already been verified
+ // at this point.
+ //
+
+ Address = AddressFile->Address;
+ CTEAssert (Address);
+
+ //
+ // Remove us from the access info for this address.
+ //
+
+ ExAcquireResourceExclusive (&Device->AddressResource, TRUE);
+#ifdef ISN_NT
+ IoRemoveShareAccess (AddressFile->FileObject, &Address->u.ShareAccess);
+#endif
+ ExReleaseResource (&Device->AddressResource);
+
+ //
+ // If this address file had broadcasts enabled, turn it off.
+ //
+
+ CTEGetLock (&Device->Lock, &LockHandle);
+ if (AddressFile->EnableBroadcast) {
+ AddressFile->EnableBroadcast = FALSE;
+ IpxRemoveBroadcast (Device);
+ }
+ CTEFreeLock (&Device->Lock, LockHandle);
+
+ IpxStopAddressFile (AddressFile);
+ IpxDereferenceAddressFile (AddressFile, AFREF_CREATE);
+
+ return STATUS_PENDING;
+
+} /* IpxCloseAddressFile */
+
+