/************************************************************ 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 ); } }
VOID PacketAllocatePacketBuffer(PNDIS_STATUS pStatus, POPEN_INSTANCE pOpen, PNDIS_PACKET *ppPacket, PDIOCPARAMETERS pDiocParms, DWORD FunctionCode ) { // allocate a buffer for reading/writing PNDIS_BUFFER pNdisBuffer; PNDIS_PACKET pPacket; // Try to get a packet from our list of free ones NdisAllocatePacket(pStatus, ppPacket, pOpen->PacketPool); if (*pStatus != NDIS_STATUS_SUCCESS) { *(DWORD *)(pDiocParms->lpcbBytesReturned) = 0; return; } pPacket = *ppPacket; // Buffers used asynchronously must be page locked switch (FunctionCode) { case IOCTL_EPACKET_READ: RESERVED(pPacket)->lpBuffer = (PVOID)PacketPageLock(pDiocParms->lpvOutBuffer, pDiocParms->cbOutBuffer); RESERVED(pPacket)->cbBuffer = pDiocParms->cbOutBuffer; break; case IOCTL_EPACKET_WRITE: RESERVED(pPacket)->lpBuffer = (PVOID)PacketPageLock(pDiocParms->lpvInBuffer, pDiocParms->cbInBuffer); RESERVED(pPacket)->cbBuffer = pDiocParms->cbInBuffer; break; default: // recycle the packet NdisReinitializePacket(pPacket); // Put the packet on the free queue NdisFreePacket(pPacket); *(DWORD *)(pDiocParms->lpcbBytesReturned) = 0; *pStatus = NDIS_STATUS_NOT_ACCEPTED; return; } RESERVED(pPacket)->lpcbBytesReturned = (PVOID)PacketPageLock(pDiocParms->lpcbBytesReturned, sizeof(DWORD)); RESERVED(pPacket)->lpoOverlapped = (PVOID)PacketPageLock(pDiocParms->lpoOverlapped, sizeof(OVERLAPPED)); RESERVED(pPacket)->hDevice = pDiocParms->hDevice; RESERVED(pPacket)->tagProcess = pDiocParms->tagProcess; switch (FunctionCode) { case IOCTL_EPACKET_READ: NdisAllocateBuffer(pStatus, &pNdisBuffer, pOpen->BufferPool, (PVOID)(RESERVED(pPacket)->lpBuffer + ETHERNET_HEADER_LENGTH), pDiocParms->cbOutBuffer); break; case IOCTL_EPACKET_WRITE: NdisAllocateBuffer(pStatus, &pNdisBuffer, pOpen->BufferPool, (PVOID)RESERVED(pPacket)->lpBuffer, pDiocParms->cbInBuffer); break; } if (*pStatus == NDIS_STATUS_SUCCESS) NdisChainBufferAtFront(pPacket, pNdisBuffer); // Attach buffer to Packet else { NdisReinitializePacket(pPacket); // recycle the packet NdisFreePacket(pPacket); // Put the packet on the free queue *(DWORD *)(pDiocParms->lpcbBytesReturned) = 0; } }
DWORD NDIS_API PacketRequest(POPEN_INSTANCE Open, DWORD FunctionCode, DWORD dwDDB, DWORD hDevice, PDIOCPARAMETERS pDiocParms) { // perform a packet request PLIST_ENTRY RequestListEntry; PINTERNAL_REQUEST pRequest; PPACKET_RESERVED pReserved; EPACKET_OID * OidData; NDIS_STATUS Status; // Acquire request element from list NdisAcquireSpinLock(&Open->RequestSpinLock); if (IsListEmpty(&Open->RequestList)) { *(DWORD *)(pDiocParms->lpcbBytesReturned) = 0; NdisReleaseSpinLock(&Open->RequestSpinLock); return NDIS_STATUS_SUCCESS; } RequestListEntry = RemoveHeadList(&Open->RequestList); NdisReleaseSpinLock(&Open->RequestSpinLock); pReserved = CONTAINING_RECORD(RequestListEntry, PACKET_RESERVED, ListElement); pRequest = CONTAINING_RECORD(pReserved, INTERNAL_REQUEST, Reserved); OidData = (EPACKET_OID*)(pDiocParms->lpvInBuffer); if ((pDiocParms->cbInBuffer != pDiocParms->cbOutBuffer) || (pDiocParms->cbInBuffer < sizeof(*OidData) - sizeof(OidData->Data) + OidData->Length)) { *(DWORD *)pDiocParms->lpcbBytesReturned = 1; return NDIS_STATUS_BUFFER_TOO_SHORT; } // The buffer is valid pReserved->lpBuffer = (PVOID)PacketPageLock(pDiocParms->lpvInBuffer, pDiocParms->cbInBuffer); pReserved->lpcbBytesReturned = (PVOID)PacketPageLock(pDiocParms->lpcbBytesReturned, sizeof(DWORD)); pReserved->lpoOverlapped = (PVOID)PacketPageLock(pDiocParms->lpoOverlapped, sizeof(OVERLAPPED)); pReserved->cbBuffer = pDiocParms->cbInBuffer; pReserved->hDevice = pDiocParms->hDevice; pReserved->tagProcess = pDiocParms->tagProcess; if (FunctionCode == IOCTL_EPACKET_SET_OID) { 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; } else { if (OidData->Oid >= 0x01000000) pRequest->Request.RequestType = NdisRequestQueryInformation; 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; } // submit the request NdisRequest(&Status, Open->AdapterHandle, &pRequest->Request); if (Status == NDIS_STATUS_PENDING) return(-1); // This will make DeviceIOControl return ERROR_IO_PENDING PacketRequestComplete(Open, &pRequest->Request, Status); return Status; }