mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2024-12-27 08:22:31 +00:00
187 lines
3.6 KiB
C
187 lines
3.6 KiB
C
|
/*
|
||
|
* TAP-Windows -- A kernel driver to provide virtual tap
|
||
|
* device functionality on Windows.
|
||
|
*
|
||
|
* This code was inspired by the CIPE-Win32 driver by Damion K. Wilson.
|
||
|
*
|
||
|
* This source code is Copyright (C) 2002-2010 OpenVPN Technologies, Inc.,
|
||
|
* and is released under the GPL version 2 (see below).
|
||
|
*
|
||
|
* This program is free software; you can redistribute it and/or modify
|
||
|
* it under the terms of the GNU General Public License version 2
|
||
|
* as published by the Free Software Foundation.
|
||
|
*
|
||
|
* This program is distributed in the hope that it will be useful,
|
||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
* GNU General Public License for more details.
|
||
|
*
|
||
|
* You should have received a copy of the GNU General Public License
|
||
|
* along with this program (see the file COPYING included with this
|
||
|
* distribution); if not, write to the Free Software Foundation, Inc.,
|
||
|
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||
|
*/
|
||
|
|
||
|
//------------------
|
||
|
// Memory Management
|
||
|
//------------------
|
||
|
|
||
|
PVOID
|
||
|
MemAlloc (ULONG p_Size, BOOLEAN zero)
|
||
|
{
|
||
|
PVOID l_Return = NULL;
|
||
|
|
||
|
if (p_Size)
|
||
|
{
|
||
|
__try
|
||
|
{
|
||
|
if (NdisAllocateMemoryWithTag (&l_Return, p_Size, 'APAT')
|
||
|
== NDIS_STATUS_SUCCESS)
|
||
|
{
|
||
|
if (zero)
|
||
|
NdisZeroMemory (l_Return, p_Size);
|
||
|
}
|
||
|
else
|
||
|
l_Return = NULL;
|
||
|
}
|
||
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
||
|
{
|
||
|
l_Return = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return l_Return;
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
MemFree (PVOID p_Addr, ULONG p_Size)
|
||
|
{
|
||
|
if (p_Addr && p_Size)
|
||
|
{
|
||
|
__try
|
||
|
{
|
||
|
#if DBG
|
||
|
NdisZeroMemory (p_Addr, p_Size);
|
||
|
#endif
|
||
|
NdisFreeMemory (p_Addr, p_Size, 0);
|
||
|
}
|
||
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
||
|
{
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Circular queue management routines.
|
||
|
*/
|
||
|
|
||
|
#define QUEUE_BYTE_ALLOCATION(size) \
|
||
|
(sizeof (Queue) + (size * sizeof (PVOID)))
|
||
|
|
||
|
#define QUEUE_ADD_INDEX(var, inc) \
|
||
|
{ \
|
||
|
var += inc; \
|
||
|
if (var >= q->capacity) \
|
||
|
var -= q->capacity; \
|
||
|
MYASSERT (var < q->capacity); \
|
||
|
}
|
||
|
|
||
|
#define QUEUE_SANITY_CHECK() \
|
||
|
MYASSERT (q != NULL && q->base < q->capacity && q->size <= q->capacity)
|
||
|
|
||
|
#define QueueCount(q) (q->size)
|
||
|
|
||
|
#define UPDATE_MAX_SIZE() \
|
||
|
{ \
|
||
|
if (q->size > q->max_size) \
|
||
|
q->max_size = q->size; \
|
||
|
}
|
||
|
|
||
|
Queue *
|
||
|
QueueInit (ULONG capacity)
|
||
|
{
|
||
|
Queue *q;
|
||
|
|
||
|
MYASSERT (capacity > 0);
|
||
|
q = (Queue *) MemAlloc (QUEUE_BYTE_ALLOCATION (capacity), TRUE);
|
||
|
if (!q)
|
||
|
return NULL;
|
||
|
|
||
|
q->base = q->size = 0;
|
||
|
q->capacity = capacity;
|
||
|
q->max_size = 0;
|
||
|
return q;
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
QueueFree (Queue *q)
|
||
|
{
|
||
|
if (q)
|
||
|
{
|
||
|
QUEUE_SANITY_CHECK ();
|
||
|
MemFree (q, QUEUE_BYTE_ALLOCATION (q->capacity));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
PVOID
|
||
|
QueuePush (Queue *q, PVOID item)
|
||
|
{
|
||
|
ULONG dest;
|
||
|
QUEUE_SANITY_CHECK ();
|
||
|
if (q->size == q->capacity)
|
||
|
return NULL;
|
||
|
dest = q->base;
|
||
|
QUEUE_ADD_INDEX (dest, q->size);
|
||
|
q->data[dest] = item;
|
||
|
++q->size;
|
||
|
UPDATE_MAX_SIZE();
|
||
|
return item;
|
||
|
}
|
||
|
|
||
|
PVOID
|
||
|
QueuePop (Queue *q)
|
||
|
{
|
||
|
ULONG oldbase;
|
||
|
QUEUE_SANITY_CHECK ();
|
||
|
if (!q->size)
|
||
|
return NULL;
|
||
|
oldbase = q->base;
|
||
|
QUEUE_ADD_INDEX (q->base, 1);
|
||
|
--q->size;
|
||
|
UPDATE_MAX_SIZE();
|
||
|
return q->data[oldbase];
|
||
|
}
|
||
|
|
||
|
PVOID
|
||
|
QueueExtract (Queue *q, PVOID item)
|
||
|
{
|
||
|
ULONG src, dest, count, n;
|
||
|
QUEUE_SANITY_CHECK ();
|
||
|
n = 0;
|
||
|
src = dest = q->base;
|
||
|
count = q->size;
|
||
|
while (count--)
|
||
|
{
|
||
|
if (item == q->data[src])
|
||
|
{
|
||
|
++n;
|
||
|
--q->size;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
q->data[dest] = q->data[src];
|
||
|
QUEUE_ADD_INDEX (dest, 1);
|
||
|
}
|
||
|
QUEUE_ADD_INDEX (src, 1);
|
||
|
}
|
||
|
if (n)
|
||
|
return item;
|
||
|
else
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
#undef QUEUE_BYTE_ALLOCATION
|
||
|
#undef QUEUE_ADD_INDEX
|
||
|
#undef QUEUE_SANITY_CHECK
|
||
|
#undef UPDATE_MAX_SIZE
|