VOID NDIS_API PacketUnbindAdapter(OUT PNDIS_STATUS Status, IN POPEN_INSTANCE Open, IN POPEN_INSTANCE junk) { // detach protocol from the NIC clean up any pending I/O requests PLIST_ENTRY PacketListEntry; PNDIS_PACKET pPacket; // The open instance of the device is about to close // We need to complete all pending I/O requests // First we complete any pending read requests NdisAcquireSpinLock(&Open->RcvQSpinLock); while (!IsListEmpty(&Open->RcvList)) { PacketListEntry = RemoveHeadList(&Open->RcvList); pPacket = CONTAINING_RECORD(PacketListEntry, NDIS_PACKET, ProtocolReserved); // complete normally PacketTransferDataComplete(Open, pPacket, NDIS_STATUS_SUCCESS, 0); } NdisReleaseSpinLock(&Open->RcvQSpinLock); // close the adapter NdisCloseAdapter(Status, Open->AdapterHandle); // Save status returned from NdisCloseAdapter for completion routine Open->Status = *Status; if (*Status != NDIS_STATUS_PENDING) PacketUnbindAdapterComplete(Open, *Status); }
/* * The plug and play support function. This function removes the adapter from * the global list of the adapter. * */ VOID PacketUnbindAdapter (OUT PNDIS_STATUS pStatus, IN NDIS_HANDLE ProtocolBindingContext, IN NDIS_HANDLE UnbindContext) { POPEN_INSTANCE pOI; NDIS_STATUS nsCloseStatus; pOI = (POPEN_INSTANCE)ProtocolBindingContext; pOI->BindAdapterContext = UnbindContext; // Calls NDIS to close the selected adapter NdisCloseAdapter (&nsCloseStatus, pOI->AdapterHandle); if (nsCloseStatus == NDIS_STATUS_PENDING) { SuspendExecution (pOI); } else { PacketCloseAdapterComplete (pOI, nsCloseStatus); } // return the status back to the ndis framework *pStatus = pOI->Status; // set all the events to release the waits SetEvent (pOI->ReadEvent); CloseHandle (pOI->ReadEvent); // Free the open instance memory //NdisFreeMemory (pOI, sizeof (OPEN_INSTANCE), 0); // set no instances open g_pDeviceExtension->pOpenInstance = NULL; return; }
/* * Closes the open adapter * */ BOOL PKTCloseAdapter (POPEN_INSTANCE pOI) { BOOL bRet = TRUE; NDIS_STATUS nsError; // close the adapter NdisCloseAdapter (&nsError, pOI->AdapterHandle); if (nsError == NDIS_STATUS_PENDING) { SuspendExecution (pOI); } else { PacketCloseAdapterComplete (pOI, nsError); } if (pOI->Status != NDIS_STATUS_SUCCESS) { bRet = FALSE; } // set all the events to release the waits SetEvent (pOI->ReadEvent); CloseHandle (pOI->ReadEvent); // Free the open instance memory NdisFreeMemory (pOI, sizeof (OPEN_INSTANCE), 0); // set no instances open g_pDeviceExtension->pOpenInstance = NULL; return bRet; }
VOID MiniportHalt5( IN NDIS_HANDLE MiniportAdapterContext ) { PADAPTER pAdapt = (PADAPTER)MiniportAdapterContext; NDIS_STATUS Status; // // Delete the ioctl interface that was created when the miniport // was created. // (VOID)ProtocolDeregisterDevice(); #ifdef _DEBUG // 关闭直接包发送接口 if(pAdapt->FileObject) { // // Make sure any threads trying to send have finished. // pAdapt->FileObject->FsContext = NULL; pAdapt->FileObject = NULL; } #endif // // If we have a valid bind, close the miniport below the protocol // if (pAdapt->BindingHandle != NULL) { // // Close the binding below. and wait for it to complete // NdisResetEvent(&pAdapt->Event); NdisCloseAdapter(&Status, pAdapt->BindingHandle); if (Status == NDIS_STATUS_PENDING) { NdisWaitEvent(&pAdapt->Event, 0); Status = pAdapt->Status; } ASSERT (Status == NDIS_STATUS_SUCCESS); pAdapt->BindingHandle = NULL; } // // Free all resources on this adapter structure. // MiniportFreeAllPacketPools5(pAdapt); NdisFreeSpinLock(&pAdapt->Lock); NdisFreeMemory(pAdapt, 0, 0); }
/************************************************************ Start the unbind of a network driver from the protocol driver ************************************************************/ VOID NDIS_API PacketUnbindAdapter( OUT PNDIS_STATUS Status, IN NDIS_HANDLE ProtocolBindingContext, IN NDIS_HANDLE UnbindContext ) { POPEN_INSTANCE Open; NDIS_STATUS nsCloseStatus; TRACE_ENTER( "UnbindAdapter" ); Open = (POPEN_INSTANCE)ProtocolBindingContext; Open->BindAdapterContext = UnbindContext; /*clean the pending requests*/ PacketCleanUp( Status, Open ); Open->Status = NDIS_STATUS_PENDING; /*Calls NDIS to close the selected adapter*/ NdisCloseAdapter( &nsCloseStatus, Open->AdapterHandle ); if ( nsCloseStatus == NDIS_STATUS_PENDING ) { while ( Open->Status == NDIS_STATUS_PENDING ) YieldExecution(); } else { PacketUnbindAdapterComplete( Open, nsCloseStatus ); } *Status = Open->Status; if ( *Status == NDIS_STATUS_SUCCESS ) { NdisFreeMemory( Open, sizeof( OPEN_INSTANCE ) , 0 ); } else { IF_TRACE( "Unbind Operation FAILED!" ); } TRACE_LEAVE( "CloseAdapter" ); return; }
VOID MPHalt( IN NDIS_HANDLE MiniportAdapterContext ) /*++ Routine Description: Halt handler. All the hard-work for clean-up is done here. Arguments: MiniportAdapterContext Pointer to the Adapter Return Value: None. --*/ { PADAPT pAdapt = (PADAPT)MiniportAdapterContext; NDIS_STATUS Status; PADAPT *ppCursor; DBGPRINT(("==>MiniportHalt: Adapt %p\n", pAdapt)); // // Remove this adapter from the global list // NdisAcquireSpinLock(&GlobalLock); for (ppCursor = &pAdaptList; *ppCursor != NULL; ppCursor = &(*ppCursor)->Next) { if (*ppCursor == pAdapt) { *ppCursor = pAdapt->Next; break; } } NdisReleaseSpinLock(&GlobalLock); // // Make Suprise Unbind Notification // netgOnUnbindAdapter( pAdapt->pOpenContext ); // // Delete the ioctl interface that was created when the miniport // was created. // (VOID)PtDeregisterDevice(); if (pAdapt->BindingHandle != NULL) { NDIS_STATUS LocalStatus; // // Close the binding to the adapter // NdisResetEvent(&pAdapt->Event); NdisCloseAdapter(&LocalStatus, pAdapt->BindingHandle); pAdapt->BindingHandle = NULL; if (LocalStatus == NDIS_STATUS_PENDING) { NdisWaitEvent(&pAdapt->Event, 0); LocalStatus = pAdapt->Status; } ASSERT (LocalStatus == NDIS_STATUS_SUCCESS); } // // Remove Reference To The Adapter // PtDerefAdapter( pAdapt ); DBGPRINT(("<== MiniportHalt: pAdapt %p\n", pAdapt)); }
VOID NPF_CloseBinding( IN POPEN_INSTANCE pOpen) { NDIS_EVENT Event; NDIS_STATUS Status; ASSERT(pOpen != NULL); ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); NdisInitializeEvent(&Event); NdisResetEvent(&Event); NdisAcquireSpinLock(&pOpen->AdapterHandleLock); while(pOpen->AdapterHandleUsageCounter > 0) { NdisReleaseSpinLock(&pOpen->AdapterHandleLock); NdisWaitEvent(&Event,1); NdisAcquireSpinLock(&pOpen->AdapterHandleLock); } // // now the UsageCounter is 0 // while(pOpen->AdapterBindingStatus == ADAPTER_UNBINDING) { NdisReleaseSpinLock(&pOpen->AdapterHandleLock); NdisWaitEvent(&Event,1); NdisAcquireSpinLock(&pOpen->AdapterHandleLock); } // // now the binding status is either bound or unbound // if (pOpen->AdapterBindingStatus == ADAPTER_UNBOUND) { NdisReleaseSpinLock(&pOpen->AdapterHandleLock); return; } ASSERT(pOpen->AdapterBindingStatus == ADAPTER_BOUND); pOpen->AdapterBindingStatus = ADAPTER_UNBINDING; NdisReleaseSpinLock(&pOpen->AdapterHandleLock); // // do the release procedure // NdisResetEvent(&pOpen->NdisOpenCloseCompleteEvent); // Close the adapter NdisCloseAdapter( &Status, pOpen->AdapterHandle ); if (Status == NDIS_STATUS_PENDING) { TRACE_MESSAGE(PACKET_DEBUG_LOUD, "Pending NdisCloseAdapter"); NdisWaitEvent(&pOpen->NdisOpenCloseCompleteEvent, 0); } else { TRACE_MESSAGE(PACKET_DEBUG_LOUD, "Not Pending NdisCloseAdapter"); } NdisAcquireSpinLock(&pOpen->AdapterHandleLock); pOpen->AdapterBindingStatus = ADAPTER_UNBOUND; NdisReleaseSpinLock(&pOpen->AdapterHandleLock); }
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; }
static NDIS_STATUS UnbindAdapterByContext(PNDISUIO_ADAPTER_CONTEXT AdapterContext) { KIRQL OldIrql; PLIST_ENTRY CurrentEntry; PNDISUIO_OPEN_ENTRY OpenEntry; PNDISUIO_PACKET_ENTRY PacketEntry; NDIS_STATUS Status; DPRINT("Unbinding adapter %wZ\n", &AdapterContext->DeviceName); /* FIXME: We don't do anything with outstanding reads */ /* Remove the adapter context from the global list */ KeAcquireSpinLock(&GlobalAdapterListLock, &OldIrql); RemoveEntryList(&AdapterContext->ListEntry); KeReleaseSpinLock(&GlobalAdapterListLock, OldIrql); /* Free the device name string */ RtlFreeUnicodeString(&AdapterContext->DeviceName); /* Invalidate all handles to this adapter */ CurrentEntry = AdapterContext->OpenEntryList.Flink; while (CurrentEntry != &AdapterContext->OpenEntryList) { OpenEntry = CONTAINING_RECORD(CurrentEntry, NDISUIO_OPEN_ENTRY, ListEntry); /* Make sure the entry is sane */ ASSERT(OpenEntry->FileObject); /* Remove the adapter context pointer */ ASSERT(AdapterContext == OpenEntry->FileObject->FsContext); OpenEntry->FileObject->FsContext = NULL; AdapterContext->OpenCount--; /* Remove the open entry pointer */ ASSERT(OpenEntry == OpenEntry->FileObject->FsContext2); OpenEntry->FileObject->FsContext2 = NULL; /* Move to the next entry */ CurrentEntry = CurrentEntry->Flink; /* Free the open entry */ ExFreePool(OpenEntry); } /* If this fails, we have a refcount mismatch somewhere */ ASSERT(AdapterContext->OpenCount == 0); /* Free all pending packet entries */ CurrentEntry = AdapterContext->PacketList.Flink; while (CurrentEntry != &AdapterContext->PacketList) { PacketEntry = CONTAINING_RECORD(CurrentEntry, NDISUIO_PACKET_ENTRY, ListEntry); /* Move to the next entry */ CurrentEntry = CurrentEntry->Flink; /* Free the packet entry */ ExFreePool(PacketEntry); } /* Send the close request */ NdisCloseAdapter(&Status, AdapterContext->BindingHandle); /* Wait for a pending close */ if (Status == NDIS_STATUS_PENDING) { KeWaitForSingleObject(&AdapterContext->AsyncEvent, Executive, KernelMode, FALSE, NULL); Status = AdapterContext->AsyncStatus; } /* Free the context */ ExFreePool(AdapterContext); return Status; }
VOID natpBindAdapter( OUT PNDIS_STATUS Status, IN NDIS_HANDLE BindContext, IN PNDIS_STRING DeviceName, IN PVOID SystemSpecific1, IN PVOID SystemSpecific2 ) { NDIS_HANDLE ConfigHandle = NULL; PNDIS_CONFIGURATION_PARAMETER Param; NDIS_STRING DeviceStr = UPPER_BINDINGS; PFILTER_ADAPTER pAdapt = NULL; NDIS_STATUS Sts; UINT MediumIndex, i; ULONG TotalSize; WCHAR DevicePrefix[] = L"\\Device\\"; UNREFERENCED_PARAMETER(BindContext); UNREFERENCED_PARAMETER(SystemSpecific2); __try{ NdisOpenProtocolConfiguration( Status, &ConfigHandle, SystemSpecific1 ); if (*Status != NDIS_STATUS_SUCCESS) __leave; NdisReadConfiguration( Status, &Param, ConfigHandle, &DeviceStr, NdisParameterString ); if (*Status != NDIS_STATUS_SUCCESS) __leave; TotalSize = sizeof(FILTER_ADAPTER) + Param->ParameterData.StringData.MaximumLength + DeviceName->MaximumLength; NdisAllocateMemoryWithTag(&pAdapt, TotalSize, NAT_TAG); if (NULL == pAdapt){ *Status = NDIS_STATUS_RESOURCES; __leave; } NdisZeroMemory(pAdapt, TotalSize); pAdapt->DeviceName.MaximumLength = Param->ParameterData.StringData.MaximumLength; pAdapt->DeviceName.Length = Param->ParameterData.StringData.Length; pAdapt->DeviceName.Buffer = (PWCHAR)((ULONG_PTR)pAdapt + sizeof(FILTER_ADAPTER)); NdisMoveMemory( pAdapt->DeviceName.Buffer, Param->ParameterData.StringData.Buffer, Param->ParameterData.StringData.MaximumLength ); if(sizeof(DevicePrefix) >= DeviceName->Length){ }else{ pAdapt->RootDeviceName.MaximumLength = DeviceName->MaximumLength; pAdapt->RootDeviceName.Length = DeviceName->Length - sizeof(DevicePrefix) + sizeof(WCHAR); pAdapt->RootDeviceName.Buffer = (PWCHAR)((ULONG_PTR)pAdapt + sizeof(FILTER_ADAPTER) + Param->ParameterData.StringData.MaximumLength); NdisMoveMemory( pAdapt->RootDeviceName.Buffer, DeviceName->Buffer + sizeof(DevicePrefix)/sizeof(WCHAR) - 1, DeviceName->MaximumLength - sizeof(DevicePrefix)/sizeof(WCHAR) + 1 ); } NdisInitializeEvent(&pAdapt->Event); NdisAllocateSpinLock(&pAdapt->Lock); natInitControlBlock(&pAdapt->ctrl); NdisAllocatePacketPoolEx( Status, &pAdapt->SndPP1, MIN_PACKET_POOL_SIZE, MAX_PACKET_POOL_SIZE, PROTOCOL_RESERVED_SIZE_IN_PACKET ); if (*Status != NDIS_STATUS_SUCCESS) __leave; NdisAllocatePacketPoolEx( Status, &pAdapt->SndPP2, MIN_PACKET_POOL_SIZE, MAX_PACKET_POOL_SIZE, PROTOCOL_RESERVED_SIZE_IN_PACKET ); if (*Status != NDIS_STATUS_SUCCESS) __leave; NdisAllocateBufferPool( Status, &pAdapt->SndBP, MIN_PACKET_POOL_SIZE ); if ( *Status != NDIS_STATUS_SUCCESS ) __leave; NdisAllocatePacketPoolEx( Status, &pAdapt->RcvPP1, MIN_PACKET_POOL_SIZE, MAX_PACKET_POOL_SIZE - MIN_PACKET_POOL_SIZE, PROTOCOL_RESERVED_SIZE_IN_PACKET ); if (*Status != NDIS_STATUS_SUCCESS) __leave; NdisAllocatePacketPoolEx( Status, &pAdapt->RcvPP2, MIN_PACKET_POOL_SIZE, MAX_PACKET_POOL_SIZE - MIN_PACKET_POOL_SIZE, PROTOCOL_RESERVED_SIZE_IN_PACKET ); if (*Status != NDIS_STATUS_SUCCESS) __leave; NdisAllocateBufferPool( Status, &pAdapt->RcvBP, MIN_PACKET_POOL_SIZE ); if ( *Status != NDIS_STATUS_SUCCESS ) __leave; NdisOpenAdapter( Status, &Sts, &pAdapt->BindingHandle, &MediumIndex, MediumArray, sizeof(MediumArray)/sizeof(NDIS_MEDIUM), ProtHandle, pAdapt, DeviceName, 0,NULL ); if (*Status == NDIS_STATUS_PENDING){ NdisWaitEvent(&pAdapt->Event, 0); *Status = pAdapt->Status; } if (*Status != NDIS_STATUS_SUCCESS) __leave; pAdapt->Medium = MediumArray[MediumIndex]; pAdapt->MiniportInitPending = TRUE; NdisInitializeEvent(&pAdapt->MiniportInitEvent); *Status = NdisIMInitializeDeviceInstanceEx( DriverHandle, &pAdapt->DeviceName, pAdapt ); if (*Status != NDIS_STATUS_SUCCESS) __leave; StartQueryInfo( pAdapt ); } __finally{ } if (ConfigHandle != NULL) NdisCloseConfiguration(ConfigHandle); if(NDIS_STATUS_SUCCESS != *Status){ if (pAdapt != NULL){ if (pAdapt->BindingHandle != NULL){ NDIS_STATUS LocalStatus; NdisResetEvent(&pAdapt->Event); NdisCloseAdapter(&LocalStatus, pAdapt->BindingHandle); pAdapt->BindingHandle = NULL; if (LocalStatus == NDIS_STATUS_PENDING){ NdisWaitEvent(&pAdapt->Event, 0); LocalStatus = pAdapt->Status; } } natFreeAllItems(&pAdapt->ctrl); natFreeAllFwSessionsAndRules(&pAdapt->ctrl); for(i = 0;i<FLT_FW_SESSION_HASH_TBL_SZ;i++) NdisFreeSpinLock(pAdapt->ctrl.FwSessionLocks + i); NdisFreeSpinLock(&pAdapt->ctrl.IcmpRuleLock); NdisFreeSpinLock(&pAdapt->ctrl.UdpRuleLock); NdisFreeSpinLock(&pAdapt->ctrl.TcpRuleLock); natmFreeAllPacketPools(pAdapt); NdisFreeSpinLock(&pAdapt->Lock); NdisFreeMemory(pAdapt, 0, 0); pAdapt = NULL; } } }
VOID natpUnbindAdapter( OUT PNDIS_STATUS Status, IN NDIS_HANDLE ProtocolBindingContext, IN NDIS_HANDLE UnbindContext ) { PFILTER_ADAPTER pAdapt; NDIS_STATUS LocalStatus; pAdapt = (PFILTER_ADAPTER)ProtocolBindingContext; UNREFERENCED_PARAMETER(UnbindContext); NdisAcquireSpinLock(&pAdapt->Lock); pAdapt->UnbindingInProcess = TRUE; if (pAdapt->QueuedRequest == TRUE){ pAdapt->QueuedRequest = FALSE; NdisReleaseSpinLock(&pAdapt->Lock); natpRequestComplete(pAdapt, &pAdapt->IntReq.NdisRequest, NDIS_STATUS_FAILURE ); }else{ NdisReleaseSpinLock(&pAdapt->Lock); } if (pAdapt->MiniportInitPending == TRUE){ LocalStatus = NdisIMCancelInitializeDeviceInstance( DriverHandle, &pAdapt->DeviceName ); if (LocalStatus == NDIS_STATUS_SUCCESS){ pAdapt->MiniportInitPending = FALSE; ASSERT(pAdapt->MiniportHandle == NULL); }else{ NdisWaitEvent(&pAdapt->MiniportInitEvent, 0); ASSERT(pAdapt->MiniportInitPending == FALSE); } } if (pAdapt->MiniportHandle != NULL){ *Status = NdisIMDeInitializeDeviceInstance( pAdapt->MiniportHandle ); if (*Status != NDIS_STATUS_SUCCESS) *Status = NDIS_STATUS_FAILURE; }else{ if(NULL != pAdapt->BindingHandle){ NdisResetEvent(&pAdapt->Event); NdisCloseAdapter(Status, pAdapt->BindingHandle); if(*Status == NDIS_STATUS_PENDING){ NdisWaitEvent(&pAdapt->Event, 0); *Status = pAdapt->Status; } pAdapt->BindingHandle = NULL; }else{ *Status = NDIS_STATUS_FAILURE; } natFreeAllItems(&pAdapt->ctrl); natFreeAllFwSessionsAndRules(&pAdapt->ctrl); natmFreeAllPacketPools(pAdapt); if (pAdapt) NdisFreeSpinLock(&pAdapt->Lock); NdisFreeMemory(pAdapt, 0, 0); } }
VOID PtUnbindAdapter( OUT PNDIS_STATUS Status, IN NDIS_HANDLE ProtocolBindingContext, IN NDIS_HANDLE UnbindContext ) /*++ Routine Description: Called by NDIS when we are required to unbind to the adapter below. This functions shares functionality with the miniport's HaltHandler. The code should ensure that NdisCloseAdapter and NdisFreeMemory is called only once between the two functions Arguments: Status Placeholder for return status ProtocolBindingContext Pointer to the adapter structure UnbindContext Context for NdisUnbindComplete() if this pends Return Value: Status for NdisIMDeinitializeDeviceContext --*/ { PADAPT pAdapt =(PADAPT)ProtocolBindingContext; NDIS_HANDLE BindingHandle = pAdapt->BindingHandle; NDIS_STATUS LocalStatus; DBGPRINT(("==> PtUnbindAdapter: Adapt %p\n", pAdapt)); if (pAdapt->QueuedRequest == TRUE) { pAdapt->QueuedRequest = FALSE; PtRequestComplete (pAdapt, &pAdapt->Request, NDIS_STATUS_FAILURE ); } #ifndef WIN9X // // Check if we had called NdisIMInitializeDeviceInstanceEx and // we are awaiting a call to MiniportInitialize. // if (pAdapt->MiniportInitPending == TRUE) { // // Try to cancel the pending IMInit process. // LocalStatus = NdisIMCancelInitializeDeviceInstance( DriverHandle, &pAdapt->DeviceName); if (LocalStatus == NDIS_STATUS_SUCCESS) { // // Successfully cancelled IM Initialization; our // Miniport Initialize routine will not be called // for this device. // pAdapt->MiniportInitPending = FALSE; ASSERT(pAdapt->MiniportHandle == NULL); } else { // // Our Miniport Initialize routine will be called // (may be running on another thread at this time). // Wait for it to finish. // NdisWaitEvent(&pAdapt->MiniportInitEvent, 0); ASSERT(pAdapt->MiniportInitPending == FALSE); } } #endif // !WIN9X // // Call NDIS to remove our device-instance. We do most of the work // inside the HaltHandler. // // The Handle will be NULL if our miniport Halt Handler has been called or // if the IM device was never initialized // if (pAdapt->MiniportHandle != NULL) { *Status = NdisIMDeInitializeDeviceInstance(pAdapt->MiniportHandle); if (*Status != NDIS_STATUS_SUCCESS) { *Status = NDIS_STATUS_FAILURE; } } else { // // We need to do some work here. // Close the binding below us // and release the memory allocated. // if(pAdapt->BindingHandle != NULL) { NdisResetEvent(&pAdapt->Event); NdisCloseAdapter(Status, pAdapt->BindingHandle); // // Wait for it to complete // if(*Status == NDIS_STATUS_PENDING) { NdisWaitEvent(&pAdapt->Event, 0); *Status = pAdapt->Status; } } else { // // Both Our MiniportHandle and Binding Handle should not be NULL. // *Status = NDIS_STATUS_FAILURE; ASSERT(0); } // // Free the memory here, if was not released earlier(by calling the HaltHandler) // NdisFreeMemory(pAdapt, sizeof(ADAPT), 0); } DBGPRINT(("<== PtUnbindAdapter: Adapt %p\n", pAdapt)); }
VOID PtBindAdapter( OUT PNDIS_STATUS Status, IN NDIS_HANDLE BindContext, IN PNDIS_STRING DeviceName, IN PVOID SystemSpecific1, IN PVOID SystemSpecific2 ) /*++ Routine Description: Called by NDIS to bind to a miniport below. Arguments: Status - Return status of bind here. BindContext - Can be passed to NdisCompleteBindAdapter if this call is pended. DeviceName - Device name to bind to. This is passed to NdisOpenAdapter. SystemSpecific1 - Can be passed to NdisOpenProtocolConfiguration to read per-binding information SystemSpecific2 - Unused Return Value: NDIS_STATUS_PENDING if this call is pended. In this case call NdisCompleteBindAdapter to complete. Anything else Completes this call synchronously --*/ { NDIS_HANDLE ConfigHandle = NULL; PNDIS_CONFIGURATION_PARAMETER Param; NDIS_STRING DeviceStr = NDIS_STRING_CONST("UpperBindings"); PADAPT pAdapt = NULL; NDIS_STATUS Sts; UINT MediumIndex; ULONG TotalSize; PNDIS_CONFIGURATION_PARAMETER BundleParam; NDIS_STRING BundleStr = NDIS_STRING_CONST("BundleId"); NDIS_STATUS BundleStatus; DBGPRINT(("==> Protocol BindAdapter\n")); do { // // Access the configuration section for our binding-specific // parameters. // NdisOpenProtocolConfiguration(Status, &ConfigHandle, SystemSpecific1); if (*Status != NDIS_STATUS_SUCCESS) { break; } // // Read the "UpperBindings" reserved key that contains a list // of device names representing our miniport instances corresponding // to this lower binding. Since this is a 1:1 IM driver, this key // contains exactly one name. // // If we want to implement a N:1 mux driver (N adapter instances // over a single lower binding), then UpperBindings will be a // MULTI_SZ containing a list of device names - we would loop through // this list, calling NdisIMInitializeDeviceInstanceEx once for // each name in it. // NdisReadConfiguration(Status, &Param, ConfigHandle, &DeviceStr, NdisParameterString); if (*Status != NDIS_STATUS_SUCCESS) { break; } // // Allocate memory for the Adapter structure. This represents both the // protocol context as well as the adapter structure when the miniport // is initialized. // // In addition to the base structure, allocate space for the device // instance string. // TotalSize = sizeof(ADAPT) + Param->ParameterData.StringData.MaximumLength; NdisAllocateMemoryWithTag(&pAdapt, TotalSize, TAG); if (pAdapt == NULL) { *Status = NDIS_STATUS_RESOURCES; break; } // // Initialize the adapter structure. We copy in the IM device // name as well, because we may need to use it in a call to // NdisIMCancelInitializeDeviceInstance. The string returned // by NdisReadConfiguration is active (i.e. available) only // for the duration of this call to our BindAdapter handler. // NdisZeroMemory(pAdapt, TotalSize); pAdapt->DeviceName.MaximumLength = Param->ParameterData.StringData.MaximumLength; pAdapt->DeviceName.Length = Param->ParameterData.StringData.Length; pAdapt->DeviceName.Buffer = (PWCHAR)((ULONG_PTR)pAdapt + sizeof(ADAPT)); NdisMoveMemory(pAdapt->DeviceName.Buffer, Param->ParameterData.StringData.Buffer, Param->ParameterData.StringData.MaximumLength); NdisInitializeEvent(&pAdapt->Event); // // Allocate a packet pool for sends. We need this to pass sends down. // We cannot use the same packet descriptor that came down to our send // handler (see also NDIS 5.1 packet stacking). // NdisAllocatePacketPoolEx(Status, &pAdapt->SendPacketPoolHandle, MIN_PACKET_POOL_SIZE, MAX_PACKET_POOL_SIZE - MIN_PACKET_POOL_SIZE, sizeof(SEND_RSVD)); if (*Status != NDIS_STATUS_SUCCESS) { break; } // // Allocate a packet pool for receives. We need this to indicate receives. // Same consideration as sends (see also NDIS 5.1 packet stacking). // NdisAllocatePacketPoolEx(Status, &pAdapt->RecvPacketPoolHandle, MIN_PACKET_POOL_SIZE, MAX_PACKET_POOL_SIZE - MIN_PACKET_POOL_SIZE, PROTOCOL_RESERVED_SIZE_IN_PACKET); if (*Status != NDIS_STATUS_SUCCESS) { break; } // // Now open the adapter below and complete the initialization // NdisOpenAdapter(Status, &Sts, &pAdapt->BindingHandle, &MediumIndex, MediumArray, sizeof(MediumArray)/sizeof(NDIS_MEDIUM), ProtHandle, pAdapt, DeviceName, 0, NULL); if (*Status == NDIS_STATUS_PENDING) { NdisWaitEvent(&pAdapt->Event, 0); *Status = pAdapt->Status; } if (*Status != NDIS_STATUS_SUCCESS) { break; } pAdapt->Medium = MediumArray[MediumIndex]; // // Now ask NDIS to initialize our miniport (upper) edge. // Set the flag below to synchronize with a possible call // to our protocol Unbind handler that may come in before // our miniport initialization happens. // pAdapt->MiniportInitPending = TRUE; NdisInitializeEvent(&pAdapt->MiniportInitEvent); *Status = NdisIMInitializeDeviceInstanceEx(DriverHandle, &pAdapt->DeviceName, pAdapt); if (*Status != NDIS_STATUS_SUCCESS) { DBGPRINT(("BindAdapter: Adapt %p, IMInitializeDeviceInstance error %x\n", pAdapt, *Status)); break; } } while(FALSE); // // Close the configuration handle now - see comments above with // the call to NdisIMInitializeDeviceInstanceEx. // if (ConfigHandle != NULL) { NdisCloseConfiguration(ConfigHandle); } if (*Status != NDIS_STATUS_SUCCESS) { if (pAdapt != NULL) { if (pAdapt->BindingHandle != NULL) { NDIS_STATUS LocalStatus; // // Close the binding we opened above. // NdisCloseAdapter(&LocalStatus, pAdapt->BindingHandle); pAdapt->BindingHandle = NULL; if (LocalStatus == NDIS_STATUS_PENDING) { NdisWaitEvent(&pAdapt->Event, 0); LocalStatus = pAdapt->Status; } } if (pAdapt->SendPacketPoolHandle != NULL) { NdisFreePacketPool(pAdapt->SendPacketPoolHandle); } if (pAdapt->RecvPacketPoolHandle != NULL) { NdisFreePacketPool(pAdapt->RecvPacketPoolHandle); } NdisFreeMemory(pAdapt, sizeof(ADAPT), 0); pAdapt = NULL; } } DBGPRINT(("<== Protocol BindAdapter: pAdapt %p, Status %x\n", pAdapt, *Status)); }
/************************************************************ Function used by NDIS to update the VXD when a new MAC driver is added ************************************************************/ VOID NDIS_API PacketBindAdapter( OUT PNDIS_STATUS Status, IN NDIS_HANDLE BindAdapterContext, IN PNDIS_STRING AdapterName, IN PVOID SystemSpecific1, IN PVOID SystemSpecific2 ) { PDEVICE_EXTENSION pde; POPEN_INSTANCE oiNew; NDIS_STATUS nsErrorStatus, nsOpenStatus; UINT uiMedium; UINT i; PWRAPPER_PROTOCOL_BLOCK pWPBlock; PNDIS_PROTOCOL_CHARACTERISTICS pNPChar; PADAPTER_NAME AName; PWRAPPER_MAC_BLOCK pWMBlock; PNDIS_MAC_CHARACTERISTICS pNMChar; BYTE *lpzName; TRACE_ENTER( "BindAdapter" ); pde = GlobalDeviceExtension; /*Allocate an element that describe an adapter*/ NdisAllocateMemory( (PVOID *)&AName, sizeof(ADAPTER_NAME), 0, -1 ); if ( AName == NULL ) { *Status = NDIS_STATUS_RESOURCES; return; } NdisAllocateMemory( (PVOID *)&oiNew, sizeof( OPEN_INSTANCE ), 0, -1 ); if ( oiNew == NULL ) { *Status = NDIS_STATUS_RESOURCES; return; } NdisZeroMemory( (PVOID)oiNew, sizeof( OPEN_INSTANCE ) ); /*Save Binding Context*/ oiNew->BindAdapterContext = BindAdapterContext; /*Save the device handle*/ oiNew->hDevice = (DWORD) SystemSpecific1; /*allocate a pool for the packet headers*/ NdisAllocatePacketPool( &nsErrorStatus, &(oiNew->PacketPool), TRANSMIT_PACKETS, sizeof(PACKET_RESERVED) ); IF_TRACE_MSG( "PACKET_RESERVED_b :%lx",sizeof(PACKET_RESERVED)); if ( nsErrorStatus != NDIS_STATUS_SUCCESS ) { IF_TRACE_MSG( "Failed to allocate packet pool AllocStatus=%x", nsErrorStatus ); NdisFreeMemory( oiNew, sizeof( OPEN_INSTANCE ) , 0 ); *Status = NDIS_STATUS_RESOURCES; TRACE_LEAVE( "BindAdapter" ); return; } /*allocate a pool for the packet data*/ NdisAllocateBufferPool( &nsErrorStatus, &(oiNew->BufferPool), TRANSMIT_PACKETS ); if ( nsErrorStatus != NDIS_STATUS_SUCCESS ) { IF_TRACE_MSG( "Failed to allocate packet pool AllocStatus=%x", nsErrorStatus ); NdisFreePacketPool( oiNew->PacketPool ); NdisFreeMemory( oiNew, sizeof( OPEN_INSTANCE ) , 0 ); *Status = NDIS_STATUS_RESOURCES; TRACE_LEAVE( "BindAdapter" ); return; } NdisAllocateSpinLock( &(oiNew->ResetSpinLock) ); InitializeListHead( &(oiNew->ResetIrpList) ); NdisAllocateSpinLock( &(oiNew->RcvQSpinLock) ); InitializeListHead( &(oiNew->RcvList) ); NdisAllocateSpinLock( &(oiNew->RequestSpinLock) ); InitializeListHead( &(oiNew->RequestList) ); for ( i=0; i<MAX_REQUESTS; i++ ) { InsertTailList( &(oiNew->RequestList), &(oiNew->Requests[i].Reserved.ListElement) ); } oiNew->Status = NDIS_STATUS_PENDING; oiNew->BindAdapterContext = BindAdapterContext; /*open the MAC driver calling NDIS*/ oiNew->hDevice=0; oiNew->tagProcess=0; NdisOpenAdapter( &nsOpenStatus, &nsErrorStatus, &oiNew->AdapterHandle, &uiMedium, MediumArray, NUM_NDIS_MEDIA, pde->NdisProtocolHandle, oiNew, AdapterName, 0, NULL ); IF_TRACE_MSG( "Open Status : %lx", nsOpenStatus ); IF_TRACE_MSG( "Error Status : %lx", nsErrorStatus ); IF_TRACE_MSG( "Completion Status : %lx", oiNew->Status ); if ( nsOpenStatus == NDIS_STATUS_PENDING ) { while ( oiNew->Status == NDIS_STATUS_PENDING ) YieldExecution(); } else { PacketOpenAdapterComplete( oiNew, nsOpenStatus, nsErrorStatus ); } pWPBlock = ((PWRAPPER_OPEN_BLOCK)(oiNew->AdapterHandle))->ProtocolHandle; pNPChar = &pWPBlock->ProtocolCharacteristics; IF_TRACE_MSG( "Protocol : %s", pNPChar->Name.Buffer ); IF_TRACE_MSG( "Protocol Handle : %lx", pde->NdisProtocolHandle ); IF_TRACE_MSG( "PWRAPPER_OPEN_BLOCK : %lx", oiNew->AdapterHandle ); IF_TRACE_MSG( "PWRAPPER_PROTOCOL_BLOCK : %lx", pWPBlock ); IF_TRACE_MSG( "NDIS_PROTOCOL_CHARACTERISTICS : %lx", pNPChar ); IF_TRACE_MSG( "Name : %lx", &pNPChar->Name ); IF_TRACE_MSG( "Adapter Name : %s", AdapterName->Buffer ); *Status = oiNew->Status; if ( *Status != NDIS_STATUS_SUCCESS ) { NdisFreeMemory( oiNew, sizeof( OPEN_INSTANCE ) , 0 ); IF_TRACE( "Bind Operation FAILED!" ); } else { AName->realnamestr.Length=AdapterName->Length; AName->realnamestr.MaximumLength=AdapterName->MaximumLength; AName->realnamestr.Buffer=AName->realname; for(i=0; i<32; i++)AName->realname[i]=AdapterName->Buffer[i]; pWMBlock = ((PWRAPPER_OPEN_BLOCK)(oiNew->AdapterHandle))->MacHandle; pNMChar = &pWMBlock->MacCharacteristics; lpzName = pNMChar->Name.Buffer; for(i=0; i<32; i++)AName->devicename[i]=lpzName[i]; InsertTailList( &GlobalDeviceExtension->AdapterNames, &AName->ListElement); //close the adapter NdisCloseAdapter(&nsErrorStatus,oiNew->AdapterHandle); if ( nsErrorStatus == NDIS_STATUS_PENDING ) { while ( oiNew->Status == NDIS_STATUS_PENDING ) YieldExecution(); } else { PacketUnbindAdapterComplete( oiNew, nsErrorStatus ); } *Status = oiNew->Status; if ( *Status == NDIS_STATUS_SUCCESS ) { //remove this adapter from the list of open adapters RemoveEntryList(&(oiNew->ListElement)); //free the memory NdisFreeMemory( oiNew, sizeof( OPEN_INSTANCE ) , 0 ); } else { IF_TRACE( "Close Operation FAILED!" ); } } TRACE_LEAVE( "BindAdapter" ); return; }
DWORD PacketClose(POPEN_INSTANCE Open,DWORD dwDDB,DWORD hDevice,PDIOCPARAMETERS pDiocParms) { NDIS_STATUS Status; NDIS_STATUS nsErrorStatus; UINT to; DWORD TEvent; TRACE_ENTER( "PacketClose" ); Open->BufSize=0; to=Open->ReadTimeoutTimer; Open->ReadTimeoutTimer=0; if(to!=0) { _asm push esi; _asm mov esi,to; CancelReadTimeOut(); _asm pop esi; } // Free the read event TEvent=Open->ReadEvent; _asm mov eax,TEvent; VxDCall(_VWIN32_CloseVxDHandle); //close the adapter NdisCloseAdapter(&nsErrorStatus,Open->AdapterHandle); if ( nsErrorStatus == NDIS_STATUS_PENDING ) { while ( Open->Status == NDIS_STATUS_PENDING ) YieldExecution(); if(Open->Status!=NDIS_STATUS_SUCCESS) { TRACE_LEAVE( "PacketClose" ); return NDIS_STATUS_FAILURE; } } else { PacketUnbindAdapterComplete( Open, nsErrorStatus ); if(nsErrorStatus!=NDIS_STATUS_SUCCESS) { TRACE_LEAVE( "PacketClose" ); return NDIS_STATUS_FAILURE; } } Status = Open->Status; if(Open->Buffer!=NULL)NdisFreeMemory(Open->Buffer,Open->BufSize,0); Open->Buffer=NULL; if(Open->bpfprogram!=NULL)NdisFreeMemory(Open->bpfprogram,Open->bpfprogramlen,0); //remove this adapter from the list of open adapters NdisAcquireSpinLock( &GlobalDeviceExtension->OpenSpinLock ); RemoveEntryList(&(Open->ListElement)); NdisReleaseSpinLock( &GlobalDeviceExtension->OpenSpinLock ); NdisFreeMemory( Open, sizeof( OPEN_INSTANCE ) , 0 ); if(pDiocParms!=NULL) *(DWORD *)(pDiocParms->lpcbBytesReturned) = 0; TRACE_LEAVE( "PacketClose" ); return Status; }