VBoxNetFlt-win.c revision af9768eb3e9427b661e43fa417be644b0fd84195
/* $Id$ */
/** @file
*/
/*
* Copyright (C) 2008 Sun Microsystems, Inc.
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
* Clara, CA 95054 USA or visit http://www.sun.com if you need
* additional information or have any questions.
*/
/*
* Based in part on Microsoft DDK sample code for Ndis Intermediate Miniport passthru driver sample.
* Copyright (c) 1993-1999, Microsoft Corporation
*/
#include "VBoxNetFltCommon-win.h"
/** represents the job element of the job queue
* see comments for JOB_QUEUE */
typedef struct _JOB
{
/** link in the job queue */
/** job function to be executed */
/** parameter to be passed to the job function */
/** event that will be fired on job completion */
/** true if the job manager should use the completion even for completion indication, false-otherwise*/
bool bUseCompletionEvent;
/**
* represents the queue of jobs processed by the worker thred
*
* we use the thread to process tasks which are required to be done at passive level
* our callbacks may be called at APC level by IntNet, there are some tasks that we can not create at APC,
* e.g. thread creation. This is why we schedule such jobs to the worker thread working at passive level
*/
typedef struct _JOB_QUEUE
{
/* jobs */
/* we are using ExInterlocked..List functions to access the jobs list */
/** this event is used to initiate a job worker thread kill */
/** this event is used to notify a worker thread that jobs are added to the queue */
/** worker thread */
} JOB_QUEUE, *PJOB_QUEUE;
typedef struct _CREATE_INSTANCE_CONTEXT
{
#ifndef VBOXNETADP
#else
#endif
/*contexts used for our jobs */
/* Attach context */
typedef struct _ATTACH_INFO
{
bool fRediscovery;
int Status;
/* general worker context */
typedef struct _WORKER_INFO
{
int Status;
/* idc initialization */
typedef struct _INIT_IDC_INFO
{
bool bInitialized;
volatile bool bStop;
volatile int rc;
/** globals */
/** global lock */
/** global job queue. some operations are required to be done at passive level, e.g. thread creation, adapter bind/unbind initiation,
* while IntNet typically calls us APC_LEVEL, so we just create a system thread in our DriverEntry and enqueue the jobs to that thread */
static JOB_QUEUE g_JobQueue;
/**
* The (common) global data.
*/
static VBOXNETFLTGLOBALS g_VBoxNetFltGlobals;
volatile static bool g_bIdcInitialized;
#ifdef VBOX_LOOPBACK_USEFLAGS
#endif
#define LIST_ENTRY_2_JOB(pListEntry) \
static int vboxNetFltWinAttachToInterface(PVBOXNETFLTINS pThis, void * pContext, bool fRediscovery);
static int vboxNetFltWinTryFiniIdc();
static void vboxNetFltWinFiniNetFltBase();
static int vboxNetFltWinInitNetFltBase();
static int vboxNetFltWinFiniNetFlt();
static int vboxNetFltWinStartInitIdcProbing();
static int vboxNetFltWinStopInitIdcProbing();
/** makes the current thread to sleep for the given number of miliseconds */
{
}
/** wait for the given device to be dereferenced */
{
#ifdef DEBUG
#endif
{
#ifdef DEBUG
{
DBGPRINT(("device not idle"));
Assert(0);
// break;
}
#endif
}
}
/**
* mem functions
*/
/* allocates and zeroes the nonpaged memory of a given size */
{
if(fStatus == NDIS_STATUS_SUCCESS)
{
}
return fStatus;
}
/* frees memory allocated with vboxNetFltWinMemAlloc */
{
NdisFreeMemory(pMemBuf, 0, 0);
}
{
/* NOTE: don't check for NULL since NULL is a valid handle */
#ifndef VBOXNETADP
#endif
#ifndef VBOX_NETFLT_ONDEMAND_BIND
#endif
}
{
do
{
/* NOTE: NULL is a valid handle !!! */
#ifndef VBOXNETADP
if (Status != NDIS_STATUS_SUCCESS)
{
break;
}
#endif
#ifndef VBOX_NETFLT_ONDEMAND_BIND
/* NOTE: NULL is a valid handle !!! */
if (Status != NDIS_STATUS_SUCCESS)
{
#ifndef VBOXNETADP
#endif
break;
}
#endif
} while (FALSE);
return Status;
}
/* initializes packet info pool and allocates the cSize packet infos for the pool */
{
UINT i;
if(fStatus == NDIS_STATUS_SUCCESS)
{
for(i = 0; i < cSize; i++)
{
pInfo = &pPacketInfos[i];
}
}
else
{
Assert(0);
}
return fStatus;
}
/* frees the packet info pool */
{
}
/**
* copies one string to another. in case the destination string size is not enough to hold the complete source string
* does nothing and returns NDIS_STATUS_RESOURCES .
*/
{
{
{
Assert(0);
}
else
{
{
}
}
}
return Status;
}
/************************************************************************************
* PINTNETSG pSG manipulation functions
************************************************************************************/
{
}
{
}
/* moves the contents of the given NDIS_BUFFER and all other buffers chained to it to the PINTNETSG
* the PINTNETSG is expected to contain one segment whose bugger is large enough to maintain
* the contents of the given NDIS_BUFFER and all other buffers chained to it */
{
while(pBuffer)
{
if(!pVirtualAddress)
{
break;
}
ptr += cbCurrentLength;
&pBuffer);
}
if(fStatus == NDIS_STATUS_SUCCESS)
{
}
return fStatus;
}
/* converts the PNDIS_BUFFER to PINTNETSG by making the PINTNETSG segments to point to the memory buffers the
* ndis buffer(s) point to (as opposed to vboxNetFltWinNdisBufferMoveToSG0 which copies the memory from ndis buffers(s) to PINTNETSG) */
{
while(pBuffer)
{
if(!pVirtualAddress) {
break;
}
cbSeg++;
&pBuffer);
}
if(fStatus == NDIS_STATUS_SUCCESS)
{
}
return fStatus;
}
{
}
{
if(Status == STATUS_SUCCESS)
{
return pSG;
}
return NULL;
}
/************************************************************************************
* packet queue functions
************************************************************************************/
#if !defined(VBOX_NETFLT_ONDEMAND_BIND) && !defined(VBOXNETADP)
static NDIS_STATUS vboxNetFltWinQuPostPacket(PADAPT pAdapt, PNDIS_PACKET pPacket, PINTNETSG pSG, uint32_t fFlags
# ifdef DEBUG_NETFLT_PACKETS
# endif
)
{
LogFlow(("posting packet back to driver stack..\n"));
if(!pPacket)
{
/* INTNETSG was in the packet queue, create a new NdisPacket from INTNETSG*/
pSG, /* PINTNETSG */
pSG, /* PVOID pBufToFree */
bSrcHost, /* bool bToWire */
false); /* bool bCopyMemory */
#ifdef DEBUG_NETFLT_PACKETS
#endif
}
else
{
/* NDIS_PACKET was in the packet queue */
if(!(fFlags & PACKET_MINE))
{
* According to the DDK, we can not post it further,
* instead we should allocate our own packet.
* So, allocate our own packet (pMyPacket) and copy the packet info there */
if(bSrcHost)
{
}
else
{
}
}
else
{
/* the packet enqueued is ours, simply assign pMyPacket and zero pPacket */
}
}
if (pMyPacket)
{
/* we have successfuly initialized our packet, post it to the host or to the wire */
if(bSrcHost)
{
#if defined(DEBUG_NETFLT_PACKETS) || !defined(VBOX_LOOPBACK_USEFLAGS)
#endif
if (fStatus != NDIS_STATUS_PENDING)
{
#if defined(DEBUG_NETFLT_PACKETS) || !defined(VBOX_LOOPBACK_USEFLAGS)
/* the status is NOT pending, complete the packet */
#endif
if(pPacket)
{
#ifndef WIN9X
#endif
}
else
{
/* should never be here since the PINTNETSG is stored only when the underlying miniport
* indicates NDIS_STATUS_RESOURCES, we should never have this when processing
* the "from-host" packets */
Assert(0);
vboxNetFltWinFreeSGNdisPacket(pMyPacket, false);
}
}
}
else
{
/* the packet receive completion is always indicated via MiniportReturnPacket */
}
}
else
{
/*we failed to create our packet */
Assert(0);
}
return fStatus;
}
#endif
static bool vboxNetFltWinQuProcessInfo(PVBOXNETFLTINS pNetFltIf, PPACKET_QUEUE_WORKER pWorker, PPACKET_INFO pInfo)
{
#ifndef VBOXNETADP
bool bSrcHost;
bool bPending;
bool bDropIt;
#endif
#ifdef DEBUG_NETFLT_PACKETS
/* packet used for matching */
#endif
#ifndef VBOXNETADP
#endif
/* we first need to obtain the INTNETSG to be passed to intnet */
/* the queue may contain two "types" of packets:
* the NDIS_PACKET and the INTNETSG.
* however in case our ProtocolReceive is called or the packet's status is set to NDIS_STSTUS_RESOURCES
* in ProtocolReceivePacket, we must return the packet immediately on ProtocolReceive*** exit
* In this case we allocate the INTNETSG, copy the ndis packet data there and enqueue it.
* In this case the packet info flags has the PACKET_SG fag set
*
* Besides that the NDIS_PACKET contained in the queue could be either the one passed to us in our send/receive callback
* or the one created by us. The latter is possible in case our ProtocolReceive callback is called and we call NdisTransferData
* in this case we need to allocate the packet the data to be transfered to.
* If the enqueued packet is the one allocated by us the PACKET_MINE flag is set
* */
{
/* we have NDIS_PACKET enqueued, we need to convert it to INTNETSG to be passed to intnet */
UINT uBytesCopied = 0;
LogFlow(("preparing pSG"));
NULL,
/* we can not allocate the INTNETSG on stack since in this case we may get stack overflow
* somewhere outside of our driver (3 pages of system thread stack does not seem to be enough)
*
* since we have a "serialized" packet processing, i.e. all packets are being processed and passed
* to intnet by this thread, we just use one previously allocated INTNETSG which is stored in PADAPT */
{
if(pSG)
{
}
else
{
LogRel(("Failed to reallocate the pSG\n"));
}
}
if(pSG)
{
/* reinitialize */
/* convert the ndis buffers to INTNETSG */
if(Status != NDIS_STATUS_SUCCESS)
{
}
else
{
}
}
}
else
{
* just use the INTNETSG to pass it to intnet */
#ifndef VBOX_NETFLT_ONDEMAND_BIND
#ifndef VBOXNETADP
/* the PINTNETSG is stored only when the underlying miniport
* indicates NDIS_STATUS_RESOURCES, we should never have this when processing
* the "from-host" packedts */
#endif
#else
/* we have both host and wire in ProtocolReceive */
#endif
}
#ifdef DEBUG_NETFLT_PACKETS
if(!pPacket && !pTmpPacket)
{
/* create tmp packet that woud be used for matching */
pSG, /* PINTNETSG */
pSG, /* PVOID pBufToFree */
bSrcHost, /* bool bToWire */
true); /* bool bCopyMemory */
}
#endif
do
{
#ifndef VBOXNETADP
/* the pSG was successfully initialized, post it to the netFlt*/
#ifndef VBOX_NETFLT_ONDEMAND_BIND
bDropIt =
#endif
)
: false;
#else
if(pSG)
{
}
else
{
}
#endif
#if !defined(VBOX_NETFLT_ONDEMAND_BIND) && !defined(VBOXNETADP)
if(!bDropIt)
{
# ifdef DEBUG_NETFLT_PACKETS
# endif
);
if(Status == NDIS_STATUS_PENDING)
{
/* we will process packet completion in the completion routine */
bPending = true;
break;
}
}
else
#endif
{
}
/* drop it */
if(pPacket)
{
if(!(fFlags & PACKET_MINE))
{
#if !defined(VBOX_NETFLT_ONDEMAND_BIND) && !defined(VBOXNETADP)
/* complete the packets */
if(fFlags & PACKET_SRC_HOST)
{
#endif
#ifndef VBOX_NETFLT_ONDEMAND_BIND
/* NDIS_SET_PACKET_STATUS(pPacket, Status); */
#endif
#if !defined(VBOX_NETFLT_ONDEMAND_BIND) && !defined(VBOXNETADP)
}
else
{
#endif
#ifndef VBOXNETADP
#endif
#if !defined(VBOX_NETFLT_ONDEMAND_BIND) && !defined(VBOXNETADP)
}
#endif
}
else
{
#ifndef VBOX_NETFLT_ONDEMAND_BIND
#endif
vboxNetFltWinFreeSGNdisPacket(pPacket, true);
}
}
else
{
}
#ifndef VBOXNETADP
bPending = false;
#endif
} while(0);
#ifdef DEBUG_NETFLT_PACKETS
if(pTmpPacket)
{
}
#endif
#ifndef VBOXNETADP
return bPending;
#else
return false;
#endif
}
/*
* thread start function for the thread which processes the packets enqueued in our send and receive callbacks called by ndis
*
* ndis calls us at DISPATCH_LEVEL, while IntNet is using kernel functions which require Irql<DISPATCH_LEVEL
* instead we put the incoming packets to the queue and maintain the system thread running at passive level
* which processes the queue and posts the packets to IntNet, and further to the host or to the wire.
*/
{
bool fResume = true;
/* two events we're waiting is "kill" and "notify" events
* the former is used for the thread termination
* the latter gets fired each time the packet is added to the queue */
};
while(fResume)
{
{
/* "kill" event was set
* will process queued packets and exit */
fResume = false;
}
LogFlow(("==> processing vboxNetFltWinQuPacketQueueWorkerThreadProc\n"));
cNumProcessed = 0;
cNumPostedToHostWire = 0;
do
{
#ifdef DEBUG_NETFLT_PACKETS
/* packet used for matching */
#endif
/*TODO: FIXME: !!! the better approach for performance would be to dequeue all packets at once
* and then go through all dequeued packets
* the same should be done for enqueue !!! */
if(!pInfo)
{
break;
}
{
}
} while(TRUE);
if(cNumProcessed)
{
{
}
}
}
}
/**
* thread start function for the job processing thread
*
* see comments for PJOB_QUEUE
*/
{
bool fResume = true;
};
do
{
{
/* will process queued jobs and exit */
fResume = false;
}
do
{
if(!pJobEntry)
break;
if(pJob->bUseCompletionEvent)
{
}
} while(TRUE);
} while(fResume);
}
/**
* enqueues the job to the job queue to be processed by the job worker thread
* see comments for PJOB_QUEUE
*/
{
if(bEnqueueHead)
{
}
else
{
}
}
DECLINLINE(VOID) vboxNetFltWinJobInit(PJOB pJob, JOB_ROUTINE pRoutine, PVOID pContext, bool bUseEvent)
{
if(bUseEvent)
}
/**
* enqueues the job to the job queue to be processed by the job worker thread and
* blocks until the job is done
* see comments for PJOB_QUEUE
*/
{
}
/**
* enqueues the job to be processed by the job worker thread at passive level and
* blocks until the job is done
*/
{
}
/**
* helper function used for system thread creation
*/
static NTSTATUS vboxNetFltWinQuCreateSystemThread(PKTHREAD * ppThread, PKSTART_ROUTINE pStartRoutine, PVOID pStartContext)
{
if (!NT_SUCCESS(fStatus))
return fStatus;
return STATUS_SUCCESS;
}
/**
* initialize the job queue
* see comments for PJOB_QUEUE
*/
{
fStatus = vboxNetFltWinQuCreateSystemThread(&pQueue->pThread, (PKSTART_ROUTINE)vboxNetFltWinJobWorkerThreadProc, pQueue);
if(fStatus != STATUS_SUCCESS)
{
}
else
{
}
return fStatus;
}
/**
* deinitialize the job queue
* see comments for PJOB_QUEUE
*/
{
{
}
}
/**
* initializes the packet queue
* */
{
do
{
if(Status == NDIS_STATUS_SUCCESS)
{
{
break;
}
Status = vboxNetFltWinQuCreateSystemThread(&pWorker->pThread, (PKSTART_ROUTINE)vboxNetFltWinQuPacketQueueWorkerThreadProc, pInstance);
if(Status != STATUS_SUCCESS)
{
break;
}
}
} while(0);
return Status;
}
/*
* deletes the packet queue
*/
{
// Assert(pAdapt->pPacketQueueSG);
/* using the pPacketQueueSG as an indicator that the packet queue is initialized */
{
}
else
{
}
}
/*
* creates the INTNETSG containing one segment pointing to the buffer of size cbBufSize
* the INTNETSG created should be cleaned with vboxNetFltWinMemFree
*/
{
/* allocation:
* 1. SG_PACKET - with one aSegs pointing to
* 2. buffer of cbPacketLength containing the entire packet */
cbBufferOffset = sizeof(INTNETSG);
/* make sure the buffer is aligned */
{
cbBufferOffset += sizeof(PVOID);
}
if(Status == NDIS_STATUS_SUCCESS)
{
}
return Status;
}
/**
* put the packet info to the queue
*/
{
}
/**
* puts the packet to the queue
*
* @return NDIST_STATUS_SUCCESS iff the packet was enqueued successfully
* and error status otherwise.
* NOTE: that the success status does NOT mean that the packet processing is completed, but only that it was enqueued successfully
* the packet can be returned to the caller protocol/moniport only in case the bReleasePacket was set to true (in this case the copy of the packet was enqueued)
* or if vboxNetFltWinQuEnqueuePacket failed, i.e. the packet was NOT enqueued
*/
DECLHIDDEN(NDIS_STATUS) vboxNetFltWinQuEnqueuePacket(PVBOXNETFLTINS pInstance, PVOID pPacket, const UINT fPacketFlags)
{
do
{
if(fPacketFlags & PACKET_COPY)
{
UINT uBytesCopied = 0;
/* the packet is Ndis packet */
NULL,
&pBuffer,
if(fStatus != NDIS_STATUS_SUCCESS)
{
Assert(0);
break;
}
if(!pInfo)
{
Assert(0);
/* TODO: what status to set? */
break;
}
/* the packet we are queueing is SG, add PACKET_SG to flags */
if(fStatus != NDIS_STATUS_SUCCESS)
{
Assert(0);
break;
}
}
else
{
if(!pInfo)
{
Assert(0);
/* TODO: what status to set? */
break;
}
}
} while(0);
return fStatus;
}
#ifndef VBOX_NETFLT_ONDEMAND_BIND
/*
* ioctl i/f
*/
static NTSTATUS
{
#if 0
int rc;
switch(CtlCode)
{
rc = vboxNetFltWinInitIdc();
if(!RT_SUCCESS(rc))
{
}
break;
/* we are finalizing during unload */
/* TODO: FIXME: need to prevent driver unload that can occur in case IntNet is connected to us,
* but we are not bound to any adapters */
/* rc = vboxNetFltWinTryFiniIdc();
if(!RT_SUCCESS(rc))
{
Status = STATUS_UNSUCCESSFUL;
}
*/
break;
default:
break;
}
return Status;
#else
return STATUS_NOT_SUPPORTED;
#endif
}
/*
Routine Description:
Process IRPs sent to this device.
Arguments:
DeviceObject - pointer to a device object
Irp - pointer to an I/O Request Packet
Return Value:
NTSTATUS - STATUS_SUCCESS always - change this when adding
real code to handle ioctls.
*/
)
{
LogFlow(("==>Pt Dispatch\n"));
switch (pIrpStack->MajorFunction)
{
case IRP_MJ_CREATE:
break;
case IRP_MJ_CLEANUP:
break;
case IRP_MJ_CLOSE:
break;
case IRP_MJ_DEVICE_CONTROL:
break;
default:
break;
}
LogFlow(("<== Pt Dispatch\n"));
return Status;
}
#endif
/*
* netflt
*/
#ifndef VBOXNETADP
/*
* NOTE! the routine is NOT re-enterable for the given pAdapt
* the serialization is not implemented for performance reasons
* since we are assuming the caller serializes the requests as IntNet does
*/
{
int rc;
/* 1. serialize */
if(RT_SUCCESS(rc))
{
/* 2. set pAdapt->pSynchRequest */
/* 3. call NdisRequest */
{
/* 3.1 if pending wait and assign the resulting status */
}
/* 4. clear the pAdapt->pSynchRequest */
return fRequestStatus;
}
return NDIS_STATUS_FAILURE;
}
{
if(status != NDIS_STATUS_SUCCESS)
{
/* TODO */
Assert(0);
}
return status;
}
DECLHIDDEN(NDIS_STATUS) vboxNetFltWinQueryPhysicalMedium(PADAPT pAdapt, NDIS_PHYSICAL_MEDIUM * pMedium)
{
if(Status != NDIS_STATUS_SUCCESS)
{
if(Status == NDIS_STATUS_NOT_SUPPORTED || Status == NDIS_STATUS_NOT_RECOGNIZED || Status == NDIS_STATUS_INVALID_OID)
{
}
else
{
Assert(0);
}
}
return Status;
}
{
/** @todo r=bird: This is too slow and is probably returning the wrong
* information. What we're interested in is whether someone besides us
* has put the interface into promiscuous mode. */
if(status != NDIS_STATUS_SUCCESS)
{
/* TODO */
Assert(0);
return false;
}
return (filter & NDIS_PACKET_TYPE_PROMISCUOUS) != 0;
}
{
{
if(fStatus != NDIS_STATUS_SUCCESS)
{
/* TODO: */
Assert(0);
return fStatus;
}
{
/* the cache was not initialized yet, initiate it with the current filter value */
pAdapt->bUpperProtSetFilterInitialized = true;
}
if(bYes)
{
}
else
{
fOurFilter = 0;
}
if(fExpectedFilter != fFilter)
{
if(fStatus != NDIS_STATUS_SUCCESS)
{
/* TODO */
Assert(0);
return fStatus;
}
}
return fStatus;
}
return NDIS_STATUS_NOT_SUPPORTED;
}
#else /* if defined VBOXNETADP */
/**
* Generates a new unique MAC address based on our vendor ID
*/
{
/* temporary use a time info */
}
{
int i;
/* validate parameters */
AssertReturn(pNdisString->MaximumLength >= 13*sizeof(pNdisString->Buffer[0]), VERR_INVALID_PARAMETER);
for( i = 0; i < 6; i++)
{
pString += 2;
}
*pString = L'\0';
return VINF_SUCCESS;
}
{
if(c >= L'A' && c <= L'F')
{
}
else if(c >= L'a' && c <= L'f')
{
}
else if(c >= L'0' && c <= L'9')
{
*pv = (c - L'0');
}
else
{
return VERR_INVALID_PARAMETER;
}
return VINF_SUCCESS;
}
{
int i, rc;
/* validate parameters */
for(i = 0; i < 6; i++)
{
if(RT_FAILURE(rc))
{
break;
}
if(RT_FAILURE(rc))
{
break;
}
pString += 2;
}
return rc;
}
#endif
/**
* creates a NDIS_PACKET from the PINTNETSG
*/
#ifdef VBOX_NETFLT_ONDEMAND_BIND
/* TODO: the bToWire parameter seems to be unneeded here, remove them*/
#endif
DECLHIDDEN(PNDIS_PACKET) vboxNetFltWinNdisPacketFromSG(PADAPT pAdapt, PINTNETSG pSG, PVOID pBufToFree, bool bToWire, bool bCopyMemory)
{
#ifdef VBOX_NETFLT_ONDEMAND_BIND
#elif defined(VBOXNETADP)
#else
NdisAllocatePacket(&fStatus, &pPacket, bToWire ? pAdapt->hSendPacketPoolHandle : pAdapt->hRecvPacketPoolHandle);
#endif
if(fStatus == NDIS_STATUS_SUCCESS)
{
if(bCopyMemory)
{
if(fStatus == NDIS_STATUS_SUCCESS)
{
}
else
{
Assert(0);
}
}
else
{
}
if(fStatus == NDIS_STATUS_SUCCESS)
{
#ifdef VBOX_NETFLT_ONDEMAND_BIND
#elif defined(VBOXNETADP)
#else
#endif
if(fStatus == NDIS_STATUS_SUCCESS)
{
#ifndef VBOX_NETFLT_ONDEMAND_BIND
if(bToWire)
#endif
{
#ifdef VBOX_LOOPBACK_USEFLAGS
/* set "don't loopback" flags */
#else
#endif
}
#ifndef VBOX_NETFLT_ONDEMAND_BIND
else
{
/* me must set the header size on receive */
/* NdisAllocatePacket zero-initializes the OOB data,
* but keeps the packet flags, clean them here */
}
#endif
/* TODO: set out of bound data */
}
else
{
Assert(0);
if(bCopyMemory)
{
}
}
}
else
{
Assert(0);
}
}
else
{
}
return pPacket;
}
/*
* frees NDIS_PACKET creaed with vboxNetFltWinNdisPacketFromSG
*/
{
do
{
{
if(bFreeMem)
{
}
}
else
{
break;
}
} while(true);
}
/*
* Free all packet pools on the specified adapter.
* @param pAdapt - pointer to ADAPT structure
*/
static VOID
)
{
#ifndef VBOX_NETFLT_ONDEMAND_BIND
{
/*
* Free the packet pool that is used to indicate receives
*/
}
#endif /* #ifndef VBOX_NETFLT_ONDEMAND_BIND*/
#ifndef VBOXNETADP
{
/*
* Free the packet pool that is used to send packets below
*/
}
#endif
}
#if !defined(VBOX_NETFLT_ONDEMAND_BIND) && !defined(VBOXNETADP)
static void vboxNetFltWinAssociateMiniportProtocol()
{
}
#endif
/*
* NetFlt driver unload function
*/
)
{
int rc;
LogFlow(("vboxNetFltWinUnload: entered\n"));
if (RT_FAILURE(rc))
{
/* TODO: we can not prevent driver unload here */
Assert(0);
Log(("vboxNetFltWinTryFiniIdc - failed, busy.\n"));
}
#ifndef VBOXNETADP
#endif
#ifndef VBOX_NETFLT_ONDEMAND_BIND
#endif
/* don't use logging or any RT after de-init */
}
);
/*
* First entry point to be called, when this driver is loaded.
* Register with NDIS as an intermediate driver.
* @return STATUS_SUCCESS if all initialization is successful, STATUS_XXX
* error code if not.
*/
)
{
int rc;
do
{
#ifdef VBOX_LOOPBACK_USEFLAGS
#endif
#ifdef VBOX_NETFLT_ONDEMAND_BIND
/* we are registering in the DriverEntry only when we are working as a protocol
* since in this case our driver is loaded after the VBoxDrv*/
#else
/* the idc registration is initiated via IOCTL since our driver
* can be loaded when the VBoxDrv is not in case we are a Ndis IM driver */
#endif
if(!RT_SUCCESS(rc))
{
break;
}
#ifdef VBOX_LOOPBACK_USEFLAGS
NULL, /* PULONG BuildNumber OPTIONAL */
NULL /* PUNICODE_STRING CSDVersion OPTIONAL */
);
{
/* this is Win2k*/
}
#endif
#ifndef VBOX_NETFLT_ONDEMAND_BIND
if (Status != NDIS_STATUS_SUCCESS)
{
break;
}
#endif
#ifndef VBOXNETADP
if (Status != NDIS_STATUS_SUCCESS)
{
#ifndef VBOX_NETFLT_ONDEMAND_BIND
#endif
break;
}
#endif
if(Status != STATUS_SUCCESS)
{
#ifndef VBOXNETADP
#endif
#ifndef VBOX_NETFLT_ONDEMAND_BIND
#endif
break;
}
/* note: we do it after we initialize the Job Queue */
#if !defined(VBOX_NETFLT_ONDEMAND_BIND) && !defined(VBOXNETADP)
#endif
} while (FALSE);
return(Status);
}
#if !defined(VBOX_NETFLT_ONDEMAND_BIND) && !defined(VBOXNETADP)
/**
* creates and initializes the packet to be sent to the underlying miniport given a packet posted to our miniport edge
* according to DDK docs we must create our own packet rather than posting the one passed to us
*/
/*, IN bool bNetFltActive */
)
{
if (fStatus == NDIS_STATUS_SUCCESS)
{
#ifdef VBOX_LOOPBACK_USEFLAGS
#endif
}
else
{
*ppMyPacket = NULL;
}
return fStatus;
}
/**
* creates and initializes the packet to be sent to the upperlying protocol given a packet indicated to our protocol edge
* according to DDK docs we must create our own packet rather than posting the one passed to us
*/
)
{
/*
* Get a packet off the pool and indicate that up
*/
if(bDpr)
{
}
else
{
}
if (fStatus == NDIS_STATUS_SUCCESS)
{
}
else
{
*ppMyPacket = NULL;
}
return fStatus;
}
#endif
/**
* initializes the ADAPT (our context structure) and binds to the given adapter
*/
#if defined(VBOX_NETFLT_ONDEMAND_BIND)
#elif defined(VBOXNETADP)
DECLHIDDEN(NDIS_STATUS) vboxNetFltWinPtInitBind(PADAPT *ppAdapt, NDIS_HANDLE hMiniportAdapter, PNDIS_STRING pBindToMiniportName /* actually this is our miniport name*/, NDIS_HANDLE hWrapperConfigurationContext)
#else
DECLHIDDEN(NDIS_STATUS) vboxNetFltWinPtInitBind(PADAPT *ppAdapt, PNDIS_STRING pOurMiniportName, PNDIS_STRING pBindToMiniportName)
#endif
{
do
{
#ifndef VBOX_NETFLT_ONDEMAND_BIND
int rc;
USHORT cbAnsiName = pBindToMiniportName->Length;/* the lenght is is bytes ; *2 ;RtlUnicodeStringToAnsiSize(pBindToMiniportName)*/
# ifndef VBOXNETADP
# else
# endif
AnsiString.Length = 0;
if(Status != STATUS_SUCCESS)
{
break;
}
if(RT_FAILURE(rc))
{
Assert(0);
break;
}
if(rc == VINF_ALREADY_INITIALIZED)
{
/* the case when our adapter was unbound while IntNet was connected to it */
/* the instance remains valid until intNet disconnects from it, we simply search and re-use it*/
/* re-initialize PADAPT */
if(RT_FAILURE(rc))
{
Assert(0);
/* release netflt */
vboxNetFltRelease(pInstance, false);
break;
}
}
#else
if (Status != NDIS_STATUS_SUCCESS)
{
break;
}
if (Status != NDIS_STATUS_SUCCESS)
{
break;
}
#endif
}while(FALSE);
return Status;
}
/**
* initializes the ADAPT
*/
#ifdef VBOX_NETFLT_ONDEMAND_BIND
{
do
{
if (Status != NDIS_STATUS_SUCCESS)
{
break;
}
} while(0);
return Status;
}
/**
* unbinds from the adapter we are bound to and deinitializes the ADAPT
*/
{
do
{
if(Status != NDIS_STATUS_SUCCESS)
{
Assert(0);
/* TODO: should we break ? */
/* break; */
}
} while(0);
return Status;
}
#endif
/*
* deinitializes the ADAPT
*/
{
#ifndef VBOXNETADP
int rc;
#endif
#ifndef VBOXNETADP
{
}
# if defined(DEBUG_NETFLT_LOOPBACK) || !defined(VBOX_LOOPBACK_USEFLAGS)
# endif
#endif
#ifndef VBOX_NETFLT_ONDEMAND_BIND
/* moved to vboxNetFltWinDetachFromInterfaceWorker */
#else
#endif
/*
* Free the memory here, if was not released earlier(by calling the HaltHandler)
*/
#ifndef VBOXNETADP
#endif
}
#ifndef VBOXNETADP
#else
#endif
{
#ifndef VBOXNETADP
int rc;
#endif
do
{
#ifndef VBOXNETADP
/*
* 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).
*/
sizeof(PT_RSVD));
if (Status != NDIS_STATUS_SUCCESS)
{
break;
}
#else
#endif
if (Status != NDIS_STATUS_SUCCESS)
{
break;
}
#ifndef VBOXNETADP
if(RT_FAILURE(rc))
{
break;
}
#endif
#ifndef VBOX_NETFLT_ONDEMAND_BIND
# ifndef VBOXNETADP
if(Status != NDIS_STATUS_SUCCESS)
{
Assert(0);
break;
}
if(Status != NDIS_STATUS_SUCCESS)
{
Assert(0);
break;
}
# endif
/*
* Allocate a packet pool for receives. We need this to indicate receives.
* Same consideration as sends (see also NDIS 5.1 packet stacking).
*/
if (Status != NDIS_STATUS_SUCCESS)
{
break;
}
#ifndef VBOXNETADP
#endif
#endif
#ifndef VBOXNETADP
# if defined(DEBUG_NETFLT_LOOPBACK) || !defined(VBOX_LOOPBACK_USEFLAGS)
# endif
#endif
/* TODO: do we need it here ?? */
#ifdef VBOX_NETFLT_ONDEMAND_BIND
{
if(RT_FAILURE(rc))
{
Assert(0);
break;
}
}
#endif
/* moved to vboxNetFltOsInitInstance */
} while(0);
if (Status != NDIS_STATUS_SUCCESS)
{
if(bCallFiniOnFail)
{
}
}
return Status;
}
/**
* match packets
*/
#define FIRST_LIST_ENTRY NEXT_LIST_ENTRY
#define LAST_LIST_ENTRY PREV_LIST_ENTRY
#ifndef VBOXNETADP
#ifdef DEBUG_misha
{
UINT i = 0;
return NULL;
if(cbLength1 < ETH_HEADER_SIZE)
return NULL;
return pEth;
}
{
return NULL;
return NULL;
}
{
if(!pHdr)
return false;
return false;
return false;
return true;
}
{
if(!pHdr)
return false;
return false;
return false;
return true;
}
#endif
# if !defined(VBOX_LOOPBACK_USEFLAGS) || defined(DEBUG_NETFLT_PACKETS)
/*
* answers whether the two given packets match based on the packet length and the first cbMatch bytes of the packets
* if cbMatch < 0 matches complete packets.
*/
DECLHIDDEN(bool) vboxNetFltWinMatchPackets(PNDIS_PACKET pPacket1, PNDIS_PACKET pPacket2, const INT cbMatch)
{
bool bMatch = true;
#ifdef DEBUG_NETFLT_PACKETS
bool bCompleteMatch = false;
#endif
{
bMatch = false;
}
else
{
UINT ucbLength2Match = 0;
{
/* NOTE: assuming uTotalPacketLength1 == uTotalPacketLength2*/
#ifdef DEBUG_NETFLT_PACKETS
bCompleteMatch = true;
#endif
}
else
{
}
for(;;)
{
if(!cbLength1)
{
}
else
{
}
if(!cbLength2)
{
}
else
{
}
{
bMatch = false;
break;
}
if(!ucbMatch)
break;
}
}
#ifdef DEBUG_NETFLT_PACKETS
if(bMatch && !bCompleteMatch)
{
/* check that the packets fully match */
}
#endif
return bMatch;
}
/*
* answers whether the ndis packet and PINTNETSG match based on the packet length and the first cbMatch bytes of the packet and PINTNETSG
* if cbMatch < 0 matches complete packets.
*/
DECLHIDDEN(bool) vboxNetFltWinMatchPacketAndSG(PNDIS_PACKET pPacket, PINTNETSG pSG, const INT cbMatch)
{
bool bMatch = true;
bool bCompleteMatch = false;
UINT i = 0;
{
Assert(0);
bMatch = false;
}
else
{
UINT ucbLength2Match = 0;
{
/* NOTE: assuming uTotalPacketLength1 == uTotalPacketLength2*/
bCompleteMatch = true;
}
else
{
}
for(;;)
{
if(!cbLength1)
{
}
else
{
}
if(!cbLength2)
{
i++;
}
else
{
}
{
bMatch = false;
Assert(0);
break;
}
if(!ucbMatch)
break;
}
}
if(bMatch && !bCompleteMatch)
{
/* check that the packets fully match */
}
return bMatch;
}
# if 0
/*
* answers whether the two PINTNETSGs match based on the packet length and the first cbMatch bytes of the PINTNETSG
* if cbMatch < 0 matches complete packets.
*/
{
bool bMatch = true;
bool bCompleteMatch = false;
{
Assert(0);
bMatch = false;
}
else
{
{
/* NOTE: assuming uTotalPacketLength1 == uTotalPacketLength2*/
bCompleteMatch = true;
}
else
{
}
do
{
if(!cbLength1)
{
i1++;
}
if(!cbLength2)
{
i2++;
}
{
bMatch = false;
Assert(0);
break;
}
} while (ucbMatch);
}
if(bMatch && !bCompleteMatch)
{
/* check that the packets fully match */
}
return bMatch;
}
# endif
# endif
#endif
static void vboxNetFltWinFiniNetFltBase()
{
do
{
/*
* Undo the work done during start (in reverse order).
*/
RTR0Term();
} while (0);
}
static int vboxNetFltWinTryFiniIdc()
{
int rc;
{
if(RT_SUCCESS(rc))
{
g_bIdcInitialized = false;
}
}
else
{
rc = VINF_SUCCESS;
}
return rc;
}
static int vboxNetFltWinFiniNetFlt()
{
int rc = vboxNetFltWinTryFiniIdc();
if(RT_SUCCESS(rc))
{
}
return rc;
}
/**
* base netflt initialization
*/
static int vboxNetFltWinInitNetFltBase()
{
int rc;
do
{
if (!RT_SUCCESS(rc))
{
break;
}
if (!RT_SUCCESS(rc))
{
RTR0Term();
break;
}
}while(0);
return rc;
}
/**
* initialize IDC
*/
static int vboxNetFltWinInitIdc()
{
int rc;
do
{
{
#ifdef VBOX_NETFLT_ONDEMAND_BIND
Assert(0);
#endif
break;
}
/*
* connect to the support driver.
*
* This will call back vboxNetFltOsOpenSupDrv (and maybe vboxNetFltOsCloseSupDrv)
* for establishing the connect to the support driver.
*/
if (!RT_SUCCESS(rc))
{
break;
}
g_bIdcInitialized = true;
} while (0);
return rc;
}
{
int rc = vboxNetFltWinInitIdc();
if(RT_FAILURE(rc))
{
if(!bInterupted)
{
if(!bInterupted)
{
return;
}
}
/* it's interupted */
}
}
static int vboxNetFltWinStopInitIdcProbing()
{
return VERR_INVALID_STATE;
return g_InitIdcInfo.rc;
}
static int vboxNetFltWinStartInitIdcProbing()
{
g_InitIdcInfo.bStop = false;
g_InitIdcInfo.bInitialized = true;
return VINF_SUCCESS;
}
static int vboxNetFltWinInitNetFlt()
{
int rc;
do
{
if(RT_FAILURE(rc))
{
Assert(0);
break;
}
/*
* connect to the support driver.
*
* This will call back vboxNetFltOsOpenSupDrv (and maybe vboxNetFltOsCloseSupDrv)
* for establishing the connect to the support driver.
*/
rc = vboxNetFltWinInitIdc();
if (RT_FAILURE(rc))
{
Assert(0);
break;
}
} while (0);
return rc;
}
/* detach*/
{
#ifndef VBOXNETADP
#endif
// Assert(!pAdapt->hMiniportHandle);
#ifndef VBOX_NETFLT_ONDEMAND_BIND
#else
if(Status != NDIS_STATUS_SUCCESS)
{
Assert(0);
/* pDetachInfo->Status = VERR_GENERAL_FAILURE; */
}
#endif
return VINF_SUCCESS;
}
{
return NDIS_STATUS_SUCCESS;
}
/* detach*/
{
int rc;
/* Assert(!pThis->fActive); */
/* paranoya to ensyre the instance is not removed while we're waiting on the mutex
* in case ndis does something unpredictable, e.g. calls our miniport halt independently
* from protocol unbind and concurrently with it*/
vboxNetFltRetain(pThis, false);
if(RT_SUCCESS(rc))
{
#ifndef VBOX_NETFLT_ONDEMAND_BIND
#ifndef VBOXNETADP
#endif
// if(
//#ifdef VBOXNETADP
// vboxNetFltWinGetOpState(&pAdapt->MPState) == kVBoxNetDevOpState_Initialized
//#else
// vboxNetFltWinGetOpState(&pAdapt->PTState) == kVBoxNetDevOpState_Initialized
//// && vboxNetFltWinGetOpState(&pAdapt->MPState) == kVBoxNetDevOpState_Initialized
//#endif
// )
{
#ifndef VBOXNETADP
#else
#endif
#ifndef VBOXNETADP
#endif
// /* paranoya */
// vboxNetFltWinSetOpState(&pAdapt->MPState, kVBoxNetDevOpState_Deinitialized);
//#ifndef VBOXNETADP
// vboxNetFltWinSetOpState(&pAdapt->PTState, kVBoxNetDevOpState_Deinitialized);
//#endif
/* we're unbinding, make an unbind-related release */
vboxNetFltRelease(pThis, false);
#else
if(Status != NDIS_STATUS_SUCCESS)
{
Assert(0);
/* pDetachInfo->Status = VERR_GENERAL_FAILURE; */
}
#endif
}
else
{
#ifndef VBOXNETADP
#endif
if(!bOnUnbind)
{
}
}
}
else
{
}
/* release for the retain we made before waining on the mutex */
vboxNetFltRelease(pThis, false);
return Status;
}
/**
* Worker for vboxNetFltWinAttachToInterface.
*
* @param pAttachInfo Structure for communicating with
* vboxNetFltWinAttachToInterface.
*/
{
int rc;
/* to ensure we're not removed while we're here */
vboxNetFltRetain(pThis, false);
if(RT_SUCCESS(rc))
{
#ifndef VBOXNETADP
#endif
// if(vboxNetFltWinGetOpState(&pAdapt->MPState) == kVBoxNetDevOpState_Deinitialized
//#ifndef VBOXNETADP
// && vboxNetFltWinGetOpState(&pAdapt->MPState) == kVBoxNetDevOpState_Deinitialized
//#endif
// )
{
#ifndef VBOX_NETFLT_ONDEMAND_BIND
if(pAttachInfo->fRediscovery)
{
/* rediscovery means adaptor bind is performed while intnet is already using it
* i.e. adaptor was unbound while being used by intnet and now being bound back again */
Assert(((VBOXNETFTLINSSTATE)ASMAtomicUoReadU32((uint32_t volatile *)&pThis->enmState)) == kVBoxNetFltInsState_Connected);
}
#ifndef VBOXNETADP
#else
#endif
if(Status == NDIS_STATUS_SUCCESS)
{
#ifndef VBOXNETADP
Status = vboxNetFltWinPtDoBinding(pAdapt, pAttachInfo->pCreateContext->pOurName, pAttachInfo->pCreateContext->pBindToName);
#else
Status = vboxNetFltWinMpDoInitialization(pAdapt, pAttachInfo->pCreateContext->hMiniportAdapter, pAttachInfo->pCreateContext->hWrapperConfigurationContext);
#endif
if (Status == NDIS_STATUS_SUCCESS)
{
if(pAttachInfo->fRediscovery || (Status = vboxNetFltWinMpReferenceControlDevice()) == NDIS_STATUS_SUCCESS)
{
#ifndef VBOXNETADP
#endif
{
// Assert(vboxNetFltWinGetOpState(&pAdapt->MPState) == kVBoxNetDevOpState_Initialized);
#ifndef VBOXNETADP
#endif
// /* paranoya */
//// vboxNetFltWinSetAdaptState(&pAdapt->MPState, kVBoxNetDevOpState_Initialized);
//#ifndef VBOXNETADP
// vboxNetFltWinSetOpState(&pAdapt->PTState, kVBoxNetDevOpState_Initialized);
//#endif
/* 4. mark as connected */
vboxNetFltRelease(pThis, false);
return;
}
if(!pAttachInfo->fRediscovery)
{
}
}
#ifndef VBOXNETADP
vboxNetFltWinPtDoUnbinding(pAdapt, true);
#else
#endif
}
}
#ifndef VBOXNETADP
#endif
// /* paranoya */
// vboxNetFltWinSetOpState(&pAdapt->MPState, kVBoxNetDevOpState_Deinitialized);
//#ifndef VBOXNETADP
// vboxNetFltWinSetOpState(&pAdapt->PTState, kVBoxNetDevOpState_Deinitialized);
//#endif
}
#else /* VBOX_NETFLT_ONDEMAND_BIND */
if (Status != NDIS_STATUS_SUCCESS)
{
break;
}
if (Status != NDIS_STATUS_SUCCESS)
{
break;
}
#endif /* VBOX_NETFLT_ONDEMAND_BIND */
}
else
{
}
vboxNetFltRelease(pThis, false);
return;
}
/**
* Common code for vboxNetFltOsInitInstance and
* vboxNetFltOsMaybeRediscovered.
*
* @returns IPRT status code.
* @param pThis The instance.
* @param fRediscovery True if vboxNetFltOsMaybeRediscovered is calling,
* false if it's vboxNetFltOsInitInstance.
*/
{
#ifdef VBOX_NETFLT_ONDEMAND_BIND
/* packet queue worker thread gets created on attach interface, need to do it via job at passive level */
#else
#endif
}
/*
*
* The OS specific interface definition
*
*/
{
/* AttachToInterface true if disconnected */
}
{
int rc = VINF_SUCCESS;
#if !defined(VBOXNETADP) && !defined(VBOX_NETFLT_ONDEMAND_BIND)
if(fDst & INTNETTRUNKDIR_WIRE)
{
cRefs++;
}
if(fDst & INTNETTRUNKDIR_HOST)
{
cRefs++;
}
#else
{
cRefs = 1;
}
#endif
{
return VERR_GENERAL_FAILURE;
}
#ifndef VBOXNETADP
if ((fDst & INTNETTRUNKDIR_WIRE)
# ifdef VBOX_NETFLT_ONDEMAND_BIND
|| (fDst & INTNETTRUNKDIR_HOST)
# endif
)
{
true /*fToWire*/, true /*fCopyMemory*/);
if (pPacket)
{
#if defined(DEBUG_NETFLT_PACKETS) || !defined(VBOX_LOOPBACK_USEFLAGS)
#endif
if (fStatus != NDIS_STATUS_PENDING)
{
#if defined(DEBUG_NETFLT_PACKETS) || !defined(VBOX_LOOPBACK_USEFLAGS)
/* the status is NOT pending, complete the packet */
#endif
if(!NT_SUCCESS(fStatus))
{
/* TODO: convert status to VERR_xxx */
}
vboxNetFltWinFreeSGNdisPacket(pPacket, true);
}
else
{
/* pending, dereference on packet complete */
cRefs--;
}
}
else
{
Assert(0);
rc = VERR_NO_MEMORY;
}
}
#endif
#ifndef VBOX_NETFLT_ONDEMAND_BIND
#ifndef VBOXNETADP
if (fDst & INTNETTRUNKDIR_HOST)
#else
if(cRefs)
#endif
{
false /*fToWire*/, true /*fCopyMemory*/);
if (pPacket)
{
cRefs--;
#ifdef VBOXNETADP
#endif
}
else
{
Assert(0);
#ifdef VBOXNETADP
#endif
rc = VERR_NO_MEMORY;
}
}
if(cRefs)
{
}
#endif
return rc;
}
{
#ifndef VBOXNETADP
{
bool bPromiscuous;
return false;
bPromiscuous = (pAdapt->fUpperProtocolSetFilter & NDIS_PACKET_TYPE_PROMISCUOUS) == NDIS_PACKET_TYPE_PROMISCUOUS;
/*vboxNetFltWinIsPromiscuous(pAdapt);*/
return bPromiscuous;
}
return false;
#else
return true;
#endif
}
{
}
{
/* ASSUMES that the MAC address never changes. */
}
{
#ifndef VBOXNETADP
#endif
/* we first wait for all pending ops to complete
* this might include all packets queued for processing */
for(;;)
{
if(fActive)
{
if(!pThis->u.s.cModePassThruRefs)
{
break;
}
}
else
{
if(!pThis->u.s.cModeNetFltRefs)
{
break;
}
}
}
return;
#ifndef VBOXNETADP
/* the packets put to ReceiveQueue Array are currently not holding the references,
* simply need to flush them */
if(fActive)
{
#ifdef DEBUG_misha
bool bPromiscSupported;
if(Status != NDIS_STATUS_SUCCESS)
{
DBGPRINT(("vboxNetFltWinQueryPhysicalMedium failed, Status (0x%x), setting medium to NdisPhysicalMediumUnspecified\n", Status));
if(Status != NDIS_STATUS_NOT_SUPPORTED)
{
LogRel(("vboxNetFltWinQueryPhysicalMedium failed, Status (0x%x), setting medium to NdisPhysicalMediumUnspecified\n", Status));
}
}
else
{
DBGPRINT(("(SUCCESS) vboxNetFltWinQueryPhysicalMedium SUCCESS\n"));
}
/*|| PhMedium == NdisPhysicalMediumWiMax */
));
#endif
}
{
if(Status != NDIS_STATUS_SUCCESS)
{
Assert(0);
}
}
#else
# ifdef VBOXNETADP_REPORT_DISCONNECTED
if(fActive)
{
0);
}
else
{
0);
}
#else
if(fActive)
{
/* indicate status change to make the ip settings be re-picked for dhcp */
0);
0);
}
# endif
#endif
return;
}
{
}
{
/* this is not a rediscovery, initialize Mac cache */
{
#ifndef VBOXNETADP
if (Status == NDIS_STATUS_SUCCESS)
#endif
{
if(Status == NDIS_STATUS_SUCCESS)
{
}
else
{
}
}
#ifndef VBOXNETADP
else
{
}
#endif
}
else
{
}
}
{
}
{
return vboxNetFltWinConnectIt(pThis);
}
{
}
{
if (RT_SUCCESS(rc))
{
if (RT_SUCCESS(rc))
{
return rc;
}
}
return rc;
}
{
pThis->u.s.cModeNetFltRefs = 0;
pThis->u.s.cModePassThruRefs = 0;
#ifndef VBOXNETADP
#endif
return VINF_SUCCESS;
}