/* * This file contains NDIS OID support procedures, common for NDIS5 and NDIS6 * * Copyright (c) 2008-2017 Red Hat, Inc. * * 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 names of the copyright holders nor the names of their 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 HOLDERS 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 "ParaNdis-Oid.h" #ifdef WPP_EVENT_TRACING #include "ParaNdis-Oid.tmh" #endif #include static const char VendorName[] = "Red Hat"; static UCHAR FORCEINLINE hexdigit(UCHAR nibble) { UCHAR c = nibble & 0xf; c += (c <= 9) ? 0 : 7; c += '0'; return c; } /********************************************************** Common implementation of copy operation when OID is set pOid->Flags (if used) controls when the source data may be truncated or padded on copy Parameters: tOidDesc *pOid - descriptor of OID PVOID pDest - buffer to receive data sent by NDIS ULONG ulSize - size of data to copy Return value: SUCCESS or NDIS error code if target buffer size is wrong Rules: PDEST <>OK SIZE PAYLOAD SZ NULL any n/a any fail BUFF any 0 any success, none copied BUFF any SZ ==SZ success, copied SZ BUFF !lessok SZ SZ fail (overflow), none copied BUFF lessok SZ SZ success, copied SZ ***************************************************/ NDIS_STATUS ParaNdis_OidSetCopy( tOidDesc *pOid, PVOID pDest, ULONG ulSize) { NDIS_STATUS status = NDIS_STATUS_SUCCESS; if (!pDest) { status = NDIS_STATUS_INVALID_OID; *(pOid->pBytesRead) = 0; *(pOid->pBytesNeeded) = 0; } else if (ulSize) { if (pOid->InformationBufferLength < ulSize) { if (pOid->ulToDoFlags & ohfSetLessOK) { *(pOid->pBytesRead) = pOid->InformationBufferLength; NdisZeroMemory(pDest, ulSize); NdisMoveMemory(pDest, pOid->InformationBuffer, pOid->InformationBufferLength); } else { status = NDIS_STATUS_BUFFER_TOO_SHORT; *(pOid->pBytesRead) = 0; *(pOid->pBytesNeeded) = ulSize; } } else if (pOid->InformationBufferLength == ulSize || (pOid->ulToDoFlags & ohfSetMoreOK)) { *(pOid->pBytesRead) = ulSize; NdisMoveMemory(pDest, pOid->InformationBuffer, ulSize); } else { status = NDIS_STATUS_BUFFER_OVERFLOW; *(pOid->pBytesNeeded) = ulSize; *(pOid->pBytesRead) = 0; } } else { *(pOid->pBytesRead) = pOid->InformationBufferLength; } return status; } /********************************************************** Common handler of setting packet filter ***********************************************************/ NDIS_STATUS ParaNdis_OnSetPacketFilter(PARANDIS_ADAPTER *pContext, tOidDesc *pOid) { ULONG newValue; NDIS_STATUS status = ParaNdis_OidSetCopy( pOid, &newValue, sizeof(newValue)); if (newValue & ~PARANDIS_PACKET_FILTERS) status = NDIS_STATUS_INVALID_DATA; if (status == NDIS_STATUS_SUCCESS) { pContext->PacketFilter = newValue; DPrintf(1, ("[%s] PACKET FILTER SET TO %x", __FUNCTION__, pContext->PacketFilter)); ParaNdis_UpdateDeviceFilters(pContext); } return status; } void ParaNdis_FillPowerCapabilities(PNDIS_PNP_CAPABILITIES pCaps) { NdisZeroMemory(pCaps, sizeof(*pCaps)); pCaps->WakeUpCapabilities.MinMagicPacketWakeUp = NdisDeviceStateUnspecified; pCaps->WakeUpCapabilities.MinPatternWakeUp = NdisDeviceStateUnspecified; pCaps->WakeUpCapabilities.MinLinkChangeWakeUp = NdisDeviceStateUnspecified; } /********************************************************** Common handler of setting multicast list ***********************************************************/ NDIS_STATUS ParaNdis_OnOidSetMulticastList(PARANDIS_ADAPTER *pContext, tOidDesc *pOid) { NDIS_STATUS status; status = ParaNdis_SetMulticastList( pContext, pOid->InformationBuffer, pOid->InformationBufferLength, pOid->pBytesRead, pOid->pBytesNeeded); ParaNdis_UpdateDeviceFilters(pContext); return status; } /********************************************************** Common helper of copy operation on GET OID Copies data from specified location to NDIS buffer 64-bit variable will be casted to 32-bit, if specified on pOid->Flags Parameters: tOidDesc *pOid - descriptor of OID PVOID pInfo - source to copy from ULONG ulSize - source info size Return value: SUCCESS or kind of failure when the dest buffer size is wrong Comments: pInfo must be non-NULL, otherwise error returned ulSize may be 0, then SUCCESS returned without copy ***********************************************************/ NDIS_STATUS ParaNdis_OidQueryCopy( tOidDesc *pOid, PVOID pInfo, ULONG ulSize, BOOLEAN bFreeInfo) { NDIS_STATUS status = NDIS_STATUS_SUCCESS; *(pOid->pBytesNeeded) = ulSize; if (!pInfo) { status = NDIS_STATUS_INVALID_OID; *(pOid->pBytesWritten) = 0; *(pOid->pBytesNeeded) = 0; } else if (pOid->InformationBufferLength >= ulSize) { if (ulSize) NdisMoveMemory(pOid->InformationBuffer, pInfo, ulSize); *(pOid->pBytesWritten) = ulSize; *(pOid->pBytesNeeded) = 0; } else if ((pOid->ulToDoFlags & ohfQuery3264) && pOid->InformationBufferLength == sizeof(ULONG) && ulSize == sizeof(ULONG64)) { ULONG64 u64 = *(ULONG64 *)pInfo; ULONG ul = (ULONG)u64; NdisMoveMemory(pOid->InformationBuffer, &ul, sizeof(ul)); *(pOid->pBytesWritten) = sizeof(ul); } else { status = NDIS_STATUS_BUFFER_TOO_SHORT; *(pOid->pBytesWritten) = 0; } if (bFreeInfo && pInfo) { NdisFreeMemory(pInfo, 0, 0); } return status; } /********************************************************** Common handler of Oid queries Parameters: context tOidDesc *pOid - filled descriptor of OID operation Return value: SUCCESS or kind of failure ***********************************************************/ NDIS_STATUS ParaNdis_OidQueryCommon(PARANDIS_ADAPTER *pContext, tOidDesc *pOid) { NDIS_STATUS status = NDIS_STATUS_SUCCESS; PVOID pInfo = NULL; ULONG ulSize = 0; BOOLEAN bFreeInfo = FALSE; union _tagtemp { NDIS_MEDIUM Medium; ULONG64 ul64; ULONG ul; USHORT us; NDIS_PNP_CAPABILITIES PMCaps; } u; #if defined(_MSC_VER) && !defined(__clang__) #define CONCATFIELD(object, field) object.##field #else #define CONCATFIELD(object, field) object.field #endif #define SETINFO(field, value) pInfo = CONCATFIELD(&u, field); ulSize = sizeof(CONCATFIELD(u, field)); CONCATFIELD(u, field) = (value) switch (pOid->Oid) { case OID_GEN_SUPPORTED_LIST: ParaNdis_GetSupportedOid(&pInfo, &ulSize); break; case OID_GEN_HARDWARE_STATUS: SETINFO(ul, NdisHardwareStatusReady); break; case OID_GEN_MEDIA_SUPPORTED: __fallthrough; case OID_GEN_MEDIA_IN_USE: SETINFO(Medium, NdisMedium802_3); break; case OID_GEN_MAXIMUM_LOOKAHEAD: SETINFO(ul, pContext->MaxPacketSize.nMaxFullSizeOS); break; case OID_GEN_MAXIMUM_FRAME_SIZE: SETINFO(ul, pContext->MaxPacketSize.nMaxDataSize); break; case OID_GEN_TRANSMIT_BUFFER_SPACE: SETINFO(ul, pContext->MaxPacketSize.nMaxFullSizeOS * pContext->nofFreeTxDescriptors); break; case OID_GEN_RECEIVE_BUFFER_SPACE: SETINFO(ul, pContext->MaxPacketSize.nMaxFullSizeOS * pContext->NetMaxReceiveBuffers); break; case OID_GEN_RECEIVE_BLOCK_SIZE: __fallthrough; case OID_GEN_TRANSMIT_BLOCK_SIZE: __fallthrough; case OID_GEN_MAXIMUM_TOTAL_SIZE: SETINFO(ul, pContext->MaxPacketSize.nMaxFullSizeOS); break; case OID_GEN_TRANSMIT_QUEUE_LENGTH: // TODO: this is not completely correct, but only if // the TX queue is not full SETINFO(ul, pContext->maxFreeTxDescriptors - pContext->nofFreeTxDescriptors); break; case OID_GEN_VENDOR_ID: SETINFO(ul, 0x00ffffff); break; case OID_GEN_VENDOR_DESCRIPTION: pInfo = (PVOID)VendorName; ulSize = sizeof(VendorName); break; case OID_GEN_VENDOR_DRIVER_VERSION: SETINFO(ul, (NDIS_MINIPORT_MAJOR_VERSION << 16) | NDIS_MINIPORT_MINOR_VERSION); break; case OID_GEN_CURRENT_PACKET_FILTER: pInfo = &pContext->PacketFilter; ulSize = sizeof(pContext->PacketFilter); break; case OID_GEN_DRIVER_VERSION: SETINFO(us, ((NDIS_MINIPORT_MAJOR_VERSION << 8) | NDIS_MINIPORT_MINOR_VERSION)); break; case OID_GEN_MAC_OPTIONS: { ULONG options = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA | NDIS_MAC_OPTION_TRANSFERS_NOT_PEND | NDIS_MAC_OPTION_NO_LOOPBACK; if (IsPrioritySupported(pContext)) options |= NDIS_MAC_OPTION_8021P_PRIORITY; if (IsVlanSupported(pContext)) options |= NDIS_MAC_OPTION_8021Q_VLAN; SETINFO(ul, options); } break; case OID_GEN_MEDIA_CONNECT_STATUS: SETINFO(ul, pContext->bConnected ? NdisMediaStateConnected : NdisMediaStateDisconnected); //NdisMediaStateConnected: break; case OID_GEN_MAXIMUM_SEND_PACKETS: // NDIS ignores it for deserialized drivers SETINFO(ul,pContext->nofFreeTxDescriptors); break; case OID_802_3_PERMANENT_ADDRESS: pInfo = pContext->PermanentMacAddress; ulSize = sizeof(pContext->PermanentMacAddress); break; case OID_802_3_CURRENT_ADDRESS: pInfo = pContext->CurrentMacAddress; ulSize = sizeof(pContext->CurrentMacAddress); break; case OID_PNP_QUERY_POWER: // size if 0, just to indicate success pInfo = &status; break; case OID_GEN_DIRECTED_BYTES_XMIT: SETINFO(ul64, pContext->Statistics.ifHCOutUcastOctets); break; case OID_GEN_DIRECTED_FRAMES_XMIT: SETINFO(ul64, pContext->Statistics.ifHCOutUcastPkts); break; case OID_GEN_MULTICAST_BYTES_XMIT: SETINFO(ul64, pContext->Statistics.ifHCOutMulticastOctets); break; case OID_GEN_MULTICAST_FRAMES_XMIT: SETINFO(ul64, pContext->Statistics.ifHCOutMulticastPkts); break; case OID_GEN_BROADCAST_BYTES_XMIT: SETINFO(ul64, pContext->Statistics.ifHCOutBroadcastOctets); break; case OID_GEN_BROADCAST_FRAMES_XMIT: SETINFO(ul64, pContext->Statistics.ifHCOutBroadcastPkts); break; case OID_GEN_DIRECTED_BYTES_RCV: SETINFO(ul64, pContext->Statistics.ifHCInUcastOctets); break; case OID_GEN_DIRECTED_FRAMES_RCV: SETINFO(ul64, pContext->Statistics.ifHCInUcastPkts); break; case OID_GEN_MULTICAST_BYTES_RCV: SETINFO(ul64, pContext->Statistics.ifHCInMulticastOctets); break; case OID_GEN_MULTICAST_FRAMES_RCV: SETINFO(ul64, pContext->Statistics.ifHCInMulticastPkts); break; case OID_GEN_BROADCAST_BYTES_RCV: SETINFO(ul64, pContext->Statistics.ifHCInBroadcastOctets); break; case OID_GEN_BROADCAST_FRAMES_RCV: SETINFO(ul64, pContext->Statistics.ifHCInBroadcastPkts); break; case OID_GEN_XMIT_OK: SETINFO(ul64, pContext->Statistics.ifHCOutUcastPkts + pContext->Statistics.ifHCOutMulticastPkts + pContext->Statistics.ifHCOutBroadcastPkts); break; case OID_GEN_RCV_OK: SETINFO(ul64, pContext->Statistics.ifHCInUcastPkts + pContext->Statistics.ifHCInMulticastPkts + pContext->Statistics.ifHCInBroadcastPkts); DPrintf(4, ("[%s] Total frames %I64u", __FUNCTION__, u.ul64)); break; case OID_GEN_XMIT_ERROR: SETINFO(ul64, pContext->Statistics.ifOutErrors ); break; case OID_GEN_RCV_ERROR: __fallthrough; case OID_GEN_RCV_NO_BUFFER: __fallthrough; case OID_802_3_RCV_OVERRUN: __fallthrough; case OID_GEN_RCV_CRC_ERROR: __fallthrough; case OID_802_3_RCV_ERROR_ALIGNMENT: __fallthrough; case OID_802_3_XMIT_UNDERRUN: __fallthrough; case OID_802_3_XMIT_ONE_COLLISION: __fallthrough; case OID_802_3_XMIT_DEFERRED: __fallthrough; case OID_802_3_XMIT_MAX_COLLISIONS: __fallthrough; case OID_802_3_XMIT_MORE_COLLISIONS: __fallthrough; case OID_802_3_XMIT_HEARTBEAT_FAILURE: __fallthrough; case OID_802_3_XMIT_TIMES_CRS_LOST: __fallthrough; case OID_802_3_XMIT_LATE_COLLISIONS: SETINFO(ul64, 0); break; case OID_802_3_MULTICAST_LIST: pInfo = pContext->MulticastData.MulticastList; ulSize = pContext->MulticastData.nofMulticastEntries * ETH_LENGTH_OF_ADDRESS; break; case OID_802_3_MAXIMUM_LIST_SIZE: SETINFO(ul, PARANDIS_MULTICAST_LIST_SIZE); break; case OID_PNP_CAPABILITIES: pInfo = &u.PMCaps; ulSize = sizeof(u.PMCaps); ParaNdis_FillPowerCapabilities(&u.PMCaps); break; case OID_802_3_MAC_OPTIONS: SETINFO(ul, 0); break; case OID_GEN_VLAN_ID: SETINFO(ul, pContext->VlanId); if (!IsVlanSupported(pContext)) status = NDIS_STATUS_NOT_SUPPORTED; break; case OID_GEN_CURRENT_LOOKAHEAD: if (!pContext->DummyLookAhead) pContext->DummyLookAhead = pContext->MaxPacketSize.nMaxFullSizeOS; pInfo = &pContext->DummyLookAhead; ulSize = sizeof(pContext->DummyLookAhead); break; case OID_PNP_ENABLE_WAKE_UP: SETINFO(ul, pContext->ulEnableWakeup); break; default: status = NDIS_STATUS_NOT_SUPPORTED; break; } if (status == NDIS_STATUS_SUCCESS) { status = ParaNdis_OidQueryCopy(pOid, pInfo, ulSize, bFreeInfo); } return status; } /********************************************************** Just gets OID name ***********************************************************/ const char *ParaNdis_OidName(NDIS_OID oid) { #undef MAKECASE #define MAKECASE(id) case id: return #id; switch (oid) { MAKECASE(OID_GEN_SUPPORTED_LIST) MAKECASE(OID_GEN_HARDWARE_STATUS) MAKECASE(OID_GEN_MEDIA_SUPPORTED) MAKECASE(OID_GEN_MEDIA_IN_USE) MAKECASE(OID_GEN_MAXIMUM_LOOKAHEAD) MAKECASE(OID_GEN_MAXIMUM_FRAME_SIZE) MAKECASE(OID_GEN_LINK_SPEED) MAKECASE(OID_GEN_TRANSMIT_BUFFER_SPACE) MAKECASE(OID_GEN_RECEIVE_BUFFER_SPACE) MAKECASE(OID_GEN_TRANSMIT_BLOCK_SIZE) MAKECASE(OID_GEN_RECEIVE_BLOCK_SIZE) MAKECASE(OID_GEN_VENDOR_ID) MAKECASE(OID_GEN_VENDOR_DESCRIPTION) MAKECASE(OID_GEN_CURRENT_PACKET_FILTER) MAKECASE(OID_GEN_CURRENT_LOOKAHEAD) MAKECASE(OID_GEN_DRIVER_VERSION) MAKECASE(OID_GEN_MAXIMUM_TOTAL_SIZE) MAKECASE(OID_GEN_PROTOCOL_OPTIONS) MAKECASE(OID_GEN_MAC_OPTIONS) MAKECASE(OID_GEN_MEDIA_CONNECT_STATUS) MAKECASE(OID_GEN_MAXIMUM_SEND_PACKETS) MAKECASE(OID_GEN_VENDOR_DRIVER_VERSION) MAKECASE(OID_GEN_SUPPORTED_GUIDS) MAKECASE(OID_GEN_TRANSPORT_HEADER_OFFSET) MAKECASE(OID_GEN_MEDIA_CAPABILITIES) MAKECASE(OID_GEN_PHYSICAL_MEDIUM) MAKECASE(OID_GEN_XMIT_OK) MAKECASE(OID_GEN_RCV_OK) MAKECASE(OID_GEN_XMIT_ERROR) MAKECASE(OID_GEN_RCV_ERROR) MAKECASE(OID_GEN_RCV_NO_BUFFER) MAKECASE(OID_GEN_DIRECTED_BYTES_XMIT) MAKECASE(OID_GEN_DIRECTED_FRAMES_XMIT) MAKECASE(OID_GEN_MULTICAST_BYTES_XMIT) MAKECASE(OID_GEN_MULTICAST_FRAMES_XMIT) MAKECASE(OID_GEN_BROADCAST_BYTES_XMIT) MAKECASE(OID_GEN_BROADCAST_FRAMES_XMIT) MAKECASE(OID_GEN_DIRECTED_BYTES_RCV) MAKECASE(OID_GEN_DIRECTED_FRAMES_RCV) MAKECASE(OID_GEN_MULTICAST_BYTES_RCV) MAKECASE(OID_GEN_MULTICAST_FRAMES_RCV) MAKECASE(OID_GEN_BROADCAST_BYTES_RCV) MAKECASE(OID_GEN_BROADCAST_FRAMES_RCV) MAKECASE(OID_GEN_RCV_CRC_ERROR) MAKECASE(OID_GEN_TRANSMIT_QUEUE_LENGTH) MAKECASE(OID_GEN_GET_TIME_CAPS) MAKECASE(OID_GEN_GET_NETCARD_TIME) MAKECASE(OID_GEN_NETCARD_LOAD) MAKECASE(OID_GEN_DEVICE_PROFILE) MAKECASE(OID_GEN_INIT_TIME_MS) MAKECASE(OID_GEN_RESET_COUNTS) MAKECASE(OID_GEN_MEDIA_SENSE_COUNTS) MAKECASE(OID_GEN_VLAN_ID) MAKECASE(OID_PNP_CAPABILITIES) MAKECASE(OID_PNP_SET_POWER) MAKECASE(OID_PNP_QUERY_POWER) MAKECASE(OID_PNP_ADD_WAKE_UP_PATTERN) MAKECASE(OID_PNP_REMOVE_WAKE_UP_PATTERN) MAKECASE(OID_PNP_ENABLE_WAKE_UP) MAKECASE(OID_802_3_PERMANENT_ADDRESS) MAKECASE(OID_802_3_CURRENT_ADDRESS) MAKECASE(OID_802_3_MULTICAST_LIST) MAKECASE(OID_802_3_MAXIMUM_LIST_SIZE) MAKECASE(OID_802_3_MAC_OPTIONS) MAKECASE(OID_802_3_RCV_ERROR_ALIGNMENT) MAKECASE(OID_802_3_XMIT_ONE_COLLISION) MAKECASE(OID_802_3_XMIT_MORE_COLLISIONS) MAKECASE(OID_802_3_XMIT_DEFERRED) MAKECASE(OID_802_3_XMIT_MAX_COLLISIONS) MAKECASE(OID_802_3_RCV_OVERRUN) MAKECASE(OID_802_3_XMIT_UNDERRUN) MAKECASE(OID_802_3_XMIT_HEARTBEAT_FAILURE) MAKECASE(OID_802_3_XMIT_TIMES_CRS_LOST) MAKECASE(OID_802_3_XMIT_LATE_COLLISIONS) MAKECASE(OID_GEN_MACHINE_NAME) MAKECASE(OID_TCP_TASK_OFFLOAD) MAKECASE(OID_TCP_OFFLOAD_PARAMETERS) MAKECASE(OID_OFFLOAD_ENCAPSULATION) MAKECASE(OID_IP4_OFFLOAD_STATS) MAKECASE(OID_IP6_OFFLOAD_STATS) default: { static UCHAR buffer[9]; UINT i; for (i = 0; i < 8; ++i) { UCHAR nibble = (UCHAR)((oid >> (28 - i * 4)) & 0xf); buffer[i] = hexdigit(nibble); } return (char *)buffer; } } } /********************************************************** Checker of valid size of provided wake-up patter Return value: SUCCESS or kind of failure where the buffer is wrong ***********************************************************/ static NDIS_STATUS ValidateWakeupPattern(PNDIS_PM_PACKET_PATTERN p, PULONG pValidSize) { NDIS_STATUS status = NDIS_STATUS_BUFFER_TOO_SHORT; if (*pValidSize < sizeof(*p)) { *pValidSize = sizeof(*p); } else { ULONG ul = p->PatternOffset + p->PatternSize; if (*pValidSize >= ul) status = NDIS_STATUS_SUCCESS; *pValidSize = ul; DPrintf(2, ("[%s] pattern of %d at %d, mask %d (%s)", __FUNCTION__, p->PatternSize, p->PatternOffset, p->MaskSize, status == NDIS_STATUS_SUCCESS ? "OK" : "Fail")); } return status; } /********************************************************** Common handler of wake-up pattern addition ***********************************************************/ NDIS_STATUS ParaNdis_OnAddWakeupPattern(PARANDIS_ADAPTER *pContext, tOidDesc *pOid) { NDIS_STATUS status; PNDIS_PM_PACKET_PATTERN pPmPattern = (PNDIS_PM_PACKET_PATTERN) pOid->InformationBuffer; ULONG ulValidSize = pOid->InformationBufferLength; status = ValidateWakeupPattern(pPmPattern, &ulValidSize); if (status == NDIS_STATUS_SUCCESS) { *pOid->pBytesRead = ulValidSize; } else { *pOid->pBytesRead = 0; *pOid->pBytesNeeded = ulValidSize; } // TODO: Apply return status; } /********************************************************** Common handler of wake-up pattern removal ***********************************************************/ NDIS_STATUS ParaNdis_OnRemoveWakeupPattern(PARANDIS_ADAPTER *pContext, tOidDesc *pOid) { NDIS_STATUS status; PNDIS_PM_PACKET_PATTERN pPmPattern = (PNDIS_PM_PACKET_PATTERN) pOid->InformationBuffer; ULONG ulValidSize = pOid->InformationBufferLength; status = ValidateWakeupPattern(pPmPattern, &ulValidSize); if (status == NDIS_STATUS_SUCCESS) { *pOid->pBytesRead = ulValidSize; } else { *pOid->pBytesRead = 0; *pOid->pBytesNeeded = ulValidSize; } return status; } /********************************************************** Common handler of wake-up enabling upon standby ***********************************************************/ NDIS_STATUS ParaNdis_OnEnableWakeup(PARANDIS_ADAPTER *pContext, tOidDesc *pOid) { NDIS_STATUS status = ParaNdis_OidSetCopy(pOid, &pContext->ulEnableWakeup, sizeof(pContext->ulEnableWakeup)); if (status == NDIS_STATUS_SUCCESS) { DPrintf(0, ("[%s] new value %lX", __FUNCTION__, pContext->ulEnableWakeup)); } return status; } /********************************************************** Dummy implementation ***********************************************************/ NDIS_STATUS ParaNdis_OnSetLookahead(PARANDIS_ADAPTER *pContext, tOidDesc *pOid) { return ParaNdis_OidSetCopy(pOid, &pContext->DummyLookAhead, sizeof(pContext->DummyLookAhead)); } NDIS_STATUS ParaNdis_OnSetVlanId(PARANDIS_ADAPTER *pContext, tOidDesc *pOid) { NDIS_STATUS status = NDIS_STATUS_NOT_SUPPORTED; if (IsVlanSupported(pContext)) { status = ParaNdis_OidSetCopy(pOid, &pContext->VlanId, sizeof(pContext->VlanId)); pContext->VlanId &= 0xfff; DPrintf(0, ("[%s] new value %d on MAC %X", __FUNCTION__, pContext->VlanId, pContext->CurrentMacAddress[5])); ParaNdis_DeviceFiltersUpdateVlanId(pContext); } return status; } /********************************************************** Retrieves support rules for specific OID ***********************************************************/ void ParaNdis_GetOidSupportRules(NDIS_OID oid, tOidWhatToDo *pRule, const tOidWhatToDo *Table) { static const tOidWhatToDo defaultRule = { 0, 0, 0, 0, 0, NULL, "Unknown OID" }; UINT i; *pRule = defaultRule; pRule->oid = oid; for (i = 0; Table[i].oid != 0; ++i) { if (Table[i].oid == oid) { *pRule = Table[i]; break; } } pRule->name = ParaNdis_OidName(oid); }