summaryrefslogtreecommitdiffstats
path: root/private/ntos/tdi/isnp/ipx/device.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/device.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/device.c')
-rw-r--r--private/ntos/tdi/isnp/ipx/device.c599
1 files changed, 599 insertions, 0 deletions
diff --git a/private/ntos/tdi/isnp/ipx/device.c b/private/ntos/tdi/isnp/ipx/device.c
new file mode 100644
index 000000000..f2d9d19f4
--- /dev/null
+++ b/private/ntos/tdi/isnp/ipx/device.c
@@ -0,0 +1,599 @@
+/*++
+
+Copyright (c) 1989-1993 Microsoft Corporation
+
+Module Name:
+
+ device.c
+
+Abstract:
+
+ This module contains code which implements the DEVICE_CONTEXT object.
+ Routines are provided to reference, and dereference transport device
+ context objects.
+
+ The transport device context object is a structure which contains a
+ system-defined DEVICE_OBJECT followed by information which is maintained
+ by the transport provider, called the context.
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Sanjay Anand (SanjayAn) - 22-Sept-1995
+ BackFill optimization changes added under #if BACK_FILL
+
+--*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,IpxCreateDevice)
+#endif
+
+
+
+VOID
+IpxRefDevice(
+ IN PDEVICE Device
+ )
+
+/*++
+
+Routine Description:
+
+ This routine increments the reference count on a device context.
+
+Arguments:
+
+ Device - Pointer to a transport device context object.
+
+Return Value:
+
+ none.
+
+--*/
+
+{
+ CTEAssert (Device->ReferenceCount > 0); // not perfect, but...
+
+ (VOID)InterlockedIncrement(&Device->ReferenceCount);
+
+} /* IpxRefDevice */
+
+
+VOID
+IpxDerefDevice(
+ IN PDEVICE Device
+ )
+
+/*++
+
+Routine Description:
+
+ This routine dereferences a device context by decrementing the
+ reference count contained in the structure. Currently, we don't
+ do anything special when the reference count drops to zero, but
+ we could dynamically unload stuff then.
+
+Arguments:
+
+ Device - Pointer to a transport device context object.
+
+Return Value:
+
+ none.
+
+--*/
+
+{
+ LONG result;
+
+ result = InterlockedDecrement (&Device->ReferenceCount);
+
+ CTEAssert (result >= 0);
+
+ if (result == 0) {
+ IpxDestroyDevice (Device);
+ }
+
+} /* IpxDerefDevice */
+
+
+NTSTATUS
+IpxCreateDevice(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING DeviceName,
+ IN ULONG SegmentCount,
+ IN OUT PDEVICE *DevicePtr
+ )
+
+/*++
+
+Routine Description:
+
+ This routine creates and initializes a device context structure.
+
+Arguments:
+
+
+ DriverObject - pointer to the IO subsystem supplied driver object.
+
+ Device - Pointer to a pointer to a transport device context object.
+
+ SegmentCount - The number of segments in the RIP router table.
+
+ DeviceName - pointer to the name of the device this device object points to.
+
+Return Value:
+
+ STATUS_SUCCESS if all is well; STATUS_INSUFFICIENT_RESOURCES otherwise.
+
+--*/
+
+{
+ NTSTATUS status;
+ PDEVICE_OBJECT deviceObject;
+ PDEVICE Device;
+ ULONG DeviceSize;
+ ULONG LocksOffset;
+ ULONG SegmentsOffset;
+ ULONG DeviceNameOffset;
+ UINT i;
+
+
+ //
+ // Create the device object for the sample transport, allowing
+ // room at the end for the device name to be stored (for use
+ // in logging errors) and the RIP fields.
+ //
+
+ DeviceSize = sizeof(DEVICE) +
+ (sizeof(CTELock) * SegmentCount) +
+ (sizeof(ROUTER_SEGMENT) * SegmentCount) +
+ DeviceName->Length + sizeof(UNICODE_NULL);
+
+ status = IoCreateDevice(
+ DriverObject,
+ DeviceSize,
+ DeviceName,
+ FILE_DEVICE_TRANSPORT,
+ 0,
+ FALSE,
+ &deviceObject);
+
+ if (!NT_SUCCESS(status)) {
+ IPX_DEBUG(DEVICE, ("Create device %ws failed %lx\n", DeviceName->Buffer, status));
+ return status;
+ }
+
+ deviceObject->Flags |= DO_DIRECT_IO;
+
+ Device = (PDEVICE)deviceObject->DeviceExtension;
+
+ IPX_DEBUG(DEVICE, ("Create device %ws succeeded %lx\n", DeviceName->Buffer));
+
+ //
+ // Initialize our part of the device context.
+ //
+
+ RtlZeroMemory(
+ ((PUCHAR)Device) + sizeof(DEVICE_OBJECT),
+ sizeof(DEVICE) - sizeof(DEVICE_OBJECT));
+
+ Device->DeviceObject = deviceObject;
+
+ LocksOffset = sizeof(DEVICE);
+ SegmentsOffset = LocksOffset + (sizeof(CTELock) * SegmentCount);
+ DeviceNameOffset = SegmentsOffset + (sizeof(ROUTER_SEGMENT) * SegmentCount);
+
+ //
+ // Set some internal pointers.
+ //
+
+ Device->SegmentLocks = (CTELock *)(((PUCHAR)Device) + LocksOffset);
+ Device->Segments = (PROUTER_SEGMENT)(((PUCHAR)Device) + SegmentsOffset);
+ Device->SegmentCount = SegmentCount;
+
+ for (i = 0; i < SegmentCount; i++) {
+
+ CTEInitLock (&Device->SegmentLocks[i]);
+ InitializeListHead (&Device->Segments[i].WaitingForRoute);
+ InitializeListHead (&Device->Segments[i].FindWaitingForRoute);
+ InitializeListHead (&Device->Segments[i].WaitingLocalTarget);
+ InitializeListHead (&Device->Segments[i].WaitingReripNetnum);
+ InitializeListHead (&Device->Segments[i].Entries);
+ Device->Segments[i].EnumerateLocation = &Device->Segments[i].Entries;
+
+ }
+
+ //
+ // Copy over the device name.
+ //
+
+ Device->DeviceNameLength = DeviceName->Length + sizeof(WCHAR);
+ Device->DeviceName = (PWCHAR)(((PUCHAR)Device) + DeviceNameOffset);
+ RtlCopyMemory(
+ Device->DeviceName,
+ DeviceName->Buffer,
+ DeviceName->Length);
+ Device->DeviceName[DeviceName->Length/sizeof(WCHAR)] = UNICODE_NULL;
+
+ //
+ // Initialize the reference count.
+ //
+
+ Device->ReferenceCount = 1;
+#if DBG
+ Device->RefTypes[DREF_CREATE] = 1;
+#endif
+
+#if DBG
+ RtlCopyMemory(Device->Signature1, "IDC1", 4);
+ RtlCopyMemory(Device->Signature2, "IDC2", 4);
+#endif
+
+ Device->Information.Version = 0x0100;
+ Device->Information.MaxSendSize = 0; // no sends allowed
+ Device->Information.MaxConnectionUserData = 0;
+ Device->Information.ServiceFlags =
+ TDI_SERVICE_CONNECTIONLESS_MODE | TDI_SERVICE_BROADCAST_SUPPORTED |
+ TDI_SERVICE_ROUTE_DIRECTED;
+ Device->Information.MinimumLookaheadData = 128;
+ Device->Information.NumberOfResources = IPX_TDI_RESOURCES;
+ KeQuerySystemTime (&Device->Information.StartTime);
+
+ Device->Statistics.Version = 0x0100;
+
+#if 0
+ //
+ // These will be filled in after all the binding is done.
+ //
+
+ Device->Information.MaxDatagramSize = 0;
+ Device->Information.MaximumLookaheadData = 0;
+
+
+ Device->SourceRoutingUsed = FALSE;
+ Device->SourceRoutingTime = 0;
+ Device->RipPacketCount = 0;
+
+ Device->RipShortTimerActive = FALSE;
+ Device->RipSendTime = 0;
+#endif
+
+
+ //
+ // Initialize the resource that guards address ACLs.
+ //
+
+ ExInitializeResource (&Device->AddressResource);
+
+#ifdef _PNP_POWER
+ //
+ // Init the resource that guards the binding array/indices
+ //
+ CTEInitLock (&Device->BindAccessLock);
+#endif _PNP_POWER
+
+ InitializeListHead (&Device->WaitingRipPackets);
+ CTEInitTimer (&Device->RipShortTimer);
+ CTEInitTimer (&Device->RipLongTimer);
+
+ CTEInitTimer (&Device->SourceRoutingTimer);
+
+ //
+ // initialize the various fields in the device context
+ //
+
+ CTEInitLock (&Device->Interlock);
+ CTEInitLock (&Device->Lock);
+ CTEInitLock (&Device->SListsLock);
+
+ Device->ControlChannelIdentifier.QuadPart = 1;
+
+ InitializeListHead (&Device->GlobalSendPacketList);
+ InitializeListHead (&Device->GlobalReceivePacketList);
+ InitializeListHead (&Device->GlobalReceiveBufferList);
+#if BACK_FILL
+ InitializeListHead (&Device->GlobalBackFillPacketList);
+#endif
+
+ InitializeListHead (&Device->AddressNotifyQueue);
+ InitializeListHead (&Device->LineChangeQueue);
+
+ for (i = 0; i < IPX_ADDRESS_HASH_COUNT; i++) {
+ InitializeListHead (&Device->AddressDatabases[i]);
+ }
+
+#if BACK_FILL
+ InitializeListHead (&Device->BackFillPoolList);
+#endif
+ InitializeListHead (&Device->SendPoolList);
+ InitializeListHead (&Device->ReceivePoolList);
+
+#ifdef _PNP_POWER
+ InitializeListHead (&Device->BindingPoolList);
+#endif
+
+ ExInitializeSListHead (&Device->SendPacketList);
+ ExInitializeSListHead (&Device->ReceivePacketList);
+#if BACK_FILL
+ ExInitializeSListHead (&Device->BackFillPacketList);
+#endif
+
+#ifdef _PNP_POWER
+ ExInitializeSListHead (&Device->BindingList);
+#endif
+
+#if 0
+ Device->MemoryUsage = 0;
+ Device->SendPacketList.Next = NULL;
+ Device->ReceivePacketList.Next = NULL;
+ Device->Bindings = NULL;
+ Device->BindingCount = 0;
+#endif
+
+ KeQuerySystemTime (&Device->IpxStartTime);
+
+ Device->State = DEVICE_STATE_CLOSED;
+ Device->AutoDetectState = AUTO_DETECT_STATE_INIT;
+
+ Device->Type = IPX_DEVICE_SIGNATURE;
+ Device->Size = sizeof (DEVICE);
+
+
+ *DevicePtr = Device;
+ return STATUS_SUCCESS;
+
+} /* IpxCreateDevice */
+
+
+VOID
+IpxDestroyDevice(
+ IN PDEVICE Device
+ )
+
+/*++
+
+Routine Description:
+
+ This routine destroys a device context structure.
+
+Arguments:
+
+ Device - Pointer to a pointer to a transport device context object.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PLIST_ENTRY p;
+ PSINGLE_LIST_ENTRY s;
+ PIPX_SEND_POOL SendPool;
+ PIPX_SEND_PACKET SendPacket;
+ PIPX_RECEIVE_POOL ReceivePool;
+ PIPX_RECEIVE_PACKET ReceivePacket;
+ PIPX_ROUTE_ENTRY RouteEntry;
+ UINT SendPoolSize;
+ UINT ReceivePoolSize;
+ UINT i;
+#if BACK_FILL
+ PIPX_SEND_POOL BackFillPool;
+ UINT BackFillPoolSize;
+ PIPX_SEND_PACKET BackFillPacket;
+#endif
+
+#ifdef _PNP_POWER
+ PIPX_BINDING_POOL BindingPool;
+ UINT BindingPoolSize;
+ PBINDING Binding;
+#endif
+
+ IPX_DEBUG (DEVICE, ("Destroy device %lx\n", Device));
+
+ //
+ // Take all the packets out of its pools.
+ //
+
+#if _PNP_POWER
+ BindingPoolSize = FIELD_OFFSET (IPX_BINDING_POOL, Bindings[0]) +
+ (sizeof(BINDING) * Device->InitBindings);
+
+ while (!IsListEmpty (&Device->BindingPoolList)) {
+
+ p = RemoveHeadList (&Device->BindingPoolList);
+ BindingPool = CONTAINING_RECORD (p, IPX_BINDING_POOL, Linkage);
+ IPX_DEBUG (PACKET, ("Free binding pool %lx\n", BindingPool));
+ IpxFreeMemory (BindingPool, BindingPoolSize, MEMORY_PACKET, "BindingPool");
+
+ }
+#endif
+
+#ifdef IPX_OWN_PACKETS
+
+#if BACK_FILL
+ BackFillPoolSize = FIELD_OFFSET (IPX_SEND_POOL, Packets[0]) +
+ (sizeof(IPX_SEND_PACKET) * Device->InitDatagrams);
+ while (!IsListEmpty (&Device->BackFillPoolList)) {
+
+ p = RemoveHeadList (&Device->BackFillPoolList);
+ BackFillPool = CONTAINING_RECORD (p, IPX_SEND_POOL, Linkage);
+
+ for (i = 0; i < BackFillPool->PacketCount; i++) {
+ BackFillPacket = &BackFillPool->Packets[i];
+ IpxDeinitializeBackFillPacket (Device, BackFillPacket);
+ }
+
+ IPX_DEBUG (PACKET, ("Free packet pool %lx\n", BackFillPool));
+ IpxFreeMemory (BackFillPool, BackFillPoolSize, MEMORY_PACKET, "BackPool");
+ }
+#endif
+
+ SendPoolSize = FIELD_OFFSET (IPX_SEND_POOL, Packets[0]) +
+ (sizeof(IPX_SEND_PACKET) * Device->InitDatagrams) +
+ (((IPX_MAXIMUM_MAC + sizeof(IPX_HEADER) + 3) & ~3) * Device->InitDatagrams);
+
+ while (!IsListEmpty (&Device->SendPoolList)) {
+
+ p = RemoveHeadList (&Device->SendPoolList);
+ SendPool = CONTAINING_RECORD (p, IPX_SEND_POOL, Linkage);
+
+ for (i = 0; i < SendPool->PacketCount; i++) {
+
+ SendPacket = &SendPool->Packets[i];
+ IpxDeinitializeSendPacket (Device, SendPacket);
+
+ }
+
+ IPX_DEBUG (PACKET, ("Free packet pool %lx\n", SendPool));
+ IpxFreeMemory (SendPool, SendPoolSize, MEMORY_PACKET, "SendPool");
+ }
+
+ ReceivePoolSize = FIELD_OFFSET (IPX_RECEIVE_POOL, Packets[0]) +
+ (sizeof(IPX_RECEIVE_PACKET) * Device->InitReceivePackets);
+
+ while (!IsListEmpty (&Device->ReceivePoolList)) {
+
+ p = RemoveHeadList (&Device->ReceivePoolList);
+ ReceivePool = CONTAINING_RECORD (p, IPX_RECEIVE_POOL, Linkage);
+
+ for (i = 0; i < ReceivePool->PacketCount; i++) {
+
+ ReceivePacket = &ReceivePool->Packets[i];
+ IpxDeinitializeReceivePacket (Device, ReceivePacket);
+
+ }
+
+ IPX_DEBUG (PACKET, ("Free receive packet pool %lx\n", ReceivePool));
+ IpxFreeMemory (ReceivePool, ReceivePoolSize, MEMORY_PACKET, "ReceivePool");
+ }
+#else
+
+#if BACK_FILL
+
+ while (s = IPX_POP_ENTRY_LIST(&Device->BackFillPacketList, &Device->Lock)) {
+ PIPX_SEND_RESERVED Reserved = CONTAINING_RECORD (s, IPX_SEND_RESERVED, PoolLinkage);
+ IPX_SEND_PACKET BackFillPacket;
+
+ BackFillPacket.Packet = CONTAINING_RECORD (Reserved, NDIS_PACKET, ProtocolReserved[0]);
+
+ IpxDeinitializeBackFillPacket (Device, &BackFillPacket);
+ Device->MemoryUsage -= (FIELD_OFFSET(NDIS_PACKET,ProtocolReserved[0]) + sizeof(IPX_SEND_RESERVED));
+ }
+
+ while (!IsListEmpty (&Device->BackFillPoolList)) {
+
+ p = RemoveHeadList (&Device->BackFillPoolList);
+ BackFillPool = CONTAINING_RECORD (p, IPX_SEND_POOL, Linkage);
+
+ IPX_DEBUG (PACKET, ("Free packet pool %lx\n", BackFillPool));
+ NdisFreePacketPool (BackFillPool->PoolHandle);
+ Device->MemoryUsage -= FIELD_OFFSET(NDIS_PACKET_POOL,Buffer[0]);
+
+ IpxFreeMemory (BackFillPool, sizeof(IPX_SEND_POOL), MEMORY_PACKET, "BafiPool");
+ }
+#endif
+
+ while (s = IPX_POP_ENTRY_LIST(&Device->SendPacketList, &Device->Lock)){
+ PIPX_SEND_RESERVED Reserved = CONTAINING_RECORD (s, IPX_SEND_RESERVED, PoolLinkage);
+ IPX_SEND_PACKET SendPacket;
+ PUCHAR Header = Reserved->Header;
+
+ SendPacket.Packet = CONTAINING_RECORD (Reserved, NDIS_PACKET, ProtocolReserved[0]);
+
+ IpxDeinitializeSendPacket (Device, &SendPacket);
+ Device->MemoryUsage -= (FIELD_OFFSET(NDIS_PACKET,ProtocolReserved[0]) + sizeof(IPX_SEND_RESERVED));
+ }
+
+ while (!IsListEmpty (&Device->SendPoolList)) {
+
+ p = RemoveHeadList (&Device->SendPoolList);
+ SendPool = CONTAINING_RECORD (p, IPX_SEND_POOL, Linkage);
+
+ IPX_DEBUG (PACKET, ("Free packet pool %lx\n", SendPool));
+ NdisFreePacketPool (SendPool->PoolHandle);
+ Device->MemoryUsage -= FIELD_OFFSET(NDIS_PACKET_POOL,Buffer[0]);
+
+ IpxFreeMemory (SendPool->Header, PACKET_HEADER_SIZE * Device->InitDatagrams, MEMORY_PACKET, "SendPool");
+
+ IpxFreeMemory (SendPool, sizeof(IPX_SEND_POOL), MEMORY_PACKET, "SendPool");
+ }
+
+ while (s = IPX_POP_ENTRY_LIST(&Device->ReceivePacketList, &Device->Lock)){
+ PIPX_RECEIVE_RESERVED Reserved = CONTAINING_RECORD (s, IPX_RECEIVE_RESERVED, PoolLinkage);
+ IPX_RECEIVE_PACKET ReceivePacket;
+
+ ReceivePacket.Packet = CONTAINING_RECORD (Reserved, NDIS_PACKET, ProtocolReserved[0]);
+
+ IpxDeinitializeReceivePacket (Device, &ReceivePacket);
+ Device->MemoryUsage -= (FIELD_OFFSET(NDIS_PACKET,ProtocolReserved[0]) + sizeof(IPX_RECEIVE_RESERVED));
+ }
+
+ while (!IsListEmpty (&Device->ReceivePoolList)) {
+
+ p = RemoveHeadList (&Device->ReceivePoolList);
+ ReceivePool = CONTAINING_RECORD (p, IPX_RECEIVE_POOL, Linkage);
+
+ IPX_DEBUG (PACKET, ("Free packet pool %lx\n", ReceivePool));
+ NdisFreePacketPool (ReceivePool->PoolHandle);
+ Device->MemoryUsage -= FIELD_OFFSET(NDIS_PACKET_POOL,Buffer[0]);
+
+ IpxFreeMemory (ReceivePool, sizeof(IPX_RECEIVE_POOL), MEMORY_PACKET, "ReceivePool");
+ }
+
+#endif IPX_OWN_PACKETS
+ //
+ // Destroy all rip table entries.
+ //
+
+ for (i = 0; i < Device->SegmentCount; i++) {
+
+ RouteEntry = RipGetFirstRoute(i);
+ while (RouteEntry != NULL) {
+
+ (VOID)RipDeleteRoute(i, RouteEntry);
+ IpxFreeMemory(RouteEntry, sizeof(IPX_ROUTE_ENTRY), MEMORY_RIP, "RouteEntry");
+ RouteEntry = RipGetNextRoute(i);
+
+ }
+
+ }
+
+ IPX_DEBUG (DEVICE, ("Final memory use is %d\n", Device->MemoryUsage));
+#if DBG
+ for (i = 0; i < MEMORY_MAX; i++) {
+ if (IpxMemoryTag[i].BytesAllocated != 0) {
+ IPX_DEBUG (DEVICE, ("Tag %d: %d bytes left\n", i, IpxMemoryTag[i].BytesAllocated));
+ }
+ }
+#endif
+
+ //
+ // If we are being unloaded then someone is waiting for this
+ // event to finish the cleanup, since we may be at DISPATCH_LEVEL;
+ // otherwise it is during load and we can just kill ourselves here.
+ //
+
+ if (Device->UnloadWaiting) {
+
+ KeSetEvent(
+ &Device->UnloadEvent,
+ 0L,
+ FALSE);
+
+ } else {
+
+ CTEAssert (KeGetCurrentIrql() < DISPATCH_LEVEL);
+ ExDeleteResource (&Device->AddressResource);
+ IoDeleteDevice (Device->DeviceObject);
+ }
+
+} /* IpxDestroyDevice */
+