Ejemplo n.º 1
0
VOID
IpxRefBinding(
    IN PBINDING Binding
    )

/*++

Routine Description:

    This routine increments the reference count on a device context.

Arguments:

    Binding - Pointer to a transport device context object.

Return Value:

    none.

--*/

{
    CTEAssert (Binding->ReferenceCount > 0);    // not perfect, but...

    (VOID)InterlockedIncrement (&Binding->ReferenceCount);

}   /* IpxRefBinding */
Ejemplo n.º 2
0
NTSTATUS
CloseRtAddress(
    IN  PDEVICE  pDevice,
    IN  PIRP            pIrp)
{

    NTSTATUS                    status;
    PRT_INFO                  pRt;
    CTELockHandle               OldIrq;
    PLIST_ENTRY                 pHead;
    ULONG Index;

    IpxPrint0("CloseRtAddress - entered\n");

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

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

    IpxVerifyRt(pRt);
    CTEAssert(pRt && (pRt == pRtInfo));
    CTEAssert(Index < IPX_RT_MAX_ADDRESSES);
    CTEAssert(pRt->AddFl[Index].State == RT_CLOSING);

    // REQUEST_OPEN_CONTEXT(pIrp) = (PVOID)(pRt->AddFl[Index].AddressFile);
    //REQUEST_OPEN_TYPE(pIrp)    = (PVOID)TDI_TRANSPORT_ADDRESS_FILE;

    CTEGetLock(&pRt->Lock, &OldIrq);
    pRt->AddFl[Index].State = RT_EMPTY;
    pRt->NoOfAdds--;
    CTEFreeLock(&pRt->Lock, OldIrq);

    //
    // THis is a counter to the RT_CREATE
    //
    IpxDereferenceRt(pRt, RT_CLOSE);

    return(STATUS_SUCCESS);
}
Ejemplo n.º 3
0
NTSTATUS
SpxTimerInit(
    VOID
)
/*++

Routine Description:

 	Initialize the timer component for the appletalk stack.

Arguments:


Return Value:


--*/
{
#if      !defined(_PNP_POWER)
    BOOLEAN	TimerStarted;
#endif  !_PNP_POWER

    // Initialize the timer and its associated Dpc. timer will be kicked
    // off when we get the first card arrival notification from ipx
    KeInitializeTimer(&spxTimer);
    CTEInitLock(&spxTimerLock);
    KeInitializeDpc(&spxTimerDpc, spxTimerDpcRoutine, NULL);
    spxTimerTick = RtlConvertLongToLargeInteger(SPX_TIMER_TICK);
#if      !defined(_PNP_POWER)
    TimerStarted = KeSetTimer(&spxTimer,
                              spxTimerTick,
                              &spxTimerDpc);
    CTEAssert(!TimerStarted);
#endif  !_PNP_POWER
    return STATUS_SUCCESS;
}
Ejemplo n.º 4
0
VOID
IpxDerefBinding(
    IN PBINDING Binding
    )

/*++

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:

    Binding - Pointer to a transport device context object.

Return Value:

    none.

--*/

{
    LONG result;

    result = InterlockedDecrement (&Binding->ReferenceCount);

    CTEAssert (result >= 0);

    if (result == 0) {
        IpxDestroyBinding (Binding);
    }

}   /* IpxDerefBinding */
Ejemplo n.º 5
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;


}
Ejemplo n.º 6
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 */
Ejemplo n.º 7
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;
	}
}
Ejemplo n.º 8
0
NTSTATUS
NbiBind(
    IN PDEVICE Device,
    IN PCONFIG Config
    )

/*++

Routine Description:

    This routine binds the Netbios module of ISN to the IPX
    module, which provides the NDIS binding services.

Arguments:

    Device - Pointer to the Netbios device.

    Config - Pointer to the configuration information.

Return Value:

    The function value is the final status from the initialization operation.

--*/

{
    NTSTATUS Status;
    IO_STATUS_BLOCK IoStatusBlock;
    OBJECT_ATTRIBUTES ObjectAttributes;
/*    union {
        IPX_INTERNAL_BIND_INPUT Input;
        IPX_INTERNAL_BIND_OUTPUT Output;
    } Bind;
*/
    InitializeObjectAttributes(
        &ObjectAttributes,
        &Config->BindName,
        OBJ_CASE_INSENSITIVE,
        NULL,
        NULL);

    Status = ZwCreateFile(
                &Device->BindHandle,
                SYNCHRONIZE | GENERIC_READ,
                &ObjectAttributes,
                &IoStatusBlock,
                NULL,
                FILE_ATTRIBUTE_NORMAL,
                FILE_SHARE_READ | FILE_SHARE_WRITE,
                FILE_OPEN,
                FILE_SYNCHRONOUS_IO_NONALERT,
                NULL,
                0L);

    if (!NT_SUCCESS(Status)) {

        NB_DEBUG (BIND, ("Could not open IPX (%ws) %lx\n",
                    Config->BindName.Buffer, Status));
        NbiWriteGeneralErrorLog(
            Device,
            EVENT_TRANSPORT_ADAPTER_NOT_FOUND,
            1,
            Status,
            Config->BindName.Buffer,
            0,
            NULL);
        return Status;
    }

    //
    // Fill in our bind data.
    //

#if     defined(_PNP_POWER)
    Device->BindInput.Version = ISN_VERSION;
#else
    Device->BindInput.Version = 1;
#endif  _PNP_POWER
    Device->BindInput.Identifier = IDENTIFIER_NB;
    Device->BindInput.BroadcastEnable = TRUE;
    Device->BindInput.LookaheadRequired = 192;
    Device->BindInput.ProtocolOptions = 0;
    Device->BindInput.ReceiveHandler = NbiReceive;
    Device->BindInput.ReceiveCompleteHandler = NbiReceiveComplete;
    Device->BindInput.StatusHandler = NbiStatus;
    Device->BindInput.SendCompleteHandler = NbiSendComplete;
    Device->BindInput.TransferDataCompleteHandler = NbiTransferDataComplete;
    Device->BindInput.FindRouteCompleteHandler = NbiFindRouteComplete;
    Device->BindInput.LineUpHandler = NbiLineUp;
    Device->BindInput.LineDownHandler = NbiLineDown;
    Device->BindInput.ScheduleRouteHandler = NULL;
#if     defined(_PNP_POWER)
    Device->BindInput.PnPHandler = NbiPnPNotification;
#endif  _PNP_POWER


    Status = ZwDeviceIoControlFile(
                Device->BindHandle,         // HANDLE to File
                NULL,                       // HANDLE to Event
                NULL,                       // ApcRoutine
                NULL,                       // ApcContext
                &IoStatusBlock,             // IO_STATUS_BLOCK
                IOCTL_IPX_INTERNAL_BIND,    // IoControlCode
                &Device->BindInput,                      // Input Buffer
                sizeof(Device->BindInput),               // Input Buffer Length
                &Device->Bind,                      // OutputBuffer
                sizeof(Device->Bind));              // OutputBufferLength

    //
    // We open synchronous, so this shouldn't happen.
    //

    CTEAssert (Status != STATUS_PENDING);

    //
    // Save the bind data.
    //

    if (Status == STATUS_SUCCESS) {

        NB_DEBUG2 (BIND, ("Successfully bound to IPX (%ws)\n",
                    Config->BindName.Buffer));
//        RtlCopyMemory (&Device->Bind, &Bind.Output, sizeof(IPX_INTERNAL_BIND_OUTPUT));

#if     !defined(_PNP_POWER)
        RtlZeroMemory (Device->ReservedNetbiosName, 16);
        RtlCopyMemory (&Device->ReservedNetbiosName[10], Device->Bind.Node, 6);

        Status = (*Device->Bind.QueryHandler)(   // BUGBUG: Check return code
                     IPX_QUERY_MAXIMUM_NIC_ID,
                     (USHORT)0,
                     &Device->MaximumNicId,
                     sizeof(Device->MaximumNicId),
                     NULL);
        CTEAssert (Status == STATUS_SUCCESS);
#endif  !_PNP_POWER

    } else {

        NB_DEBUG (BIND, ("Could not bind to IPX (%ws) %lx\n",
                    Config->BindName.Buffer, Status));
        NbiWriteGeneralErrorLog(
            Device,
            EVENT_TRANSPORT_BINDING_FAILED,
            1,
            Status,
            Config->BindName.Buffer,
            0,
            NULL);
        ZwClose(Device->BindHandle);
    }

    return Status;

}   /* NbiBind */
Ejemplo n.º 9
0
VOID
NbiProcessDatagram(
    IN NDIS_HANDLE MacBindingHandle,
    IN NDIS_HANDLE MacReceiveContext,
    IN PIPX_LOCAL_TARGET RemoteAddress,
    IN ULONG MacOptions,
    IN PUCHAR LookaheadBuffer,
    IN UINT LookaheadBufferSize,
    IN UINT LookaheadBufferOffset,
    IN UINT PacketSize,
    IN BOOLEAN Broadcast
    )

/*++

Routine Description:

    This routine handles datagram indications.

Arguments:

    MacBindingHandle - A handle to use when calling NdisTransferData.

    MacReceiveContext - A context to use when calling NdisTransferData.

    RemoteAddress - The local target this packet was received from.

    MacOptions - The MAC options for the underlying NDIS binding.

    LookaheadBuffer - The lookahead buffer, starting at the IPX
        header.

    LookaheadBufferSize - The length of the lookahead data.

    LookaheadBufferOffset - The offset to add when calling
        NdisTransferData.

    PacketSize - The total length of the packet, starting at the
        IPX header.

    Broadcast - TRUE if the frame was a broadcast datagram.

Return Value:

    None.

--*/

{

    PADDRESS Address;
    NDIS_STATUS NdisStatus;
    PUCHAR NetbiosName;
    NB_CONNECTIONLESS UNALIGNED * Connectionless =
                        (NB_CONNECTIONLESS UNALIGNED *)LookaheadBuffer;
    PDEVICE Device = NbiDevice;
    PSINGLE_LIST_ENTRY s;
    PNB_RECEIVE_RESERVED ReceiveReserved;
    PNB_RECEIVE_BUFFER ReceiveBuffer;
    ULONG DataOffset;
    UINT BytesTransferred;
    PNDIS_PACKET Packet;
    CTELockHandle   LockHandle;


    //
    // See if there is an address that might want this.
    //

    if (Broadcast) {
        NetbiosName = (PVOID)-1;
    } else {
        NetbiosName = (PUCHAR)Connectionless->Datagram.DestinationName;
        if (Device->AddressCounts[NetbiosName[0]] == 0) {
            return;
        }
    }

    DataOffset = sizeof(IPX_HEADER) + sizeof(NB_DATAGRAM);

#if     defined(_PNP_POWER)
    if ((PacketSize < DataOffset) ||
        (PacketSize > DataOffset + Device->CurMaxReceiveBufferSize)) {
#else
        if ((PacketSize < DataOffset) ||
            (PacketSize > DataOffset + Device->Bind.LineInfo.MaximumPacketSize)) {
#endif  _PNP_POWER

        NB_DEBUG (DATAGRAM, ("Datagram length %d discarded\n", PacketSize));
        return;
    }

    Address = NbiFindAddress (Device, NetbiosName);

    if (Address == NULL) {
        return;
    }

    //
    // We need to cache the remote name if the packet came across the router.
    // This allows this machine to get back to the RAS client which might
    // have sent this datagram. We currently dont allow broadcasts to go out
    // on the dial-in line.
    // Dont cache some of the widely used group names, that would be too much
    // to store in cache.
    //

#if 0
    if ( Connectionless->IpxHeader.TransportControl &&
         !( (Address->NetbiosAddress.NetbiosName[15] == 0x0 ) &&
            (Address->NetbiosAddress.NetbiosNameType & TDI_ADDRESS_NETBIOS_TYPE_GROUP))  &&
         !( (Address->NetbiosAddress.NetbiosName[15] == 0x01 ) &&
            (Address->NetbiosAddress.NetbiosNameType & TDI_ADDRESS_NETBIOS_TYPE_GROUP))  &&
         !( (Address->NetbiosAddress.NetbiosName[15] == 0x1E ) &&
            (Address->NetbiosAddress.NetbiosNameType & TDI_ADDRESS_NETBIOS_TYPE_GROUP))  ) {
#endif
    if ( Connectionless->IpxHeader.TransportControl &&
         ( (Address->NetbiosAddress.NetbiosName[15] == 0x1c ) &&
           (Address->NetbiosAddress.NetbiosNameType & TDI_ADDRESS_NETBIOS_TYPE_GROUP))  ) {

        PNETBIOS_CACHE CacheName;

        NB_GET_LOCK (&Device->Lock, &LockHandle);
        if ( FindInNetbiosCacheTable ( Device->NameCache,
                                       Connectionless->Datagram.SourceName,
                                       &CacheName ) != STATUS_SUCCESS ) {

            CacheName = NbiAllocateMemory (sizeof(NETBIOS_CACHE), MEMORY_CACHE, "Cache Entry");
            if (CacheName ) {
                RtlCopyMemory (CacheName->NetbiosName, Connectionless->Datagram.SourceName, 16);
                CacheName->Unique = TRUE;
                CacheName->ReferenceCount = 1;
                RtlCopyMemory (&CacheName->FirstResponse, Connectionless->IpxHeader.SourceNetwork, 12);
                CacheName->NetworksAllocated = 1;
                CacheName->NetworksUsed = 1;
                CacheName->Networks[0].Network = *(UNALIGNED ULONG *)(Connectionless->IpxHeader.SourceNetwork);
                CacheName->Networks[0].LocalTarget = *RemoteAddress;
                NB_DEBUG2 (CACHE, ("Alloc new cache from Datagram %lx for <%.16s>\n",
                                        CacheName, CacheName->NetbiosName));

                CacheName->TimeStamp = Device->CacheTimeStamp;

                InsertInNetbiosCacheTable(
                    Device->NameCache,
                    CacheName);

            }
        } else if ( CacheName->Unique ) {
            //
            // We already have an entry for this remote. We should update
            // the address. This is so that if the ras client dials-out
            // then dials-in again and gets a new address, we dont end up
            // caching the old address.
            //
            if ( !RtlEqualMemory( &CacheName->FirstResponse, Connectionless->IpxHeader.SourceNetwork, 12) ) {

                RtlCopyMemory (&CacheName->FirstResponse, Connectionless->IpxHeader.SourceNetwork, 12);
                CacheName->Networks[0].Network = *(UNALIGNED ULONG *)(Connectionless->IpxHeader.SourceNetwork);
                CacheName->Networks[0].LocalTarget = *RemoteAddress;

            }
        }
        NB_FREE_LOCK (&Device->Lock, LockHandle);
    }

    //
    // We need to allocate a packet and buffer for the transfer.
    //

    s = NbiPopReceivePacket (Device);
    if (s == NULL) {
        NbiDereferenceAddress (Address, AREF_FIND);
        return;
    }

    ReceiveReserved = CONTAINING_RECORD (s, NB_RECEIVE_RESERVED, PoolLinkage);


    s = NbiPopReceiveBuffer (Device);
    if (s == NULL) {
        ExInterlockedPushEntrySList(
            &Device->ReceivePacketList,
            &ReceiveReserved->PoolLinkage,
            &NbiGlobalPoolInterlock);
        NbiDereferenceAddress (Address, AREF_FIND);
        return;
    }

    ReceiveBuffer = CONTAINING_RECORD (s, NB_RECEIVE_BUFFER, PoolLinkage);

    Packet = CONTAINING_RECORD (ReceiveReserved, NDIS_PACKET, ProtocolReserved[0]);
    ReceiveReserved->u.RR_DG.ReceiveBuffer = ReceiveBuffer;


    //
    // Now that we have a packet and a buffer, set up the transfer.
    // The indication to the TDI clients will happen at receive
    // complete time.
    //

    NdisChainBufferAtFront (Packet, ReceiveBuffer->NdisBuffer);
    ReceiveBuffer->Address = Address;

    ReceiveReserved->Type = RECEIVE_TYPE_DATAGRAM;
    CTEAssert (!ReceiveReserved->TransferInProgress);
    ReceiveReserved->TransferInProgress = TRUE;

    TdiCopyLookaheadData(
        &ReceiveBuffer->RemoteName,
        Connectionless->Datagram.SourceName,
        16,
        (MacOptions & NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA) ? TDI_RECEIVE_COPY_LOOKAHEAD : 0);

    (*Device->Bind.TransferDataHandler) (
        &NdisStatus,
        MacBindingHandle,
        MacReceiveContext,
        LookaheadBufferOffset + DataOffset,
        PacketSize - DataOffset,
        Packet,
        &BytesTransferred);

    if (NdisStatus != NDIS_STATUS_PENDING) {
#if DBG
        if (NdisStatus == STATUS_SUCCESS) {
            CTEAssert (BytesTransferred == PacketSize - DataOffset);
        }
#endif

        NbiTransferDataComplete(
            Packet,
            NdisStatus,
            BytesTransferred);

    }

}   /* NbiProcessDatagram */


VOID
NbiIndicateDatagram(
    IN PADDRESS Address,
    IN PUCHAR RemoteName,
    IN PUCHAR Data,
    IN ULONG DataLength
    )

/*++

Routine Description:

    This routine indicates a datagram to clients on the specified
    address. It is called from NbiReceiveComplete.

Arguments:

    Address - The address the datagram was sent to.

    RemoteName - The source netbios address of the datagram.

    Data - The data.

    DataLength - The length of the data.

Return Value:

    None.

--*/

{
    PLIST_ENTRY p, q;
    PIRP Irp;
    ULONG IndicateBytesCopied;
    PREQUEST Request;
    TA_NETBIOS_ADDRESS SourceName;
    PTDI_CONNECTION_INFORMATION RemoteInformation;
    PADDRESS_FILE AddressFile, ReferencedAddressFile;
    PTDI_CONNECTION_INFORMATION DatagramInformation;
    TDI_ADDRESS_NETBIOS UNALIGNED * DatagramAddress;
    PDEVICE Device = NbiDevice;
    NB_DEFINE_LOCK_HANDLE (LockHandle)
    CTELockHandle   CancelLH;

    //
    // Update our statistics.
    //

    ++Device->Statistics.DatagramsReceived;
    ADD_TO_LARGE_INTEGER(
        &Device->Statistics.DatagramBytesReceived,
        DataLength);

    //
    // Call the client's ReceiveDatagram indication handler.  He may
    // want to accept the datagram that way.
    //

    TdiBuildNetbiosAddress (RemoteName, FALSE, &SourceName);
    ReferencedAddressFile = NULL;

    NB_SYNC_GET_LOCK (&Address->Lock, &LockHandle);

    for (p = Address->AddressFileDatabase.Flink;
         p != &Address->AddressFileDatabase;
         p = p->Flink) {

        //
        // Find the next open address file in the list.
        //

        AddressFile = CONTAINING_RECORD (p, ADDRESS_FILE, Linkage);
        if (AddressFile->State != ADDRESSFILE_STATE_OPEN) {
            continue;
        }

        NbiReferenceAddressFileLock (AddressFile, AFREF_INDICATION);

        //
        // do we have a datagram receive request outstanding? If so, we will
        // satisfy it first. We run through the receive datagram queue
        // until we find a datagram with no remote address or with
        // this sender's address as its remote address.
        //

        for (q = AddressFile->ReceiveDatagramQueue.Flink;
             q != &AddressFile->ReceiveDatagramQueue;
             q = q->Flink) {

            Request = LIST_ENTRY_TO_REQUEST (q);
            DatagramInformation = ((PTDI_REQUEST_KERNEL_RECEIVEDG)
                REQUEST_PARAMETERS(Request))->ReceiveDatagramInformation;

            if (DatagramInformation &&
                (DatagramInformation->RemoteAddress) &&
                (DatagramAddress = NbiParseTdiAddress(DatagramInformation->RemoteAddress, FALSE)) &&
                (!RtlEqualMemory(
                    RemoteName,
                    DatagramAddress->NetbiosName,
                    16))) {
                continue;
            }
            break;
        }

        if (q != &AddressFile->ReceiveDatagramQueue) {

            RemoveEntryList (q);
            NB_SYNC_FREE_LOCK (&Address->Lock, LockHandle);

            if (ReferencedAddressFile != NULL) {
                NbiDereferenceAddressFile (ReferencedAddressFile, AFREF_INDICATION);
            }
            ReferencedAddressFile = AddressFile;

            //
            // Do this deref now, we hold another one so it
            // will stick around.
            //

            NbiDereferenceAddressFile (AddressFile, AFREF_RCV_DGRAM);

            IndicateBytesCopied = 0;

            //
            // Fall past the else to copy the data.
            //

        } else {

            NB_SYNC_FREE_LOCK (&Address->Lock, LockHandle);

            if (ReferencedAddressFile != NULL) {
                NbiDereferenceAddressFile (ReferencedAddressFile, AFREF_INDICATION);
            }
            ReferencedAddressFile = AddressFile;

            //
            // No receive datagram requests; is there a kernel client?
            //

            if (AddressFile->RegisteredHandler[TDI_EVENT_RECEIVE_DATAGRAM]) {

                IndicateBytesCopied = 0;

                if ((*AddressFile->ReceiveDatagramHandler)(
                         AddressFile->HandlerContexts[TDI_EVENT_RECEIVE_DATAGRAM],
                         sizeof (TA_NETBIOS_ADDRESS),
                         &SourceName,
                         0,
                         NULL,
                         TDI_RECEIVE_COPY_LOOKAHEAD,
                         DataLength,      // indicated
                         DataLength,     // available
                         &IndicateBytesCopied,
                         Data,
                         &Irp) != STATUS_MORE_PROCESSING_REQUIRED) {

                    //
                    // The client did not return a request, go to the
                    // next address file.
                    //

                    NB_SYNC_GET_LOCK (&Address->Lock, &LockHandle);
                    continue;

                }

                Request = NbiAllocateRequest (Device, Irp);

                IF_NOT_ALLOCATED(Request) {
                    Irp->IoStatus.Information = 0;
                    Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
                    IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);


                    NB_SYNC_GET_LOCK (&Address->Lock, &LockHandle);
                    continue;
                }

            } else {

                //
                // The client has nothing posted and no handler,
                // go on to the next address file.
                //

                NB_SYNC_GET_LOCK (&Address->Lock, &LockHandle);
                continue;

            }

        }

        //
        // We have a request; copy the actual user data.
        //
        if ( REQUEST_NDIS_BUFFER (Request) ) {

            REQUEST_STATUS(Request) =
                TdiCopyBufferToMdl (
                         Data,
                         IndicateBytesCopied,
                         DataLength - IndicateBytesCopied,
                         REQUEST_NDIS_BUFFER (Request),
                         0,
                         &REQUEST_INFORMATION (Request));

        } else {
            //
            // No buffer specified in the request
            //
            REQUEST_INFORMATION (Request) = 0;
            //
            // If there was any data to be copied, return error o/w success
            //
            REQUEST_STATUS(Request) = ( (DataLength - IndicateBytesCopied) ? STATUS_BUFFER_OVERFLOW : STATUS_SUCCESS );
        }

        //
        // Copy the addressing information.
        //

        RemoteInformation = ((PTDI_REQUEST_KERNEL_RECEIVEDG)
                REQUEST_PARAMETERS(Request))->ReturnDatagramInformation;

        if (RemoteInformation != NULL) {

            RtlCopyMemory(
                (PTA_NETBIOS_ADDRESS)RemoteInformation->RemoteAddress,
                &SourceName,
                (RemoteInformation->RemoteAddressLength < sizeof(TA_NETBIOS_ADDRESS)) ?
                    RemoteInformation->RemoteAddressLength : sizeof(TA_NETBIOS_ADDRESS));
        }


        NB_GET_CANCEL_LOCK( &CancelLH );
        IoSetCancelRoutine (Request, (PDRIVER_CANCEL)NULL);
        NB_FREE_CANCEL_LOCK( CancelLH );

        NbiCompleteRequest (Request);
        NbiFreeRequest (Device, Request);

        NB_SYNC_GET_LOCK (&Address->Lock, &LockHandle);

    }    // end of for loop through the address files
Ejemplo n.º 10
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;
}
Ejemplo n.º 11
0
VOID
NbiPnPNotification(
    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.

--*/

{

    PDEVICE         Device  =   NbiDevice;
    USHORT          MaximumNicId = 0;
    CTELockHandle   LockHandle;
    UCHAR           PrevReservedName[NB_NETBIOS_NAME_SIZE];
    UNICODE_STRING  UnicodeDeviceName;


    NB_DEBUG2( DEVICE, ("Received a pnp notification, opcode %d\n",OpCode ));

    switch( OpCode ) {
    case IPX_PNP_ADD_DEVICE : {
        IPX_PNP_INFO   UNALIGNED *PnPInfo = (IPX_PNP_INFO UNALIGNED *)PnPData;
        BOOLEAN        ReallocReceiveBuffers = FALSE;

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

        if ( PnPInfo->NewReservedAddress ) {

            *(UNALIGNED ULONG *)Device->Bind.Network    =   PnPInfo->NetworkAddress;
            RtlCopyMemory( Device->Bind.Node, PnPInfo->NodeAddress, 6);

//            RtlZeroMemory(Device->ReservedNetbiosName, NB_NETBIOS_NAME_SIZE);
//            RtlCopyMemory(&Device->ReservedNetbiosName[10], Device->Bind.Node, 6);

            *(UNALIGNED ULONG *)Device->ConnectionlessHeader.SourceNetwork = *(UNALIGNED ULONG *)Device->Bind.Network;
            RtlCopyMemory(Device->ConnectionlessHeader.SourceNode, Device->Bind.Node, 6);
        }

        if ( PnPInfo->FirstORLastDevice ) {
            CTEAssert( PnPInfo->NewReservedAddress );
            CTEAssert( Device->State != DEVICE_STATE_OPEN );


            //
            // we must do this while we still have the device lock.
            //
            if ( !Device->LongTimerRunning ) {
                Device->LongTimerRunning    =   TRUE;
                NbiReferenceDevice (Device, DREF_LONG_TIMER);

                CTEStartTimer(
                    &Device->LongTimer,
                    LONG_TIMER_DELTA,
                    NbiLongTimeout,
                    (PVOID)Device);

            }

            Device->State   =   DEVICE_STATE_OPEN;

            CTEAssert( !Device->MaximumNicId );

            Device->Bind.LineInfo.MaximumSendSize = PnPInfo->LineInfo.MaximumSendSize;
            Device->Bind.LineInfo.MaximumPacketSize = PnPInfo->LineInfo.MaximumSendSize;
            ReallocReceiveBuffers   = TRUE;
        } else {
            if ( PnPInfo->LineInfo.MaximumPacketSize > Device->CurMaxReceiveBufferSize ) {
                ReallocReceiveBuffers =  TRUE;
            }
            //
            // MaxSendSize could become smaller.
            //
            Device->Bind.LineInfo.MaximumSendSize = PnPInfo->LineInfo.MaximumSendSize;
        }

        Device->MaximumNicId++;


        //
        //
        NbiCreateAdapterAddress( PnPInfo->NodeAddress );

        //
        // And finally remove all the failed cache entries since we might
        // find those routes using this new adapter
        //
        FlushFailedNetbiosCacheEntries(Device->NameCache);

        NB_FREE_LOCK( &Device->Lock, LockHandle );


        if ( ReallocReceiveBuffers ) {
            PWORK_QUEUE_ITEM    WorkItem;

            WorkItem = NbiAllocateMemory( sizeof(WORK_QUEUE_ITEM), MEMORY_WORK_ITEM, "Alloc Rcv Buffer work item");

            if ( WorkItem ) {
                ExInitializeWorkItem( WorkItem, NbiReAllocateReceiveBufferPool, (PVOID) WorkItem );
                ExQueueWorkItem( WorkItem, DelayedWorkQueue );
            } else {
                NB_DEBUG( DEVICE, ("Cannt schdule work item to realloc receive buffer pool\n"));
            }
        }
        //
        // Notify the TDI clients about the device creation
        //
        if ( PnPInfo->FirstORLastDevice ) {
            UnicodeDeviceName.Buffer        =  Device->DeviceName;
            UnicodeDeviceName.MaximumLength =  Device->DeviceNameLength;
            UnicodeDeviceName.Length        =  Device->DeviceNameLength - sizeof(WCHAR);

            if ( !NT_SUCCESS( TdiRegisterDeviceObject(
                                &UnicodeDeviceName,
                                &Device->TdiRegistrationHandle ) )) {
                NB_DEBUG( DEVICE, ("Failed to register nwlnknb with TDI\n"));
            }
        }

        break;
    }
    case IPX_PNP_DELETE_DEVICE : {

        IPX_PNP_INFO   UNALIGNED *PnPInfo = (IPX_PNP_INFO UNALIGNED *)PnPData;

        PLIST_ENTRY     p;
        PNETBIOS_CACHE  CacheName;
        USHORT          i,j,NetworksRemoved;

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

        CTEAssert( Device->MaximumNicId );
        Device->MaximumNicId--;

        if ( PnPInfo->FirstORLastDevice ) {
            Device->State   =   DEVICE_STATE_LOADED;
            Device->MaximumNicId    = 0;

        }


        //
        // MaximumSendSize could change if the card with the smallest send size just
        // got removed. MaximumPacketSize could only become smaller and we ignore that
        // since we dont need to(want to) realloc ReceiveBuffers.
        //

        Device->Bind.LineInfo.MaximumSendSize   =   PnPInfo->LineInfo.MaximumSendSize;

        //
        // Flush all the cache entries that are using this NicId in the local
        // target.
        //
        RemoveInvalidRoutesFromNetbiosCacheTable( Device->NameCache, &PnPInfo->NicHandle );

        NbiDestroyAdapterAddress( NULL, PnPInfo->NodeAddress );

        NB_FREE_LOCK( &Device->Lock, LockHandle );

/*        //
        // Now mark the previous reserved name in conflict if it has
        // been registered by any of our client
        //
            if ( Address = NbiFindAddress( Device, PrevReservedName ) ) {
                NB_GET_LOCK( &Address->Lock, &LockHandle );
                Address->Flags  |=  ADDRESS_FLAGS_CONFLICT;
                NB_FREE_LOCK( &Address->Lock, LockHandle );

                NB_DEBUG( ADDRESS, ("Reserved Address %lx<%.16s> is marked CONFLICT\n",Address,Address->NetbiosAddress.NetbiosName));
                //
                // nbifindaddress added a reference, so deref
                //
                NbiDereferenceAddress( Address, AREF_FIND );
            }
*/

        //
        // inform tdi clients about the device deletion
        //
        if ( PnPInfo->FirstORLastDevice ) {
            if ( !NT_SUCCESS( TdiDeregisterDeviceObject(
                                Device->TdiRegistrationHandle ) )) {
                NB_DEBUG( DEVICE, ("Failed to Deregister nwlnknb with TDI\n"));
            }
        }

        break;
    }
    case IPX_PNP_ADDRESS_CHANGE: {
        IPX_PNP_INFO   UNALIGNED *PnPInfo = (IPX_PNP_INFO UNALIGNED *)PnPData;
        PADDRESS        Address;
        BOOLEAN ReservedNameClosing = FALSE;

        CTEAssert( PnPInfo->NewReservedAddress );

        NB_GET_LOCK( &Device->Lock, &LockHandle );
        *(UNALIGNED ULONG *)Device->Bind.Network    =   PnPInfo->NetworkAddress;
        RtlCopyMemory( Device->Bind.Node, PnPInfo->NodeAddress, 6);

        *(UNALIGNED ULONG *)Device->ConnectionlessHeader.SourceNetwork = *(UNALIGNED ULONG *)Device->Bind.Network;
        RtlCopyMemory(Device->ConnectionlessHeader.SourceNode, Device->Bind.Node, 6);

        NB_FREE_LOCK( &Device->Lock, LockHandle );


        break;
    }
    case IPX_PNP_TRANSLATE_DEVICE:
        break;
    case IPX_PNP_TRANSLATE_ADDRESS:
        break;
    default:
        CTEAssert( FALSE );
    }
}   /* NbiPnPNotification */
Ejemplo n.º 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);
}
Ejemplo n.º 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);
}
Ejemplo n.º 14
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);
    }
}
Ejemplo n.º 15
0
VOID
spxTimerEnqueue(
    IN	PTIMERLIST	pListNew
)
/*++

Routine Description:

 	Here is a thesis on the code that follows.

 	The timer events are maintained as a list which the timer dpc routine
 	looks at every timer tick. The list is maintained in such a way that only
 	the head of the list needs to be updated every tick i.e. the entire list
 	is never scanned. The way this is achieved is by keeping delta times
 	relative to the previous entry.

 	Every timer tick, the relative time at the head of the list is decremented.
 	When that goes to ZERO, the head of the list is unlinked and dispatched.

 	To give an example, we have the following events queued at time slots
 	X			Schedule A after 10 ticks.
 	X+3			Schedule B after 5  ticks.
 	X+5			Schedule C after 4  ticks.
 	X+8			Schedule D after 6  ticks.

 	So A will schedule at X+10, B at X+8 (X+3+5), C at X+9 (X+5+4) and
 	D at X+14 (X+8+6).

 	The above example covers all the situations.

 	- NULL List.
 	- Inserting at head of list.
 	- Inserting in the middle of the list.
 	- Appending to the list tail.

 	The list will look as follows.

 		    BEFORE                          AFTER
 		    ------                          -----

     X   Head -->|                  Head -> A(10) ->|
     A(10)

     X+3 Head -> A(7) ->|           Head -> B(5) -> A(2) ->|
     B(5)

     X+5 Head -> B(3) -> A(2) ->|   Head -> B(3) -> C(1) -> A(1) ->|
     C(4)

     X+8 Head -> C(1) -> A(1) ->|   Head -> C(1) -> A(1) -> D(4) ->|
     D(6)

 	The granularity is one tick. THIS MUST BE CALLED WITH THE TIMER LOCK HELD.

Arguments:


Return Value:


--*/
{
    PTIMERLIST	pList, *ppList;
    ULONG		DeltaTime = pListNew->tmr_AbsTime;

    // The DeltaTime is adjusted in every pass of the loop to reflect the
    // time after the previous entry that the new entry will schedule.
    for (ppList = &spxTimerList;
            (pList = *ppList) != NULL;
            ppList = &pList->tmr_Next)
    {
        CTEAssert(VALID_TMR(pList));
        if (DeltaTime <= pList->tmr_RelDelta)
        {
            pList->tmr_RelDelta -= DeltaTime;
            break;
        }
        DeltaTime -= pList->tmr_RelDelta;
    }


    // Link this in the chain
    pListNew->tmr_RelDelta = DeltaTime;
    pListNew->tmr_Next = pList;
    pListNew->tmr_Prev = ppList;
    *ppList = pListNew;
    if (pList != NULL)
    {
        pList->tmr_Prev = &pListNew->tmr_Next;
    }

    // Now link it in the hash table
    pListNew->tmr_Overflow = spxTimerTable[pListNew->tmr_Id % TIMER_HASH_TABLE];
    spxTimerTable[pListNew->tmr_Id % TIMER_HASH_TABLE] = pListNew;
    spxTimerCount ++;
}
Ejemplo n.º 16
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
}
Ejemplo n.º 17
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);

}
Ejemplo n.º 18
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);

}
Ejemplo n.º 19
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);
}
Ejemplo n.º 20
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);
}