NDIS_STATUS FilterDoInternalRequest( IN PNETGW_ADAPT FilterModuleContext, IN NDIS_REQUEST_TYPE RequestType, IN NDIS_OID Oid, IN PVOID InformationBuffer, IN ULONG InformationBufferLength, IN ULONG OutputBufferLength ) { PNETGW_ADAPT pAdapter = (PNETGW_ADAPT)FilterModuleContext; PFILTER_REQUEST_CONTEXT pContext; PINTERNAL_OID_REQUEST pInternalRequest; PNDIS_OID_REQUEST pNdisRequest = NULL; NDIS_STATUS Status; UNREFERENCED_PARAMETER(OutputBufferLength); pInternalRequest = (PINTERNAL_OID_REQUEST)NdisAllocateMemoryWithTagPriority( pAdapter->FilterHandle, sizeof(INTERNAL_OID_REQUEST), FILTER_TAG, NormalPoolPriority); if (pInternalRequest == NULL) return NDIS_STATUS_RESOURCES; NdisZeroMemory(pInternalRequest, sizeof(*pInternalRequest)); pNdisRequest = &pInternalRequest->NdisReq; pNdisRequest->Header.Type = NDIS_OBJECT_TYPE_OID_REQUEST; pNdisRequest->Header.Revision = NDIS_OID_REQUEST_REVISION_1; pNdisRequest->Header.Size = sizeof(NDIS_OID_REQUEST); pNdisRequest->RequestType = RequestType; pInternalRequest->bLocal = TRUE; pInternalRequest->pReq = pNdisRequest; pInternalRequest->pOrigReq = NULL; pContext = (PFILTER_REQUEST_CONTEXT)(&pNdisRequest->SourceReserved[0]); *pContext = (NDIS_OID_REQUEST*)pInternalRequest; pNdisRequest->Header.Type = NDIS_OBJECT_TYPE_OID_REQUEST; pNdisRequest->Header.Revision = NDIS_OID_REQUEST_REVISION_1; pNdisRequest->Header.Size = NDIS_SIZEOF_OID_REQUEST_REVISION_1; pNdisRequest->RequestHandle = pAdapter->FilterHandle; pNdisRequest->SupportedRevision = NDIS_OID_REQUEST_REVISION_1; switch (RequestType) { case NdisRequestQueryInformation: pNdisRequest->DATA.QUERY_INFORMATION.Oid = Oid; pNdisRequest->DATA.QUERY_INFORMATION.InformationBuffer = InformationBuffer; pNdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength = InformationBufferLength; break; case NdisRequestSetInformation: pNdisRequest->DATA.SET_INFORMATION.Oid = Oid; pNdisRequest->DATA.SET_INFORMATION.InformationBuffer = InformationBuffer; pNdisRequest->DATA.SET_INFORMATION.InformationBufferLength = InformationBufferLength; break; default: ASSERT(FALSE); break; } pNdisRequest->RequestId = (PVOID)FILTER_REQUEST_ID; Status = NdisFOidRequest(pAdapter->FilterHandle, pNdisRequest); if (Status != NDIS_STATUS_PENDING) FilterOidRequestComplete(pAdapter, pNdisRequest, Status); return Status; }
NDIS_STATUS FilterOidRequest( IN NDIS_HANDLE FilterModuleContext, IN PNDIS_OID_REQUEST Request ) { PNETGW_ADAPT pAdapter = (PNETGW_ADAPT)FilterModuleContext; NDIS_STATUS Status = NDIS_STATUS_FAILURE; PNDIS_OID_REQUEST ClonedRequest = NULL; PFILTER_REQUEST_CONTEXT pContext = NULL; BOOLEAN bSubmit = FALSE; if (NdisRequestSetInformation == Request->RequestType || NdisRequestQueryInformation == Request->RequestType) { if (OID_TCP_OFFLOAD_PARAMETERS == Request->DATA.QUERY_INFORMATION.Oid || OID_TCP_OFFLOAD_HARDWARE_CAPABILITIES == Request->DATA.QUERY_INFORMATION.Oid || OID_TCP_OFFLOAD_CURRENT_CONFIG == Request->DATA.QUERY_INFORMATION.Oid ) { Status = NDIS_STATUS_NOT_SUPPORTED; goto finish; } } Status = NdisAllocateCloneOidRequest(pAdapter->FilterHandle, Request, FILTER_TAG, &ClonedRequest); if (Status != NDIS_STATUS_SUCCESS) goto finish; bSubmit = TRUE; ClonedRequest->RequestId = Request->RequestId; pContext = (PFILTER_REQUEST_CONTEXT)(&ClonedRequest->SourceReserved[0]); *pContext = (NDIS_OID_REQUEST*)&(pAdapter->m_IntReq); pAdapter->m_IntReq.pOrigReq = Request; pAdapter->m_IntReq.pReq = ClonedRequest; pAdapter->m_IntReq.bLocal = FALSE; pAdapter->m_IntReq.Status = NDIS_STATUS_PENDING; Status = NdisFOidRequest(pAdapter->FilterHandle, ClonedRequest); if (Status != NDIS_STATUS_PENDING) { FilterOidRequestComplete(pAdapter, ClonedRequest, Status); Status = NDIS_STATUS_PENDING; } finish: if (bSubmit) return Status; switch (Request->RequestType) { case NdisRequestMethod: Request->DATA.METHOD_INFORMATION.BytesRead = 0; Request->DATA.METHOD_INFORMATION.BytesNeeded = 0; Request->DATA.METHOD_INFORMATION.BytesWritten = 0; break; case NdisRequestSetInformation: Request->DATA.SET_INFORMATION.BytesRead = 0; Request->DATA.SET_INFORMATION.BytesNeeded = 0; break; case NdisRequestQueryInformation: case NdisRequestQueryStatistics: break; default: Request->DATA.QUERY_INFORMATION.BytesWritten = 0; Request->DATA.QUERY_INFORMATION.BytesNeeded = 0; break; } return Status; }
_Use_decl_annotations_ NDIS_STATUS FilterOidRequest( NDIS_HANDLE FilterModuleContext, PNDIS_OID_REQUEST Request ) /*++ Routine Description: Request handler Handle requests from upper layers Arguments: FilterModuleContext - our filter Request - the request passed down Return Value: NDIS_STATUS_SUCCESS NDIS_STATUS_PENDING NDIS_STATUS_XXX NOTE: Called at <= DISPATCH_LEVEL (unlike a miniport's MiniportOidRequest) --*/ { PMS_FILTER pFilter = (PMS_FILTER)FilterModuleContext; NDIS_STATUS Status; PNDIS_OID_REQUEST ClonedRequest=NULL; BOOLEAN bSubmitted = FALSE; POTLWF_REQUEST_CONTEXT Context; BOOLEAN bFalse = FALSE; LogFuncEntryMsg(DRIVER_OID, "Request %p", Request); // // Most of the time, a filter will clone the OID request and pass down // the clone. When the clone completes, the filter completes the original // OID request. // // If your filter needs to modify a specific request, it can modify the // request before or after sending down the cloned request. Or, it can // complete the original request on its own without sending down any // clone at all. // // If your filter driver does not need to modify any OID requests, then // you may simply omit this routine entirely; NDIS will pass OID requests // down on your behalf. This is more efficient than implementing a // routine that does nothing but clone all requests, as in the sample here. // do { Status = NdisAllocateCloneOidRequest(pFilter->FilterHandle, Request, OTLWF_CLONED_OID_TAG, &ClonedRequest); if (Status != NDIS_STATUS_SUCCESS) { LogWarning(DRIVER_OID, "Failed to Clone Request, %!NDIS_STATUS!", Status); break; } Context = (POTLWF_REQUEST_CONTEXT)(&ClonedRequest->SourceReserved[0]); *Context = Request; bSubmitted = TRUE; // // Use same request ID // ClonedRequest->RequestId = Request->RequestId; pFilter->PendingOidRequest = ClonedRequest; LogVerbose(DRIVER_OID, "Sending (cloned) Oid Request %p", ClonedRequest); Status = NdisFOidRequest(pFilter->FilterHandle, ClonedRequest); if (Status != NDIS_STATUS_PENDING) { FilterOidRequestComplete(pFilter, ClonedRequest, Status); Status = NDIS_STATUS_PENDING; } } while(bFalse); if (bSubmitted == FALSE) { switch(Request->RequestType) { case NdisRequestMethod: Request->DATA.METHOD_INFORMATION.BytesRead = 0; Request->DATA.METHOD_INFORMATION.BytesNeeded = 0; Request->DATA.METHOD_INFORMATION.BytesWritten = 0; break; case NdisRequestSetInformation: Request->DATA.SET_INFORMATION.BytesRead = 0; Request->DATA.SET_INFORMATION.BytesNeeded = 0; break; case NdisRequestQueryInformation: case NdisRequestQueryStatistics: default: Request->DATA.QUERY_INFORMATION.BytesWritten = 0; Request->DATA.QUERY_INFORMATION.BytesNeeded = 0; break; } } LogFuncExitNDIS(DRIVER_OID, Status); return Status; }
/* * -------------------------------------------------------------------------- * Utility function to issue the specified OID to the NDIS stack. The OID is * directed towards the miniport edge of the extensible switch. * An OID that gets issued may not complete immediately, and in such cases, the * function waits for the OID to complete. Thus, this function must not be * called at the PASSIVE_LEVEL. * -------------------------------------------------------------------------- */ static NDIS_STATUS OvsIssueOidRequest(POVS_SWITCH_CONTEXT switchContext, NDIS_REQUEST_TYPE oidType, UINT32 oidRequestEnum, PVOID oidInputBuffer, UINT32 inputSize, PVOID oidOutputBuffer, UINT32 outputSize, UINT32 *outputSizeNeeded) { NDIS_STATUS status; PNDIS_OID_REQUEST oidRequest; POVS_OID_CONTEXT oidContext; ULONG OvsExtOidRequestId = 'ISVO'; DBG_UNREFERENCED_PARAMETER(inputSize); DBG_UNREFERENCED_PARAMETER(oidInputBuffer); OVS_LOG_TRACE("Enter: switchContext: %p, oidType: %d", switchContext, oidType); ASSERT(oidInputBuffer == NULL || inputSize != 0); ASSERT(oidOutputBuffer == NULL || outputSize != 0); ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); oidRequest = OvsAllocateMemoryWithTag(sizeof *oidRequest, OVS_OID_POOL_TAG); if (!oidRequest) { status = NDIS_STATUS_RESOURCES; goto done; } oidContext = OvsAllocateMemoryWithTag(sizeof *oidContext, OVS_OID_POOL_TAG); if (!oidContext) { OvsFreeMemoryWithTag(oidRequest, OVS_OID_POOL_TAG); status = NDIS_STATUS_RESOURCES; goto done; } RtlZeroMemory(oidRequest, sizeof *oidRequest); RtlZeroMemory(oidContext, sizeof *oidContext); oidRequest->Header.Type = NDIS_OBJECT_TYPE_OID_REQUEST; oidRequest->Header.Revision = NDIS_OID_REQUEST_REVISION_1; oidRequest->Header.Size = NDIS_SIZEOF_OID_REQUEST_REVISION_1; oidRequest->RequestType = oidType; oidRequest->PortNumber = 0; oidRequest->Timeout = 0; oidRequest->RequestId = (PVOID)OvsExtOidRequestId; switch(oidType) { case NdisRequestQueryInformation: oidRequest->DATA.QUERY_INFORMATION.Oid = oidRequestEnum; oidRequest->DATA.QUERY_INFORMATION.InformationBuffer = oidOutputBuffer; oidRequest->DATA.QUERY_INFORMATION.InformationBufferLength = outputSize; break; default: ASSERT(FALSE); status = NDIS_STATUS_INVALID_PARAMETER; break; } /* * We make use of the SourceReserved field in the OID request to store * pointers to the original OID (if any), and also context for completion * (if any). */ oidContext->status = NDIS_STATUS_SUCCESS; NdisInitializeEvent(&oidContext->oidComplete); OvsOidSetOrigRequest(oidRequest, NULL); OvsOidSetContext(oidRequest, oidContext); NdisInterlockedIncrement(&(switchContext->pendingOidCount)); status = NdisFOidRequest(switchContext->NdisFilterHandle, oidRequest); if (status == NDIS_STATUS_PENDING) { NdisWaitEvent(&oidContext->oidComplete, 0); } else { NdisInterlockedDecrement(&(switchContext->pendingOidCount)); } if (status == NDIS_STATUS_INVALID_LENGTH || oidContext->status == NDIS_STATUS_INVALID_LENGTH) { switch(oidType) { case NdisRequestQueryInformation: *outputSizeNeeded = oidRequest->DATA.QUERY_INFORMATION.BytesNeeded; } } status = oidContext->status; ASSERT(status != NDIS_STATUS_PENDING); OvsFreeMemoryWithTag(oidRequest, OVS_OID_POOL_TAG); OvsFreeMemoryWithTag(oidContext, OVS_OID_POOL_TAG); done: OVS_LOG_TRACE("Exit: status %8x.", status); return status; }
NDIS_STATUS OvsExtOidRequest(NDIS_HANDLE filterModuleContext, PNDIS_OID_REQUEST oidRequest) { POVS_SWITCH_CONTEXT switchObject = (POVS_SWITCH_CONTEXT)filterModuleContext; NDIS_STATUS status = NDIS_STATUS_SUCCESS; PNDIS_OID_REQUEST clonedOidRequest = NULL; struct _METHOD *methodInfo = &(oidRequest->DATA.METHOD_INFORMATION); BOOLEAN completeOid = FALSE; ULONG bytesNeeded = 0; OVS_LOG_TRACE("Enter: oidRequest %p, reqType: %d", oidRequest, oidRequest->RequestType); status = NdisAllocateCloneOidRequest(switchObject->NdisFilterHandle, oidRequest, OVS_MEMORY_TAG, &clonedOidRequest); if (status != NDIS_STATUS_SUCCESS) { goto done; } NdisInterlockedIncrement(&(switchObject->pendingOidCount)); /* set the original oid request in cloned one. */ OvsOidSetOrigRequest(clonedOidRequest, oidRequest); OvsOidSetContext(clonedOidRequest, NULL); switch(clonedOidRequest->RequestType) { case NdisRequestSetInformation: status = OvsProcessSetOid(switchObject, clonedOidRequest, &completeOid); break; case NdisRequestMethod: status = OvsProcessMethodOid(switchObject, clonedOidRequest, &completeOid, &bytesNeeded); break; default: /* We do not handle other request types as of now. * We are just a passthrough for those. */ break; } if (completeOid == TRUE) { /* dont leave any reference back to original request, * even if we are freeing it up. */ OVS_LOG_INFO("Complete True oidRequest %p.", oidRequest); OvsOidSetOrigRequest(clonedOidRequest, NULL); NdisFreeCloneOidRequest(switchObject->NdisFilterHandle, clonedOidRequest); methodInfo->BytesNeeded = bytesNeeded; NdisInterlockedDecrement(&switchObject->pendingOidCount); goto done; } /* pass the request down */ status = NdisFOidRequest(switchObject->NdisFilterHandle, clonedOidRequest); if (status != NDIS_STATUS_PENDING) { OvsExtOidRequestComplete(switchObject, clonedOidRequest, status); /* sample code says so */ status = NDIS_STATUS_PENDING; } done: OVS_LOG_TRACE("Exit: status %8x.", status); return status; }
NDIS_STATUS SxLibIssueOidRequest( _In_ PSX_SWITCH_OBJECT Switch, _In_ NDIS_REQUEST_TYPE RequestType, _In_ NDIS_OID Oid, _In_opt_ PVOID InformationBuffer, _In_ ULONG InformationBufferLength, _In_ ULONG OutputBufferLength, _In_ ULONG MethodId, _In_ UINT Timeout, _Out_ PULONG BytesNeeded ) { NDIS_STATUS status; PSX_OID_REQUEST oidRequest; PNDIS_OID_REQUEST ndisOidRequest; ULONG bytesNeeded; BOOLEAN asyncCompletion; status = NDIS_STATUS_SUCCESS; oidRequest = NULL; bytesNeeded = 0; asyncCompletion = FALSE; NdisInterlockedIncrement(&Switch->PendingOidCount); if (Switch->ControlFlowState != SxSwitchAttached) { status = NDIS_STATUS_CLOSING; goto Cleanup; } // // Dynamically allocate filter request so that we can handle asynchronous // completion. // oidRequest = (PSX_OID_REQUEST)ExAllocatePoolWithTag(NonPagedPoolNx, sizeof(SX_OID_REQUEST), SxExtAllocationTag); if (oidRequest == NULL) { goto Cleanup; } NdisZeroMemory(oidRequest, sizeof(SX_OID_REQUEST)); ndisOidRequest = &oidRequest->NdisOidRequest; NdisInitializeEvent(&oidRequest->ReqEvent); ndisOidRequest->Header.Type = NDIS_OBJECT_TYPE_OID_REQUEST; ndisOidRequest->Header.Revision = NDIS_OID_REQUEST_REVISION_1; ndisOidRequest->Header.Size = sizeof(NDIS_OID_REQUEST); ndisOidRequest->RequestType = RequestType; ndisOidRequest->Timeout = Timeout; switch (RequestType) { case NdisRequestQueryInformation: ndisOidRequest->DATA.QUERY_INFORMATION.Oid = Oid; ndisOidRequest->DATA.QUERY_INFORMATION.InformationBuffer = InformationBuffer; ndisOidRequest->DATA.QUERY_INFORMATION.InformationBufferLength = InformationBufferLength; break; case NdisRequestSetInformation: ndisOidRequest->DATA.SET_INFORMATION.Oid = Oid; ndisOidRequest->DATA.SET_INFORMATION.InformationBuffer = InformationBuffer; ndisOidRequest->DATA.SET_INFORMATION.InformationBufferLength = InformationBufferLength; break; case NdisRequestMethod: ndisOidRequest->DATA.METHOD_INFORMATION.Oid = Oid; ndisOidRequest->DATA.METHOD_INFORMATION.MethodId = MethodId; ndisOidRequest->DATA.METHOD_INFORMATION.InformationBuffer = InformationBuffer; ndisOidRequest->DATA.METHOD_INFORMATION.InputBufferLength = InformationBufferLength; ndisOidRequest->DATA.METHOD_INFORMATION.OutputBufferLength = OutputBufferLength; break; default: NT_ASSERT(FALSE); break; } ndisOidRequest->RequestId = (PVOID)SxExtOidRequestId; status = NdisFOidRequest(Switch->NdisFilterHandle, ndisOidRequest); if (status == NDIS_STATUS_PENDING) { asyncCompletion = TRUE; NdisWaitEvent(&oidRequest->ReqEvent, 0); } else { SxpNdisCompleteInternalOidRequest(Switch, ndisOidRequest, status); } bytesNeeded = oidRequest->BytesNeeded; status = oidRequest->Status; Cleanup: if (BytesNeeded != NULL) { *BytesNeeded = bytesNeeded; } if (!asyncCompletion) { NdisInterlockedDecrement(&Switch->PendingOidCount); } if (oidRequest != NULL) { ExFreePoolWithTag(oidRequest, SxExtAllocationTag); } return status; }
// // FilterOidRequest Function // http://msdn.microsoft.com/en-us/library/ff549954(v=VS.85).aspx // _Use_decl_annotations_ NDIS_STATUS SxNdisOidRequest( NDIS_HANDLE FilterModuleContext, PNDIS_OID_REQUEST OidRequest ) { PSX_SWITCH_OBJECT switchObject = (PSX_SWITCH_OBJECT)FilterModuleContext; NDIS_STATUS status; PNDIS_OID_REQUEST clonedRequest=NULL; PVOID *cloneRequestContext; BOOLEAN completeOid = FALSE; ULONG bytesNeeded = 0; status = NDIS_STATUS_SUCCESS; DEBUGP(DL_TRACE, ("===>SxOidRequest: OidRequest %p.\n", OidRequest)); NdisInterlockedIncrement(&switchObject->PendingOidCount); status = NdisAllocateCloneOidRequest(switchObject->NdisFilterHandle, OidRequest, SxExtAllocationTag, &clonedRequest); if (status != NDIS_STATUS_SUCCESS) { DEBUGP(DL_WARN, ("FilerOidRequest: Cannot Clone OidRequest\n")); goto Cleanup; } cloneRequestContext = (PVOID*)(&clonedRequest->SourceReserved[0]); *cloneRequestContext = OidRequest; switch (clonedRequest->RequestType) { case NdisRequestSetInformation: status = SxpNdisProcessSetOid(switchObject, clonedRequest, &completeOid); break; case NdisRequestMethod: status = SxpNdisProcessMethodOid(switchObject, clonedRequest, &completeOid, &bytesNeeded); break; } if (completeOid) { NdisFreeCloneOidRequest(switchObject->NdisFilterHandle, clonedRequest); OidRequest->DATA.METHOD_INFORMATION.BytesNeeded = bytesNeeded; NdisInterlockedDecrement(&switchObject->PendingOidCount); goto Cleanup; } status = NdisFOidRequest(switchObject->NdisFilterHandle, clonedRequest); if (status != NDIS_STATUS_PENDING) { SxNdisOidRequestComplete(switchObject, clonedRequest, status); // // We must still return status as pending because we complete the // request using NdisFOidRequestComplete() in SxOidRequestComplete(). // status = NDIS_STATUS_PENDING; } Cleanup: DEBUGP(DL_TRACE, ("<===SxOidRequest: status %8x.\n", status)); return status; }