Example #1
0
//*	TdiQueryInfoEx - Extended TDI query information.
//
//	This is the new TDI query information handler. We take in a TDIObjectID
//	structure, a buffer and length, and some context information, and return
//	the requested information if possible.
//
//	Input:	Request			- The request structure for this command.
//			ID				- The object ID
//			Buffer			- Pointer to buffer to be filled in.
//			Size			- Pointer to size in bytes of Buffer. On exit,
//								filled in with bytes written.
//			Context			- Pointer to context buffer.
//
//	Returns: Status of attempt to get information.
//
TDI_STATUS
TdiQueryInformationEx(PTDI_REQUEST Request, TDIObjectID *ID,
	PNDIS_BUFFER Buffer, uint *Size, void *Context)
{
	uint			BufferSize = *Size;
	uint			InfoSize;
	void			*InfoPtr;
	uint			Fixed;
	CTELockHandle	Handle;
#ifndef VXD	
	CTELock			*LockPtr;
#else
#ifdef DEBUG
	CTELock			*LockPtr;
#endif
#endif
	uint			Offset = 0;
	uchar			InfoBuffer[sizeof(TCPConnTableEntry)];
	uint			BytesRead;
	uint			Valid;
	uint			Entity;
    uint            BytesCopied;

	// First check to see if he's querying for list of entities.
	Entity = ID->toi_entity.tei_entity;
	if (Entity == GENERIC_ENTITY) {
		*Size = 0;
		
		if (ID->toi_class  != INFO_CLASS_GENERIC ||
			ID->toi_type != INFO_TYPE_PROVIDER ||
			ID->toi_id != ENTITY_LIST_ID) {
			return TDI_INVALID_PARAMETER;
		}

		// Make sure we have room for it the list in the buffer.
		InfoSize = EntityCount * sizeof(TDIEntityID);

		if (BufferSize < InfoSize) {
			// Not enough room.
			return TDI_BUFFER_TOO_SMALL;
		}

		*Size = InfoSize;

		// Copy it in, free our temp. buffer, and return success.
		(void)CopyFlatToNdis(Buffer, (uchar *)EntityList, InfoSize, &Offset,
                  &BytesCopied);
		return TDI_SUCCESS;
	}


	//* Check the level. If it can't be for us, pass it down.
#ifndef UDP_ONLY
	if (Entity != CO_TL_ENTITY &&  Entity != CL_TL_ENTITY) {
#else
	if (Entity != CL_TL_ENTITY) {
#endif
			
		// When we support multiple lower entities at this layer we'll have
		// to figure out which one to dispatch to. For now, just pass it
		// straight down.
		return (*LocalNetInfo.ipi_qinfo)(ID, Buffer, Size, Context);
	}

	if (ID->toi_entity.tei_instance != TL_INSTANCE) {
		// We only support a single instance.
		return TDI_INVALID_REQUEST;
	}

	// Zero returned parameters in case of an error below.
	*Size = 0;

	if (ID->toi_class == INFO_CLASS_GENERIC) {
		// This is a generic request.
		if (ID->toi_type == INFO_TYPE_PROVIDER && ID->toi_id == ENTITY_TYPE_ID) {
			if (BufferSize >= sizeof(uint)) {
				*(uint *)&InfoBuffer[0] = (Entity == CO_TL_ENTITY) ? CO_TL_TCP
					: CL_TL_UDP;
				(void)CopyFlatToNdis(Buffer, InfoBuffer, sizeof(uint), &Offset,
                          &BytesCopied);
				return TDI_SUCCESS;
			} else
				return TDI_BUFFER_TOO_SMALL;
		}
		return TDI_INVALID_PARAMETER;	
	}

	if (ID->toi_class == INFO_CLASS_PROTOCOL) {
		// Handle protocol specific class of information. For us, this is
		// the MIB-2 stuff or the minimal stuff we do for oob_inline support.
		
#ifndef UDP_ONLY
		if (ID->toi_type == INFO_TYPE_CONNECTION) {
			TCPConn			*Conn;
			TCB				*QueryTCB;
			TCPSocketAMInfo	*AMInfo;
			CTELockHandle	TCBHandle;
			
			if (BufferSize < sizeof(TCPSocketAMInfo) ||
				ID->toi_id != TCP_SOCKET_ATMARK)
				return TDI_INVALID_PARAMETER;
		
			AMInfo = (TCPSocketAMInfo *)InfoBuffer;
		    CTEGetLock(&ConnTableLock, &Handle);
		
		    Conn = GetConnFromConnID((uint)Request->Handle.ConnectionContext);
		
			if (Conn != NULL) {
				CTEStructAssert(Conn, tc);
				
				QueryTCB = Conn->tc_tcb;
				if (QueryTCB != NULL) {
					CTEStructAssert(QueryTCB, tcb);		
					CTEGetLock(&QueryTCB->tcb_lock, &TCBHandle);
					if ((QueryTCB->tcb_flags & (URG_INLINE | URG_VALID)) ==
						(URG_INLINE | URG_VALID)) {
						// We're in inline mode, and the urgent data fields are
						// valid.
						AMInfo->tsa_size = QueryTCB->tcb_urgend -
							QueryTCB->tcb_urgstart + 1;
						// Rcvnext - pendingcnt is the sequence number of the
						// next byte of data that will be delivered to the
						// client. Urgend - that value is the offset in the
						// data stream of the end of urgent data.
						AMInfo->tsa_offset = QueryTCB->tcb_urgend -
							(QueryTCB->tcb_rcvnext - QueryTCB->tcb_pendingcnt);
					} else {
						AMInfo->tsa_size = 0;
						AMInfo->tsa_offset = 0;
					}
					CTEFreeLock(&QueryTCB->tcb_lock, TCBHandle);
					*Size = sizeof(TCPSocketAMInfo);
					CopyFlatToNdis(Buffer, InfoBuffer, sizeof(TCPSocketAMInfo),
						&Offset, &BytesCopied);
					return TDI_SUCCESS;
				}
			}
			return TDI_INVALID_PARAMETER;
					
		}
		
#endif
		if (ID->toi_type != INFO_TYPE_PROVIDER)
			return TDI_INVALID_PARAMETER;

		switch (ID->toi_id) {
			
			case UDP_MIB_STAT_ID:
#if UDP_MIB_STAT_ID != TCP_MIB_STAT_ID
			case TCP_MIB_STAT_ID:
#endif
				Fixed = TRUE;
				if (Entity == CL_TL_ENTITY) {
					InfoSize = sizeof(UDPStats);
					InfoPtr = &UStats;
				} else {
#ifndef UDP_ONLY
					InfoSize = sizeof(TCPStats);
					InfoPtr = &TStats;
#else
					return TDI_INVALID_PARAMETER;
#endif
				}
				break;
			case UDP_MIB_TABLE_ID:
#if UDP_MIB_TABLE_ID != TCP_MIB_TABLE_ID
			case TCP_MIB_TABLE_ID:
#endif
				Fixed = FALSE;
				if (Entity == CL_TL_ENTITY) {
					InfoSize = sizeof(UDPEntry);
					InfoPtr = &ReadAOTable;
					CTEGetLock(&AddrObjTableLock, &Handle);
#ifndef VXD
					LockPtr = &AddrObjTableLock;
#else
#ifdef DEBUG
					LockPtr = &AddrObjTableLock;
#endif
#endif
				} else {
#ifndef UDP_ONLY
					InfoSize = sizeof(TCPConnTableEntry);
					InfoPtr = &ReadTCBTable;
					CTEGetLock(&TCBTableLock, &Handle);
#ifndef VXD
					LockPtr = &TCBTableLock;
#else
#ifdef DEBUG
					LockPtr = &TCBTableLock;
#endif
#endif

#else
					return TDI_INVALID_PARAMETER;
#endif
				}
				break;
			default:
				return TDI_INVALID_PARAMETER;
				break;
		}

		if (Fixed) {
			if (BufferSize < InfoSize)
				return TDI_BUFFER_TOO_SMALL;

			*Size = InfoSize;

			(void)CopyFlatToNdis(Buffer, InfoPtr, InfoSize, &Offset,
                      &BytesCopied);
			return TDI_SUCCESS;
		} else {
			struct ReadTableStruct	*RTSPtr;
			uint					ReadStatus;

			// Have a variable length (or mult-instance) structure to copy.
			// InfoPtr points to the structure describing the routines to
			// call to read the table.
			// Loop through up to CountWanted times, calling the routine
			// each time.
			BytesRead = 0;

			RTSPtr = InfoPtr;

			ReadStatus = (*(RTSPtr->rts_validate))(Context, &Valid);

			// If we successfully read something we'll continue. Otherwise
			// we'll bail out.
			if (!Valid) {
				CTEFreeLock(LockPtr, Handle);
				return TDI_INVALID_PARAMETER;
			}

			while (ReadStatus)  {
				// The invariant here is that there is data in the table to
				// read. We may or may not have room for it. So ReadStatus
				// is TRUE, and BufferSize - BytesRead is the room left
				// in the buffer.
				if ((int)(BufferSize - BytesRead) >= (int)InfoSize) {
					ReadStatus = (*(RTSPtr->rts_readnext))(Context,
						InfoBuffer);
					BytesRead += InfoSize;
					Buffer = CopyFlatToNdis(Buffer, InfoBuffer, InfoSize,
						&Offset, &BytesCopied);
				} else
					break;

			}

			*Size = BytesRead;
			CTEFreeLock(LockPtr, Handle);
			return (!ReadStatus ? TDI_SUCCESS : TDI_BUFFER_OVERFLOW);
		}		

	}

	if (ID->toi_class == INFO_CLASS_IMPLEMENTATION) {
		// We want to return implementation specific info. For now, error out.
		return TDI_INVALID_PARAMETER;
	}

	return TDI_INVALID_PARAMETER;
	
}

//*	TdiSetInfoEx - Extended TDI set information.
//
//	This is the new TDI set information handler. We take in a TDIObjectID
//	structure, a buffer and length. We set the object specifed by the ID
//	(and possibly by the Request) to the value specified in the buffer.
//
//	Input:	Request			- The request structure for this command.
//			ID				- The object ID
//			Buffer			- Pointer to buffer containing value to set.
//			Size			- Size in bytes of Buffer.
//
//	Returns: Status of attempt to get information.
//
TDI_STATUS
TdiSetInformationEx(PTDI_REQUEST Request, TDIObjectID *ID, void *Buffer,
	uint Size)
{
	TCPConnTableEntry		*TCPEntry;
	CTELockHandle			TableHandle, TCBHandle;
	TCB						*SetTCB;
	uint					Entity;
	TCPConn					*Conn;
	TDI_STATUS				Status;


	//* Check the level. If it can't be for us, pass it down.
	Entity = ID->toi_entity.tei_entity;

	if (Entity != CO_TL_ENTITY && Entity != CL_TL_ENTITY) {
		// Someday we'll have to figure out how to dispatch. For now, just pass
		// it down.
		return (*LocalNetInfo.ipi_setinfo)(ID, Buffer, Size);
	}

	if (ID->toi_entity.tei_instance != TL_INSTANCE)
		return TDI_INVALID_REQUEST;

	if (ID->toi_class == INFO_CLASS_GENERIC) {
		// Fill this in when we have generic class defines.
		return TDI_INVALID_PARAMETER;	
	}

	//* Now look at the rest of it.
	if (ID->toi_class == INFO_CLASS_PROTOCOL) {
		// Handle protocol specific class of information. For us, this is
		// the MIB-2 stuff, as well as common sockets options,
		// and in particular the setting of the state of a TCP connection.
		
		if (ID->toi_type == INFO_TYPE_CONNECTION) {
			TCPSocketOption	*Option;
			uint			Flag;
			uint			Value;
			
#ifndef UDP_ONLY
			// A connection type. Get the connection, and then figure out
			// what to do with it.
			Status = TDI_INVALID_PARAMETER;
			
			if (Size < sizeof(TCPSocketOption))
				return Status;
		
		    CTEGetLock(&ConnTableLock, &TableHandle);
		
		    Conn = GetConnFromConnID((uint)Request->Handle.ConnectionContext);
		
			if (Conn != NULL) {
				CTEStructAssert(Conn, tc);
				
				Status = TDI_SUCCESS;
				
				if (ID->toi_id == TCP_SOCKET_WINDOW) {
					// This is a funny option, because it doesn't involve
					// flags. Handle this specially.
					Option = (TCPSocketOption *)Buffer;
					
					// We don't allow anyone to shrink the window, as this
					// gets too weird from a protocol point of view. Also,
					// make sure they don't try and set anything too big.
					if (Option->tso_value > 0xffff)
						Status = TDI_INVALID_PARAMETER;
					else if (Option->tso_value > Conn->tc_window ||
						Conn->tc_tcb == NULL) {
						Conn->tc_flags |= CONN_WINSET;
						Conn->tc_window = Option->tso_value;
						SetTCB = Conn->tc_tcb;
						
						if (SetTCB != NULL) {
							CTEStructAssert(SetTCB, tcb);		
							CTEGetLock(&SetTCB->tcb_lock, &TCBHandle);
							CTEAssert(Option->tso_value > SetTCB->tcb_defaultwin);
							if (DATA_RCV_STATE(SetTCB->tcb_state) &&
								!CLOSING(SetTCB)) {
								SetTCB->tcb_flags |= WINDOW_SET;
								SetTCB->tcb_defaultwin = Option->tso_value;
								SetTCB->tcb_refcnt++;
								CTEFreeLock(&SetTCB->tcb_lock, TCBHandle);
								SendACK(SetTCB);
								CTEGetLock(&SetTCB->tcb_lock, &TCBHandle);
								DerefTCB(SetTCB, TCBHandle);
							} else {
								CTEFreeLock(&SetTCB->tcb_lock, TCBHandle);
							}
						}
					}
					CTEFreeLock(&ConnTableLock, TableHandle);
					return Status;
				}
				
				Flag = 0;
				Option = (TCPSocketOption *)Buffer;
				Value = Option->tso_value;
				// We have the connection, so figure out which flag to set.
				switch (ID->toi_id) {
					
					case TCP_SOCKET_NODELAY:
						Value = !Value;
						Flag = NAGLING;
						break;
					case TCP_SOCKET_KEEPALIVE:
						Flag = KEEPALIVE;
						break;
					case TCP_SOCKET_BSDURGENT:
						Flag = BSD_URGENT;
						break;
					case TCP_SOCKET_OOBINLINE:
						Flag = URG_INLINE;
						break;
					default:
						Status = TDI_INVALID_PARAMETER;
						break;
				}
				
				if (Status == TDI_SUCCESS) {
					if (Value)
						Conn->tc_tcbflags |= Flag;
					else
						Conn->tc_tcbflags &= ~Flag;
						
					SetTCB = Conn->tc_tcb;
					if (SetTCB != NULL) {
						CTEStructAssert(SetTCB, tcb);		
						CTEGetLock(&SetTCB->tcb_lock, &TCBHandle);
						if (Value)
							SetTCB->tcb_flags |= Flag;
						else
							SetTCB->tcb_flags &= ~Flag;
							
						if (ID->toi_id == TCP_SOCKET_KEEPALIVE) {
							SetTCB->tcb_alive = TCPTime;
							SetTCB->tcb_kacount = 0;
						}
						
						CTEFreeLock(&SetTCB->tcb_lock, TCBHandle);
					}
				}
			}
			
			CTEFreeLock(&ConnTableLock, TableHandle);
			return Status;
#else
			return TDI_INVALID_PARAMETER;
#endif
		}
		
		if (ID->toi_type == INFO_TYPE_ADDRESS_OBJECT) {
			// We're setting information on an address object. This is
			// pretty simple.
			
				return SetAddrOptions(Request, ID->toi_id, Size, Buffer);

		}
		
			
		if (ID->toi_type != INFO_TYPE_PROVIDER)
			return TDI_INVALID_PARAMETER;

#ifndef UDP_ONLY
		if (ID->toi_id == TCP_MIB_TABLE_ID) {
			if (Size != sizeof(TCPConnTableEntry))
				return TDI_INVALID_PARAMETER;

			TCPEntry = (TCPConnTableEntry *)Buffer;

			if (TCPEntry->tct_state != TCP_DELETE_TCB)
				return TDI_INVALID_PARAMETER;

			// We have an apparently valid request. Look up the TCB.
			CTEGetLock(&TCBTableLock, &TableHandle);
			SetTCB = FindTCB(TCPEntry->tct_localaddr,
				TCPEntry->tct_remoteaddr, (ushort)TCPEntry->tct_remoteport,
				(ushort)TCPEntry->tct_localport);

			// We found him. If he's not closing or closed, close him.
			if (SetTCB != NULL)	{
				CTEGetLock(&SetTCB->tcb_lock, &TCBHandle);
				CTEFreeLock(&TCBTableLock, TCBHandle);
				
				// We've got him. Bump his ref. count, and call TryToCloseTCB
				// to mark him as closing. Then notify the upper layer client
				// of the disconnect.
				SetTCB->tcb_refcnt++;
				if (SetTCB->tcb_state != TCB_CLOSED && !CLOSING(SetTCB)) {
					SetTCB->tcb_flags |= NEED_RST;
					TryToCloseTCB(SetTCB, TCB_CLOSE_ABORTED, TableHandle);
					CTEGetLock(&SetTCB->tcb_lock, &TableHandle);

					if (SetTCB->tcb_state != TCB_TIME_WAIT) {
						// Remove him from the TCB, and notify the client.
						CTEFreeLock(&SetTCB->tcb_lock, TableHandle);
						RemoveTCBFromConn(SetTCB);
						NotifyOfDisc(SetTCB, NULL, TDI_CONNECTION_RESET);
						CTEGetLock(&SetTCB->tcb_lock, &TableHandle);
					}
			
				}

				DerefTCB(SetTCB, TableHandle);
				return TDI_SUCCESS;
			} else {
				CTEFreeLock(&TCBTableLock, TableHandle);
				return TDI_INVALID_PARAMETER;
			}
		} else
			return TDI_INVALID_PARAMETER;
#else
		return TDI_INVALID_PARAMETER;
#endif

	}
	
	if (ID->toi_class == INFO_CLASS_IMPLEMENTATION) {
		// We want to return implementation specific info. For now, error out.
		return TDI_INVALID_REQUEST;
	}

	return TDI_INVALID_REQUEST;


}
Example #2
0
VOID
IpxAllocateBindingPool(
    IN PDEVICE Device
    )

/*++

Routine Description:

    This routine adds 10 bindings to the pool for this device.

Arguments:

    Device - The device.

Return Value:

    None.

--*/

{
    PIPX_BINDING_POOL BindingPool;
    UINT BindingPoolSize;
    UINT BindingNum;
    PBINDING Binding;
    CTELockHandle LockHandle;

    BindingPoolSize = FIELD_OFFSET (IPX_BINDING_POOL, Bindings[0]) +
                       (sizeof(BINDING) * Device->InitBindings);

    BindingPool = (PIPX_BINDING_POOL)IpxAllocateMemory (BindingPoolSize, MEMORY_PACKET, "BindingPool");

    if (BindingPool == NULL) {
        IPX_DEBUG (PNP, ("Could not allocate binding pool memory\n"));
        return;
    }


    IPX_DEBUG (PNP, ("Initializing Binding pool %lx, %d bindings\n",
                             BindingPool, Device->InitBindings));

    BindingPool->BindingCount = Device->InitBindings;

    CTEGetLock (&Device->Lock, &LockHandle);

    for (BindingNum = 0; BindingNum < BindingPool->BindingCount; BindingNum++) {

        Binding = &BindingPool->Bindings[BindingNum];
        IPX_PUSH_ENTRY_LIST (&Device->BindingList, &Binding->PoolLinkage, &Device->SListsLock);

#ifdef IPX_TRACK_POOL
        Binding->Pool = BindingPool;
#endif
    }

    InsertTailList (&Device->BindingPoolList, &BindingPool->Linkage);

    Device->AllocatedBindings += BindingPool->BindingCount;

    CTEFreeLock (&Device->Lock, LockHandle);

}   /* IpxAllocateBindingPool */
Example #3
0
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 */
Example #4
0
//* TdiQueryInformation - Query Information handler.
//
//	The TDI QueryInformation routine. Called when the client wants to
//	query information on a connection, the provider as a whole, or to
//	get statistics.
//
//	Input:	Request				- The request structure for this command.
//			QueryType			- The type of query to be performed.
//			Buffer				- Buffer to place data into.
//			BufferSize			- Pointer to size in bytes of buffer. On return,
//									filled in with bytes copied.
//			IsConn				- Valid only for TDI_QUERY_ADDRESS_INFO. TRUE
//									if we are querying the address info on
//									a connection.
//
//	Returns: Status of attempt to query information.
//
TDI_STATUS
TdiQueryInformation(PTDI_REQUEST Request, uint QueryType, PNDIS_BUFFER Buffer,
	uint *BufferSize, uint IsConn)
{
	union {
		TDI_CONNECTION_INFO		ConnInfo;
		TDI_ADDRESS_INFO		AddrInfo;
		TDI_PROVIDER_INFO		ProviderInfo;
		TDI_PROVIDER_STATISTICS	ProviderStats;
	} InfoBuf;

	uint			InfoSize;
	CTELockHandle	ConnTableHandle, TCBHandle, AddrHandle, AOHandle;
#ifndef UDP_ONLY
	TCPConn			*Conn;
	TCB				*InfoTCB;
#endif
	AddrObj			*InfoAO;
	void			*InfoPtr = NULL;
	uint			Offset;
	uint			Size;
    uint            BytesCopied;

	switch (QueryType) {
		
		case TDI_QUERY_BROADCAST_ADDRESS:
			return TDI_INVALID_QUERY;
			break;

		case TDI_QUERY_PROVIDER_INFO:
			InfoBuf.ProviderInfo.Version = 0x100;
#ifndef UDP_ONLY
			InfoBuf.ProviderInfo.MaxSendSize = 0xffffffff;
#else
			InfoBuf.ProviderInfo.MaxSendSize = 0;
#endif
			InfoBuf.ProviderInfo.MaxConnectionUserData = 0;
			InfoBuf.ProviderInfo.MaxDatagramSize = 0xffff - sizeof(UDPHeader);
			InfoBuf.ProviderInfo.ServiceFlags = MY_SERVICE_FLAGS;
			InfoBuf.ProviderInfo.MinimumLookaheadData = 1;
			InfoBuf.ProviderInfo.MaximumLookaheadData = 0xffff;
			InfoBuf.ProviderInfo.NumberOfResources = 0;
			InfoBuf.ProviderInfo.StartTime.LowPart = StartTime;
			InfoBuf.ProviderInfo.StartTime.HighPart = 0;
			InfoSize = sizeof(TDI_PROVIDER_INFO);
			InfoPtr = &InfoBuf.ProviderInfo;
			break;

		case TDI_QUERY_ADDRESS_INFO:
			InfoSize = sizeof(TDI_ADDRESS_INFO) - sizeof(TRANSPORT_ADDRESS) +
				TCP_TA_SIZE;
			CTEMemSet(&InfoBuf.AddrInfo, 0, TCP_TA_SIZE);
			InfoBuf.AddrInfo.ActivityCount = 1;		// Since noone knows what
													// this means, we'll set
													// it to one.

			if (IsConn) {
#ifdef UDP_ONLY
				return TDI_INVALID_QUERY;
#else

				CTEGetLock(&AddrObjTableLock, &AddrHandle);
				CTEGetLock(&ConnTableLock, &ConnTableHandle);
				Conn = GetConnFromConnID((uint)Request->Handle.ConnectionContext);
	
				if (Conn != NULL) {
					CTEStructAssert(Conn, tc);
					
					InfoTCB = Conn->tc_tcb;
					// If we have a TCB we'll
					// return information about that TCB. Otherwise we'll return
					// info about the address object.
					if (InfoTCB != NULL) {
						CTEStructAssert(InfoTCB, tcb);		
						CTEGetLock(&InfoTCB->tcb_lock, &TCBHandle);
						CTEFreeLock(&ConnTableLock, TCBHandle);
						CTEFreeLock(&AddrObjTableLock, ConnTableHandle);
						BuildTDIAddress((uchar *)&InfoBuf.AddrInfo.Address,
							InfoTCB->tcb_saddr, InfoTCB->tcb_sport);
						CTEFreeLock(&InfoTCB->tcb_lock, AddrHandle);
						InfoPtr = &InfoBuf.AddrInfo;
						break;
					} else {
						// No TCB, return info on the AddrObj.
						InfoAO = Conn->tc_ao;
						if (InfoAO != NULL) {
							// We have an AddrObj.
							CTEStructAssert(InfoAO, ao);
							CTEGetLock(&InfoAO->ao_lock, &AOHandle);
							BuildTDIAddress((uchar *)&InfoBuf.AddrInfo.Address,
								InfoAO->ao_addr, InfoAO->ao_port);
							CTEFreeLock(&InfoAO->ao_lock, AOHandle);
							CTEFreeLock(&ConnTableLock, ConnTableHandle);
							CTEFreeLock(&AddrObjTableLock, AddrHandle);
							InfoPtr = &InfoBuf.AddrInfo;
							break;
						}
					}

				}

				// Fall through to here when we can't find the connection, or
				// the connection isn't associated.
				CTEFreeLock(&ConnTableLock, ConnTableHandle);
				CTEFreeLock(&AddrObjTableLock, AddrHandle);
				return TDI_INVALID_CONNECTION;
				break;

#endif
			} else {
				// Asking for information on an addr. object.
#ifdef VXD
				InfoAO = GetIndexedAO((uint)Request->Handle.AddressHandle);

				if (InfoAO == NULL)
					return TDI_ADDR_INVALID;
#else	
				InfoAO = Request->Handle.AddressHandle;
#endif

				CTEStructAssert(InfoAO, ao);
	
				CTEGetLock(&InfoAO->ao_lock, &AOHandle);

				if (!AO_VALID(InfoAO)) {
					CTEFreeLock(&InfoAO->ao_lock, AOHandle);
					return TDI_ADDR_INVALID;
				}

				BuildTDIAddress((uchar *)&InfoBuf.AddrInfo.Address,
					InfoAO->ao_addr, InfoAO->ao_port);
				CTEFreeLock(&InfoAO->ao_lock, AOHandle);
				InfoPtr = &InfoBuf.AddrInfo;
				break;
			}
				
			break;

		case TDI_QUERY_CONNECTION_INFO:
#ifndef UDP_ONLY
			InfoSize = sizeof(TDI_CONNECTION_INFO);
			CTEGetLock(&ConnTableLock, &ConnTableHandle);
			Conn = GetConnFromConnID((uint)Request->Handle.ConnectionContext);

			if (Conn != NULL) {
				CTEStructAssert(Conn, tc);
				
				InfoTCB = Conn->tc_tcb;
				// If we have a TCB we'll return the information. Otherwise
				// we'll error out.
				if (InfoTCB != NULL) {
					
					ulong			TotalTime;
					ulong			BPS, PathBPS;
					IP_STATUS		IPStatus;
					CTEULargeInt	TempULargeInt;
					
					CTEStructAssert(InfoTCB, tcb);		
					CTEGetLock(&InfoTCB->tcb_lock, &TCBHandle);
					CTEFreeLock(&ConnTableLock, TCBHandle);
					CTEMemSet(&InfoBuf.ConnInfo, 0, sizeof(TDI_CONNECTION_INFO));
					InfoBuf.ConnInfo.State = (ulong)InfoTCB->tcb_state;
					IPStatus = (*LocalNetInfo.ipi_getpinfo)(InfoTCB->tcb_daddr,
						InfoTCB->tcb_saddr, NULL, &PathBPS);
					
					if (IPStatus != IP_SUCCESS) {
						InfoBuf.ConnInfo.Throughput.LowPart = 0xFFFFFFFF;
						InfoBuf.ConnInfo.Throughput.HighPart = 0xFFFFFFFF;
					} else {
						InfoBuf.ConnInfo.Throughput.HighPart = 0;
						TotalTime = InfoTCB->tcb_totaltime /
							(1000 / MS_PER_TICK);
						if (TotalTime != 0) {
							TempULargeInt.LowPart = InfoTCB->tcb_bcountlow;
							TempULargeInt.HighPart = InfoTCB->tcb_bcounthi;
							
							BPS = CTEEnlargedUnsignedDivide(TempULargeInt,
								TotalTime, NULL);
							InfoBuf.ConnInfo.Throughput.LowPart =
								MIN(BPS, PathBPS);
						} else
							InfoBuf.ConnInfo.Throughput.LowPart = PathBPS;
					}
							
							

					// To figure the delay we use the rexmit timeout. Our
					// rexmit timeout is roughly the round trip time plus
					// some slop, so we use half of that as the one way delay.
#ifdef VXD
					InfoBuf.ConnInfo.Delay.LowPart =
						(REXMIT_TO(InfoTCB) * MS_PER_TICK) / 2;
					InfoBuf.ConnInfo.Throughput.HighPart = 0;
#else // VXD
                    InfoBuf.ConnInfo.Delay.LowPart =
                        (REXMIT_TO(InfoTCB) * MS_PER_TICK) / 2;
                    InfoBuf.ConnInfo.Delay.HighPart = 0;
					//
					// Convert milliseconds to 100ns and negate for relative
					// time.
					//
					InfoBuf.ConnInfo.Delay =
					    RtlExtendedIntegerMultiply(
						    InfoBuf.ConnInfo.Delay,
							10000
							);

                    CTEAssert(InfoBuf.ConnInfo.Delay.HighPart == 0);

					InfoBuf.ConnInfo.Delay.QuadPart =
                        -InfoBuf.ConnInfo.Delay.QuadPart;

#endif // VXD
					CTEFreeLock(&InfoTCB->tcb_lock, ConnTableHandle);
					InfoPtr = &InfoBuf.ConnInfo;
					break;
				}

			}

			// Come through here if we can't find the connection or it has
			// no TCB.
			CTEFreeLock(&ConnTableLock, ConnTableHandle);
			return TDI_INVALID_CONNECTION;
			break;

#else // UDP_ONLY
			return TDI_INVALID_QUERY;
			break;
#endif // UDP_ONLY
		case TDI_QUERY_PROVIDER_STATISTICS:
			CTEMemSet(&InfoBuf.ProviderStats, 0, sizeof(TDI_PROVIDER_STATISTICS));
			InfoBuf.ProviderStats.Version = 0x100;
			InfoSize = sizeof(TDI_PROVIDER_STATISTICS);
			InfoPtr = &InfoBuf.ProviderStats;
			break;
		default:
			return TDI_INVALID_QUERY;
			break;
	}

	// When we get here, we've got the pointers set up and the information
	// filled in.

	CTEAssert(InfoPtr != NULL);
	Offset = 0;
	Size = *BufferSize;
	(void)CopyFlatToNdis(Buffer, InfoPtr, MIN(InfoSize, Size), &Offset,
              &BytesCopied);
	if (Size < InfoSize)
		return TDI_BUFFER_OVERFLOW;
	else {
		*BufferSize = InfoSize;
		return TDI_SUCCESS;
	}
}
Example #5
0
BOOLEAN
SpxTimerCancelEvent(
    IN	ULONG	TimerId,
    IN	BOOLEAN	ReEnqueue
)
/*++

Routine Description:

 	Cancel a previously scheduled timer event, if it hasn't fired already.

Arguments:


Return Value:


--*/
{
    PTIMERLIST		pList, *ppList;
    CTELockHandle	lockHandle;

    DBGPRINT(SYSTEM, INFO,
             ("SpxTimerCancelEvent: Entered for TimerId %ld\n", TimerId));

    CTEAssert(TimerId != 0);

    CTEGetLock(&spxTimerLock, &lockHandle);

    for (ppList = &spxTimerTable[TimerId % TIMER_HASH_TABLE];
            (pList = *ppList) != NULL;
            ppList = &pList->tmr_Overflow)
    {
        CTEAssert(VALID_TMR(pList));
        // If we find it, cancel it
        if (pList->tmr_Id == TimerId)
        {
            // Unlink this from the hash table
            *ppList = pList->tmr_Overflow;

            // ... and from the list
            if (pList->tmr_Next != NULL)
            {
                pList->tmr_Next->tmr_RelDelta += pList->tmr_RelDelta;
                pList->tmr_Next->tmr_Prev = pList->tmr_Prev;
            }
            *(pList->tmr_Prev) = pList->tmr_Next;

            spxTimerCount --;
            if (ReEnqueue)
                spxTimerEnqueue(pList);
            else SpxBPFreeBlock(pList, BLKID_TIMERLIST);
            break;
        }
    }

    // If we could not find it in the list, see if it currently running.
    // If so mark him to not reschedule itself, only if reenqueue was false.
    if (pList == NULL)
    {
        if ((spxTimerActive != NULL) &&
                (spxTimerActive->tmr_Id == TimerId) &&
                !ReEnqueue)
        {
            spxTimerActive->tmr_Cancelled = TRUE;
        }
    }

    CTEFreeLock(&spxTimerLock, lockHandle);

    DBGPRINT(SYSTEM, INFO,
             ("SpxTimerCancelEvent: %s for Id %ld\n",
              (pList != NULL) ? "Success" : "Failure", TimerId));

    return (pList != NULL);
}
Example #6
0
ULONG
SpxTimerScheduleEvent(
    IN	TIMER_ROUTINE		Worker,		// Routine to invoke when time expires
    IN	ULONG				MsTime,		// Schedule after this much time
    IN	PVOID				pContext	// Context(s) to pass to the routine
)
/*++

Routine Description:

 	Insert an event in the timer event list. If the list is empty, then
 	fire off a timer. The time is specified in ms. We convert to ticks.
	Each tick is currently 100ms. It may not be zero or negative. The internal
	timer fires at 100ms granularity.

Arguments:


Return Value:


--*/
{
    PTIMERLIST		pList;
    CTELockHandle	lockHandle;
    ULONG			DeltaTime;
    ULONG			Id = 0;

    //	Convert to ticks.
    DeltaTime	= MsTime/SPX_MS_TO_TICKS;
    if (DeltaTime == 0)
    {
        DBGPRINT(SYSTEM, INFO,
                 ("SpxTimerScheduleEvent: Converting %ld to ticks %ld\n",
                  MsTime, DeltaTime));

        DeltaTime = 1;
    }

    DBGPRINT(SYSTEM, INFO,
             ("SpxTimerScheduleEvent: Converting %ld to ticks %ld\n",
              MsTime, DeltaTime));

    // Negative or Zero DeltaTime is invalid.
    CTEAssert (DeltaTime > 0);

    DBGPRINT(SYSTEM, INFO,
             ("SpxTimerScheduleEvent: Routine %lx, Time %d, Context %lx\n",
              Worker, DeltaTime, pContext));

    CTEGetLock(&spxTimerLock, &lockHandle);

    if (spxTimerStopped)
    {
        DBGPRINT(SYSTEM, FATAL,
                 ("SpxTimerScheduleEvent: Called after Flush !!\n"));
    }

    else do
        {
            pList = SpxBPAllocBlock(BLKID_TIMERLIST);

            if (pList == NULL)
            {
                break;
            }

#if	DBG
            pList->tmr_Signature = TMR_SIGNATURE;
#endif
            pList->tmr_Cancelled = FALSE;
            pList->tmr_Worker = Worker;
            pList->tmr_AbsTime = DeltaTime;
            pList->tmr_Context = pContext;

            Id = pList->tmr_Id = spxTimerId++;

            // Take care of wrap around
            if (spxTimerId == 0)
                spxTimerId = 1;

            // Enqueue this handler
            spxTimerEnqueue(pList);
        } while (FALSE);

    CTEFreeLock(&spxTimerLock, lockHandle);

    return Id;
}
Example #7
0
VOID
spxTimerDpcRoutine(
    IN	PKDPC	pKDpc,
    IN	PVOID	pContext,
    IN	PVOID	SystemArgument1,
    IN	PVOID	SystemArgument2
)
/*++

Routine Description:

 	This is called in at DISPATCH_LEVEL when the timer expires. The entry at
 	the head of the list is decremented and if ZERO unlinked and dispatched.
 	If the list is non-empty, the timer is fired again.

Arguments:


Return Value:


--*/
{
    PTIMERLIST		pList, *ppList;
    BOOLEAN			TimerStarted;
    ULONG			ReEnqueueTime;
    CTELockHandle	lockHandle;

    pKDpc;
    pContext;
    SystemArgument1;
    SystemArgument2;

#if     defined(_PNP_POWER)
    CTEGetLock(&spxTimerLock, &lockHandle);
    if (spxTimerStopped)
    {
        DBGPRINT(SYSTEM, ERR,
                 ("spxTimerDpc: Enetered after Flush !!!\n"));

        CTEFreeLock(&spxTimerLock, lockHandle);
        return;
    }
#else
    if (spxTimerStopped)
    {
        DBGPRINT(SYSTEM, ERR,
                 ("spxTimerDpc: Enetered after Flush !!!\n"));
        return;
    }

    CTEGetLock(&spxTimerLock, &lockHandle);
#endif  _PNP_POWER

    SpxTimerCurrentTime ++;	// Update our relative time

#ifdef	PROFILING
    //	This is the only place where this is changed. And it always increases.
    SpxStatistics.stat_ElapsedTime = SpxTimerCurrentTime;
#endif

    // We should never be here if we have no work to do
    if ((spxTimerList != NULL))
    {
        // Careful here. If two guys wanna go off together - let them !!
        if (spxTimerList->tmr_RelDelta != 0)
            (spxTimerList->tmr_RelDelta)--;

        // Dispatch the entry if it is ready to go
        if (spxTimerList->tmr_RelDelta == 0)
        {
            pList = spxTimerList;
            CTEAssert(VALID_TMR(pList));

            // Unlink from the list
            spxTimerList = pList->tmr_Next;
            if (spxTimerList != NULL)
                spxTimerList->tmr_Prev = &spxTimerList;

            // Unlink from the hash table now
            for (ppList = &spxTimerTable[pList->tmr_Id % TIMER_HASH_TABLE];
                    *ppList != NULL;
                    ppList = &((*ppList)->tmr_Overflow))
            {
                CTEAssert(VALID_TMR(*ppList));
                if (*ppList == pList)
                {
                    *ppList = pList->tmr_Overflow;
                    break;
                }
            }

            CTEAssert (*ppList == pList->tmr_Overflow);

            DBGPRINT(SYSTEM, INFO,
                     ("spxTimerDpcRoutine: Dispatching %lx\n",
                      pList->tmr_Worker));

            spxTimerDispatchCount ++;
            spxTimerCount --;
            spxTimerActive = pList;
            CTEFreeLock(&spxTimerLock, lockHandle);

            //	If reenqueue time is 0, do not requeue. If 1, then requeue with
            //	current value, else use value specified.
            ReEnqueueTime = (*pList->tmr_Worker)(pList->tmr_Context, FALSE);
            DBGPRINT(SYSTEM, INFO,
                     ("spxTimerDpcRoutine: Reenequeu time %lx.%lx\n",
                      ReEnqueueTime, pList->tmr_AbsTime));

            CTEGetLock(&spxTimerLock, &lockHandle);

            spxTimerActive = NULL;
            spxTimerDispatchCount --;

            if (ReEnqueueTime != TIMER_DONT_REQUEUE)
            {
                // If this chappie was cancelled while it was running
                // and it wants to be re-queued, do it right away.
                if (pList->tmr_Cancelled)
                {
                    (*pList->tmr_Worker)(pList->tmr_Context, FALSE);
                    SpxBPFreeBlock(pList, BLKID_TIMERLIST);
                }
                else
                {
                    if (ReEnqueueTime != TIMER_REQUEUE_CUR_VALUE)
                    {
                        pList->tmr_AbsTime = ReEnqueueTime/SPX_MS_TO_TICKS;
                        if (pList->tmr_AbsTime == 0)
                        {
                            DBGPRINT(SYSTEM, INFO,
                                     ("SpxTimerDispatch: Requeue at %ld\n",
                                      pList->tmr_AbsTime));
                        }
                        DBGPRINT(SYSTEM, INFO,
                                 ("SpxTimerDispatch: Requeue at %ld.%ld\n",
                                  ReEnqueueTime, pList->tmr_AbsTime));
                    }

                    spxTimerEnqueue(pList);
                }
            }
            else
            {
                SpxBPFreeBlock(pList, BLKID_TIMERLIST);
            }
        }
    }

#if     defined(_PNP_POWER)
    if (!spxTimerStopped)
    {
        TimerStarted = KeSetTimer(&spxTimer,
                                  spxTimerTick,
                                  &spxTimerDpc);

        // it is possible that while we were here in Dpc, PNP_ADD_DEVICE
        // restarted the timer, so this assert is commented out for PnP
//		CTEAssert(!TimerStarted);
    }

    CTEFreeLock(&spxTimerLock, lockHandle);
#else
    CTEFreeLock(&spxTimerLock, lockHandle);

    if (!spxTimerStopped)
    {
        TimerStarted = KeSetTimer(&spxTimer,
                                  spxTimerTick,
                                  &spxTimerDpc);
        CTEAssert(!TimerStarted);
    }
#endif  _PNP_POWER
}
Example #8
0
VOID
SpxTimerFlushAndStop(
    VOID
)
/*++

Routine Description:

 	Force all entries in the timer queue to be dispatched immediately. No
 	more queue'ing of timer routines is permitted after this. The timer
 	essentially shuts down.

Arguments:


Return Value:


--*/
{
    PTIMERLIST		pList;
    CTELockHandle	lockHandle;

    CTEAssert (KeGetCurrentIrql() == LOW_LEVEL);

    DBGPRINT(SYSTEM, ERR,
             ("SpxTimerFlushAndStop: Entered\n"));

    CTEGetLock(&spxTimerLock, &lockHandle);

    spxTimerStopped = TRUE;

    KeCancelTimer(&spxTimer);

    if (spxTimerList != NULL)
    {
        // Dispatch all entries right away
        while (spxTimerList != NULL)
        {
            pList = spxTimerList;
            CTEAssert(VALID_TMR(pList));
            spxTimerList = pList->tmr_Next;

            DBGPRINT(SYSTEM, INFO,
                     ("spxTimerFlushAndStop: Dispatching %lx\n",
                      pList->tmr_Worker));

            // The timer routines assume they are being called at DISPATCH
            // level. This is OK since we are calling with SpinLock held.

            (*pList->tmr_Worker)(pList->tmr_Context, TRUE);

            spxTimerCount --;
            SpxBPFreeBlock(pList, BLKID_TIMERLIST);
        }
        RtlZeroMemory(spxTimerTable, sizeof(spxTimerTable));
    }

    CTEFreeLock(&spxTimerLock, lockHandle);

    // Wait for all timer routines to complete
    while (spxTimerDispatchCount != 0)
    {
        SpxSleep(SPX_TIMER_WAIT);
    }
}
Example #9
0
//----------------------------------------------------------------------------
NTSTATUS
PassDgToRt (
    IN PDEVICE                  pDevice,
    IN PIPX_DATAGRAM_OPTIONS2   pContext,
    IN ULONG                    Index,
    IN VOID UNALIGNED           *pDgrm,
    IN ULONG                    uNumBytes
    )
/*++

Routine Description;

    This function is used to allow NBT to pass name query service Pdu's to
    RT.  Rt posts a Rcv irp to Netbt.  If the Irp is here then simply
    copy the data to the irp and return it, otherwise buffer the data up
    to a maximum # of bytes. Beyond that limit the datagrams are discarded.

    If Retstatus is not success then the pdu will also be processed by
    nbt. This allows nbt to process packets when wins pauses and
    its list of queued buffers is exceeded.

Arguments;

    pDevice  - card that the request can in on
    pSrcAddress     - source address
    pDgrm        - ptr to the datagram
    uNumBytes       - length of datagram

Return Value;

    STATUS_PENDING if the buffer is to be held on to , the normal case.

Notes;


--*/

{
    NTSTATUS                status;
    PIPX_DATAGRAM_OPTIONS2  pRtBuffer;
    PIRP                    pIrp;
    CTELockHandle           OldIrq;


    IpxPrint0("PassDgToRt - Entered\n");

    //
    // Get the source port and ip address, since RT needs this information.
    //
    IpxPrint1("PassDgToRt: Index = (%d)\n", Index);
    CTEGetLock(&pRtInfo->Lock,&OldIrq);

    do
    {
        PRT_IRP pRtAF = &pRtInfo->AddFl[Index];
        if (pRtAF->State != RT_OPEN)
        {
          CTEFreeLock(&pRtInfo->Lock,OldIrq);
          break;
        }
        IpxReferenceRt(pRtInfo, RT_BUFF);
        if (IsListEmpty(&pRtAF->RcvIrpList))
        {
            IpxPrint0("PassDgToRt: No Rcv Irp\n");
            if (pRtInfo->RcvMemoryAllocated < pRtInfo->RcvMemoryMax)
            {
                PRTRCV_BUFFER    pBuffer;

                pBuffer = RtAllocMem(uNumBytes + sizeof(RTRCV_BUFFER));
                if (pBuffer)
                {
                    pBuffer->TotalAllocSize = uNumBytes + sizeof(RTRCV_BUFFER);

                    //
                    // Copy the user data
                    //
                    RtlCopyMemory(
                      (PUCHAR)((PUCHAR)pBuffer + OFFSET_PKT_IN_RCVBUFF),
                                (PVOID)pDgrm,uNumBytes);


                    pBuffer->Options.DgrmOptions.LocalTarget.NicId =
                             pContext->DgrmOptions.LocalTarget.NicId;
                    pBuffer->Options.LengthOfExtraOpInfo = 0;

                    //
                    // total amount allocated for user
                    //
                    pBuffer->UserBufferLengthToPass = uNumBytes + OFFSET_PKT_IN_OPTIONS;

                    CTEAssert(pContext->DgrmOptions.LocalTarget.NicId);
                    IpxPrint2("PassDgToRt: Nic Id is (%d). BufferLength is (%lx)\n", pContext->DgrmOptions.LocalTarget.NicId, uNumBytes);



                    //
                    // Keep track of the total amount buffered so that we don't
                    // eat up all non-paged pool buffering for RT
                    //
                    pRtInfo->RcvMemoryAllocated += pBuffer->TotalAllocSize;

                    IpxPrint0("IpxRt;Buffering Rt Rcv - no Irp, status=%X\n");
                    InsertTailList(&pRtAF->RcvList,&pBuffer->Linkage);
                    IpxPrint0("PassDgToRt: Buffer Queued\n");
                    status = STATUS_SUCCESS;
                }
                else
                {
                  IpxPrint0("PassDgToRt; Could not allocate buffer\n");
                  status = STATUS_INSUFFICIENT_RESOURCES;
                }
            }
            else
            {
                // this ret status will allow netbt to process the packet.
                //
                IpxPrint0("PassDgToRt; Dropping Pkt\n");
                status = STATUS_INSUFFICIENT_RESOURCES;
            }
            CTEFreeLock(&pRtInfo->Lock,OldIrq);
        }
        else
        {
            PMDL    pMdl;
            ULONG   CopyLength;
            ULONG   DgrmLength;
            ULONG   MdlBufferLength;
            ULONG   BytesToCopy;
            PLIST_ENTRY pLE;

            //
            // The recv irp is here so copy the data to its buffer and
            // pass it up to RT
            //
            pLE = RemoveHeadList(&pRtAF->RcvIrpList);
            pIrp = CONTAINING_RECORD(pLE, IRP, Tail.Overlay.ListEntry);

            (*(REQUEST_LINKAGE(pIrp))).Flink = NULL;
            (*(REQUEST_LINKAGE(pIrp))).Blink = NULL;

            //
            // Copy the datagram and the source address to RT buffer and
            // return to RT
            //
            pMdl = pIrp->MdlAddress;
            IpxPrint2("PassDgToRt: Irp=(%lx); Mdl=(%lx)\n", pIrp, pMdl);
            CTEAssert(pMdl);

            pRtBuffer = MmGetSystemAddressForMdl(pIrp->MdlAddress);

            MdlBufferLength = MmGetMdlByteCount(pMdl);
            DgrmLength  = uNumBytes;
            BytesToCopy = DgrmLength + OFFSET_PKT_IN_OPTIONS;

            CopyLength = (BytesToCopy <= MdlBufferLength) ? BytesToCopy : MdlBufferLength;
            IpxPrint2("PassDgToRt: Copy Length = (%d); Mdl Buffer Length is (%d)\n", CopyLength, MdlBufferLength);

            //
            // Copy user datagram into pRtBuffer
            //
            RtlCopyMemory((PVOID)((PUCHAR)pRtBuffer + OFFSET_PKT_IN_OPTIONS),
                       (PVOID)pDgrm,
                       CopyLength-OFFSET_PKT_IN_OPTIONS);

            IpxPrint1("Data copied is (%.12s)\n", (PUCHAR)((PUCHAR)pRtBuffer + OFFSET_PKT_IN_OPTIONS + sizeof(IPX_HEADER)));

            pRtBuffer->DgrmOptions.LocalTarget.NicId       = pContext->DgrmOptions.LocalTarget.NicId;
            pRtBuffer->LengthOfExtraOpInfo       = 0;

             IpxPrint3("PassDgToRt: Copy to RcvIrp;Nic Id is (%d/%d). BufferLength is (%lx)\n", pContext->DgrmOptions.LocalTarget.NicId, pRtBuffer->DgrmOptions.LocalTarget.NicId, uNumBytes);


            CTEAssert(pContext->DgrmOptions.LocalTarget.NicId);

            //
            // pass the irp up to RT
            //
            if (CopyLength < BytesToCopy)
            {
                status = STATUS_BUFFER_OVERFLOW;
            }
            else
            {
                status = STATUS_SUCCESS;
            }

           InsertTailList(&pRtInfo->CompletedIrps, REQUEST_LINKAGE(pIrp));
           pRtAF->NoOfRcvIrps--;
            IpxPrint4("PassDgToRt;Returning Rt Rcv Irp - data from net, Length=%X,pIrp=%X; status = (%d). NoOfRcvIrp = (%d)\n"  ,uNumBytes,pIrp, status, pRtAF->NoOfRcvIrps);

           pIrp->IoStatus.Status      = status;
           pIrp->IoStatus.Information = CopyLength;
           CTEFreeLock(&pRtInfo->Lock,OldIrq);

        }
        IpxDereferenceRt(pRtInfo, RT_BUFF);
  } while (FALSE);


    IpxPrint0("PassDgToRt - Entered\n");
    return(status);

}
Example #10
0
//----------------------------------------------------------------------------
VOID
RtIrpCancel(
    IN PDEVICE_OBJECT pDeviceObject,
    IN PIRP pIrp
    )
/*++

Routine Description;

    This routine handles the cancelling a RtRcv Irp. It must release the
    cancel spin lock before returning re; IoCancelIrp().

Arguments;


Return Value;

    The final status from the operation.

--*/
{
    KIRQL                OldIrq;
    PRT_INFO           pRt;
    PDEVICE  pDevice = IpxDevice;
    ULONG    Index;
    PIRP pTmpIrp;

    IpxPrint0("RtIrpCancel;Got a Rt Irp Cancel !!! *****************\n");

    Index = RT_ADDRESS_INDEX(pIrp);
    IpxPrint1("RtIrpCancel: Index = (%d)\n", Index);
    // pRt = (PRT_INFO)REQUEST_OPEN_CONTEXT(pIrp);
    pRt = pRtInfo;

    IoReleaseCancelSpinLock(pIrp->CancelIrql);
    if ((pRt->Type != IPX_RT_SIGNATURE) || (pRt->Size != sizeof(RT_INFO))) {
        return;
    }


    //
    // Be sure that PassNamePduToRt has not taken the RcvIrp for a
    // Rcv just now.
    //
    CTEGetLock(&pRt->Lock,&OldIrq);
    if (pRt && (pRt == pRtInfo) && (*(REQUEST_LINKAGE(pIrp))).Flink != NULL)
    {

        PRT_IRP pRtAF = &pRt->AddFl[Index];

        RemoveEntryList(REQUEST_LINKAGE(pIrp));

        pIrp->IoStatus.Status = STATUS_CANCELLED;
        pRtAF->NoOfRcvIrps--;
        CTEFreeLock(&pRt->Lock,OldIrq);
        IpxPrint1("RtIrpCancel;Completing Request. NoOfRcvIrp = (%d)\n", pRtAF->NoOfRcvIrps);
        IoCompleteRequest(pIrp,IO_NETWORK_INCREMENT);
    } else {
        CTEFreeLock(&pRt->Lock,OldIrq);
    }
}
Example #11
0
NTSTATUS
RcvIrpFromRt (
    IN  PDEVICE  pDevice,
    IN  PIRP        pIrp
    )
/*++

Routine Description;

    This function takes the rcv irp posted by RT and decides if there are
    any datagram queued waiting to go up to RT.  If so then the datagram
    is copied to the RT buffer and passed back up.  Otherwise the irp is
    held by Netbt until a datagram does come in.

Arguments;

    pDevice  - not used
    pIrp            - Rt Rcv Irp

Return Value;

    STATUS_PENDING if the buffer is to be held on to , the normal case.

Notes;


--*/

{
    NTSTATUS                status;
    PRTRCV_BUFFER            pBuffer;
    PLIST_ENTRY             pEntry;
    CTELockHandle           OldIrq;
    PRT_INFO                pRt;
    PIPX_DATAGRAM_OPTIONS2  pRtBuffer;
    PRT_IRP pRtAF;
    ULONG Index;
#if DBG
    ULONG NoOfRcvIrp;
#endif

   IpxPrint0("RcvIrpfromRt - Entered\n");

   // pRt = REQUEST_OPEN_CONTEXT(pIrp);
   pRt = pRtInfo;

   Index = RT_ADDRESS_INDEX(pIrp);

   IpxPrint1("RcvIrpFromRt: Index = (%d)\n", Index);

   IpxVerifyRt(pRt);
   CTEAssert(pRt && (pRt == pRtInfo));
   CTEAssert(Index < IPX_RT_MAX_ADDRESSES);

   CTEGetLock (&pRt->Lock, &OldIrq);
   do
   {
        pRtAF = &pRt->AddFl[Index];
        if (pRtAF->State != RT_OPEN)
        {
             status = STATUS_INVALID_HANDLE;
             CTEFreeLock (&pRt->Lock, OldIrq);
             break;
        }
        IpxReferenceRt(pRt, RT_IRPIN);

        if (!IsListEmpty(&pRtAF->RcvList))
        {
            PMDL    pMdl;
            ULONG   CopyLength;
            ULONG   UserBufferLengthToPass;
            ULONG   MdlLength;

            //
            // There is at least one datagram waiting to be received
            //
            pEntry = RemoveHeadList(&pRtAF->RcvList);

            pBuffer = (PRTRCV_BUFFER)CONTAINING_RECORD(pEntry,RTRCV_BUFFER,
                                                                  Linkage);

            IpxPrint0("RcvIrpFromRt: Buffer dequeued\n");
            //
            // Copy the datagram and the source address to RT buffer and
            // return to RT
            //
            pMdl = pIrp->MdlAddress;
            IpxPrint2("RcvIrpFromRt: Irp=(%lx); Mdl=(%lx)\n", pIrp, pMdl);
            CTEAssert(pMdl);
            if (!pMdl)
            {
                status = STATUS_BUFFER_TOO_SMALL;
                CTEFreeLock (&pRt->Lock, OldIrq);
                IpxDereferenceRt(pRtInfo, RT_IRPIN);
                break;

            }
            pRtBuffer = MmGetSystemAddressForMdl(pMdl);
            MdlLength = MmGetMdlByteCount(pMdl);

            UserBufferLengthToPass = pBuffer->UserBufferLengthToPass;

            CopyLength = (UserBufferLengthToPass <= MdlLength) ? UserBufferLengthToPass : MdlLength;
            IpxPrint0("RcvIrpFromRt: Copying Options\n");
            RtlCopyMemory((PVOID)pRtBuffer,
                       (PVOID)&pBuffer->Options,
                       CopyLength);

            //
            // subtract from the total amount buffered for RT since we are
            // passing a datagram up to RT now.
            //
            pRtInfo->RcvMemoryAllocated -= pBuffer->TotalAllocSize;
            RtFreeMem(pBuffer, pBuffer->TotalAllocSize);

            CTEAssert(pRtBuffer->DgrmOptions.LocalTarget.NicId);

            //
            // pass the irp up to RT
            //
            if (CopyLength < UserBufferLengthToPass)
            {
                status = STATUS_BUFFER_OVERFLOW;
            }
            else
            {
                status = STATUS_SUCCESS;
            }
#if DBG
            NoOfRcvIrp = pRtAF->NoOfRcvIrps;
#endif

            CTEFreeLock (&pRt->Lock, OldIrq);


            IpxPrint3("Returning Rt rcv Irp immediately with queued dgram, status=%X,pIrp=%X. NoOfRcvIrp=(%d)\n" ,status,pIrp, NoOfRcvIrp);

            pIrp->IoStatus.Information = CopyLength;
            pIrp->IoStatus.Status      = status;
        }
        else
        {

            status = NTCheckSetCancelRoutine(pIrp,RtIrpCancel,pDevice);

            if (!NT_SUCCESS(status))
            {
                CTEFreeLock (&pRt->Lock, OldIrq);
            }
            else
            {
                if (pRtAF->NoOfRcvIrps++ > RT_IRP_MAX)
                {
                     IpxPrint1("RcvIrpFromRt; REACHED LIMIT OF IRPS. NoOfRcvIrp=(%d)\n", pRtAF->NoOfRcvIrps);
                     status = STATUS_INSUFFICIENT_RESOURCES;
                     pRtAF->NoOfRcvIrps--;
                     CTEFreeLock (&pRt->Lock, OldIrq);

                }
                else
                {
                  InsertTailList(&pRtAF->RcvIrpList,REQUEST_LINKAGE(pIrp));
                  IpxPrint2("IpxRt;Holding onto Rt Rcv Irp, pIrp =%Xstatus=%X\n",   status,pIrp);

                  status = STATUS_PENDING;
                  CTEFreeLock(&pRt->Lock,OldIrq);
               }
            }


        }
        IpxDereferenceRt(pRtInfo, RT_IRPIN);
   } while(FALSE);

    IpxPrint0("RcvIrpfromRt - Leaving\n");
    return(status);

}
Example #12
0
//----------------------------------------------------------------------------
NTSTATUS
SendIrpFromRt (
    IN  PDEVICE  pDevice,
    IN  PIRP        pIrp
    )
{
    CTELockHandle OldIrq;
    NTSTATUS      Status;
    ULONG         Index;
    PRT_INFO      pRt;

    IpxPrint0("SendIrpfromRt - entered\n");
    // pRt = REQUEST_OPEN_CONTEXT(pIrp);
    pRt = pRtInfo;

    Index = RT_ADDRESS_INDEX(pIrp);
    IpxVerifyRt(pRt);
    CTEAssert(pRt && (pRt == pRtInfo));
    do {
      //
      // Check if the add. file slot indicates that it is OPEN.  If it is
      // not open, then we should return STATUS_INVALID_HANDLE.  The
      // reason why it may not be open is if we got a cleanup/close before
      // this irp.
      //
      CTEGetLock(&pRt->Lock, &OldIrq);
      if (pRt->AddFl[Index].State != RT_OPEN)
      {

         //
         // free the lock, set the status and break out
         //
         CTEFreeLock (&pRt->Lock, OldIrq);
         Status = STATUS_INVALID_HANDLE;
         break;
      }
      //
      // Let us reference the RtInfo structure so that it does not dissapear
      // and also for some accounting
      //
      IpxReferenceRt(pRt, RT_SEND);


      IpxPrint1("SendIrpFromRt: Index = (%d)\n", Index);

      //
      // Store the AF pointer since IpxTdiSendDatagram will use it. Free
      // the device lock since we have nothing more to do with our structures
      // here.
      //
      // REQUEST_OPEN_CONTEXT(pIrp) = (PVOID)(pRtInfo->AddFl[Index].AddressFile);
      CTEFreeLock (&pRt->Lock, OldIrq);

      Status = IpxTdiSendDatagram(pDevice->DeviceObject, pIrp);

      //
      // All done with this send.  Derefernce the RtInfo structure.
      //
      IpxDereferenceRt(pRtInfo, RT_SEND);
   } while(FALSE);

    IpxPrint0("SendIrpfromRt - leaving\n");
    return(Status);
}
Example #13
0
NTSTATUS
CleanupRtAddress(
    IN  PDEVICE  pDevice,
    IN  PIRP     pIrp)

/*++
Routine Description;

    This Routine handles closing the Rt Object that is used by
    by RT to send and receive name service datagrams on port 137.


Arguments;

    pIrp - a  ptr to an IRP

Return Value;

    NTSTATUS - status of the request

--*/

{
    NTSTATUS                   status;
    PRT_INFO                   pRt;
    CTELockHandle              OldIrq;
    PLIST_ENTRY                pHead;
    ULONG                      Index;
    PLIST_ENTRY                pLE;
    PIRP                       pTmpIrp;



    IpxPrint0("CleanupRtAddress - entered\n");

    //
    // if the endpoint structure is allocated, then deallocate it
    //
    // pRt   = REQUEST_OPEN_CONTEXT(pIrp);
    pRt = pRtInfo;

    Index = RT_ADDRESS_INDEX(pIrp);
    IpxPrint1("CleanupRtAdd: Index = (%d)\n", Index);

    IpxVerifyRt(pRt);
    CTEAssert(pRt  && (pRt == pRtInfo));
    CTEAssert(Index < IPX_RT_MAX_ADDRESSES);

    do
    {
        PLIST_ENTRY          pRcvEntry;
        PRTRCV_BUFFER        pRcv;
        PRT_IRP pRtAddFl   = &pRt->AddFl[Index];

        CTEAssert(pRtAddFl->State == RT_OPEN);
        IpxPrint1("CleanupRtAddress: Got AF handle = (%lx)\n", pRtAddFl);
        IpxReferenceRt(pRt, RT_CLEANUP);
        status = STATUS_SUCCESS;

        CTEGetLock (&pRt->Lock, &OldIrq);

        //
        // prevent any more dgram getting queued up
        //
        pRtAddFl->State = RT_CLOSING;
        CTEFreeLock (&pRt->Lock, OldIrq);

        //
        // free any rcv buffers that may be queued up
        //
        pHead = &pRtAddFl->RcvList;
        while (pRcvEntry = ExInterlockedRemoveHeadList(pHead, &pRt->Lock))
        {
           pRcv = CONTAINING_RECORD(pRcvEntry,RTRCV_BUFFER,Linkage);

           CTEAssert(pRcv);
           IpxPrint1("CleanupRtAddress:Freeing buffer = (%lx)\n", pRcv);
           RtFreeMem(pRcv,pRcv->TotalAllocSize);
        }

        //
        // Complete all irps that are queued
        //
        while (pLE = ExInterlockedRemoveHeadList(&pRtAddFl->RcvIrpList, &pRt->Lock)) {

           //
           // The recv irp is here so copy the data to its buffer and
           // pass it up to RT
           //
           pTmpIrp = CONTAINING_RECORD(pLE, IRP, Tail.Overlay.ListEntry);
           IpxPrint1("CleanupRtAddress: Completing Rt rcv Irp from AdFl queue pIrp=%X\n" ,pTmpIrp);
           pTmpIrp->IoStatus.Information = 0;
           pTmpIrp->IoStatus.Status      = STATUS_CANCELLED;

           NTIoComplete(pTmpIrp, (NTSTATUS)-1, (ULONG)-1);

        } //end of while

       //
       // dequeue and complete any irps on the complete queue.
       //

       while (pLE = ExInterlockedRemoveHeadList(&pRt->CompletedIrps, &pRt->Lock))
       {
           pTmpIrp = CONTAINING_RECORD(pLE, IRP, Tail.Overlay.ListEntry);
           if (RT_ADDRESS_INDEX(pTmpIrp) == Index)
           {
              IpxPrint1("CleanupRtAddress:Completing Rt rcv Irp from CompleteIrps queue pIrp=%X\n" ,pTmpIrp);

               pTmpIrp->IoStatus.Information = 0;
               pTmpIrp->IoStatus.Status = STATUS_CANCELLED;
               NTIoComplete(pTmpIrp, (NTSTATUS)-1, (ULONG)-1);
           }
           else
           {
                ExInterlockedInsertHeadList(&pRt->HolderIrpsList, pLE, &pRt->Lock);
           }
       }
       CTEGetLock(&pRt->Lock, &OldIrq);
       while(!IsListEmpty(&pRt->HolderIrpsList))
       {
          pLE = RemoveHeadList(&pRt->HolderIrpsList);
          InsertHeadList(&pRt->CompletedIrps, pLE);
       }
       CTEFreeLock(&pRt->Lock, OldIrq);

       //
       // Store AF pointer in Irp since we will now be freeing the address file
       // (in driver.c).
       //

       //
       // We always have addressfile in the Irp
       //

       // REQUEST_OPEN_CONTEXT(pIrp) = (PVOID)(pRtAddFl->AddressFile);

       IpxDereferenceRt(pRt, RT_CLEANUP);
  } while (FALSE);

   IpxPrint0("CleanupRtAddress: Return\n");
   return(status);
}
Example #14
0
NTSTATUS
OpenRtAddress(
    IN PDEVICE pDevice,
    IN PREQUEST pIrp
    )
{
   PRT_INFO pRt;
   CTELockHandle OldIrq;
   NTSTATUS status;
   ULONG SaveReqCode;


   IpxPrint0("OpenRtAddress - entered\n");

   //
   // if the RTINFO endpoint structure is not allocated, then allocate it
   // and initialize it. But first get the device lock.  This gurantees that
   // we can not have two irps doing the creation at the same time
   //
   CTEGetLock(&pDevice->Lock, &OldIrq);
   if (!pRtInfo)
   {

     pRt = AllocMem(sizeof(RT_INFO));

     //
     // Do this after locking the pagable rtns.
     //
     // pRtInfo = pRt;       //store it in pRtInfo.  When irps come down from RM,
                          // we can compare pRt passed in them with pRtInfo
     if (pRt)
     {
       RtlZeroMemory(pRt,sizeof(RT_INFO));
       IpxPrint1("OpenRtAddress: Initializing CompletedIrps for pRt=(%lx)\n", pRt);
       pRt->RcvMemoryMax  = RT_MAX_BUFF_MEM;    // max. memory we can allocate
       pRt->Type      = IPX_RT_SIGNATURE;
       pRt->Size      = sizeof(RT_INFO);
       pRt->pDevice   = pDevice;
       IpxPrint1("OpenRtAddress: pRtInfo=(%lx)\n", pRt);
       IpxPrint1("Completed Irp list is (%lx)\n", IsListEmpty(&pRt->CompletedIrps));

#if DBG
       RtlCopyMemory(pRt->Signature, "RTIF", sizeof("RTIF") - 1);
#endif
       InitializeListHead(&pRt->CompletedIrps);
       InitializeListHead(&pRt->HolderIrpsList);
     }
     CTEFreeLock(&pDevice->Lock, OldIrq);
   }
   else
   {
     pRt = pRtInfo;
     CTEFreeLock(&pDevice->Lock, OldIrq);
     IpxPrint1("OpenRtAddress: RTINFO found = (%lx)\n", pRtInfo);
   }

   if (pRt)
   {

         // Page in the Rt Code, if it hasn't already been paged in.
         //
         if (!IpxRtDiscardableCodeHandle)
         {
             IpxRtDiscardableCodeHandle = MmLockPagableCodeSection( CloseRtAddress );

             pRtInfo = pRt;       //store it in pRtInfo.  When irps come down from RM,
                          // we can compare pRt passed in them with pRtInfo
         }

         //
         // it could fail to lock the pages so check for that
         //
         if (IpxRtDiscardableCodeHandle)
         {

            ULONG i;
            status = STATUS_SUCCESS;

            IpxReferenceRt(pRtInfo, RT_CREATE);

             //
             // Find an empty slot and mark it open
             //
             CTEGetLock(&pRt->Lock, &OldIrq);
             for (i=0; i<IPX_RT_MAX_ADDRESSES; i++)
             {
                 if (pRt->AddFl[i].State == RT_EMPTY)
                 {
                     break;
                 }
             }
             if (i < IPX_RT_MAX_ADDRESSES)
             {
               pRt->AddFl[i].State       = RT_OPEN;
               pRt->NoOfAdds++;
               InitializeListHead(&pRt->AddFl[i].RcvList);
               InitializeListHead(&pRt->AddFl[i].RcvIrpList);
             }
             else
             {
               CTEFreeLock(&pRt->Lock, OldIrq);
               IpxPrint1("OpenRtAddress; All %d  slots used up\n", IPX_RT_MAX_ADDRESSES);
               IpxDereferenceRt(pRtInfo, RT_CREATE);
               status = STATUS_INSUFFICIENT_RESOURCES;
               goto RET;
             }
             CTEFreeLock(&pRt->Lock, OldIrq);

             //
             // Found an empty slot.  Initialize all relevant info. and then
             // open an address object.
             //
             SaveReqCode        = REQUEST_CODE(pIrp);
             REQUEST_CODE(pIrp) = MIPX_RT_CREATE;
             status             = IpxOpenAddressM(pDevice, pIrp, i);
             REQUEST_CODE(pIrp) = SaveReqCode;

             IpxPrint1("After IpxOpenAddressM: Completed Irp list is (%lx)\n", IsListEmpty(&pRtInfo->CompletedIrps));
             if (status != STATUS_SUCCESS)
             {
                 IpxPrint0("OpenRtAddress; Access Denied due to OpenAddress\n");
                 IpxDereferenceRt(pRtInfo, RT_CREATE);
                 CTEGetLock(&pRt->Lock, &OldIrq);
                 pRt->AddFl[i].State       = RT_EMPTY;
                 pRt->NoOfAdds--;
                 CTEFreeLock(&pRt->Lock, OldIrq);
             }
             else
             {
                 CTEGetLock(&pRt->Lock, &OldIrq);
                 pRt->AddFl[i].AddressFile = REQUEST_OPEN_CONTEXT(pIrp);
                 CTEFreeLock(&pRt->Lock, OldIrq);

                 //
                 // No need to put pRt since it is global. We stick with the addressfile here.
                 //

                 // REQUEST_OPEN_CONTEXT(pIrp) = (PVOID)pRt;
                 REQUEST_OPEN_TYPE(pIrp)    = (PVOID)(ROUTER_ADDRESS_FILE + i);
                 IpxPrint1("OpenRtAdd: Index = (%d)\n", RT_ADDRESS_INDEX(pIrp));
              }
           }
           else
           {
                 IpxPrint1("OpenRtAddress; All %d  slots used up\n", IPX_RT_MAX_ADDRESSES);

                 status = STATUS_INSUFFICIENT_RESOURCES;
            }
     }
     else
     {
       IpxPrint0("OpenRtCreate; Couldn't allocate a RT_INFO structure\n");
       CTEAssert(FALSE);       //should never happen unless system is running
                               //out of non-paged pool
       status = STATUS_INSUFFICIENT_RESOURCES;

     }
RET:
     IpxPrint1("OpenRtAddress status prior to return= %X\n",status);
     return(status);
}
Example #15
0
NTSTATUS
IpxTdiSetEventHandler(
    IN PREQUEST Request
    )

/*++

Routine Description:

    This routine performs the TdiSetEventHandler request for the
    transport provider.  The caller (request dispatcher) verifies
    that this routine will not be executed on behalf of a user-mode
    client, as this request enables direct callouts at DISPATCH_LEVEL.

Arguments:

    Request - Pointer to the request

Return Value:

    NTSTATUS - status of operation.

--*/

{
    NTSTATUS Status;
    CTELockHandle LockHandle;
    PTDI_REQUEST_KERNEL_SET_EVENT Parameters;
    PADDRESS_FILE AddressFile;

    //
    // Get the Address this is associated with; if there is none, get out.
    //

    AddressFile  = REQUEST_OPEN_CONTEXT(Request);
    Status = IpxVerifyAddressFile (AddressFile);

    if (!NT_SUCCESS (Status)) {
        return Status;
    }

    CTEGetLock (&AddressFile->Address->Lock, &LockHandle);

    Parameters = (PTDI_REQUEST_KERNEL_SET_EVENT)REQUEST_PARAMETERS(Request);

    switch (Parameters->EventType) {

    case TDI_EVENT_RECEIVE_DATAGRAM:

        if (Parameters->EventHandler == NULL) {
            AddressFile->ReceiveDatagramHandler =
                (PTDI_IND_RECEIVE_DATAGRAM)TdiDefaultRcvDatagramHandler;
            AddressFile->ReceiveDatagramHandlerContext = NULL;
            AddressFile->RegisteredReceiveDatagramHandler = FALSE;
        } else {
            AddressFile->ReceiveDatagramHandler =
                (PTDI_IND_RECEIVE_DATAGRAM)Parameters->EventHandler;
            AddressFile->ReceiveDatagramHandlerContext = Parameters->EventContext;
            AddressFile->RegisteredReceiveDatagramHandler = TRUE;
        }

        break;
    //
    // [SA] New event handler to receive chained buffers
    //
    case TDI_EVENT_CHAINED_RECEIVE_DATAGRAM:

        if (Parameters->EventHandler == NULL) {
            AddressFile->ChainedReceiveDatagramHandler =
                (PTDI_IND_CHAINED_RECEIVE_DATAGRAM)TdiDefaultChainedRcvDatagramHandler;
            AddressFile->ChainedReceiveDatagramHandlerContext = NULL;
            AddressFile->RegisteredChainedReceiveDatagramHandler = FALSE;
        } else {
            AddressFile->ChainedReceiveDatagramHandler =
                (PTDI_IND_CHAINED_RECEIVE_DATAGRAM)Parameters->EventHandler;
            AddressFile->ChainedReceiveDatagramHandlerContext = Parameters->EventContext;
            AddressFile->RegisteredChainedReceiveDatagramHandler = TRUE;
        }

        break;

    case TDI_EVENT_ERROR:

        if (Parameters->EventHandler == NULL) {
            AddressFile->ErrorHandler =
                (PTDI_IND_ERROR)TdiDefaultErrorHandler;
            AddressFile->ErrorHandlerContext = NULL;
            AddressFile->RegisteredErrorHandler = FALSE;
        } else {
            AddressFile->ErrorHandler =
                (PTDI_IND_ERROR)Parameters->EventHandler;
            AddressFile->ErrorHandlerContext = Parameters->EventContext;
            AddressFile->RegisteredErrorHandler = TRUE;
        }

        break;

    default:

        Status = STATUS_INVALID_PARAMETER;

    } /* switch */

    CTEFreeLock (&AddressFile->Address->Lock, LockHandle);

    IpxDereferenceAddressFile (AddressFile, AFREF_VERIFY);

    REQUEST_INFORMATION(Request) = 0;

    return Status;

}   /* IpxTdiSetEventHandler */