summaryrefslogtreecommitdiffstats
path: root/private/ntos/tdi/isn/spx/spxbind.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/isn/spx/spxbind.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/isn/spx/spxbind.c')
-rw-r--r--private/ntos/tdi/isn/spx/spxbind.c602
1 files changed, 602 insertions, 0 deletions
diff --git a/private/ntos/tdi/isn/spx/spxbind.c b/private/ntos/tdi/isn/spx/spxbind.c
new file mode 100644
index 000000000..ba46eb7a9
--- /dev/null
+++ b/private/ntos/tdi/isn/spx/spxbind.c
@@ -0,0 +1,602 @@
+/*++
+
+Copyright (c) 1989-1993 Microsoft Corporation
+
+Module Name:
+
+ spxbind.c
+
+Abstract:
+
+ This module contains the code to bind to the IPX transport, as well as the
+ indication routines for the IPX transport not including the send/recv ones.
+
+Author:
+
+ Stefan Solomon (stefans) Original Version
+ Nikhil Kamkolkar (nikhilk) 11-November-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+// Define module number for event logging entries
+#define FILENUM SPXBIND
+
+VOID
+SpxStatus (
+ IN USHORT NicId,
+ IN NDIS_STATUS GeneralStatus,
+ IN PVOID StatusBuffer,
+ IN UINT StatusBufferLength);
+
+VOID
+SpxFindRouteComplete (
+ IN PIPX_FIND_ROUTE_REQUEST FindRouteRequest,
+ IN BOOLEAN FoundRoute);
+
+VOID
+SpxScheduleRoute (
+ IN PIPX_ROUTE_ENTRY RouteEntry);
+
+VOID
+SpxLineDown (
+ IN USHORT NicId,
+ IN ULONG FwdAdapterContext);
+
+VOID
+SpxLineUp (
+ IN USHORT NicId,
+ IN PIPX_LINE_INFO LineInfo,
+ IN NDIS_MEDIUM DeviceType,
+ IN PVOID ConfigurationData);
+
+VOID
+SpxFindRouteComplete (
+ IN PIPX_FIND_ROUTE_REQUEST FindRouteRequest,
+ IN BOOLEAN FoundRoute);
+
+#if defined(_PNP_POWER)
+VOID
+SpxPnPNotification(
+ IN IPX_PNP_OPCODE OpCode,
+ IN PVOID PnPData
+ );
+#endif _PNP_POWER
+
+#if defined(_PNP_POWER)
+//
+// globals and externs
+//
+extern CTELock spxTimerLock;
+extern LARGE_INTEGER spxTimerTick;
+extern KTIMER spxTimer;
+extern KDPC spxTimerDpc;
+extern BOOLEAN spxTimerStopped;
+#endif _PNP_POWER
+
+NTSTATUS
+SpxInitBindToIpx(
+ VOID
+ )
+
+{
+ NTSTATUS status;
+ IO_STATUS_BLOCK ioStatusBlock;
+ OBJECT_ATTRIBUTES objectAttr;
+ PIPX_INTERNAL_BIND_INPUT pBindInput;
+ PIPX_INTERNAL_BIND_OUTPUT pBindOutput;
+
+ InitializeObjectAttributes(
+ &objectAttr,
+ &IpxDeviceName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ status = NtCreateFile(
+ &IpxHandle,
+ SYNCHRONIZE | GENERIC_READ,
+ &objectAttr,
+ &ioStatusBlock,
+ NULL,
+ FILE_ATTRIBUTE_NORMAL,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ FILE_OPEN,
+ FILE_SYNCHRONOUS_IO_NONALERT,
+ NULL,
+ 0L);
+
+ if (!NT_SUCCESS(status)) {
+ return status;
+ }
+
+ if ((pBindInput = CTEAllocMem(sizeof(IPX_INTERNAL_BIND_INPUT))) == NULL) {
+ NtClose(IpxHandle);
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ // Fill in our bind data
+#if defined(_PNP_POWER)
+ pBindInput->Version = ISN_VERSION;
+#else
+ pBindInput->Version = 1;
+#endif _PNP_POWER
+ pBindInput->Identifier = IDENTIFIER_SPX;
+ pBindInput->BroadcastEnable = FALSE;
+ pBindInput->LookaheadRequired = IPX_HDRSIZE;
+ pBindInput->ProtocolOptions = 0;
+ pBindInput->ReceiveHandler = SpxReceive;
+ pBindInput->ReceiveCompleteHandler = SpxReceiveComplete;
+ pBindInput->StatusHandler = SpxStatus;
+ pBindInput->SendCompleteHandler = SpxSendComplete;
+ pBindInput->TransferDataCompleteHandler = SpxTransferDataComplete;
+ pBindInput->FindRouteCompleteHandler = SpxFindRouteComplete;
+ pBindInput->LineUpHandler = SpxLineUp;
+ pBindInput->LineDownHandler = SpxLineDown;
+ pBindInput->ScheduleRouteHandler = SpxScheduleRoute;
+#if defined(_PNP_POWER)
+ pBindInput->PnPHandler = SpxPnPNotification;
+#endif _PNP_POWER
+
+
+ // First get the length for the output buffer.
+ status = NtDeviceIoControlFile(
+ IpxHandle, // HANDLE to File
+ NULL, // HANDLE to Event
+ NULL, // ApcRoutine
+ NULL, // ApcContext
+ &ioStatusBlock, // IO_STATUS_BLOCK
+ IOCTL_IPX_INTERNAL_BIND, // IoControlCode
+ pBindInput, // Input Buffer
+ sizeof(IPX_INTERNAL_BIND_INPUT), // Input Buffer Length
+ NULL, // Output Buffer
+ 0);
+
+ if (status == STATUS_PENDING) {
+ status = NtWaitForSingleObject(
+ IpxHandle,
+ (BOOLEAN)FALSE,
+ NULL);
+ }
+
+ if (status != STATUS_BUFFER_TOO_SMALL) {
+ CTEFreeMem(pBindInput);
+ NtClose(IpxHandle);
+ return(STATUS_INVALID_PARAMETER);
+ }
+
+ if ((pBindOutput = CTEAllocMem(ioStatusBlock.Information)) == NULL) {
+ CTEFreeMem(pBindInput);
+ NtClose(IpxHandle);
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ status = NtDeviceIoControlFile(
+ IpxHandle, // HANDLE to File
+ NULL, // HANDLE to Event
+ NULL, // ApcRoutine
+ NULL, // ApcContext
+ &ioStatusBlock, // IO_STATUS_BLOCK
+ IOCTL_IPX_INTERNAL_BIND, // IoControlCode
+ pBindInput, // Input Buffer
+ sizeof(IPX_INTERNAL_BIND_INPUT), // Input Buffer Length
+ pBindOutput, // Output Buffer
+ ioStatusBlock.Information);
+
+ if (status == STATUS_PENDING) {
+ status = NtWaitForSingleObject(
+ IpxHandle,
+ (BOOLEAN)FALSE,
+ NULL);
+ }
+
+ if (status == STATUS_SUCCESS) {
+
+ // Get all the info from the bind output buffer and save in
+ // appropriate places.
+ IpxLineInfo = pBindOutput->LineInfo;
+ IpxMacHdrNeeded = pBindOutput->MacHeaderNeeded;
+ IpxInclHdrOffset = pBindOutput->IncludedHeaderOffset;
+
+ IpxSendPacket = pBindOutput->SendHandler;
+ IpxFindRoute = pBindOutput->FindRouteHandler;
+ IpxQuery = pBindOutput->QueryHandler;
+ IpxTransferData = pBindOutput->TransferDataHandler;
+
+#if !defined(_PNP_POWER)
+ // Copy over the network node info.
+ RtlCopyMemory(
+ SpxDevice->dev_Network,
+ pBindOutput->Network,
+ IPX_NET_LEN);
+
+ RtlCopyMemory(
+ SpxDevice->dev_Node,
+ pBindOutput->Node,
+ IPX_NODE_LEN);
+
+
+ DBGPRINT(TDI, INFO,
+ ("SpxInitBindToIpx: Ipx Net %lx\n",
+ *(UNALIGNED ULONG *)SpxDevice->dev_Network));
+
+ //
+ // Find out how many adapters IPX has, if this fails
+ // just assume one.
+ //
+
+ if ((*IpxQuery)(
+ IPX_QUERY_MAXIMUM_NIC_ID,
+ 0,
+ &SpxDevice->dev_Adapters,
+ sizeof(USHORT),
+ NULL) != STATUS_SUCCESS) {
+
+ SpxDevice->dev_Adapters = 1;
+
+ }
+#endif !_PNP_POWER
+ } else {
+
+ NtClose(IpxHandle);
+ status = STATUS_INVALID_PARAMETER;
+ }
+ CTEFreeMem(pBindInput);
+ CTEFreeMem(pBindOutput);
+
+ return status;
+}
+
+
+
+
+VOID
+SpxUnbindFromIpx(
+ VOID
+ )
+
+{
+ NtClose(IpxHandle);
+ return;
+}
+
+
+
+
+VOID
+SpxStatus(
+ IN USHORT NicId,
+ IN NDIS_STATUS GeneralStatus,
+ IN PVOID StatusBuffer,
+ IN UINT StatusBufferLength
+ )
+
+{
+ DBGPRINT(RECEIVE, ERR,
+ ("SpxStatus: CALLED WITH %lx\n",
+ GeneralStatus));
+
+ return;
+}
+
+
+
+VOID
+SpxFindRouteComplete (
+ IN PIPX_FIND_ROUTE_REQUEST FindRouteRequest,
+ IN BOOLEAN FoundRoute
+ )
+
+{
+ CTELockHandle lockHandle;
+ PSPX_FIND_ROUTE_REQUEST pSpxFrReq = (PSPX_FIND_ROUTE_REQUEST)FindRouteRequest;
+ PSPX_CONN_FILE pSpxConnFile = (PSPX_CONN_FILE)pSpxFrReq->fr_Ctx;
+
+ // This will be on a connection. Grab the lock, check the state and go from
+ // there.
+ if (pSpxConnFile == NULL)
+ {
+ // Should this ever happen?
+ KeBugCheck(0);
+ return;
+ }
+
+ // Check the state. The called routines release the lock, remove the reference.
+ CTEGetLock(&pSpxConnFile->scf_Lock, &lockHandle);
+ if (SPX_CONN_CONNECTING(pSpxConnFile))
+ {
+ // We are doing an active connect!
+ SpxConnConnectFindRouteComplete(
+ pSpxConnFile,
+ pSpxFrReq,
+ FoundRoute,
+ lockHandle);
+ }
+ else // For all others call active
+ {
+ SpxConnActiveFindRouteComplete(
+ pSpxConnFile,
+ pSpxFrReq,
+ FoundRoute,
+ lockHandle);
+ }
+
+ // Free the find route request.
+ SpxFreeMemory(pSpxFrReq);
+
+ return;
+}
+
+
+
+
+VOID
+SpxLineUp (
+ IN USHORT NicId,
+ IN PIPX_LINE_INFO LineInfo,
+ IN NDIS_MEDIUM DeviceType,
+ IN PVOID ConfigurationData
+ )
+
+{
+ // With PnP, our local address is changed when we get PnP
+ // notification.
+#if !defined(_PNP_POWER)
+
+ //
+ // If we get a line up for NicId 0, it means our local
+ // network number has changed, re-query from IPX.
+ //
+
+ if (NicId == 0) {
+
+ TDI_ADDRESS_IPX IpxAddress;
+
+ if ((*IpxQuery)(
+ IPX_QUERY_IPX_ADDRESS,
+ 0,
+ &IpxAddress,
+ sizeof(TDI_ADDRESS_IPX),
+ NULL) == STATUS_SUCCESS) {
+
+ RtlCopyMemory(
+ SpxDevice->dev_Network,
+ &IpxAddress.NetworkAddress,
+ IPX_NET_LEN);
+
+ DBGPRINT(TDI, INFO,
+ ("SpxLineUp: Ipx Net %lx\n",
+ *(UNALIGNED ULONG *)SpxDevice->dev_Network));
+
+ //
+ // The node shouldn't change!
+ //
+
+ if (!RtlEqualMemory(
+ SpxDevice->dev_Node,
+ IpxAddress.NodeAddress,
+ IPX_NODE_LEN)) {
+
+ DBGPRINT(TDI, ERR,
+ ("SpxLineUp: Node address has changed\n"));
+ }
+ }
+
+ } else {
+
+ DBGPRINT(RECEIVE, ERR,
+ ("SpxLineUp: CALLED WITH %lx\n",
+ NicId));
+ }
+
+ return;
+#endif !_PNP_POWER
+
+}
+
+
+
+
+VOID
+SpxLineDown (
+ IN USHORT NicId,
+ IN ULONG FwdAdapterContext
+ )
+
+{
+ DBGPRINT(RECEIVE, ERR,
+ ("SpxLineDown: CALLED WITH %lx\n",
+ NicId));
+
+ return;
+}
+
+
+
+
+VOID
+SpxScheduleRoute (
+ IN PIPX_ROUTE_ENTRY RouteEntry
+ )
+
+{
+ DBGPRINT(RECEIVE, ERR,
+ ("SpxScheduleRoute: CALLED WITH %lx\n",
+ RouteEntry));
+
+ return;
+}
+
+#if defined(_PNP_POWER)
+VOID
+SpxPnPNotification(
+ IN IPX_PNP_OPCODE OpCode,
+ IN PVOID PnPData
+ )
+
+/*++
+
+Routine Description:
+
+ This function receives the notification about PnP events from IPX
+
+Arguments:
+
+ OpCode - Type of the PnP event
+
+ PnPData - Data associated with this event.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ USHORT MaximumNicId = 0;
+ CTELockHandle LockHandle;
+ NTSTATUS Status;
+ PDEVICE Device = SpxDevice;
+ UNICODE_STRING UnicodeDeviceName;
+
+ DBGPRINT(DEVICE, DBG,("Received a pnp notification, opcode %d\n",OpCode));
+
+ switch( OpCode ) {
+ case IPX_PNP_ADD_DEVICE : {
+ CTELockHandle TimerLockHandle;
+ IPX_PNP_INFO UNALIGNED *PnPInfo = (IPX_PNP_INFO UNALIGNED *)PnPData;
+
+
+ CTEGetLock (&Device->dev_Lock, &LockHandle);
+
+ if ( PnPInfo->FirstORLastDevice ) {
+ CTEAssert( PnPInfo->NewReservedAddress );
+ CTEAssert( Device->dev_State != DEVICE_STATE_OPEN );
+
+ *(UNALIGNED ULONG *)Device->dev_Network = PnPInfo->NetworkAddress;
+ RtlCopyMemory( Device->dev_Node, PnPInfo->NodeAddress, 6);
+
+ //
+ // Start the timer. It is possible that the timer
+ // was still running or we are still in the timer dpc
+ // from the previous ADD_DEVICE - DELETE_DEVICE execution
+ // cycle. But it is ok simply restart this, because
+ // KeSetTimer implicitly cancels the previous Dpc.
+ //
+
+ CTEGetLock(&spxTimerLock, &TimerLockHandle);
+ spxTimerStopped = FALSE;
+ CTEFreeLock(&spxTimerLock, TimerLockHandle);
+ KeSetTimer(&spxTimer,
+ spxTimerTick,
+ &spxTimerDpc);
+
+
+ Device->dev_State = DEVICE_STATE_OPEN;
+
+
+ CTEAssert( !Device->dev_Adapters );
+
+ IpxLineInfo.MaximumSendSize = PnPInfo->LineInfo.MaximumSendSize;
+ IpxLineInfo.MaximumPacketSize = PnPInfo->LineInfo.MaximumPacketSize;
+ // set the provider info
+ SpxDevice->dev_ProviderInfo.MaximumLookaheadData = IpxLineInfo.MaximumPacketSize;
+ // Set the window size in statistics
+ SpxDevice->dev_Stat.MaximumSendWindow =
+ SpxDevice->dev_Stat.AverageSendWindow = PARAM(CONFIG_WINDOW_SIZE) *
+ IpxLineInfo.MaximumSendSize;
+
+ }else {
+ IpxLineInfo.MaximumSendSize = PnPInfo->LineInfo.MaximumSendSize;
+ // Set the window size in statistics
+ SpxDevice->dev_Stat.MaximumSendWindow =
+ SpxDevice->dev_Stat.AverageSendWindow = PARAM(CONFIG_WINDOW_SIZE) *
+ IpxLineInfo.MaximumSendSize;
+
+ }
+
+ Device->dev_Adapters++;
+ CTEFreeLock ( &Device->dev_Lock, LockHandle );
+
+ //
+ // Notify the TDI clients about the device creation
+ //
+ if ( PnPInfo->FirstORLastDevice ) {
+ UnicodeDeviceName.Buffer = Device->dev_DeviceName;
+ UnicodeDeviceName.MaximumLength = Device->dev_DeviceNameLen;
+ UnicodeDeviceName.Length = Device->dev_DeviceNameLen - sizeof(WCHAR);
+
+ if ( !NT_SUCCESS( TdiRegisterDeviceObject(
+ &UnicodeDeviceName,
+ &Device->dev_TdiRegistrationHandle ) )) {
+ DBGPRINT(TDI,ERR, ("Failed to register Spx Device with TDI\n"));
+ }
+ }
+
+ break;
+ }
+ case IPX_PNP_DELETE_DEVICE : {
+
+ IPX_PNP_INFO UNALIGNED *PnPInfo = (IPX_PNP_INFO UNALIGNED *)PnPData;
+
+ CTEGetLock (&Device->dev_Lock, &LockHandle);
+
+ CTEAssert( Device->dev_Adapters );
+ Device->dev_Adapters--;
+
+ if ( PnPInfo->FirstORLastDevice ) {
+ Device->dev_State = DEVICE_STATE_LOADED;
+ Device->dev_Adapters = 0;
+ }
+
+ IpxLineInfo.MaximumSendSize = PnPInfo->LineInfo.MaximumSendSize;
+ CTEFreeLock ( &Device->dev_Lock, LockHandle );
+
+ if ( PnPInfo->FirstORLastDevice ) {
+ SpxTimerFlushAndStop();
+ //
+ // inform tdi clients about the device deletion
+ //
+ if ( !NT_SUCCESS( TdiDeregisterDeviceObject(
+ Device->dev_TdiRegistrationHandle ) )) {
+ DBGPRINT(TDI,ERR, ("Failed to Deregister Spx Device with TDI\n"));
+ }
+ }
+ //
+ // TBD: call ExNotifyCallback
+ //
+
+ break;
+ }
+ case IPX_PNP_ADDRESS_CHANGE: {
+ IPX_PNP_INFO UNALIGNED *PnPInfo = (IPX_PNP_INFO UNALIGNED *)PnPData;
+
+ CTEGetLock (&Device->dev_Lock, &LockHandle);
+ CTEAssert( PnPInfo->NewReservedAddress );
+
+ *(UNALIGNED ULONG *)Device->dev_Network = PnPInfo->NetworkAddress;
+ RtlCopyMemory( Device->dev_Node, PnPInfo->NodeAddress, 6);
+
+ CTEFreeLock ( &Device->dev_Lock, LockHandle );
+ break;
+ }
+ case IPX_PNP_TRANSLATE_DEVICE:
+ break;
+ case IPX_PNP_TRANSLATE_ADDRESS:
+ break;
+ default:
+ CTEAssert( FALSE );
+ }
+} /* NbiPnPNotification */
+
+#endif _PNP_POWER