/* * Copyright (c) 1999 - 2003 * NetGroup, Politecnico di Torino (Italy) * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the Politecnico di Torino nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include "debug.h" #include "packet.h" #include #pragma VxD_LOCKED_CODE_SEG #pragma VxD_LOCKED_DATA_SEG /************************************************************ Function that allows to perform a query on a network driver or to set the parameters of an adapter. ************************************************************/ DWORD PacketRequest( POPEN_INSTANCE Open, DWORD FunctionCode, DWORD dwDDB, DWORD hDevice, PDIOCPARAMETERS pDiocParms ) { PLIST_ENTRY RequestListEntry; PINTERNAL_REQUEST pRequest; PPACKET_RESERVED pReserved; PPACKET_OID_DATA OidData; NDIS_STATUS Status; TRACE_ENTER( "Request Packet" ); /*extract a request from the list*/ NdisAcquireSpinLock( &Open->RequestSpinLock ); RequestListEntry = PacketRemoveHeadList(&Open->RequestList); NdisReleaseSpinLock( &Open->RequestSpinLock ); if ( RequestListEntry == NULL ) { IF_TRACE( "Request List Error" ); *(DWORD *)(pDiocParms->lpcbBytesReturned) = 0; TRACE_LEAVE( "Request Packet" ); return NDIS_STATUS_FAILURE/*NDIS_STATUS_SUCCESS*/; } pReserved = CONTAINING_RECORD( RequestListEntry, PACKET_RESERVED, ListElement ); pRequest = CONTAINING_RECORD( pReserved, INTERNAL_REQUEST, Reserved ); OidData = (PPACKET_OID_DATA)(pDiocParms->lpvInBuffer); if ( ( pDiocParms->cbInBuffer == pDiocParms->cbOutBuffer ) && ( pDiocParms->cbInBuffer >= sizeof(PACKET_OID_DATA) - 1 + OidData->Length) ) { pReserved->lpBuffer = (PVOID)PacketPageLock( pDiocParms->lpvInBuffer, pDiocParms->cbInBuffer ); pReserved->lpcbBytesReturned= (PVOID)PacketPageLock( (PVOID)pDiocParms->lpcbBytesReturned, sizeof(DWORD) ); pReserved->lpoOverlapped = (PVOID)PacketPageLock( (PVOID)pDiocParms->lpoOverlapped, sizeof(OVERLAPPED) ); pReserved->cbBuffer = pDiocParms->cbInBuffer; if ( FunctionCode == BIOCSETOID ) { pRequest->Request.RequestType = NdisRequestSetInformation; pRequest->Request.DATA.SET_INFORMATION.Oid = OidData->Oid; pRequest->Request.DATA.SET_INFORMATION.InformationBufferLength = OidData->Length; pRequest->Request.DATA.SET_INFORMATION.InformationBuffer = OidData->Data; IF_PACKETDEBUG( PACKET_DEBUG_VERY_LOUD ) { IF_TRACE_MSG2( "Request Set: Oid=%08lx, Length=%08lx", OidData->Oid, OidData->Length ); } } else if ( FunctionCode == BIOCQUERYOID ) { pRequest->Request.RequestType = NdisRequestQueryInformation; pRequest->Request.DATA.QUERY_INFORMATION.Oid = OidData->Oid; pRequest->Request.DATA.QUERY_INFORMATION.InformationBufferLength= OidData->Length; pRequest->Request.DATA.QUERY_INFORMATION.InformationBuffer = OidData->Data; IF_PACKETDEBUG( PACKET_DEBUG_VERY_LOUD ) { IF_TRACE_MSG3( "Request Query: Type:%d Oid=%08lx, Length=%08lx", NdisRequestQueryInformation, OidData->Oid, OidData->Length ); } } else { pRequest->Request.RequestType = NdisRequestGeneric1; pRequest->Request.DATA.QUERY_INFORMATION.Oid = OidData->Oid; pRequest->Request.DATA.QUERY_INFORMATION.InformationBufferLength= OidData->Length; pRequest->Request.DATA.QUERY_INFORMATION.InformationBuffer = OidData->Data; IF_PACKETDEBUG( PACKET_DEBUG_VERY_LOUD ) { IF_TRACE_MSG3( "Request Statistic: Type:%d Oid=%08lx, Length=%08lx", NdisRequestGeneric1, OidData->Oid, OidData->Length ); } } NdisRequest( &Status, Open->AdapterHandle, &pRequest->Request ); if ( Status != NDIS_STATUS_PENDING ) { PacketRequestComplete( Open, &pRequest->Request, Status ); TRACE_LEAVE( "Request Packet" ); return /*NDIS_STATUS_FAILURE*/NDIS_STATUS_SUCCESS; } TRACE_LEAVE( "Request Packet" ); return (-1); /*Return ERROR_IO_PENDING and block the application*/ } else { IF_TRACE_MSG4( "Request Buffer Error: In=%lx Out=%lx Size=%lx Length=%lx", pDiocParms->cbInBuffer, pDiocParms->cbOutBuffer, sizeof( PACKET_OID_DATA ), OidData->Length ); *(DWORD *)(pDiocParms->lpcbBytesReturned) = 0; } TRACE_LEAVE( "Request Packet" ); return NDIS_STATUS_FAILURE/*NDIS_STATUS_SUCCESS*/; } /************************************************************ Function called by NDIS to complete asynchornously a request INPUT: ProtocolBindingContext - Structure describing the current adapter NdisRequest - Queue of NDIS internal requests Status - Status of the operation reported by NDIS ************************************************************/ VOID NDIS_API PacketRequestComplete( IN NDIS_HANDLE ProtocolBindingContext, IN PNDIS_REQUEST NdisRequest, IN NDIS_STATUS Status ) { POPEN_INSTANCE Open; PINTERNAL_REQUEST pRequest; PPACKET_RESERVED pReserved; OVERLAPPED* pOverlap; PPACKET_OID_DATA oidData; TRACE_ENTER( "RequestComplete" ); Open = (POPEN_INSTANCE)ProtocolBindingContext; pRequest = CONTAINING_RECORD( NdisRequest, INTERNAL_REQUEST, Request ); pReserved = &pRequest->Reserved; pOverlap = (OVERLAPPED *) pReserved->lpoOverlapped; oidData = (PPACKET_OID_DATA)(pReserved->lpBuffer); #if DEBUG IF_PACKETDEBUG( PACKET_DEBUG_VERY_LOUD ) { ULONG i; UCHAR* pcData = oidData->Data; DbgPrint( "Packet: OID=%lx Status=%lx Buffer Length=%ld Buffer=%lx", oidData->Oid, Status, oidData->Length, pcData ); for ( i=0; iLength; i++, pcData++ ) { if ( i%16 == 0 ) DbgPrint( "\r\nPacket: " ); DbgPrint( "%02x ", *pcData ); } DbgPrint( "\r\n" ); IF_BREAK_SET; } #endif if ( Status == NDIS_STATUS_SUCCESS ) { /*if the operation was succesful*/ *(pReserved->lpcbBytesReturned) = oidData->Length + sizeof(PACKET_OID_DATA) - 1; pOverlap->O_InternalHigh = *(pReserved->lpcbBytesReturned); } else { /*if there is an error length contains the type of error*/ *(pReserved->lpcbBytesReturned) = 0; pOverlap->O_InternalHigh = 0; oidData->Length = Status; } /*wakes the suspended process */ VWIN32_DIOCCompletionRoutine( pOverlap->O_Internal ); PacketPageUnlock( pReserved->lpBuffer, pReserved->cbBuffer ); PacketPageUnlock( pReserved->lpcbBytesReturned, sizeof(DWORD) ); PacketPageUnlock( pReserved->lpoOverlapped, sizeof(OVERLAPPED) ); /*reinsert the request in the queue*/ NdisAcquireSpinLock( &Open->RequestSpinLock ); InsertTailList( &Open->RequestList, &pReserved->ListElement ); NdisReleaseSpinLock( &Open->RequestSpinLock ); TRACE_LEAVE( "RequestComplete" ); return; }