// XXX this whole thing is f****d up static void get_mac(PADAPT adapt) { NDIS_STATUS Status; _req.RequestType = NdisRequestQueryInformation; _req.DATA.QUERY_INFORMATION.Oid = OID_802_3_CURRENT_ADDRESS; _req.DATA.QUERY_INFORMATION.InformationBuffer = _mac; _req.DATA.QUERY_INFORMATION.InformationBufferLength = NPROT_MAC_ADDR_LEN; NdisRequest(&Status, adapt->BindingHandle, &_req); if (Status == NDIS_STATUS_PENDING) { DbgPrint("f**K PENDING\n"); while (_req.DATA.QUERY_INFORMATION.Oid != 0) NdisMSleep(2); } else { _req.DATA.QUERY_INFORMATION.Oid = 0; DbgPrint("MAC %x %x %x %x %x %x\n", _mac[0], _mac[1], _mac[2], _mac[3], _mac[4], _mac[5]); } }
VOID StartQueryInfo( IN PFILTER_ADAPTER pAdapter ) { NTSTATUS nNtStatus; PINTERNAL_REQUEST pIntReq; pIntReq = &pAdapter->IntReq; RtlZeroMemory(pIntReq, sizeof(*pIntReq)); pIntReq->NdisRequest.RequestType = NdisRequestQueryInformation; pIntReq->NdisRequest.DATA.QUERY_INFORMATION.Oid = OID_802_3_CURRENT_ADDRESS; pIntReq->NdisRequest.DATA.QUERY_INFORMATION.InformationBuffer = pAdapter->ctrl.MacAddr.Arr; pIntReq->NdisRequest.DATA.QUERY_INFORMATION.InformationBufferLength = sizeof( pAdapter->ctrl.MacAddr.Arr); nNtStatus = NDIS_STATUS_FAILURE; pIntReq->nRequestStatus = NDIS_STATUS_PENDING; pIntReq->bLocalRequest = TRUE; pIntReq->pLocalCompletionFunc = MakeCurrentAddressQueryComplete; pAdapter->LocalOutstandingRequests = TRUE; NdisRequest( &nNtStatus, pAdapter->BindingHandle, &pIntReq->NdisRequest ); if( nNtStatus != NDIS_STATUS_PENDING ){ natpRequestComplete( (NDIS_HANDLE )pAdapter, &pIntReq->NdisRequest, nNtStatus ); } }
NDIS_STATUS MPSetInformation( IN NDIS_HANDLE MiniportAdapterContext, IN NDIS_OID Oid, IN PVOID InformationBuffer, IN ULONG InformationBufferLength, OUT PULONG BytesRead, OUT PULONG BytesNeeded ) /*++ Routine Description: Miniport SetInfo handler. In the case of OID_PNP_SET_POWER, record the power state and return the OID. Do not pass below If the device is suspended, do not block the SET_POWER_OID as it is used to reactivate the Passthru miniport PM- If the MP is not ON (DeviceState > D0) return immediately (except for 'query power' and 'set power') If MP is ON, but the PT is not at D0, then queue the queue the request for later processing Requests to miniports are always serialized Arguments: MiniportAdapterContext Pointer to the adapter structure Oid Oid for this query InformationBuffer Buffer for information InformationBufferLength Size of this buffer BytesRead Specifies how much info is read BytesNeeded In case the buffer is smaller than what we need, tell them how much is needed Return Value: Return code from the NdisRequest below. --*/ { PADAPT pAdapt = (PADAPT)MiniportAdapterContext; NDIS_STATUS Status; Status = NDIS_STATUS_FAILURE; do { // // The Set Power should not be sent to the miniport below the Passthru, but is handled internally // if (Oid == OID_PNP_SET_POWER) { MPProcessSetPowerOid(&Status, pAdapt, InformationBuffer, InformationBufferLength, BytesRead, BytesNeeded); break; } // // If the miniport below is unbinding, fail the request // NdisAcquireSpinLock(&pAdapt->Lock); if (pAdapt->UnbindingInProcess == TRUE) { NdisReleaseSpinLock(&pAdapt->Lock); Status = NDIS_STATUS_FAILURE; break; } NdisReleaseSpinLock(&pAdapt->Lock); // // All other Set Information requests are failed, if the miniport is // not at D0 or is transitioning to a device state greater than D0. // if (pAdapt->MPDeviceState > NdisDeviceStateD0) { Status = NDIS_STATUS_FAILURE; break; } // Set up the Request and return the result pAdapt->Request.RequestType = NdisRequestSetInformation; pAdapt->Request.DATA.SET_INFORMATION.Oid = Oid; pAdapt->Request.DATA.SET_INFORMATION.InformationBuffer = InformationBuffer; pAdapt->Request.DATA.SET_INFORMATION.InformationBufferLength = InformationBufferLength; pAdapt->BytesNeeded = BytesNeeded; pAdapt->BytesReadOrWritten = BytesRead; // // If the miniport below is unbinding, fail the request // NdisAcquireSpinLock(&pAdapt->Lock); if (pAdapt->UnbindingInProcess == TRUE) { NdisReleaseSpinLock(&pAdapt->Lock); Status = NDIS_STATUS_FAILURE; break; } // // If the device below is at a low power state, we cannot send it the // request now, and must pend it. // if ((pAdapt->PTDeviceState > NdisDeviceStateD0) && (pAdapt->StandingBy == FALSE)) { pAdapt->QueuedRequest = TRUE; NdisReleaseSpinLock(&pAdapt->Lock); Status = NDIS_STATUS_PENDING; break; } // // This is in the process of powering down the system, always fail the request // if (pAdapt->StandingBy == TRUE) { NdisReleaseSpinLock(&pAdapt->Lock); Status = NDIS_STATUS_FAILURE; break; } pAdapt->OutstandingRequests = TRUE; NdisReleaseSpinLock(&pAdapt->Lock); // // Forward the request to the device below. // NdisRequest(&Status, pAdapt->BindingHandle, &pAdapt->Request); if (Status != NDIS_STATUS_PENDING) { *BytesRead = pAdapt->Request.DATA.SET_INFORMATION.BytesRead; *BytesNeeded = pAdapt->Request.DATA.SET_INFORMATION.BytesNeeded; pAdapt->OutstandingRequests = FALSE; } } while (FALSE); return(Status); }
NDIS_STATUS MPQueryInformation( IN NDIS_HANDLE MiniportAdapterContext, IN NDIS_OID Oid, IN PVOID InformationBuffer, IN ULONG InformationBufferLength, OUT PULONG BytesWritten, OUT PULONG BytesNeeded ) /*++ Routine Description: Entry point called by NDIS to query for the value of the specified OID. Typical processing is to forward the query down to the underlying miniport. The following OIDs are filtered here: OID_PNP_QUERY_POWER - return success right here OID_GEN_SUPPORTED_GUIDS - do not forward, otherwise we will show up multiple instances of private GUIDs supported by the underlying miniport. OID_PNP_CAPABILITIES - we do send this down to the lower miniport, but the values returned are postprocessed before we complete this request; see PtRequestComplete. NOTE on OID_TCP_TASK_OFFLOAD - if this IM driver modifies the contents of data it passes through such that a lower miniport may not be able to perform TCP task offload, then it should not forward this OID down, but fail it here with the status NDIS_STATUS_NOT_SUPPORTED. This is to avoid performing incorrect transformations on data. If our miniport edge (upper edge) is at a low-power state, fail the request. If our protocol edge (lower edge) has been notified of a low-power state, we pend this request until the miniport below has been set to D0. Since requests to miniports are serialized always, at most a single request will be pended. Arguments: MiniportAdapterContext Pointer to the adapter structure Oid Oid for this query InformationBuffer Buffer for information InformationBufferLength Size of this buffer BytesWritten Specifies how much info is written BytesNeeded In case the buffer is smaller than what we need, tell them how much is needed Return Value: Return code from the NdisRequest below. --*/ { PADAPT pAdapt = (PADAPT)MiniportAdapterContext; NDIS_STATUS Status = NDIS_STATUS_FAILURE; do { if (Oid == OID_PNP_QUERY_POWER) { // // Do not forward this. // Status = NDIS_STATUS_SUCCESS; break; } if (Oid == OID_GEN_SUPPORTED_GUIDS) { // // Do not forward this, otherwise we will end up with multiple // instances of private GUIDs that the underlying miniport // supports. // Status = NDIS_STATUS_NOT_SUPPORTED; break; } if (Oid == OID_TCP_TASK_OFFLOAD) { // // Fail this -if- this driver performs data transformations // that can interfere with a lower driver's ability to offload // TCP tasks. // // Status = NDIS_STATUS_NOT_SUPPORTED; // break; // } // // If the miniport below is unbinding, just fail any request // NdisAcquireSpinLock(&pAdapt->Lock); if (pAdapt->UnbindingInProcess == TRUE) { NdisReleaseSpinLock(&pAdapt->Lock); Status = NDIS_STATUS_FAILURE; break; } NdisReleaseSpinLock(&pAdapt->Lock); // // All other queries are failed, if the miniport is not at D0, // if (pAdapt->MPDeviceState > NdisDeviceStateD0) { Status = NDIS_STATUS_FAILURE; break; } pAdapt->Request.RequestType = NdisRequestQueryInformation; pAdapt->Request.DATA.QUERY_INFORMATION.Oid = Oid; pAdapt->Request.DATA.QUERY_INFORMATION.InformationBuffer = InformationBuffer; pAdapt->Request.DATA.QUERY_INFORMATION.InformationBufferLength = InformationBufferLength; pAdapt->BytesNeeded = BytesNeeded; pAdapt->BytesReadOrWritten = BytesWritten; // // If the miniport below is binding, fail the request // NdisAcquireSpinLock(&pAdapt->Lock); if (pAdapt->UnbindingInProcess == TRUE) { NdisReleaseSpinLock(&pAdapt->Lock); Status = NDIS_STATUS_FAILURE; break; } // // If the Protocol device state is OFF, mark this request as being // pended. We queue this until the device state is back to D0. // if ((pAdapt->PTDeviceState > NdisDeviceStateD0) && (pAdapt->StandingBy == FALSE)) { pAdapt->QueuedRequest = TRUE; NdisReleaseSpinLock(&pAdapt->Lock); Status = NDIS_STATUS_PENDING; break; } // // This is in the process of powering down the system, always fail the request // if (pAdapt->StandingBy == TRUE) { NdisReleaseSpinLock(&pAdapt->Lock); Status = NDIS_STATUS_FAILURE; break; } pAdapt->OutstandingRequests = TRUE; NdisReleaseSpinLock(&pAdapt->Lock); // // default case, most requests will be passed to the miniport below // NdisRequest(&Status, pAdapt->BindingHandle, &pAdapt->Request); if (Status != NDIS_STATUS_PENDING) { PtRequestComplete(pAdapt, &pAdapt->Request, Status); Status = NDIS_STATUS_PENDING; } } while (FALSE); return(Status); }
NTSTATUS NPF_GetDeviceMTU( IN POPEN_INSTANCE pOpen, IN PIRP pIrp, OUT PUINT pMtu) { PLIST_ENTRY RequestListEntry; PINTERNAL_REQUEST MaxSizeReq; NDIS_STATUS ReqStatus; TRACE_ENTER(); ASSERT(pOpen != NULL); ASSERT(pIrp != NULL); ASSERT(pMtu != NULL); // Extract a request from the list of free ones RequestListEntry = ExInterlockedRemoveHeadList(&pOpen->RequestList, &pOpen->RequestSpinLock); if (RequestListEntry == NULL) { // // THIS IS WRONG // // // Assume Ethernet // *pMtu = 1514; TRACE_EXIT(); return STATUS_SUCCESS; } MaxSizeReq = CONTAINING_RECORD(RequestListEntry, INTERNAL_REQUEST, ListElement); MaxSizeReq->Request.RequestType = NdisRequestQueryInformation; MaxSizeReq->Request.DATA.QUERY_INFORMATION.Oid = OID_GEN_MAXIMUM_TOTAL_SIZE; MaxSizeReq->Request.DATA.QUERY_INFORMATION.InformationBuffer = pMtu; MaxSizeReq->Request.DATA.QUERY_INFORMATION.InformationBufferLength = sizeof(*pMtu); NdisResetEvent(&MaxSizeReq->InternalRequestCompletedEvent); // submit the request NdisRequest( &ReqStatus, pOpen->AdapterHandle, &MaxSizeReq->Request); if (ReqStatus == NDIS_STATUS_PENDING) { NdisWaitEvent(&MaxSizeReq->InternalRequestCompletedEvent, 0); ReqStatus = MaxSizeReq->RequestStatus; } // // Put the request in the list of the free ones // ExInterlockedInsertTailList(&pOpen->RequestList, &MaxSizeReq->ListElement, &pOpen->RequestSpinLock); if (ReqStatus == NDIS_STATUS_SUCCESS) { TRACE_EXIT(); return STATUS_SUCCESS; } else { // // THIS IS WRONG // // // Assume Ethernet // *pMtu = 1514; TRACE_EXIT(); return STATUS_SUCCESS; // return ReqStatus; } }
static NDIS_STATUS BindAdapterByName(PNDIS_STRING DeviceName) { NDIS_STATUS OpenErrorStatus; PNDISUIO_ADAPTER_CONTEXT AdapterContext; NDIS_MEDIUM SupportedMedia[1] = {NdisMedium802_3}; UINT SelectedMedium; NDIS_STATUS Status; NDIS_REQUEST Request; /* Allocate the adapter context */ AdapterContext = ExAllocatePool(NonPagedPool, sizeof(*AdapterContext)); if (!AdapterContext) { return NDIS_STATUS_RESOURCES; } /* Set up the adapter context */ RtlZeroMemory(AdapterContext, sizeof(*AdapterContext)); KeInitializeEvent(&AdapterContext->AsyncEvent, SynchronizationEvent, FALSE); KeInitializeEvent(&AdapterContext->PacketReadEvent, SynchronizationEvent, FALSE); KeInitializeSpinLock(&AdapterContext->Spinlock); InitializeListHead(&AdapterContext->PacketList); InitializeListHead(&AdapterContext->OpenEntryList); AdapterContext->OpenCount = 0; AdapterContext->DeviceName.Length = AdapterContext->DeviceName.MaximumLength = DeviceName->Length; AdapterContext->DeviceName.Buffer = ExAllocatePool(NonPagedPool, DeviceName->Length); if (!AdapterContext->DeviceName.Buffer) { ExFreePool(AdapterContext); return NDIS_STATUS_RESOURCES; } /* Copy the device name into the adapter context */ RtlCopyMemory(AdapterContext->DeviceName.Buffer, DeviceName->Buffer, DeviceName->Length); DPRINT("Binding adapter %wZ\n", &AdapterContext->DeviceName); /* Create the buffer pool */ NdisAllocateBufferPool(&Status, &AdapterContext->BufferPoolHandle, 50); if (Status != NDIS_STATUS_SUCCESS) { DPRINT1("Failed to allocate buffer pool with status 0x%x\n", Status); RtlFreeUnicodeString(&AdapterContext->DeviceName); ExFreePool(AdapterContext); return Status; } /* Create the packet pool */ NdisAllocatePacketPool(&Status, &AdapterContext->PacketPoolHandle, 25, PROTOCOL_RESERVED_SIZE_IN_PACKET); if (Status != NDIS_STATUS_SUCCESS) { DPRINT1("Failed to allocate packet pool with status 0x%x\n", Status); NdisFreeBufferPool(AdapterContext->BufferPoolHandle); RtlFreeUnicodeString(&AdapterContext->DeviceName); ExFreePool(AdapterContext); return Status; } /* Send the open request */ NdisOpenAdapter(&Status, &OpenErrorStatus, &AdapterContext->BindingHandle, &SelectedMedium, SupportedMedia, 1, GlobalProtocolHandle, AdapterContext, DeviceName, 0, NULL); /* Wait for a pending open */ if (Status == NDIS_STATUS_PENDING) { KeWaitForSingleObject(&AdapterContext->AsyncEvent, Executive, KernelMode, FALSE, NULL); Status = AdapterContext->AsyncStatus; } /* Check the final status */ if (Status != NDIS_STATUS_SUCCESS) { DPRINT1("Failed to open adapter for bind with status 0x%x\n", Status); NdisFreePacketPool(AdapterContext->PacketPoolHandle); NdisFreeBufferPool(AdapterContext->BufferPoolHandle); RtlFreeUnicodeString(&AdapterContext->DeviceName); ExFreePool(AdapterContext); return Status; } /* Get the MAC options */ Request.RequestType = NdisRequestQueryInformation; Request.DATA.QUERY_INFORMATION.Oid = OID_GEN_MAC_OPTIONS; Request.DATA.QUERY_INFORMATION.InformationBuffer = &AdapterContext->MacOptions; Request.DATA.QUERY_INFORMATION.InformationBufferLength = sizeof(ULONG); NdisRequest(&Status, AdapterContext->BindingHandle, &Request); /* Wait for a pending request */ if (Status == NDIS_STATUS_PENDING) { KeWaitForSingleObject(&AdapterContext->AsyncEvent, Executive, KernelMode, FALSE, NULL); Status = AdapterContext->AsyncStatus; } /* Check the final status */ if (Status != NDIS_STATUS_SUCCESS) { NDIS_STATUS CloseStatus; DPRINT1("Failed to get MAC options with status 0x%x\n", Status); NdisCloseAdapter(&CloseStatus, AdapterContext->BindingHandle); if (CloseStatus == NDIS_STATUS_PENDING) { KeWaitForSingleObject(&AdapterContext->AsyncEvent, Executive, KernelMode, FALSE, NULL); } NdisFreePacketPool(AdapterContext->PacketPoolHandle); NdisFreeBufferPool(AdapterContext->BufferPoolHandle); RtlFreeUnicodeString(&AdapterContext->DeviceName); ExFreePool(AdapterContext); return Status; } /* Add the adapter context to the global list */ ExInterlockedInsertTailList(&GlobalAdapterList, &AdapterContext->ListEntry, &GlobalAdapterListLock); return STATUS_SUCCESS; }
NDIS_STATUS natpPnPNetEventSetPower( IN PFILTER_ADAPTER pAdapt, IN PNET_PNP_EVENT pNetPnPEvent ) { PNDIS_DEVICE_POWER_STATE pDeviceState =(PNDIS_DEVICE_POWER_STATE)(pNetPnPEvent->Buffer); NDIS_DEVICE_POWER_STATE PrevDeviceState = pAdapt->natpDeviceState; NDIS_STATUS Status; NDIS_STATUS ReturnStatus; ReturnStatus = NDIS_STATUS_SUCCESS; NdisAcquireSpinLock(&pAdapt->Lock); pAdapt->natpDeviceState = *pDeviceState; if (pAdapt->natpDeviceState > NdisDeviceStateD0){ if (PrevDeviceState == NdisDeviceStateD0) pAdapt->StandingBy = TRUE; NdisReleaseSpinLock(&pAdapt->Lock); while (pAdapt->SendPending != 0) NdisMSleep(2); while (pAdapt->OutstandingRequests == TRUE) NdisMSleep(2); while (pAdapt->LocalOutstandingRequests == TRUE) NdisMSleep(2); NdisAcquireSpinLock(&pAdapt->Lock); if (pAdapt->QueuedRequest){ pAdapt->QueuedRequest = FALSE; NdisReleaseSpinLock(&pAdapt->Lock); natpRequestComplete(pAdapt, &pAdapt->IntReq.NdisRequest, NDIS_STATUS_FAILURE); }else{ NdisReleaseSpinLock(&pAdapt->Lock); } }else{ if (PrevDeviceState > NdisDeviceStateD0) pAdapt->StandingBy = FALSE; if (pAdapt->QueuedRequest == TRUE){ pAdapt->QueuedRequest = FALSE; pAdapt->OutstandingRequests = TRUE; NdisReleaseSpinLock(&pAdapt->Lock); NdisRequest( &Status, pAdapt->BindingHandle, &pAdapt->IntReq.NdisRequest ); if (Status != NDIS_STATUS_PENDING){ natpRequestComplete( pAdapt, &pAdapt->IntReq.NdisRequest, Status ); } }else{ NdisReleaseSpinLock(&pAdapt->Lock); } } return ReturnStatus; }
NDIS_STATUS PtPnPNetEventSetPower( IN PADAPT pAdapt, IN PNET_PNP_EVENT pNetPnPEvent ) /*++ Routine Description: This is a notification to our protocol edge of the power state of the lower miniport. If it is going to a low-power state, we must wait here for all outstanding sends and requests to complete. NDIS 5.1: Since we use packet stacking, it is not sufficient to check usage of our local send packet pool to detect whether or not all outstanding sends have completed. For this, use the new API NdisQueryPendingIOCount. NDIS 5.1: Use the 5.1 API NdisIMNotifyPnPEvent to pass on PnP notifications to upper protocol(s). Arguments: pAdapt - Pointer to the adpater structure pNetPnPEvent - The Net Pnp Event. this contains the new device state Return Value: NDIS_STATUS_SUCCESS or the status returned by upper-layer protocols. --*/ { PNDIS_DEVICE_POWER_STATE pDeviceState =(PNDIS_DEVICE_POWER_STATE)(pNetPnPEvent->Buffer); NDIS_DEVICE_POWER_STATE PrevDeviceState = pAdapt->PTDeviceState; NDIS_STATUS Status; NDIS_STATUS ReturnStatus; #ifdef NDIS51 ULONG PendingIoCount = 0; #endif // NDIS51 ReturnStatus = NDIS_STATUS_SUCCESS; // // Set the Internal Device State, this blocks all new sends or receives // pAdapt->PTDeviceState = *pDeviceState; // // Check if the miniport below is going to a low power state. // if (*pDeviceState > NdisDeviceStateD0) { #ifdef NDIS51 // // Notify upper layer protocol(s) first. // if (pAdapt->MiniportHandle != NULL) { ReturnStatus = NdisIMNotifyPnPEvent(pAdapt->MiniportHandle, pNetPnPEvent); } #endif // NDIS51 // // If the miniport below is going to standby, fail all incoming requests // if (PrevDeviceState == NdisDeviceStateD0) { pAdapt->StandingBy = TRUE; } // // Wait for outstanding sends and requests to complete. // #ifdef NDIS51 do { Status = NdisQueryPendingIOCount(pAdapt->BindingHandle, &PendingIoCount); if ((Status != NDIS_STATUS_SUCCESS) || (PendingIoCount == 0)) { break; } NdisMSleep(2); } while (TRUE); #else while (NdisPacketPoolUsage(pAdapt->SendPacketPoolHandle) != 0) { NdisMSleep(2); } while (pAdapt->OutstandingRequests == TRUE) { // // sleep till outstanding requests complete // NdisMSleep(2); } #endif // NDIS51 ASSERT(NdisPacketPoolUsage(pAdapt->SendPacketPoolHandle) == 0); ASSERT(pAdapt->OutstandingRequests == FALSE); } else { // // The device below is being turned on. If we had a request // pending, send it down now. // if (pAdapt->QueuedRequest == TRUE) { pAdapt->QueuedRequest = FALSE; NdisRequest(&Status, pAdapt->BindingHandle, &pAdapt->Request); if (Status != NDIS_STATUS_PENDING) { PtRequestComplete(pAdapt, &pAdapt->Request, Status); } } // // If the physical miniport is powering up (from Low power state to D0), // clear the flag // if (PrevDeviceState > NdisDeviceStateD0) { pAdapt->StandingBy = FALSE; } #ifdef NDIS51 // // Pass on this notification to protocol(s) above // if (pAdapt->MiniportHandle) { ReturnStatus = NdisIMNotifyPnPEvent(pAdapt->MiniportHandle, pNetPnPEvent); } #endif // NDIS51 } return ReturnStatus; }
NDIS_STATUS MiniportSetInformation5( IN NDIS_HANDLE MiniportAdapterContext, IN NDIS_OID Oid, IN PVOID InformationBuffer, IN ULONG InformationBufferLength, OUT PULONG BytesRead, OUT PULONG BytesNeeded ) { PADAPTER pAdapt = (PADAPTER)MiniportAdapterContext; NDIS_STATUS Status; Status = NDIS_STATUS_FAILURE; do { // // The Set Power should not be sent to the miniport below the Passthru, but is handled internally // if (Oid == OID_PNP_SET_POWER) { MiniportProcessSetPowerOid5(&Status, pAdapt, InformationBuffer, InformationBufferLength, BytesRead, BytesNeeded); break; } // // If the miniport below is unbinding, fail the request // NdisAcquireSpinLock(&pAdapt->Lock); if (pAdapt->UnbindingInProcess == TRUE) { NdisReleaseSpinLock(&pAdapt->Lock); Status = NDIS_STATUS_FAILURE; break; } NdisReleaseSpinLock(&pAdapt->Lock); // // All other Set Information requests are failed, if the miniport is // not at D0 or is transitioning to a device state greater than D0. // if (pAdapt->MiniportDeviceState > NdisDeviceStateD0) { Status = NDIS_STATUS_FAILURE; break; } // Set up the Request and return the result pAdapt->Request5.RequestType = NdisRequestSetInformation; pAdapt->Request5.DATA.SET_INFORMATION.Oid = Oid; pAdapt->Request5.DATA.SET_INFORMATION.InformationBuffer = InformationBuffer; pAdapt->Request5.DATA.SET_INFORMATION.InformationBufferLength = InformationBufferLength; pAdapt->BytesNeeded = BytesNeeded; pAdapt->BytesReadOrWritten = BytesRead; // // If the miniport below is unbinding, fail the request // NdisAcquireSpinLock(&pAdapt->Lock); if (pAdapt->UnbindingInProcess == TRUE) { NdisReleaseSpinLock(&pAdapt->Lock); Status = NDIS_STATUS_FAILURE; break; } // // If the device below is at a low power state, we cannot send it the // request now, and must pend it. // if ((pAdapt->PTDeviceState > NdisDeviceStateD0) && (pAdapt->StandingBy == FALSE)) { pAdapt->QueuedRequest = TRUE; NdisReleaseSpinLock(&pAdapt->Lock); Status = NDIS_STATUS_PENDING; break; } // // This is in the process of powering down the system, always fail the request // if (pAdapt->StandingBy == TRUE) { NdisReleaseSpinLock(&pAdapt->Lock); Status = NDIS_STATUS_FAILURE; break; } pAdapt->OutstandingRequests = TRUE; NdisReleaseSpinLock(&pAdapt->Lock); // // Forward the request to the device below. // NdisRequest(&Status, pAdapt->BindingHandle, (PVOID)&pAdapt->Request5); if (Status != NDIS_STATUS_PENDING) { *BytesRead = pAdapt->Request5.DATA.SET_INFORMATION.BytesRead; *BytesNeeded = pAdapt->Request5.DATA.SET_INFORMATION.BytesNeeded; pAdapt->OutstandingRequests = FALSE; } } while (FALSE); return(Status); }
// I/O控制派遣例程 NTSTATUS DispatchIoctl(PDEVICE_OBJECT pDevObj, PIRP pIrp) { // 假设失败 NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST; // 取得此IRP(pIrp)的I/O堆栈指针 PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp); // 取得I/O控制代码 ULONG uIoControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode; // 取得I/O缓冲区指针和它的长度 PVOID pIoBuffer = pIrp->AssociatedIrp.SystemBuffer; ULONG uInSize = pIrpStack->Parameters.DeviceIoControl.InputBufferLength; ULONG uOutSize = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength; if(uIoControlCode == IOCTL_ENUM_ADAPTERS) { ULONG nDataLen = 0; if(pDevObj != g_data.pControlDevice) status = STATUS_INVALID_DEVICE_REQUEST; else { status = GetAdapterList(pIoBuffer, uOutSize, &nDataLen); if(status != STATUS_SUCCESS) DbgPrint("GetAdapterList error "); } pIrp->IoStatus.Information = nDataLen; pIrp->IoStatus.Status = status; IoCompleteRequest(pIrp, IO_NO_INCREMENT); return status; } OPEN_INSTANCE *pOpen = (OPEN_INSTANCE *)pDevObj->DeviceExtension; if(pOpen == NULL || !pOpen->bBound) { pIrp->IoStatus.Status = STATUS_UNSUCCESSFUL; IoCompleteRequest(pIrp, IO_NO_INCREMENT); return STATUS_UNSUCCESSFUL; } IoIncrement(pOpen); IoMarkIrpPending(pIrp); if(uIoControlCode == IOCTL_PROTOCOL_RESET) { // 插入此IRP到重置IRP列表 ExInterlockedInsertTailList( &pOpen->ResetIrpList, &pIrp->Tail.Overlay.ListEntry, &pOpen->ResetQueueLock); // 发出重置请求 NdisReset( &status, pOpen->hAdapter ); if(status != NDIS_STATUS_PENDING) { ProtocolResetComplete( pOpen, status); } } // 获取或者设置OID信息 else if(uIoControlCode == IOCTL_PROTOCOL_SET_OID || uIoControlCode == IOCTL_PROTOCOL_QUERY_OID) // 输入参数是一个自定义的PROTOCOL_OID_DATA结构 { PPROTOCOL_OID_DATA pOidData = (PPROTOCOL_OID_DATA)pIoBuffer; // 申请一个INTERNAL_REQUEST结构 PINTERNAL_REQUEST pInterRequest = (PINTERNAL_REQUEST)ExAllocatePool(NonPagedPool, sizeof(INTERNAL_REQUEST)); if(pInterRequest == NULL) { pIrp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; IoCompleteRequest(pIrp, IO_NO_INCREMENT); IoDecrement(pOpen); return STATUS_PENDING; } pInterRequest->pIrp = pIrp; if(uOutSize == uInSize && uOutSize >= sizeof(PROTOCOL_OID_DATA) && uOutSize >= sizeof(PROTOCOL_OID_DATA) - 1 + pOidData->Length) // 缓冲区可用? { // 初始化NDIS_REQUEST结构 if(uIoControlCode == IOCTL_PROTOCOL_SET_OID) { pInterRequest->Request.RequestType = NdisRequestSetInformation; pInterRequest->Request.DATA.SET_INFORMATION.Oid = pOidData->Oid; pInterRequest->Request.DATA.SET_INFORMATION.InformationBuffer = pOidData->Data; pInterRequest->Request.DATA.SET_INFORMATION.InformationBufferLength = pOidData->Length; } else { pInterRequest->Request.RequestType = NdisRequestQueryInformation; pInterRequest->Request.DATA.QUERY_INFORMATION.Oid = pOidData->Oid; pInterRequest->Request.DATA.QUERY_INFORMATION.InformationBuffer = pOidData->Data; pInterRequest->Request.DATA.QUERY_INFORMATION.InformationBufferLength = pOidData->Length; } // 提交这个请求 NdisRequest(&status, pOpen->hAdapter, &pInterRequest->Request); } else { status = NDIS_STATUS_FAILURE; pInterRequest->Request.DATA.SET_INFORMATION.BytesRead = 0; pInterRequest->Request.DATA.QUERY_INFORMATION.BytesWritten = 0; } if(status != NDIS_STATUS_PENDING) { ProtocolRequestComplete(pOpen, &pInterRequest->Request, status); } } return STATUS_PENDING; }
NDIS_STATUS MiniportQueryInformation5( IN NDIS_HANDLE MiniportAdapterContext, IN NDIS_OID Oid, IN PVOID InformationBuffer, IN ULONG InformationBufferLength, OUT PULONG BytesWritten, OUT PULONG BytesNeeded ) { PADAPTER pAdapt = (PADAPTER)MiniportAdapterContext; NDIS_STATUS Status = NDIS_STATUS_FAILURE; do { if (Oid == OID_PNP_QUERY_POWER) { // // Do not forward this. // Status = NDIS_STATUS_SUCCESS; break; } if (Oid == OID_GEN_SUPPORTED_GUIDS) { // // Do not forward this, otherwise we will end up with multiple // instances of private GUIDs that the underlying miniport // supports. // Status = NDIS_STATUS_NOT_SUPPORTED; break; } if (Oid == OID_TCP_TASK_OFFLOAD) { // // Fail this -if- this driver performs data transformations // that can interfere with a lower driver's ability to offload // TCP tasks. // // Status = NDIS_STATUS_NOT_SUPPORTED; // break; // } // // If the miniport below is unbinding, just fail any request // NdisAcquireSpinLock(&pAdapt->Lock); if (pAdapt->UnbindingInProcess == TRUE) { NdisReleaseSpinLock(&pAdapt->Lock); Status = NDIS_STATUS_FAILURE; break; } NdisReleaseSpinLock(&pAdapt->Lock); // // All other queries are failed, if the miniport is not at D0, // if (pAdapt->MiniportDeviceState > NdisDeviceStateD0) { Status = NDIS_STATUS_FAILURE; break; } pAdapt->Request5.RequestType = NdisRequestQueryInformation; pAdapt->Request5.DATA.QUERY_INFORMATION.Oid = Oid; pAdapt->Request5.DATA.QUERY_INFORMATION.InformationBuffer = InformationBuffer; pAdapt->Request5.DATA.QUERY_INFORMATION.InformationBufferLength = InformationBufferLength; pAdapt->BytesNeeded = BytesNeeded; pAdapt->BytesReadOrWritten = BytesWritten; // // If the miniport below is binding, fail the request // NdisAcquireSpinLock(&pAdapt->Lock); if (pAdapt->UnbindingInProcess == TRUE) { NdisReleaseSpinLock(&pAdapt->Lock); Status = NDIS_STATUS_FAILURE; break; } // // If the Protocol device state is OFF, mark this request as being // pended. We queue this until the device state is back to D0. // if ((pAdapt->PTDeviceState > NdisDeviceStateD0) && (pAdapt->StandingBy == FALSE)) { pAdapt->QueuedRequest = TRUE; NdisReleaseSpinLock(&pAdapt->Lock); Status = NDIS_STATUS_PENDING; break; } // // This is in the process of powering down the system, always fail the request // if (pAdapt->StandingBy == TRUE) { NdisReleaseSpinLock(&pAdapt->Lock); Status = NDIS_STATUS_FAILURE; break; } pAdapt->OutstandingRequests = TRUE; NdisReleaseSpinLock(&pAdapt->Lock); // // default case, most requests will be passed to the miniport below // NdisRequest(&Status, pAdapt->BindingHandle, (PVOID)&pAdapt->Request5); if (Status != NDIS_STATUS_PENDING) { ProtocolRequestComplete5(pAdapt, (PVOID)&pAdapt->Request5, Status); Status = NDIS_STATUS_PENDING; } } while (FALSE); return(Status); }
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; }
static NTSTATUS QueryAdapterOid(PIRP Irp, PIO_STACK_LOCATION IrpSp) { PNDISUIO_ADAPTER_CONTEXT AdapterContext = IrpSp->FileObject->FsContext; PNDISUIO_QUERY_OID QueryOidRequest; NDIS_REQUEST Request; ULONG RequestLength; NDIS_STATUS Status; Irp->IoStatus.Information = 0; QueryOidRequest = Irp->AssociatedIrp.SystemBuffer; RequestLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength; if (QueryOidRequest && RequestLength >= sizeof(NDIS_OID)) { /* Setup the NDIS request */ Request.RequestType = NdisRequestQueryInformation; Request.DATA.QUERY_INFORMATION.Oid = QueryOidRequest->Oid; Request.DATA.QUERY_INFORMATION.InformationBufferLength = RequestLength - sizeof(NDIS_OID); if (Request.DATA.QUERY_INFORMATION.InformationBufferLength != 0) { Request.DATA.QUERY_INFORMATION.InformationBuffer = QueryOidRequest->Data; } else { Request.DATA.QUERY_INFORMATION.InformationBuffer = NULL; } Request.DATA.QUERY_INFORMATION.BytesWritten = 0; DPRINT("Querying OID 0x%x on adapter %wZ\n", QueryOidRequest->Oid, &AdapterContext->DeviceName); /* Dispatch the request */ NdisRequest(&Status, AdapterContext->BindingHandle, &Request); /* Wait for the request */ if (Status == NDIS_STATUS_PENDING) { KeWaitForSingleObject(&AdapterContext->AsyncEvent, Executive, KernelMode, FALSE, NULL); Status = AdapterContext->AsyncStatus; } /* Return the bytes written */ if (NT_SUCCESS(Status)) Irp->IoStatus.Information = sizeof(NDIS_OID) + Request.DATA.QUERY_INFORMATION.BytesWritten; DPRINT("Final request status: 0x%x (%d)\n", Status, Irp->IoStatus.Information); } else { /* Bad parameters */ Status = STATUS_INVALID_PARAMETER; } Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); return Status; }
VOID NdisMlidStatisticTimer( IN PVOID SystemSpecific1, IN PVOID Context, IN PVOID SystemSpecific2, IN PVOID SystemSpecific3 ) /*++ Routine Description: This DPC routine is queued to gather statistics from then NDIS MAC. Arguments: Context - Really a pointer to the MLID. Return Value: None. --*/ { PMLID_STRUCT Mlid = (PMLID_STRUCT)Context; PNDIS_REQUEST NdisMlidRequest = &(Mlid->StatsTable->NdisRequest); NDIS_STATUS NdisStatus; NdisAcquireSpinLock(&(Mlid->MlidSpinLock)); // // Loop // while (TRUE) { // // Set up NdisRequest // NdisMlidRequest->RequestType = NdisRequestQueryInformation; switch (Mlid->NdisMlidMedium) { case NdisMedium802_3: switch (Mlid->StatsTable->StatisticNumber) { case 0: NdisMlidRequest->DATA.QUERY_INFORMATION.Oid = OID_802_3_XMIT_ONE_COLLISION; break; case 1: NdisMlidRequest->DATA.QUERY_INFORMATION.Oid = OID_802_3_XMIT_MORE_COLLISIONS; break; case 2: NdisMlidRequest->DATA.QUERY_INFORMATION.Oid = OID_802_3_XMIT_DEFERRED; break; case 3: NdisMlidRequest->DATA.QUERY_INFORMATION.Oid = OID_802_3_XMIT_LATE_COLLISIONS; break; case 4: NdisMlidRequest->DATA.QUERY_INFORMATION.Oid = OID_802_3_XMIT_MAX_COLLISIONS; break; case 5: NdisMlidRequest->DATA.QUERY_INFORMATION.Oid = OID_802_3_XMIT_TIMES_CRS_LOST; break; case 6: goto DoNextStatistic; case 7: NdisMlidRequest->DATA.QUERY_INFORMATION.Oid = OID_802_3_RCV_ERROR_ALIGNMENT; break; } break; case NdisMedium802_5: switch (Mlid->StatsTable->StatisticNumber) { case 0: NdisMlidRequest->DATA.QUERY_INFORMATION.Oid = OID_802_5_AC_ERRORS; break; case 1: NdisMlidRequest->DATA.QUERY_INFORMATION.Oid = OID_802_5_ABORT_DELIMETERS; break; case 2: NdisMlidRequest->DATA.QUERY_INFORMATION.Oid = OID_802_5_BURST_ERRORS; break; case 3: NdisMlidRequest->DATA.QUERY_INFORMATION.Oid = OID_802_5_FRAME_COPIED_ERRORS; break; case 4: NdisMlidRequest->DATA.QUERY_INFORMATION.Oid = OID_802_5_FREQUENCY_ERRORS; break; case 5: NdisMlidRequest->DATA.QUERY_INFORMATION.Oid = OID_802_5_INTERNAL_ERRORS; break; case 6: goto DoNextStatistic; case 7: NdisMlidRequest->DATA.QUERY_INFORMATION.Oid = OID_802_5_LINE_ERRORS; break; case 8: NdisMlidRequest->DATA.QUERY_INFORMATION.Oid = OID_802_5_LOST_FRAMES; break; case 9: NdisMlidRequest->DATA.QUERY_INFORMATION.Oid = OID_802_5_TOKEN_ERRORS; break; case 10: case 11: case 12: goto DoNextStatistic; } break; case NdisMediumFddi: switch (Mlid->StatsTable->StatisticNumber) { case 0: NdisMlidRequest->DATA.QUERY_INFORMATION.Oid = OID_FDDI_ATTACHMENT_TYPE; break; case 1: NdisMlidRequest->DATA.QUERY_INFORMATION.Oid = OID_FDDI_UPSTREAM_NODE_LONG; break; case 2: NdisMlidRequest->DATA.QUERY_INFORMATION.Oid = OID_FDDI_DOWNSTREAM_NODE_LONG; break; case 3: NdisMlidRequest->DATA.QUERY_INFORMATION.Oid = OID_FDDI_FRAME_ERRORS; break; case 4: NdisMlidRequest->DATA.QUERY_INFORMATION.Oid = OID_FDDI_FRAMES_LOST; break; case 5: NdisMlidRequest->DATA.QUERY_INFORMATION.Oid = OID_FDDI_RING_MGT_STATE; break; case 6: NdisMlidRequest->DATA.QUERY_INFORMATION.Oid = OID_FDDI_LCT_FAILURES; break; case 7: NdisMlidRequest->DATA.QUERY_INFORMATION.Oid = OID_FDDI_LEM_REJECTS; break; case 8: // LemCount goto DoNextStatistic; case 9: NdisMlidRequest->DATA.QUERY_INFORMATION.Oid = OID_FDDI_LCONNECTION_STATE; break; default: goto DoNextStatistic; } break; } NdisMlidRequest->DATA.QUERY_INFORMATION.InformationBuffer = (PVOID)&(Mlid->StatsTable->StatisticValue); NdisMlidRequest->DATA.QUERY_INFORMATION.InformationBufferLength = sizeof(Mlid->StatsTable->StatisticValue); NdisMlidRequest->DATA.QUERY_INFORMATION.BytesWritten = 0; NdisMlidRequest->DATA.QUERY_INFORMATION.BytesNeeded = 0; NdisReleaseSpinLock(&(Mlid->MlidSpinLock)); NdisRequest( &NdisStatus, Mlid->NdisBindingHandle, NdisMlidRequest ); // // if (pending), exit. // if (NdisStatus == NDIS_STATUS_PENDING) { return; } NdisAcquireSpinLock(&(Mlid->MlidSpinLock)); if (NdisStatus == NDIS_STATUS_SUCCESS) { // // Store Statistic // (*((PUINT32)((*(Mlid->StatsTable->StatsTable.MMediaCountsPtr)) [ Mlid->StatsTable->StatisticNumber ].StatCounter))) = Mlid->StatsTable->StatisticValue; } DoNextStatistic: Mlid->StatsTable->StatisticNumber++; switch (Mlid->NdisMlidMedium) { case NdisMedium802_3: if (Mlid->StatsTable->StatisticNumber >= NUM_ETHERNET_COUNTS) { Mlid->StatsTable->StatisticNumber = 0; } break; case NdisMedium802_5: if (Mlid->StatsTable->StatisticNumber >= NUM_TOKEN_RING_COUNTS) { Mlid->StatsTable->StatisticNumber = 0; } break; case NdisMediumFddi: if (Mlid->StatsTable->StatisticNumber >= NUM_FDDI_COUNTS) { Mlid->StatsTable->StatisticNumber = 0; } break; } if (Mlid->StatsTable->StatisticNumber == 0) { // // Set timer for 30 seconds from now. // NdisReleaseSpinLock(&(Mlid->MlidSpinLock)); NdisSetTimer(&(Mlid->StatsTable->StatisticTimer), 30000); return; } } }
NDIS_STATUS SecLabDoRequest( IN PADAPT pAdapt, IN NDIS_REQUEST_TYPE RequestType, IN NDIS_OID Oid, IN PVOID InformationBuffer, IN UINT InformationBufferLength, OUT PUINT pBytesProcessed ) { SECLAB_REQUEST ReqContext; PNDIS_REQUEST pNdisRequest = &ReqContext.Request; NDIS_STATUS Status; NdisInitializeEvent(&ReqContext.ReqEvent); ReqContext.Signal=REQUEST_SIGNAL; pNdisRequest->RequestType = RequestType; 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: break; } NdisRequest(&Status, pAdapt->BindingHandle, pNdisRequest); if (Status == NDIS_STATUS_PENDING) { NdisWaitEvent(&ReqContext.ReqEvent, 0); Status = ReqContext.Status; } if (Status == NDIS_STATUS_SUCCESS) { *pBytesProcessed = (RequestType == NdisRequestQueryInformation)? pNdisRequest->DATA.QUERY_INFORMATION.BytesWritten: pNdisRequest->DATA.SET_INFORMATION.BytesRead; } return (Status); }