Upgrade to OpenVPN 2.1.0
[tomato.git] / release / src / router / openvpn / tap-win32 / mem.c
blob3f8d949748082d650a9fefdb3537b1301dbfacfe
1 /*
2 * TAP-Win32/TAP-Win64 -- A kernel driver to provide virtual tap
3 * device functionality on Windows.
5 * This code was inspired by the CIPE-Win32 driver by Damion K. Wilson.
7 * This source code is Copyright (C) 2002-2009 OpenVPN Technologies, Inc.,
8 * and is released under the GPL version 2 (see below).
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2
12 * as published by the Free Software Foundation.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program (see the file COPYING included with this
21 * distribution); if not, write to the Free Software Foundation, Inc.,
22 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 //------------------
26 // Memory Management
27 //------------------
29 PVOID
30 MemAlloc (ULONG p_Size, BOOLEAN zero)
32 PVOID l_Return = NULL;
34 if (p_Size)
36 __try
38 if (NdisAllocateMemoryWithTag (&l_Return, p_Size, 'APAT')
39 == NDIS_STATUS_SUCCESS)
41 if (zero)
42 NdisZeroMemory (l_Return, p_Size);
44 else
45 l_Return = NULL;
47 __except (EXCEPTION_EXECUTE_HANDLER)
49 l_Return = NULL;
53 return l_Return;
56 VOID
57 MemFree (PVOID p_Addr, ULONG p_Size)
59 if (p_Addr && p_Size)
61 __try
63 #if DBG
64 NdisZeroMemory (p_Addr, p_Size);
65 #endif
66 NdisFreeMemory (p_Addr, p_Size, 0);
68 __except (EXCEPTION_EXECUTE_HANDLER)
75 * Circular queue management routines.
78 #define QUEUE_BYTE_ALLOCATION(size) \
79 (sizeof (Queue) + (size * sizeof (PVOID)))
81 #define QUEUE_ADD_INDEX(var, inc) \
82 { \
83 var += inc; \
84 if (var >= q->capacity) \
85 var -= q->capacity; \
86 MYASSERT (var < q->capacity); \
89 #define QUEUE_SANITY_CHECK() \
90 MYASSERT (q != NULL && q->base < q->capacity && q->size <= q->capacity)
92 #define QueueCount(q) (q->size)
94 #define UPDATE_MAX_SIZE() \
95 { \
96 if (q->size > q->max_size) \
97 q->max_size = q->size; \
100 Queue *
101 QueueInit (ULONG capacity)
103 Queue *q;
105 MYASSERT (capacity > 0);
106 q = (Queue *) MemAlloc (QUEUE_BYTE_ALLOCATION (capacity), TRUE);
107 if (!q)
108 return NULL;
110 q->base = q->size = 0;
111 q->capacity = capacity;
112 q->max_size = 0;
113 return q;
116 VOID
117 QueueFree (Queue *q)
119 if (q)
121 QUEUE_SANITY_CHECK ();
122 MemFree (q, QUEUE_BYTE_ALLOCATION (q->capacity));
126 PVOID
127 QueuePush (Queue *q, PVOID item)
129 ULONG dest;
130 QUEUE_SANITY_CHECK ();
131 if (q->size == q->capacity)
132 return NULL;
133 dest = q->base;
134 QUEUE_ADD_INDEX (dest, q->size);
135 q->data[dest] = item;
136 ++q->size;
137 UPDATE_MAX_SIZE();
138 return item;
141 PVOID
142 QueuePop (Queue *q)
144 ULONG oldbase;
145 QUEUE_SANITY_CHECK ();
146 if (!q->size)
147 return NULL;
148 oldbase = q->base;
149 QUEUE_ADD_INDEX (q->base, 1);
150 --q->size;
151 UPDATE_MAX_SIZE();
152 return q->data[oldbase];
155 PVOID
156 QueueExtract (Queue *q, PVOID item)
158 ULONG src, dest, count, n;
159 QUEUE_SANITY_CHECK ();
160 n = 0;
161 src = dest = q->base;
162 count = q->size;
163 while (count--)
165 if (item == q->data[src])
167 ++n;
168 --q->size;
170 else
172 q->data[dest] = q->data[src];
173 QUEUE_ADD_INDEX (dest, 1);
175 QUEUE_ADD_INDEX (src, 1);
177 if (n)
178 return item;
179 else
180 return NULL;
183 #undef QUEUE_BYTE_ALLOCATION
184 #undef QUEUE_ADD_INDEX
185 #undef QUEUE_SANITY_CHECK
186 #undef UPDATE_MAX_SIZE