Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/SoftEtherVPN/SoftEtherVPN_Stable.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src/SeLow
diff options
context:
space:
mode:
Diffstat (limited to 'src/SeLow')
-rw-r--r--src/SeLow/SeLow.c2104
-rw-r--r--src/SeLow/SeLow.h361
-rw-r--r--src/SeLow/SeLow.rc63
-rw-r--r--src/SeLow/SeLow.vcproj278
-rw-r--r--src/SeLow/SeLowCommon.h175
-rw-r--r--src/SeLow/resource.h84
6 files changed, 3065 insertions, 0 deletions
diff --git a/src/SeLow/SeLow.c b/src/SeLow/SeLow.c
new file mode 100644
index 00000000..439fbd25
--- /dev/null
+++ b/src/SeLow/SeLow.c
@@ -0,0 +1,2104 @@
+// SoftEther VPN Source Code
+// SeLow: SoftEther Lightweight Network Protocol
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// 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 version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// SeLow.c
+// SeLow Device Driver
+
+#include <GlobalConst.h>
+
+#define SELOW_DEVICE_DRIVER
+
+#include "SeLow.h"
+
+static SL_CTX sl_ctx = {0};
+static SL_CTX *sl = &sl_ctx;
+
+// Win32 driver entry point
+NDIS_STATUS DriverEntry(DRIVER_OBJECT *driver_object, UNICODE_STRING *registry_path)
+{
+ NDIS_PROTOCOL_DRIVER_CHARACTERISTICS t;
+ NDIS_STATUS ret = NDIS_STATUS_FAILURE;
+ SL_UNICODE *protocol_name = NULL;
+ NDIS_HANDLE protocol_handle = NULL;
+ SL_CTX *sl_ctx = NULL;
+ DEVICE_OBJECT *device_object = NULL;
+
+ SlZero(sl, sizeof(SL_CTX));
+
+ // Register the NDIS protocol
+ protocol_name = SlNewUnicode(SL_PROTOCOL_NAME);
+ if (protocol_name == NULL)
+ {
+ goto LABEL_CLEANUP;
+ }
+
+ SlZero(&t, sizeof(t));
+ t.Header.Type = NDIS_OBJECT_TYPE_PROTOCOL_DRIVER_CHARACTERISTICS;
+ t.Header.Revision = NDIS_PROTOCOL_DRIVER_CHARACTERISTICS_REVISION_2;
+ t.Header.Size = NDIS_SIZEOF_PROTOCOL_DRIVER_CHARACTERISTICS_REVISION_2;
+ t.MajorNdisVersion = 6;
+ t.MinorNdisVersion = 20;
+ t.Name = protocol_name->String;
+
+ t.BindAdapterHandlerEx = SlNdisBindAdapterExProc;
+ t.UnbindAdapterHandlerEx = SlNdisUnbindAdapterExProc;
+ t.OpenAdapterCompleteHandlerEx = SlNdisOpenAdapterCompleteExProc;
+ t.CloseAdapterCompleteHandlerEx = SlNdisCloseAdapterCompleteExProc;
+ t.NetPnPEventHandler = SlNdisNetPnPEventProc;
+ t.UninstallHandler = SlNdisUninstallProc;
+ t.OidRequestCompleteHandler = SlNdisOidRequestCompleteProc;
+ t.StatusHandlerEx = SlNdisStatusExProc;
+ t.ReceiveNetBufferListsHandler = SlNdisReceiveNetBufferListsProc;
+ t.SendNetBufferListsCompleteHandler = SlNdisSendNetBufferListsCompleteProc;
+
+ // Create an adapters list
+ sl->DriverObject = driver_object;
+ sl->AdapterList = SlNewList();
+
+ ret = NdisRegisterProtocolDriver(NULL, &t, &protocol_handle);
+
+ if (NG(ret))
+ {
+ protocol_handle = NULL;
+ goto LABEL_CLEANUP;
+ }
+
+ SlZero(driver_object->MajorFunction, sizeof(driver_object->MajorFunction));
+ driver_object->MajorFunction[IRP_MJ_CREATE] = SlDeviceOpenProc;
+ driver_object->MajorFunction[IRP_MJ_CLOSE] = SlDeviceCloseProc;
+ driver_object->MajorFunction[IRP_MJ_READ] = SlDeviceReadProc;
+ driver_object->MajorFunction[IRP_MJ_WRITE] = SlDeviceWriteProc;
+ driver_object->MajorFunction[IRP_MJ_DEVICE_CONTROL] = SlDeviceIoControlProc;
+ driver_object->DriverUnload = SlUnloadProc;
+
+ // Initialize the SL context
+ sl->ProtocolHandle = protocol_handle;
+
+ // Create a basic device
+ sl->BasicDevice = SlNewDevice(SL_BASIC_DEVICE_NAME, SL_BASIC_DEVICE_NAME_SYMBOLIC);
+ if (sl->BasicDevice == NULL)
+ {
+ ret = NDIS_STATUS_FAILURE;
+ goto LABEL_CLEANUP;
+ }
+ sl->BasicDevice->IsBasicDevice = true;
+
+LABEL_CLEANUP:
+
+ SlFreeUnicode(protocol_name);
+
+ if (NG(ret))
+ {
+ SlUnloadProc(driver_object);
+ }
+
+ return ret;
+}
+
+// Unloading procedure of the device driver
+void SlUnloadProc(DRIVER_OBJECT *driver_object)
+{
+ // Release the protocol
+ if (sl->ProtocolHandle != NULL)
+ {
+ NdisDeregisterProtocolDriver(sl->ProtocolHandle);
+ sl->ProtocolHandle = NULL;
+ }
+
+ // Release the basic device
+ SlFreeDevice(sl->BasicDevice);
+
+ // Release the adapter list
+ SlFreeList(sl->AdapterList);
+
+ // Initialize the SL context
+ SlZero(sl, sizeof(SL_CTX));
+}
+
+// Delete a device
+void SlFreeDevice(SL_DEVICE *dev)
+{
+ NTSTATUS r;
+ // Validate arguments
+ if (dev == NULL)
+ {
+ return;
+ }
+
+ r = IoDeleteSymbolicLink(&dev->SymbolicLinkName->String);
+ if (NG(r))
+ {
+ // May fail due to a bug in Windows Kernel
+ }
+
+ IoDeleteDevice(dev->DeviceObject);
+
+ SlFreeUnicode(dev->DeviceName);
+ SlFreeUnicode(dev->SymbolicLinkName);
+
+ SlFreeLock(dev->OpenCloseLock);
+
+ SlFree(dev);
+}
+
+// Create a new device
+SL_DEVICE *SlNewDevice(char *device_name, char *symbolic_link_name)
+{
+ SL_UNICODE *u_device_name = SlNewUnicode(device_name);
+ SL_UNICODE *u_sym_name = SlNewUnicode(symbolic_link_name);
+
+ SL_DEVICE *ret = SlNewDeviceUnicode(u_device_name, u_sym_name);
+
+ if (ret == NULL)
+ {
+ SlFreeUnicode(u_device_name);
+ SlFreeUnicode(u_sym_name);
+ }
+
+ return ret;
+}
+SL_DEVICE *SlNewDeviceUnicode(SL_UNICODE *u_device_name, SL_UNICODE *u_sym_name)
+{
+ SL_DEVICE *ret = NULL;
+ DEVICE_OBJECT *dev_obj = NULL;
+ NTSTATUS r;
+ SL_UNICODE *sddl;
+
+ sddl = SlNewUnicode("D:P(A;;GA;;;SY)(A;;GA;;;BA)");
+
+ /*r = IoCreateDevice(sl->DriverObject, sizeof(SL_DEVICE *),
+ &u_device_name->String, FILE_DEVICE_TRANSPORT, 0, false, &dev_obj);*/
+
+ r = IoCreateDeviceSecure(sl->DriverObject, sizeof(SL_DEVICE *),
+ &u_device_name->String, FILE_DEVICE_TRANSPORT, 0, false, SlGetUnicode(sddl),
+ NULL, &dev_obj);
+
+ SlFreeUnicode(sddl);
+
+ if (NG(r))
+ {
+ dev_obj = NULL;
+ goto LABEL_CLEANUP;
+ }
+
+ r = IoCreateSymbolicLink(&u_sym_name->String, &u_device_name->String);
+ if (NG(r))
+ {
+ // May fail due to a bug in Windows Kernel
+ }
+
+ ret = SlZeroMalloc(sizeof(SL_DEVICE));
+ if (ret == NULL)
+ {
+ goto LABEL_CLEANUP;
+ }
+
+ ret->DeviceObject = dev_obj;
+ ret->DeviceName = u_device_name;
+ ret->SymbolicLinkName = u_sym_name;
+ *((SL_DEVICE **)dev_obj->DeviceExtension) = ret;
+
+ dev_obj->Flags &= ~DO_DEVICE_INITIALIZING;
+
+ ret->OpenCloseLock = SlNewLock();
+
+LABEL_CLEANUP:
+ if (ret == NULL)
+ {
+ if (dev_obj != NULL)
+ {
+ IoDeleteDevice(dev_obj);
+ }
+ }
+
+ return ret;
+}
+
+// Device is opened
+NTSTATUS SlDeviceOpenProc(DEVICE_OBJECT *device_object, IRP *irp)
+{
+ SL_DEVICE *dev = *((SL_DEVICE **)device_object->DeviceExtension);
+ NTSTATUS ret = STATUS_UNSUCCESSFUL;
+ IO_STACK_LOCATION *irp_stack = IoGetCurrentIrpStackLocation(irp);
+
+ if (dev->IsBasicDevice)
+ {
+ // Basic device
+ ret = STATUS_SUCCESS;
+ }
+ else
+ {
+ bool set_promisc = false;
+ volatile UINT *num_pending_oid_requests = NULL;
+ UINT64 v;
+ char event_name[SL_EVENT_NAME_SIZE];
+ char event_name_win32[SL_EVENT_NAME_SIZE];
+ SL_EVENT *event_object = NULL;
+ LARGE_INTEGER count;
+ LARGE_INTEGER freq;
+
+ count = KeQueryPerformanceCounter(&freq);
+
+ InterlockedIncrement(&sl->IntCounter1);
+
+ // Create a new event object
+ v = (UINT64)device_object + (UINT64)(++sl->IntCounter1) + *((UINT64 *)(&count));
+ sprintf(event_name, SL_EVENT_NAME, (UINT)v, (UINT)(v >> 32) + sl->IntCounter1);
+ sprintf(event_name_win32, SL_EVENT_NAME_WIN32, (UINT)v, (UINT)(v >> 32) + sl->IntCounter1);
+ event_object = SlNewEvent(event_name);
+
+ SlLock(dev->OpenCloseLock);
+ {
+ // Add to the opened file list
+ SlLockList(dev->FileList);
+ {
+ if (dev->Halting == false && dev->Adapter != NULL && dev->Adapter->Ready && dev->Adapter->Halt == false)
+ {
+ // Adapter device
+ SL_FILE *f = SlZeroMalloc(sizeof(SL_FILE));
+ NET_BUFFER_LIST_POOL_PARAMETERS p;
+
+ f->Device = dev;
+ f->Adapter = dev->Adapter;
+ f->FileObject = irp_stack->FileObject;
+
+ irp_stack->FileObject->FsContext = f;
+
+ SlAdd(dev->FileList, f);
+
+ ret = STATUS_SUCCESS;
+ set_promisc = true;
+
+ // Event
+ f->Event = event_object;
+ event_object = NULL;
+ strcpy(f->EventNameWin32, event_name_win32);
+
+ // Create a lock
+ f->RecvLock = SlNewLock();
+
+ // Create a NET_BUFFER_LIST pool
+ SlZero(&p, sizeof(p));
+ p.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
+ p.Header.Revision = NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1;
+ p.Header.Size = NDIS_SIZEOF_NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1;
+ p.ProtocolId = NDIS_PROTOCOL_ID_DEFAULT;
+ p.fAllocateNetBuffer = true;
+ p.ContextSize = 32;
+ p.DataSize = SL_MAX_PACKET_SIZE;
+
+ f->NetBufferListPool = NdisAllocateNetBufferListPool(NULL, &p);
+
+ num_pending_oid_requests = &dev->Adapter->NumPendingOidRequests;
+ }
+ }
+ SlUnlockList(dev->FileList);
+ }
+ SlUnlock(dev->OpenCloseLock);
+
+ if (event_object != NULL)
+ {
+ SlFreeEvent(event_object);
+ }
+
+ if (set_promisc)
+ {
+ // Enable promiscuous mode
+ UINT filter = NDIS_PACKET_TYPE_PROMISCUOUS;
+ SlSendOidRequest(dev->Adapter, true, OID_GEN_CURRENT_PACKET_FILTER, &filter, sizeof(filter));
+
+ // Wait until the number of OID requests being processed becomes 0
+ while ((*num_pending_oid_requests) != 0)
+ {
+ SlSleep(50);
+ }
+ }
+ }
+
+ irp->IoStatus.Status = ret;
+ IoCompleteRequest(irp, IO_NO_INCREMENT);
+
+ return ret;
+}
+
+// Send an OID request to the device
+void SlSendOidRequest(SL_ADAPTER *a, bool set, NDIS_OID oid, void *data, UINT size)
+{
+ NDIS_OID_REQUEST *t;
+ NDIS_STATUS ret;
+ // Validate arguments
+ if (a == NULL || data == NULL || size == 0)
+ {
+ return;
+ }
+
+ if (a->Halt == false)
+ {
+ bool ok = false;
+
+ t = SlZeroMalloc(sizeof(NDIS_OID_REQUEST));
+
+ t->Header.Type = NDIS_OBJECT_TYPE_OID_REQUEST;
+ t->Header.Revision = NDIS_OID_REQUEST_REVISION_1;
+ t->Header.Size = NDIS_SIZEOF_OID_REQUEST_REVISION_1;
+
+ if (set == false)
+ {
+ t->RequestType = NdisRequestQueryInformation;
+ t->DATA.QUERY_INFORMATION.Oid = oid;
+ t->DATA.QUERY_INFORMATION.InformationBuffer = data;
+ t->DATA.QUERY_INFORMATION.InformationBufferLength = size;
+ }
+ else
+ {
+ t->RequestType = NdisRequestSetInformation;
+ t->DATA.SET_INFORMATION.Oid = oid;
+ t->DATA.SET_INFORMATION.InformationBuffer = SlClone(data, size);
+ t->DATA.SET_INFORMATION.InformationBufferLength = size;
+ }
+
+ SlLock(a->Lock);
+ {
+ if (a->AdapterHandle != NULL && a->Halt == false)
+ {
+ InterlockedIncrement(&a->NumPendingOidRequests);
+ ok = true;
+ }
+ }
+ SlUnlock(a->Lock);
+
+ if (ok)
+ {
+ ret = NdisOidRequest(a->AdapterHandle, t);
+
+ if (ret != NDIS_STATUS_PENDING)
+ {
+ InterlockedDecrement(&a->NumPendingOidRequests);
+ if (set)
+ {
+ SlFree(t->DATA.SET_INFORMATION.InformationBuffer);
+ }
+ SlFree(t);
+ }
+ }
+ else
+ {
+ if (set)
+ {
+ SlFree(t->DATA.SET_INFORMATION.InformationBuffer);
+ }
+ SlFree(t);
+ }
+ }
+}
+
+// Device is closed
+NTSTATUS SlDeviceCloseProc(DEVICE_OBJECT *device_object, IRP *irp)
+{
+ SL_DEVICE *dev = *((SL_DEVICE **)device_object->DeviceExtension);
+ NTSTATUS ret = STATUS_UNSUCCESSFUL;
+ IO_STACK_LOCATION *irp_stack = IoGetCurrentIrpStackLocation(irp);
+
+ if (dev->IsBasicDevice)
+ {
+ // Basic device
+ ret = STATUS_SUCCESS;
+ }
+ else
+ {
+ // Adapter device
+ SL_FILE *f = irp_stack->FileObject->FsContext;
+
+ if (f != NULL)
+ {
+ bool clear_filter = false;
+
+ // Wait until the number of packet being sent becomes the zero
+ while (true)
+ {
+ if (f->NumSendingPacketets == 0)
+ {
+ break;
+ }
+
+ SlSleep(50);
+ }
+
+ SlLock(dev->OpenCloseLock);
+ {
+ // Delete the file from the list
+ SlLockList(dev->FileList);
+ {
+ SlDelete(dev->FileList, f);
+
+ if (SL_LIST_NUM(dev->FileList) == 0)
+ {
+ // Clear the filter when all files are closed
+ clear_filter = true;
+ }
+ }
+ SlUnlockList(dev->FileList);
+
+ if (dev->Adapter->Halt)
+ {
+ clear_filter = false;
+ }
+
+ if (clear_filter)
+ {
+ InterlockedIncrement(&dev->Adapter->NumPendingOidRequests);
+ }
+ }
+ SlUnlock(dev->OpenCloseLock);
+
+ if (clear_filter)
+ {
+ // Clear the filter when all files are closed
+ UINT filter = 0;
+ SlSendOidRequest(dev->Adapter, true, OID_GEN_CURRENT_PACKET_FILTER, &filter, sizeof(filter));
+ InterlockedDecrement(&dev->Adapter->NumPendingOidRequests);
+ }
+
+ // Release the event
+ SlFreeEvent(f->Event);
+
+ // Release the receive queue
+ if (true)
+ {
+ SL_PACKET *p = f->RecvPacketHead;
+
+ while (p != NULL)
+ {
+ SL_PACKET *p_next = p->Next;
+
+ SlFree(p);
+
+ p = p_next;
+ }
+ }
+
+ // Release the NET_BUFFER_LIST pool
+ NdisFreeNetBufferListPool(f->NetBufferListPool);
+
+ // Release the lock
+ SlFreeLock(f->RecvLock);
+
+ SlFree(f);
+
+ ret = STATUS_SUCCESS;
+ }
+ }
+
+ irp->IoStatus.Status = ret;
+ IoCompleteRequest(irp, IO_NO_INCREMENT);
+
+ return ret;
+}
+
+// Read procedure of the device
+NTSTATUS SlDeviceReadProc(DEVICE_OBJECT *device_object, IRP *irp)
+{
+ SL_DEVICE *dev = *((SL_DEVICE **)device_object->DeviceExtension);
+ NTSTATUS ret = STATUS_UNSUCCESSFUL;
+ UINT ret_size = 0;
+ IO_STACK_LOCATION *irp_stack = IoGetCurrentIrpStackLocation(irp);
+
+ if (dev->IsBasicDevice)
+ {
+ // Return the adapter list in the case of basic device
+ if (irp_stack->Parameters.Read.Length >= sizeof(SL_ADAPTER_INFO_LIST))
+ {
+ SL_ADAPTER_INFO_LIST *dst = irp->UserBuffer;
+
+ if (dst != NULL)
+ {
+ MDL *mdl;
+
+ mdl = IoAllocateMdl(dst, irp_stack->Parameters.Read.Length, false, false, NULL);
+ if (mdl != NULL)
+ {
+ MmProbeAndLockPages(mdl, KernelMode, IoWriteAccess);
+ }
+
+ SlZero(dst, sizeof(SL_ADAPTER_INFO_LIST));
+
+ dst->Signature = SL_SIGNATURE;
+ dst->SeLowVersion = SL_VER;
+ dst->EnumCompleted = sl->IsEnumCompleted ? 8 : 1;
+
+ SlLockList(sl->AdapterList);
+ {
+ UINT i;
+
+ dst->NumAdapters = MIN(SL_LIST_NUM(sl->AdapterList), SL_MAX_ADAPTER_INFO_LIST_ENTRY);
+
+ for (i = 0;i < dst->NumAdapters;i++)
+ {
+ SL_ADAPTER *a = SL_LIST_DATA(sl->AdapterList, i);
+ SL_ADAPTER_INFO *d = &dst->Adapters[i];
+
+ d->MtuSize = a->MtuSize;
+ SlCopy(d->MacAddress, a->MacAddress, 6);
+ SlCopy(d->AdapterId, a->AdapterId, sizeof(a->AdapterId));
+ strcpy(d->FriendlyName, a->FriendlyName);
+ }
+ }
+ SlUnlockList(sl->AdapterList);
+
+ ret_size = sizeof(SL_ADAPTER_INFO);
+ ret = STATUS_SUCCESS;
+
+ if (mdl != NULL)
+ {
+ MmUnlockPages(mdl);
+ IoFreeMdl(mdl);
+ }
+ }
+ }
+ }
+ else
+ {
+ // Adapter device
+ SL_FILE *f = irp_stack->FileObject->FsContext;
+
+ if (irp_stack->Parameters.Read.Length == SL_EXCHANGE_BUFFER_SIZE)
+ {
+ UCHAR *buf = irp->UserBuffer;
+
+ if (dev->Halting || f->Adapter->Halt || buf == NULL)
+ {
+ // Halting
+ }
+ else
+ {
+ UINT num = 0;
+ bool left = true;
+ MDL *mdl;
+
+ mdl = IoAllocateMdl(buf, SL_EXCHANGE_BUFFER_SIZE, false, false, NULL);
+ if (mdl != NULL)
+ {
+ MmProbeAndLockPages(mdl, KernelMode, IoWriteAccess);
+ }
+
+ // Lock the receive queue
+ SlLock(f->RecvLock);
+ {
+ while (true)
+ {
+ SL_PACKET *q;
+ if (num >= SL_MAX_PACKET_EXCHANGE)
+ {
+ if (f->RecvPacketHead == NULL)
+ {
+ left = false;
+ }
+ break;
+ }
+ q = f->RecvPacketHead;
+ if (q != NULL)
+ {
+ f->RecvPacketHead = f->RecvPacketHead->Next;
+ q->Next = NULL;
+ f->NumRecvPackets--;
+
+ if (f->RecvPacketHead == NULL)
+ {
+ f->RecvPacketTail = NULL;
+ }
+ }
+ else
+ {
+ left = false;
+ break;
+ }
+ SL_SIZE_OF_PACKET(buf, num) = q->Size;
+ SlCopy(SL_ADDR_OF_PACKET(buf, num), q->Data, q->Size);
+ num++;
+ SlFree(q);
+ }
+ }
+ SlUnlock(f->RecvLock);
+
+ if (mdl != NULL)
+ {
+ MmUnlockPages(mdl);
+ IoFreeMdl(mdl);
+ }
+
+ SL_NUM_PACKET(buf) = num;
+ SL_LEFT_FLAG(buf) = left;
+
+ if (left == false)
+ {
+ SlReset(f->Event);
+ }
+ else
+ {
+ SlSet(f->Event);
+ }
+
+ ret = STATUS_SUCCESS;
+ ret_size = SL_EXCHANGE_BUFFER_SIZE;
+ }
+ }
+ }
+
+ irp->IoStatus.Status = ret;
+ irp->IoStatus.Information = ret_size;
+ IoCompleteRequest(irp, IO_NO_INCREMENT);
+
+ return ret;
+}
+
+// Write procedure of the device
+NTSTATUS SlDeviceWriteProc(DEVICE_OBJECT *device_object, IRP *irp)
+{
+ SL_DEVICE *dev = *((SL_DEVICE **)device_object->DeviceExtension);
+ NTSTATUS ret = STATUS_UNSUCCESSFUL;
+ IO_STACK_LOCATION *irp_stack = IoGetCurrentIrpStackLocation(irp);
+ UINT ret_size = 0;
+
+ if (dev->IsBasicDevice == false)
+ {
+ // Adapter device
+ SL_FILE *f = irp_stack->FileObject->FsContext;
+
+ if (irp_stack->Parameters.Write.Length == SL_EXCHANGE_BUFFER_SIZE)
+ {
+ UCHAR *buf = irp->UserBuffer;
+
+ if (dev->Halting || dev->Adapter->Halt || buf == NULL)
+ {
+ // Halting
+ }
+ else
+ {
+ // Write the packet
+ MDL *mdl;
+ UINT num = SL_NUM_PACKET(buf);
+
+ mdl = IoAllocateMdl(buf, SL_EXCHANGE_BUFFER_SIZE, false, false, NULL);
+ if (mdl != NULL)
+ {
+ MmProbeAndLockPages(mdl, KernelMode, IoReadAccess);
+ }
+
+ ret = true;
+ ret_size = SL_EXCHANGE_BUFFER_SIZE;
+
+ if (num >= 1 && num <= SL_MAX_PACKET_EXCHANGE)
+ {
+ UINT i, j;
+ NET_BUFFER_LIST *nbl_head = NULL;
+ NET_BUFFER_LIST *nbl_tail = NULL;
+ UINT num_packets = 0;
+ NDIS_HANDLE adapter_handle = NULL;
+
+ SlLock(f->Adapter->Lock);
+
+ if (f->Adapter->NumPendingSendPackets <= SL_MAX_PACKET_QUEUED)
+ {
+ // Admit to send only if the number of packets being transmitted does not exceed the specified limit
+ adapter_handle = f->Adapter->AdapterHandle;
+ }
+
+ if (adapter_handle != NULL)
+ {
+ // Lock the file list which opens the same adapter
+ SlLockList(dev->FileList);
+ for (j = 0;j < SL_LIST_NUM(dev->FileList);j++)
+ {
+ SL_FILE *other = SL_LIST_DATA(dev->FileList, j);
+
+ if (other != f)
+ {
+ // Lock the receive queue of other file lists
+ SlLock(other->RecvLock);
+
+ other->SetEventFlag = false;
+ }
+ }
+
+ for (i = 0;i < num;i++)
+ {
+ UINT packet_size = SL_SIZE_OF_PACKET(buf, i);
+ UCHAR *packet_buf;
+ NET_BUFFER_LIST *nbl = NULL;
+ bool ok = false;
+
+ if (packet_size > SL_MAX_PACKET_SIZE)
+ {
+ packet_size = SL_MAX_PACKET_SIZE;
+ }
+ else if (packet_size < SL_PACKET_HEADER_SIZE)
+ {
+ packet_size = SL_PACKET_HEADER_SIZE;
+ }
+
+ packet_buf = (UCHAR *)SL_ADDR_OF_PACKET(buf, i);
+
+ for (j = 0;j < SL_LIST_NUM(dev->FileList);j++)
+ {
+ SL_FILE *other = SL_LIST_DATA(dev->FileList, j);
+
+ if (other != f)
+ {
+ // Insert into the receive queue of the other file lists
+ if (other->NumRecvPackets < SL_MAX_PACKET_QUEUED)
+ {
+ SL_PACKET *q = SlMalloc(sizeof(SL_PACKET));
+
+ SlCopy(q->Data, packet_buf, packet_size);
+ q->Size = packet_size;
+ q->Next = NULL;
+
+ if (other->RecvPacketHead == NULL)
+ {
+ other->RecvPacketHead = q;
+ }
+ else
+ {
+ other->RecvPacketTail->Next = q;
+ }
+
+ other->RecvPacketTail = q;
+
+ other->NumRecvPackets++;
+
+ other->SetEventFlag = true;
+ }
+ }
+ }
+
+ // Allocate a new NET_BUFFER_LIST
+ if (f->NetBufferListPool != NULL)
+ {
+ nbl = NdisAllocateNetBufferList(f->NetBufferListPool, 16, 0);
+
+ if (nbl != NULL)
+ {
+ nbl->SourceHandle = adapter_handle;
+ }
+ }
+
+ if (nbl != NULL)
+ {
+ // Get the NET_BUFFER from the NET_BUFFER_LIST
+ NET_BUFFER *nb = NET_BUFFER_LIST_FIRST_NB(nbl);
+
+ NET_BUFFER_LIST_NEXT_NBL(nbl) = NULL;
+
+ if (nb != NULL && OK(NdisRetreatNetBufferDataStart(nb, packet_size, 0, NULL)))
+ {
+ // Buffer copy
+ UCHAR *dst = NdisGetDataBuffer(nb, packet_size, NULL, 1, 0);
+
+ if (dst != NULL)
+ {
+ SlCopy(dst, packet_buf, packet_size);
+
+ ok = true;
+ }
+ else
+ {
+ NdisAdvanceNetBufferDataStart(nb, packet_size, false, NULL);
+ }
+ }
+ }
+
+ if (ok == false)
+ {
+ if (nbl != NULL)
+ {
+ NdisFreeNetBufferList(nbl);
+ }
+ }
+ else
+ {
+ if (nbl_head == NULL)
+ {
+ nbl_head = nbl;
+ }
+
+ if (nbl_tail != NULL)
+ {
+ NET_BUFFER_LIST_NEXT_NBL(nbl_tail) = nbl;
+ }
+
+ nbl_tail = nbl;
+
+ *((void **)NET_BUFFER_LIST_CONTEXT_DATA_START(nbl)) = f;
+
+ num_packets++;
+ }
+ }
+
+ for (j = 0;j < SL_LIST_NUM(dev->FileList);j++)
+ {
+ SL_FILE *other = SL_LIST_DATA(dev->FileList, j);
+
+ if (other != f)
+ {
+ // Release the receive queue of other file lists
+ SlUnlock(other->RecvLock);
+
+ // Set an event
+ if (other->SetEventFlag)
+ {
+ SlSet(other->Event);
+ }
+ }
+ }
+ SlUnlockList(dev->FileList);
+
+ if (nbl_head != NULL)
+ {
+ InterlockedExchangeAdd(&f->NumSendingPacketets, num_packets);
+ InterlockedExchangeAdd(&f->Adapter->NumPendingSendPackets, num_packets);
+
+ SlUnlock(f->Adapter->Lock);
+
+ NdisSendNetBufferLists(adapter_handle, nbl_head, 0, 0);
+ }
+ else
+ {
+ SlUnlock(f->Adapter->Lock);
+ }
+ }
+ else
+ {
+ SlUnlock(f->Adapter->Lock);
+ }
+ }
+
+ if (mdl != NULL)
+ {
+ MmUnlockPages(mdl);
+ IoFreeMdl(mdl);
+ }
+ }
+ }
+ }
+
+ irp->IoStatus.Information = ret_size;
+ irp->IoStatus.Status = ret;
+ IoCompleteRequest(irp, IO_NO_INCREMENT);
+
+ return ret;
+}
+
+// IOCTL procedure of the device
+NTSTATUS SlDeviceIoControlProc(DEVICE_OBJECT *device_object, IRP *irp)
+{
+ SL_DEVICE *dev = *((SL_DEVICE **)device_object->DeviceExtension);
+ NTSTATUS ret = STATUS_UNSUCCESSFUL;
+ IO_STACK_LOCATION *irp_stack = IoGetCurrentIrpStackLocation(irp);
+ UINT ret_size = 0;
+
+ if (dev->IsBasicDevice == false)
+ {
+ // Adapter device
+ SL_FILE *f = irp_stack->FileObject->FsContext;
+
+ switch (irp_stack->Parameters.DeviceIoControl.IoControlCode)
+ {
+ case SL_IOCTL_GET_EVENT_NAME:
+ if (irp_stack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(SL_IOCTL_EVENT_NAME))
+ {
+ SL_IOCTL_EVENT_NAME *t = irp->UserBuffer;
+
+ if (t != NULL)
+ {
+ strcpy(t->EventNameWin32, f->EventNameWin32);
+
+ ret_size = sizeof(SL_IOCTL_EVENT_NAME);
+
+ ret = STATUS_SUCCESS;
+ }
+ }
+ break;
+ }
+ }
+
+ irp->IoStatus.Status = ret;
+ irp->IoStatus.Information = ret_size;
+ IoCompleteRequest(irp, IO_NO_INCREMENT);
+
+ return ret;
+}
+
+// NDIS bind notification procedure
+NDIS_STATUS SlNdisBindAdapterExProc(NDIS_HANDLE protocol_driver_context, NDIS_HANDLE bind_context, NDIS_BIND_PARAMETERS *bind_parameters)
+{
+ NDIS_STATUS ret = NDIS_STATUS_FAILURE;
+
+ InterlockedIncrement(&sl->NumBoundAdapters);
+
+ // Check the attributes of the adapter, and process only adapter which should be bound to
+ if (bind_parameters->MediaType == NdisMedium802_3 &&
+ bind_parameters->MacAddressLength == 6 &&
+// (bind_parameters->PhysicalMediumType == NdisPhysicalMedium802_3 || bind_parameters->PhysicalMediumType == 0) &&
+ bind_parameters->AccessType == NET_IF_ACCESS_BROADCAST &&
+ bind_parameters->DirectionType == NET_IF_DIRECTION_SENDRECEIVE &&
+ bind_parameters->ConnectionType == NET_IF_CONNECTION_DEDICATED)
+ {
+ // Open the adapter
+ NDIS_OPEN_PARAMETERS t;
+ NDIS_MEDIUM medium_array = {NdisMedium802_3};
+ SL_ADAPTER *a;
+ wchar_t adapter_id_tag[] = SL_ADAPTER_ID_PREFIX_W;
+
+ SlZero(&t, sizeof(t));
+ t.Header.Type = NDIS_OBJECT_TYPE_OPEN_PARAMETERS;
+ t.Header.Revision = NDIS_OPEN_PARAMETERS_REVISION_1;
+ t.Header.Size = NDIS_SIZEOF_OPEN_PARAMETERS_REVSION_1;
+
+ t.AdapterName = bind_parameters->AdapterName;
+ t.MediumArray = &medium_array;
+ t.MediumArraySize = 1;
+ t.SelectedMediumIndex = &sl->DummyInt;
+ t.FrameTypeArray = NULL;
+ t.FrameTypeArraySize = 0;
+
+ a = SlZeroMalloc(sizeof(SL_ADAPTER));
+
+ a->Lock = SlNewLock();
+ a->AdapterName = SlNewUnicodeFromUnicodeString(bind_parameters->AdapterName);
+
+ SlCopy(a->AdapterId, a->AdapterName->String.Buffer, MIN(sizeof(a->AdapterId) - sizeof(wchar_t), a->AdapterName->String.Length));
+ SlCopy(a->AdapterId, adapter_id_tag, sizeof(adapter_id_tag) - sizeof(wchar_t));
+
+ SlCopy(a->MacAddress, bind_parameters->CurrentMacAddress, 6);
+ SlCopy(&a->BindParamCopy, bind_parameters, sizeof(NDIS_BIND_PARAMETERS));
+ a->BindingContext = bind_context;
+ a->MtuSize = bind_parameters->MtuSize;
+
+ a->IsOpenPending = true;
+
+ ret = NdisOpenAdapterEx(sl->ProtocolHandle, a, &t, bind_context, &a->AdapterHandle);
+ a->AdapterHandle2 = a->AdapterHandle;
+
+ if (ret != NDIS_STATUS_PENDING)
+ {
+ a->IsOpenPending = false;
+ SlNdisOpenAdapterCompleteExProc(a, ret);
+ }
+ }
+
+ if (ret != NDIS_STATUS_PENDING)
+ {
+ if (ret != NDIS_STATUS_SUCCESS)
+ {
+ InterlockedDecrement(&sl->NumBoundAdapters);
+ }
+ }
+
+ return ret;
+}
+
+// Open success notification procedure of NDIS adapter
+void SlNdisOpenAdapterCompleteExProc(NDIS_HANDLE protocol_binding_context, NDIS_STATUS status)
+{
+ SL_ADAPTER *a = (SL_ADAPTER *)protocol_binding_context;
+ bool is_pending = a->IsOpenPending;
+ NDIS_HANDLE binding_context = a->BindingContext;
+
+ if (OK(status))
+ {
+ // Create an adapter device
+ SL_UNICODE *device_name = SlNewUnicode(SL_ADAPTER_DEVICE_NAME);
+ SL_UNICODE *symbolic_name = SlNewUnicode(SL_ADAPTER_DEVICE_NAME_SYMBOLIC);
+ SL_DEVICE *dev;
+
+ // Create a device name
+ SlCopy(device_name->String.Buffer + 8, a->AdapterId, sizeof(wchar_t) * 46);
+ SlCopy(symbolic_name->String.Buffer + 19, a->AdapterId, sizeof(wchar_t) * 46);
+
+ dev = SlNewDeviceUnicode(device_name, symbolic_name);
+
+ if (dev == NULL)
+ {
+ // Device creation failed
+ SlFreeUnicode(device_name);
+ SlFreeUnicode(symbolic_name);
+ }
+ else
+ {
+ // Create a file list
+ dev->FileList = SlNewList();
+ }
+ if (dev != NULL)
+ {
+ // Get the display name
+ SlSendOidRequest(a, false, OID_GEN_VENDOR_DESCRIPTION, a->FriendlyName,
+ sizeof(a->FriendlyName) - 1);
+
+ dev->Adapter = a;
+ a->Device = dev;
+
+ // Add this adapter to the adapter list
+ SlLockList(sl->AdapterList);
+ {
+ SlAdd(sl->AdapterList, a);
+ }
+ SlUnlockList(sl->AdapterList);
+ }
+ }
+ else
+ {
+ // Discard the adapter handle
+ a->AdapterHandle = NULL;
+
+ // Release the SL_ADAPTER
+ SlFreeAdapter(a);
+
+ a = NULL;
+ }
+
+ if (is_pending)
+ {
+ NdisCompleteBindAdapterEx(binding_context, status);
+ }
+
+ if (a != NULL)
+ {
+ a->Ready = true;
+ }
+
+ if (is_pending)
+ {
+ if (NG(status))
+ {
+ InterlockedDecrement(&sl->NumBoundAdapters);
+ }
+ }
+}
+
+// Release the SL_ADAPTER
+void SlFreeAdapter(SL_ADAPTER *a)
+{
+ // Validate arguments
+ if (a == NULL)
+ {
+ return;
+ }
+
+ SlFreeUnicode(a->AdapterName);
+
+ SlFreeLock(a->Lock);
+
+ SlFree(a);
+}
+
+// NDIS unbind notification procedure
+NDIS_STATUS SlNdisUnbindAdapterExProc(NDIS_HANDLE unbind_context, NDIS_HANDLE protocol_binding_context)
+{
+ NDIS_STATUS ret;
+ SL_ADAPTER *a = (SL_ADAPTER *)protocol_binding_context;
+ UINT j;
+ NDIS_HANDLE adapter_handle = NULL;
+
+ if (a->Halt)
+ {
+ //SL_WHERE;
+ }
+
+ adapter_handle = a->AdapterHandle;
+ a->Halt = true;
+ if (a->Device != NULL)
+ {
+ a->Device->Halting = true;
+ }
+ a->AdapterHandle = NULL;
+
+ SlLock(a->Lock);
+ {
+ }
+ SlUnlock(a->Lock);
+
+ a->UnbindContext = unbind_context;
+ a->IsClosePending = true;
+
+ // Delete the adapter from the adapter list
+ SlLockList(sl->AdapterList);
+ {
+ SlDelete(sl->AdapterList, a);
+ }
+ SlUnlockList(sl->AdapterList);
+
+ for (j = 0;j < 32;j++)
+ {
+ // Wait until the number of OID requests of being processed by this adapter becomes zero
+ while (true)
+ {
+ UINT num;
+
+ num = a->NumPendingOidRequests;
+
+ if (num == 0)
+ {
+ break;
+ }
+ else
+ {
+ j = 0;
+ }
+
+ //SlSleep(50);
+ }
+
+ // Wait until the number of packets this adapter is transmitting becomes zero
+ while (true)
+ {
+ UINT num;
+
+ num = a->NumPendingSendPackets;
+
+ if (num == 0)
+ {
+ break;
+ }
+ else
+ {
+ j = 0;
+ }
+
+ //SlSleep(50);
+ }
+
+ }
+
+ ret = NdisCloseAdapterEx(adapter_handle);
+
+ if (ret != NDIS_STATUS_PENDING)
+ {
+ a->IsClosePending = false;
+ SlNdisCloseAdapterCompleteExProc(a);
+
+ ret = NDIS_STATUS_SUCCESS;
+
+ InterlockedDecrement(&sl->NumBoundAdapters);
+ }
+
+ return ret;
+}
+
+// Close success notification procedure of NDIS adapter
+void SlNdisCloseAdapterCompleteExProc(NDIS_HANDLE protocol_binding_context)
+{
+ SL_ADAPTER *a = (SL_ADAPTER *)protocol_binding_context;
+ NDIS_HANDLE unbind_context = a->UnbindContext;
+ bool is_pending = a->IsClosePending;
+ UINT j;
+
+ if (is_pending)
+ {
+ NdisCompleteUnbindAdapterEx(unbind_context);
+ }
+
+ for (j = 0;j < 32;j++)
+ {
+ if (a->Device != NULL)
+ {
+ a->Device->Halting = true;
+
+ // Wait until the number of file handles that are associated with this device becomes zero
+ while (true)
+ {
+ UINT num_files = 0;
+
+ SlLock(a->Device->OpenCloseLock);
+ {
+ SlLockList(a->Device->FileList);
+ {
+ UINT i;
+ num_files = SL_LIST_NUM(a->Device->FileList);
+
+ for (i = 0;i < num_files;i++)
+ {
+ // Hit the associated event
+ SL_FILE *f = SL_LIST_DATA(a->Device->FileList, i);
+
+ if (f->FinalWakeUp == false)
+ {
+ SlSet(f->Event);
+ f->FinalWakeUp = true;
+ }
+ }
+ }
+ SlUnlockList(a->Device->FileList);
+ }
+ SlUnlock(a->Device->OpenCloseLock);
+
+ if (num_files == 0)
+ {
+ break;
+ }
+
+ SlSleep(50);
+ }
+ }
+ }
+
+ // Release the device
+ if (a->Device != NULL)
+ {
+ // Delete the file list
+ SlFreeList(a->Device->FileList);
+
+ SlFreeDevice(a->Device);
+ a->Device = NULL;
+ }
+
+ // Release the SL_ADAPTER
+ SlFreeAdapter(a);
+
+ if (is_pending)
+ {
+ InterlockedDecrement(&sl->NumBoundAdapters);
+ }
+}
+
+// NDIS PnP notification procedure
+NDIS_STATUS SlNdisNetPnPEventProc(NDIS_HANDLE protocol_binding_context, NET_PNP_EVENT_NOTIFICATION *net_pnp_event)
+{
+ SL_ADAPTER *a = (SL_ADAPTER *)protocol_binding_context;
+
+ if (net_pnp_event != NULL)
+ {
+ if (net_pnp_event->NetPnPEvent.NetEvent == NetEventBindsComplete)
+ {
+ sl->IsEnumCompleted = true;
+ }
+ }
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+// NDIS uninstall procedure
+void SlNdisUninstallProc(void)
+{
+}
+
+// NDIS OID request completion notification procedure
+void SlNdisOidRequestCompleteProc(NDIS_HANDLE protocol_binding_context, NDIS_OID_REQUEST *oid_request, NDIS_STATUS status)
+{
+ SL_ADAPTER *a = (SL_ADAPTER *)protocol_binding_context;
+ bool no_not_free = false;
+
+ // Check the results
+ if (oid_request->RequestType == NdisRequestQueryInformation)
+ {
+ if (oid_request->DATA.QUERY_INFORMATION.Oid == OID_GEN_VENDOR_DESCRIPTION)
+ {
+ no_not_free = true;
+ }
+ }
+
+ // Release the memory
+ if (no_not_free == false)
+ {
+ SlFree(oid_request->DATA.SET_INFORMATION.InformationBuffer);
+ }
+
+ SlFree(oid_request);
+
+ // Counter subtraction
+ InterlockedDecrement(&a->NumPendingOidRequests);
+}
+
+// NDIS status notification procedure
+void SlNdisStatusExProc(NDIS_HANDLE protocol_binding_context, NDIS_STATUS_INDICATION *status_indication)
+{
+ SL_ADAPTER *a = (SL_ADAPTER *)protocol_binding_context;
+}
+
+// NDIS packet reception notification procedure
+void SlNdisReceiveNetBufferListsProc(NDIS_HANDLE protocol_binding_context, NET_BUFFER_LIST *net_buffer_lists,
+ NDIS_PORT_NUMBER port_number, ULONG NumberOfNetBufferLists,
+ ULONG receive_flags)
+{
+ SL_ADAPTER *a = (SL_ADAPTER *)protocol_binding_context;
+ UINT i;
+ UINT return_flags = 0;
+ NET_BUFFER_LIST *nbl;
+ UCHAR *tmp_buffer;
+ UINT tmp_size;
+
+ if (net_buffer_lists == NULL || NumberOfNetBufferLists == 0)
+ {
+ return;
+ }
+
+ if (a->AdapterHandle2 == NULL)
+ {
+ a->AdapterHandle2 = a->AdapterHandle;
+ }
+
+ if (NDIS_TEST_RECEIVE_AT_DISPATCH_LEVEL(receive_flags))
+ {
+ NDIS_SET_RETURN_FLAG(return_flags, NDIS_RETURN_FLAGS_DISPATCH_LEVEL);
+ }
+
+ if (a->Halt || a->Device == NULL || a->Device->Halting || a->Ready == false || a->AdapterHandle == NULL)
+ {
+ goto LABEL_CLEANUP;
+ }
+
+ tmp_buffer = a->TmpBuffer;
+ tmp_size = sizeof(a->TmpBuffer);
+
+ nbl = net_buffer_lists;
+
+ SlLockList(a->Device->FileList);
+ {
+ if (a->Halt == false)
+ {
+ for (i = 0;i < SL_LIST_NUM(a->Device->FileList);i++)
+ {
+ // Lock the receive queue
+ SL_FILE *f = SL_LIST_DATA(a->Device->FileList, i);
+
+ SlLock(f->RecvLock);
+ }
+
+ while (nbl != NULL)
+ {
+ NET_BUFFER *nb = NET_BUFFER_LIST_FIRST_NB(nbl);
+ bool is_vlan = false;
+ UCHAR vlan_tag[2];
+
+ if (NET_BUFFER_LIST_INFO(nbl, Ieee8021QNetBufferListInfo) != 0)
+ {
+ NDIS_NET_BUFFER_LIST_8021Q_INFO qinfo;
+ qinfo.Value = NET_BUFFER_LIST_INFO(nbl, Ieee8021QNetBufferListInfo);
+ if (qinfo.TagHeader.VlanId != 0)
+ {
+ USHORT tag_us;
+ is_vlan = true;
+
+ tag_us = (qinfo.TagHeader.UserPriority & 0x07 << 13) |
+ (qinfo.TagHeader.CanonicalFormatId & 0x01 << 12) |
+ (qinfo.TagHeader.VlanId & 0x0FFF);
+
+ vlan_tag[0] = ((UCHAR *)(&tag_us))[1];
+ vlan_tag[1] = ((UCHAR *)(&tag_us))[0];
+ }
+ }
+
+ while (nb != NULL)
+ {
+ UINT size = NET_BUFFER_DATA_LENGTH(nb);
+
+ if (size >= 14 && size <= tmp_size && size <= (UINT)((is_vlan == false) ? SL_MAX_PACKET_SIZE : (SL_MAX_PACKET_SIZE - 4)))
+ {
+ UCHAR *ptr = NdisGetDataBuffer(nb, size, tmp_buffer, 1, 0);
+
+ if (ptr != NULL)
+ {
+ // Insert the queue to all waiting files
+ for (i = 0;i < SL_LIST_NUM(a->Device->FileList);i++)
+ {
+ SL_FILE *f = SL_LIST_DATA(a->Device->FileList, i);
+
+ if (f->NumRecvPackets < SL_MAX_PACKET_QUEUED)
+ {
+ SL_PACKET *q = SlMalloc(sizeof(SL_PACKET));
+
+ if (is_vlan == false)
+ {
+ // Normal packet
+ SlCopy(q->Data, ptr, size);
+ q->Size = size;
+ }
+ else
+ {
+ // Insert a tag in the case of IEEE802.1Q packet
+ SlCopy(q->Data, ptr, 12);
+ q->Data[12] = 0x81;
+ q->Data[13] = 0x00;
+ SlCopy(&q->Data[14], vlan_tag, 2);
+ SlCopy(&q->Data[16], &ptr[12], size - 12);
+
+ q->Size = size + 4;
+ }
+
+ q->Next = NULL;
+
+ if (f->RecvPacketHead == NULL)
+ {
+ f->RecvPacketHead = q;
+ }
+ else
+ {
+ f->RecvPacketTail->Next = q;
+ }
+
+ f->RecvPacketTail = q;
+
+ f->NumRecvPackets++;
+ }
+ }
+ }
+ }
+
+ nb = NET_BUFFER_NEXT_NB(nb);
+ }
+
+ nbl = NET_BUFFER_LIST_NEXT_NBL(nbl);
+ }
+
+ // Hit the event
+ for (i = 0;i < SL_LIST_NUM(a->Device->FileList);i++)
+ {
+ SL_FILE *f = SL_LIST_DATA(a->Device->FileList, i);
+
+ // Unlock the receive queue
+ SlUnlock(f->RecvLock);
+
+ SlSet(f->Event);
+ }
+ }
+ }
+ SlUnlockList(a->Device->FileList);
+
+LABEL_CLEANUP:
+
+ if (NDIS_TEST_RECEIVE_CAN_PEND(receive_flags))
+ {
+ NdisReturnNetBufferLists(a->AdapterHandle2, net_buffer_lists, return_flags);
+ }
+}
+
+// NDIS packet transmission completion notification procedure
+void SlNdisSendNetBufferListsCompleteProc(NDIS_HANDLE protocol_binding_context, NET_BUFFER_LIST *net_buffer_lists,
+ ULONG send_complete_flags)
+{
+ NET_BUFFER_LIST *nbl;
+
+ nbl = net_buffer_lists;
+
+ while (nbl != NULL)
+ {
+ NET_BUFFER_LIST *current_nbl = nbl;
+ SL_FILE *f;
+ NET_BUFFER *nb = NET_BUFFER_LIST_FIRST_NB(nbl);
+
+ if (nb != NULL)
+ {
+ UINT size = NET_BUFFER_DATA_LENGTH(nb);
+
+ NdisAdvanceNetBufferDataStart(nb, size, false, NULL);
+ }
+
+ // Get a file context
+ f = *((void **)NET_BUFFER_LIST_CONTEXT_DATA_START(nbl));
+
+ nbl = NET_BUFFER_LIST_NEXT_NBL(nbl);
+ NET_BUFFER_LIST_NEXT_NBL(current_nbl) = NULL;
+
+ // Release the NET_BUFFER_LIST
+ NdisFreeNetBufferList(current_nbl);
+
+ // Reduce the number of packets being sent by 1
+ InterlockedExchangeAdd(&f->NumSendingPacketets, (LONG)-1);
+ InterlockedExchangeAdd(&f->Adapter->NumPendingSendPackets, (LONG)-1);
+ }
+}
+
+// Crash
+void SlCrash(UINT a, UINT b, UINT c, UINT d)
+{
+ KeBugCheckEx(0x00000061, (ULONG_PTR)a, (ULONG_PTR)b, (ULONG_PTR)c, (ULONG_PTR)d);
+}
+
+// Memory allocation
+void *SlMalloc(UINT size)
+{
+ NDIS_STATUS r;
+ void *p;
+ if (size == 0)
+ {
+ size = 1;
+ }
+
+ // Allocate the non-paged memory
+ r = NdisAllocateMemoryWithTag(&p, size, 0);
+
+ if (NG(r))
+ {
+ return NULL;
+ }
+
+ return p;
+}
+
+// Clear to zero by allocating the memory
+void *SlZeroMalloc(UINT size)
+{
+ void *p = SlMalloc(size);
+ if (p == NULL)
+ {
+ // Memory allocation failure
+ return NULL;
+ }
+
+ // Clear to zero
+ SlZero(p, size);
+
+ return p;
+}
+
+// Release the memory
+void SlFree(void *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ // Release the memory
+ NdisFreeMemory(p, 0, 0);
+}
+
+// Memory zero clear
+void SlZero(void *dst, UINT size)
+{
+ // Validate arguments
+ if (dst == NULL || size == 0)
+ {
+ return;
+ }
+
+ // Clear
+ NdisZeroMemory(dst, size);
+}
+
+// Copy memory
+void SlCopy(void *dst, void *src, UINT size)
+{
+ // Validate arguments
+ if (dst == NULL || src == NULL || size == 0)
+ {
+ return;
+ }
+
+ // Copy
+ NdisMoveMemory(dst, src, size);
+}
+
+// Create a lock
+SL_LOCK *SlNewLock()
+{
+ NDIS_SPIN_LOCK *spin_lock;
+
+ // Memory allocation
+ SL_LOCK *lock = SlZeroMalloc(sizeof(SL_LOCK));
+ if (lock == NULL)
+ {
+ return NULL;
+ }
+
+ // Initialize spin lock
+ spin_lock = &lock->spin_lock;
+
+ NdisAllocateSpinLock(spin_lock);
+
+ return lock;
+}
+
+// Lock
+void SlLock(SL_LOCK *lock)
+{
+ NDIS_SPIN_LOCK *spin_lock;
+ // Validate arguments
+ if (lock == NULL)
+ {
+ return;
+ }
+
+ spin_lock = &lock->spin_lock;
+ NdisAcquireSpinLock(spin_lock);
+}
+
+// Unlock
+void SlUnlock(SL_LOCK *lock)
+{
+ NDIS_SPIN_LOCK *spin_lock;
+ // Validate arguments
+ if (lock == NULL)
+ {
+ return;
+ }
+
+ spin_lock = &lock->spin_lock;
+ NdisReleaseSpinLock(spin_lock);
+}
+
+// Release the lock
+void SlFreeLock(SL_LOCK *lock)
+{
+ NDIS_SPIN_LOCK *spin_lock;
+ // Validate arguments
+ if (lock == NULL)
+ {
+ return;
+ }
+
+ spin_lock = &lock->spin_lock;
+ NdisFreeSpinLock(spin_lock);
+
+ // Release the memory
+ SlFree(lock);
+}
+
+// Create an event
+SL_EVENT *SlNewEvent(char *name)
+{
+ SL_UNICODE *unicode_name;
+ SL_EVENT *event;
+ // Validate arguments
+ if (name == NULL)
+ {
+ return NULL;
+ }
+
+ // Convert to Unicode name
+ unicode_name = SlNewUnicode(name);
+ if (unicode_name == NULL)
+ {
+ return NULL;
+ }
+
+ // Memory allocation
+ event = SlZeroMalloc(sizeof(SL_EVENT));
+ if (event == NULL)
+ {
+ SlFreeUnicode(unicode_name);
+ return NULL;
+ }
+
+ // Create an event
+ event->event = IoCreateNotificationEvent(SlGetUnicode(unicode_name), &event->event_handle);
+ if (event->event == NULL)
+ {
+ SlFree(event);
+ SlFreeUnicode(unicode_name);
+ return NULL;
+ }
+
+ // Initialize the event
+ KeInitializeEvent(event->event, NotificationEvent, FALSE);
+ KeClearEvent(event->event);
+
+ // Release the string
+ SlFreeUnicode(unicode_name);
+
+ return event;
+}
+
+// Release the event
+void SlFreeEvent(SL_EVENT *event)
+{
+ // Validate arguments
+ if (event == NULL)
+ {
+ return;
+ }
+
+ ZwClose(event->event_handle);
+
+ // Release the memory
+ SlFree(event);
+}
+
+// Set the event
+void SlSet(SL_EVENT *event)
+{
+ // Validate arguments
+ if (event == NULL)
+ {
+ return;
+ }
+
+ KeSetEvent(event->event, 0, FALSE);
+}
+
+// Reset the event
+void SlReset(SL_EVENT *event)
+{
+ // Validate arguments
+ if (event == NULL)
+ {
+ return;
+ }
+
+ KeResetEvent(event->event);
+}
+
+// Create by copying the Unicode
+SL_UNICODE *SlNewUnicodeFromUnicodeString(UNICODE_STRING *src)
+{
+ SL_UNICODE *u;
+ // Validate arguments
+ if (src == NULL)
+ {
+ return NULL;
+ }
+
+ // Memory allocation
+ u = SlZeroMalloc(sizeof(SL_UNICODE));
+ if (u == NULL)
+ {
+ return NULL;
+ }
+
+ u->String.Length = u->String.MaximumLength = src->Length;
+
+ u->String.Buffer = SlZeroMalloc(src->Length);
+ SlCopy(u->String.Buffer, src->Buffer, src->Length);
+
+ return u;
+}
+
+// Create a Unicode
+SL_UNICODE *SlNewUnicode(char *str)
+{
+ SL_UNICODE *u;
+ // Validate arguments
+ if (str == NULL)
+ {
+ return NULL;
+ }
+
+ // Memory allocation
+ u = SlZeroMalloc(sizeof(SL_UNICODE));
+ if (u == NULL)
+ {
+ return NULL;
+ }
+
+ // String initialization
+ NdisInitializeString(&u->String, str);
+
+ return u;
+}
+
+// Release the Unicode
+void SlFreeUnicode(SL_UNICODE *u)
+{
+ // Validate arguments
+ if (u == NULL)
+ {
+ return;
+ }
+
+ // Release the string
+ NdisFreeString(u->String);
+
+ // Release the memory
+ SlFree(u);
+}
+
+// Get an Unicode
+NDIS_STRING *SlGetUnicode(SL_UNICODE *u)
+{
+ // Validate arguments
+ if (u == NULL)
+ {
+ return NULL;
+ }
+
+ return &u->String;
+}
+
+// Create a packet buffer
+SL_PACKET_BUFFER *SlNewPacketBuffer()
+{
+ SL_PACKET_BUFFER *p;
+ NET_BUFFER_LIST_POOL_PARAMETERS p1;
+
+ // Memory allocation
+ p = SlZeroMalloc(sizeof(SL_PACKET_BUFFER));
+
+ // Create a NET_BUFFER_LIST pool
+ SlZero(&p1, sizeof(p1));
+ p1.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
+ p1.Header.Revision = NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1;
+ p1.Header.Size = NDIS_SIZEOF_NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1;
+ p1.ProtocolId = NDIS_PROTOCOL_ID_DEFAULT;
+ p1.fAllocateNetBuffer = TRUE;
+ p1.DataSize = SL_MAX_PACKET_SIZE;
+
+ p->NetBufferListPool = NdisAllocateNetBufferListPool(NULL, &p1);
+
+ // Create a NET_BUFFER_LIST
+ p->NetBufferList = NdisAllocateNetBufferList(p->NetBufferListPool, 0, 0);
+
+ return p;
+}
+
+// Release the packet buffer
+void SlFreePacketBuffer(SL_PACKET_BUFFER *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ // Release the NET_BUFFER_LIST
+ NdisFreeNetBufferList(p->NetBufferList);
+
+ // Release the NET_BUFFER_LIST pool
+ NdisFreeNetBufferListPool(p->NetBufferListPool);
+
+ // Release the memory
+ SlFree(p);
+}
+
+// Create a list
+SL_LIST *SlNewList()
+{
+ SL_LIST *o;
+
+ o = (SL_LIST *)SlZeroMalloc(sizeof(SL_LIST));
+
+ o->lock = SlNewLock();
+
+ o->num_item = 0;
+ o->num_reserved = SL_INIT_NUM_RESERVED;
+
+ o->p = (void **)SlZeroMalloc(sizeof(void *) * o->num_reserved);
+
+ return o;
+}
+
+// Add an element to the list
+void SlAdd(SL_LIST *o, void *p)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL || p == NULL)
+ {
+ return;
+ }
+
+ i = o->num_item;
+ o->num_item++;
+
+ if (o->num_item > o->num_reserved)
+ {
+ UINT old_num_reserved = o->num_reserved;
+ void *p_old = o->p;
+
+ o->num_reserved = o->num_reserved * 2;
+
+ o->p = SlZeroMalloc(sizeof(void *) * o->num_reserved);
+ SlCopy(o->p, p_old, sizeof(void *) * old_num_reserved);
+ SlFree(p_old);
+ }
+
+ o->p[i] = p;
+}
+
+// Delete the element from the list
+bool SlDelete(SL_LIST *o, void *p)
+{
+ UINT i, n;
+ // Validate arguments
+ if (o == NULL || p == NULL)
+ {
+ return false;
+ }
+
+ for (i = 0;i < o->num_item;i++)
+ {
+ if (o->p[i] == p)
+ {
+ break;
+ }
+ }
+ if (i == o->num_item)
+ {
+ return false;
+ }
+
+ n = i;
+ for (i = n;i < (o->num_item - 1);i++)
+ {
+ o->p[i] = o->p[i + 1];
+ }
+ o->num_item--;
+
+ return true;
+}
+
+// Delete all elements from the list
+void SlDeleteAll(SL_LIST *o)
+{
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ o->num_item = 0;
+}
+
+// Lock the list
+void SlLockList(SL_LIST *o)
+{
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ SlLock(o->lock);
+}
+
+// Unlock the list
+void SlUnlockList(SL_LIST *o)
+{
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ SlUnlock(o->lock);
+}
+
+// Release the list
+void SlFreeList(SL_LIST *o)
+{
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ SlFree(o->p);
+ SlFreeLock(o->lock);
+
+ SlFree(o);
+}
+
+// Clone the memory
+void *SlClone(void *p, UINT size)
+{
+ void *ret;
+ // Validate arguments
+ if (p == NULL)
+ {
+ return NULL;
+ }
+
+ ret = SlMalloc(size);
+ SlCopy(ret, p, size);
+
+ return ret;
+}
+
+
+// Sleep
+void SlSleep(int milliSeconds)
+{
+ PKTIMER timer = SlMalloc(sizeof(KTIMER));
+ LARGE_INTEGER duetime;
+
+ duetime.QuadPart = (__int64)milliSeconds * -10000;
+ KeInitializeTimerEx(timer, NotificationTimer);
+ KeSetTimerEx(timer, duetime, 0, NULL);
+
+ KeWaitForSingleObject(timer, Executive, KernelMode, FALSE, NULL);
+
+ SlFree(timer);
+}
+
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/SeLow/SeLow.h b/src/SeLow/SeLow.h
new file mode 100644
index 00000000..40b6f922
--- /dev/null
+++ b/src/SeLow/SeLow.h
@@ -0,0 +1,361 @@
+// SoftEther VPN Source Code
+// SeLow - SoftEther Lightweight Network Protocol
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// 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 version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// SeLow.h
+// Header of SeLow.c
+
+#ifndef SELOW_H
+#define SELOW_H
+
+// Win32 DDK related
+#ifndef CPU_64
+#define _X86_
+#else // CPU_64
+#ifndef NEO_IA64
+#define _AMD64_
+#define AMD64
+#else // NEO_IA64
+#define _IA64_
+#define IA64
+#endif // NEO_IA64
+#endif // CPU_64
+#define NDIS_MINIPORT_DRIVER
+// NDIS 6.2
+#define NDIS620_MINIPORT
+#define NDIS_SUPPORT_NDIS61 1
+#define NDIS_SUPPORT_NDIS620 1
+#define NEO_NDIS_MAJOR_VERSION 6
+#define NEO_NDIS_MINOR_VERSION 20
+#define NDIS_WDM 1
+
+#include <wdm.h>
+#include <wdmsec.h>
+#include <ndis.h>
+#include <stdio.h>
+#include <string.h>
+
+// OS determination
+#ifdef WIN32
+#define OS_WIN32 // Microsoft Windows
+#else
+#define OS_UNIX // UNIX / Linux
+#endif
+
+
+// Type declaration
+#ifndef WINDOWS_H_INCLUDED
+#ifndef WIN9X
+typedef unsigned long BOOL;
+#endif // WIN9X
+#define TRUE 1
+#define FALSE 0
+#endif
+typedef unsigned long bool;
+#define true 1
+#define false 0
+typedef unsigned long long UINT64;
+typedef signed long long INT64;
+typedef unsigned short WORD;
+typedef unsigned short USHORT;
+typedef signed short SHORT;
+typedef unsigned char BYTE;
+typedef unsigned char UCHAR;
+typedef signed char CHAR;
+typedef unsigned long DWORD;
+#define INFINITE 0xFFFFFFFF
+
+#define LESS(a, max_value) ((a) < (max_value) ? (a) : (max_value))
+#define MORE(a, min_value) ((a) > (min_value) ? (a) : (min_value))
+#define INNER(a, b, c) (((b) <= (c) && (a) >= (b) && (a) <= (c)) || ((b) >= (c) && (a) >= (c) && (a) <= (b)))
+#define OUTER(a, b, c) (!INNER((a), (b), (c)))
+#define MAKESURE(a, b, c) (((b) <= (c)) ? (MORE(LESS((a), (c)), (b))) : (MORE(LESS((a), (b)), (c))))
+#define MIN(a, b) ((a) >= (b) ? (b) : (a))
+#define MAX(a, b) ((a) >= (b) ? (a) : (b))
+#define EQUAL_BOOL(a, b) (((a) && (b)) || ((!(a)) && (!(b))))
+
+// Error checking macro
+#define OK(val) ((val) == STATUS_SUCCESS)
+#define NG(val) (!OK(val))
+
+#define MAX_PATH 260
+#define MAX_SIZE 512
+#define STD_SIZE 512
+
+#define SL_WHERE SlCrash(__LINE__, __LINE__, __LINE__, __LINE__)
+#define SL_CRUSH(x) SlCrash(__LINE__, (UINT)(x), (UINT)(x), (UINT)(x))
+
+// Common header
+#include "SeLowCommon.h"
+
+
+//// Utility data structure
+
+// Lock
+typedef struct SL_LOCK
+{
+ NDIS_SPIN_LOCK spin_lock;
+} SL_LOCK;
+
+// Event
+typedef struct SL_EVENT
+{
+ KEVENT *event;
+ HANDLE event_handle;
+} SL_EVENT;
+
+// Unicode string
+typedef struct SL_UNICODE
+{
+ UNICODE_STRING String;
+} SL_UNICODE;
+
+// NDIS packet buffer
+typedef struct SL_PACKET_BUFFER
+{
+ NDIS_HANDLE NetBufferListPool; // NET_BUFFER_LIST Pool
+ NET_BUFFER_LIST *NetBufferList; // NET_BUFFER_LIST
+} SL_PACKET_BUFFER;
+
+// List
+typedef struct SL_LIST
+{
+ UINT num_item, num_reserved;
+ void **p;
+ SL_LOCK *lock;
+} SL_LIST;
+
+#define SL_LIST_DATA(o, i) (((o) != NULL) ? ((o)->p[(i)]) : NULL)
+#define SL_LIST_NUM(o) (((o) != NULL) ? (o)->num_item : 0)
+#define SL_INIT_NUM_RESERVED 32
+
+//// SL data structure
+
+// Packet queue
+typedef struct SL_PACKET
+{
+ UCHAR Data[SL_MAX_PACKET_SIZE]; // Data
+ UINT Size; // Size
+
+ struct SL_PACKET *Next; // Next packet
+} SL_PACKET;
+
+// File context
+typedef struct SL_FILE
+{
+ struct SL_DEVICE *Device; // Device
+ struct SL_ADAPTER *Adapter; // Adapter
+ FILE_OBJECT *FileObject; // File object
+ SL_EVENT *Event; // Event
+ char EventNameWin32[SL_EVENT_NAME_SIZE]; // Win32 event name
+
+ SL_LOCK *RecvLock; // Receive lock
+ SL_PACKET *RecvPacketHead; // Head of the received packet
+ SL_PACKET *RecvPacketTail; // Tail of the received packet
+ UINT NumRecvPackets; // Number of items of the received packet queue
+ NDIS_HANDLE NetBufferListPool; // NET_BUFFER_LIST Pool
+ volatile UINT NumSendingPacketets; // Number of packets being transmitted
+ bool SetEventFlag; // Flag to set an event
+ bool FinalWakeUp;
+} SL_FILE;
+
+// Device context
+typedef struct SL_DEVICE
+{
+ DEVICE_OBJECT *DeviceObject; // Device object
+ SL_UNICODE *DeviceName; // Device name
+ SL_UNICODE *SymbolicLinkName; // Symbolic link name
+ volatile bool Halting; // Halting
+
+ bool IsBasicDevice; // Whether basic device
+ struct SL_ADAPTER *Adapter; // Adapter
+
+ SL_LIST *FileList; // File List
+ SL_LOCK *OpenCloseLock; // Open / Close lock of the device
+} SL_DEVICE;
+
+// Adapter context
+typedef struct SL_ADAPTER
+{
+ volatile bool Halt; // Halt flag
+ volatile bool Ready; // Ready flag
+ SL_UNICODE *AdapterName; // Adapter name
+ NDIS_BIND_PARAMETERS BindParamCopy; // Copy of the bind parameters
+ UCHAR MacAddress[6]; // MAC address
+ UINT MtuSize; // MTU size
+ wchar_t AdapterId[SL_ADAPTER_ID_LEN]; // Adapter ID
+ volatile bool IsOpenPending; // Whether Open is Pending
+ volatile bool IsClosePending; // Whether Close is Pending
+ NDIS_HANDLE BindingContext; // Binding context
+ NDIS_HANDLE AdapterHandle; // Handle of the adapter
+ NDIS_HANDLE AdapterHandle2; // Handle of the adapter (receive-only)
+ NDIS_HANDLE UnbindContext; // Unbind context
+ SL_LOCK *Lock; // Lock object
+ volatile UINT NumPendingOidRequests; // Number of running OID requests
+ volatile UINT NumPendingSendPackets; // Number of packets being transmitted
+ UCHAR TmpBuffer[SL_MAX_PACKET_SIZE]; // Temporally buffer size
+ char FriendlyName[256]; // Adapter name
+
+ SL_DEVICE *Device; // Handle of the device
+} SL_ADAPTER;
+
+// SL context
+typedef struct SL_CTX
+{
+ DRIVER_OBJECT *DriverObject; // Driver object
+ NDIS_HANDLE ProtocolHandle; // NDIS protocol handle
+ SL_DEVICE *BasicDevice; // Basic device
+ SL_LIST *AdapterList; // Adapter list
+
+ volatile UINT IntCounter1;
+ UINT DummyInt;
+ volatile bool IsEnumCompleted; // Enumeration completion flag
+ volatile UINT NumBoundAdapters;
+} SL_CTX;
+
+
+//// SL function
+NDIS_STATUS DriverEntry(DRIVER_OBJECT *driver_object, UNICODE_STRING *registry_path);
+
+NTSTATUS SlDeviceOpenProc(DEVICE_OBJECT *device_object, IRP *irp);
+NTSTATUS SlDeviceCloseProc(DEVICE_OBJECT *device_object, IRP *irp);
+NTSTATUS SlDeviceReadProc(DEVICE_OBJECT *device_object, IRP *irp);
+NTSTATUS SlDeviceWriteProc(DEVICE_OBJECT *device_object, IRP *irp);
+NTSTATUS SlDeviceIoControlProc(DEVICE_OBJECT *device_object, IRP *irp);
+
+void SlUnloadProc(DRIVER_OBJECT *driver_object);
+
+NDIS_STATUS SlNdisBindAdapterExProc(NDIS_HANDLE protocol_driver_context, NDIS_HANDLE bind_context, NDIS_BIND_PARAMETERS *bind_parameters);
+NDIS_STATUS SlNdisUnbindAdapterExProc(NDIS_HANDLE unbind_context, NDIS_HANDLE protocol_binding_context);
+void SlNdisOpenAdapterCompleteExProc(NDIS_HANDLE protocol_binding_context, NDIS_STATUS status);
+void SlNdisCloseAdapterCompleteExProc(NDIS_HANDLE protocol_binding_context);
+NDIS_STATUS SlNdisNetPnPEventProc(NDIS_HANDLE protocol_binding_context, NET_PNP_EVENT_NOTIFICATION *net_pnp_event);
+void SlNdisUninstallProc(void);
+void SlNdisOidRequestCompleteProc(NDIS_HANDLE protocol_binding_context, NDIS_OID_REQUEST *oid_request, NDIS_STATUS status);
+void SlNdisStatusExProc(NDIS_HANDLE protocol_binding_context, NDIS_STATUS_INDICATION *status_indication);
+void SlNdisReceiveNetBufferListsProc(NDIS_HANDLE protocol_binding_context, NET_BUFFER_LIST *net_buffer_lists, NDIS_PORT_NUMBER port_number, ULONG NumberOfNetBufferLists, ULONG receive_flags);
+void SlNdisSendNetBufferListsCompleteProc(NDIS_HANDLE protocol_binding_context, NET_BUFFER_LIST *net_buffer_lists, ULONG send_complete_flags);
+
+SL_DEVICE *SlNewDevice(char *device_name, char *symbolic_link_name);
+SL_DEVICE *SlNewDeviceUnicode(SL_UNICODE *u_device_name, SL_UNICODE *u_sym_name);
+void SlFreeDevice(SL_DEVICE *dev);
+void SlFreeAdapter(SL_ADAPTER *a);
+
+void SlSendOidRequest(SL_ADAPTER *a, bool set, NDIS_OID oid, void *data, UINT size);
+
+//// Utility function
+void *SlMalloc(UINT size);
+void *SlZeroMalloc(UINT size);
+void SlFree(void *p);
+void SlCopy(void *dst, void *src, UINT size);
+void SlZero(void *dst, UINT size);
+SL_LOCK *SlNewLock();
+void SlLock(SL_LOCK *lock);
+void SlUnlock(SL_LOCK *lock);
+void SlFreeLock(SL_LOCK *lock);
+SL_EVENT *SlNewEvent(char *name);
+void SlFreeEvent(SL_EVENT *event);
+void SlSet(SL_EVENT *event);
+void SlReset(SL_EVENT *event);
+SL_UNICODE *SlNewUnicode(char *str);
+SL_UNICODE *SlNewUnicodeFromUnicodeString(UNICODE_STRING *src);
+void SlFreeUnicode(SL_UNICODE *u);
+NDIS_STRING *SlGetUnicode(SL_UNICODE *u);
+SL_PACKET_BUFFER *SlNewPacketBuffer();
+void SlFreePacketBuffer(SL_PACKET_BUFFER *p);
+void SlCrash(UINT a, UINT b, UINT c, UINT d);
+SL_LIST *SlNewList();
+void SlAdd(SL_LIST *o, void *p);
+bool SlDelete(SL_LIST *o, void *p);
+void SlDeleteAll(SL_LIST *o);
+void SlLockList(SL_LIST *o);
+void SlUnlockList(SL_LIST *o);
+void SlFreeList(SL_LIST *o);
+void *SlClone(void *p, UINT size);
+void SlSleep(int milliSeconds);
+
+
+
+
+#endif // SELOW_H
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/SeLow/SeLow.rc b/src/SeLow/SeLow.rc
new file mode 100644
index 00000000..2e72f111
--- /dev/null
+++ b/src/SeLow/SeLow.rc
@@ -0,0 +1,63 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Japanese resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_JPN)
+#ifdef _WIN32
+LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT
+#pragma code_page(932)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+#endif // Japanese resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/src/SeLow/SeLow.vcproj b/src/SeLow/SeLow.vcproj
new file mode 100644
index 00000000..a7719953
--- /dev/null
+++ b/src/SeLow/SeLow.vcproj
@@ -0,0 +1,278 @@
+<?xml version="1.0" encoding="shift_jis"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="SeLow"
+ ProjectGUID="{94CA5DD2-1543-42F6-9F96-EE7694DDC837}"
+ RootNamespace="SeLow"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="0"
+ EnableIntrinsicFunctions="false"
+ FavorSizeOrSpeed="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;C:\WINDDK\7600.16385.0\inc\ddk;C:\WinDDK\7600.16385.0\inc\api;C:\WinDDK\7600.16385.0\inc\crt;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;VPN_SPEED"
+ StringPooling="false"
+ ExceptionHandling="0"
+ RuntimeLibrary="0"
+ StructMemberAlignment="4"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ CallingConvention="2"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ IgnoreImportLibrary="true"
+ LinkLibraryDependencies="false"
+ AdditionalOptions="/driver /subsystem:native,5.00 /FULLBUILD /align:0x80 /osversion:5.00 /STACK:0x40000,0x1000 /MERGE:_PAGE=PAGE /MERGE:_TEXT=.text /NODEFAULTLIB /stub:C:\WINDDK\7600.16385.0\lib\win7\stub512.com"
+ AdditionalDependencies="bufferoverflowK.lib wdm.lib ndis.lib wdmsec.lib ntoskrnl.lib fwpkclnt.lib &quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\hamcore\not_signed\SeLow_x86.sys"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="C:\WINDDK\7600.16385.0\lib\win7\i386"
+ GenerateManifest="false"
+ IgnoreAllDefaultLibraries="true"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="0"
+ OptimizeReferences="1"
+ EnableCOMDATFolding="1"
+ EntryPointSymbol="DriverEntry"
+ BaseAddress="0x10000"
+ RandomizedBaseAddress="0"
+ FixedBaseAddress="1"
+ DataExecutionPrevention="0"
+ ImportLibrary="$(SolutionDir)tmp\lib\$(PlatformName)_$(ConfigurationName)\$(ProjectName).lib"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SignCode &quot;$(TargetPath)&quot; /COMMENT:&quot;VPN Software&quot; /KERNEL:yes&#x0D;&#x0A;$(SolutionDir)bin\BuildUtil.exe /CMD:SignSeLowInfFiles x86&#x0D;&#x0A;"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="0"
+ EnableIntrinsicFunctions="false"
+ FavorSizeOrSpeed="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;C:\WINDDK\7600.16385.0\inc\ddk;C:\WinDDK\7600.16385.0\inc\api;C:\WinDDK\7600.16385.0\inc\crt;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;VPN_SPEED;CPU_64"
+ StringPooling="false"
+ ExceptionHandling="0"
+ RuntimeLibrary="0"
+ StructMemberAlignment="4"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ CallingConvention="2"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ IgnoreImportLibrary="true"
+ LinkLibraryDependencies="false"
+ AdditionalOptions="/driver /subsystem:native /FULLBUILD /align:0x80 /osversion:5.00 /STACK:0x40000,0x1000 /MERGE:_PAGE=PAGE /MERGE:_TEXT=.text /NODEFAULTLIB /stub:C:\WINDDK\7600.16385.0\lib\win7\stub512.com"
+ AdditionalDependencies="bufferoverflowK.lib wdm.lib ndis.lib wdmsec.lib ntoskrnl.lib fwpkclnt.lib &quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\hamcore\not_signed\SeLow_x64.sys"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="C:\WINDDK\7600.16385.0\lib\win7\amd64"
+ GenerateManifest="false"
+ IgnoreAllDefaultLibraries="true"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="0"
+ OptimizeReferences="1"
+ EnableCOMDATFolding="1"
+ EntryPointSymbol="DriverEntry"
+ BaseAddress="0x10000"
+ RandomizedBaseAddress="0"
+ FixedBaseAddress="1"
+ DataExecutionPrevention="0"
+ ImportLibrary="$(SolutionDir)tmp\lib\$(PlatformName)_$(ConfigurationName)\$(ProjectName).lib"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SignCode &quot;$(TargetPath)&quot; /COMMENT:&quot;VPN Software&quot; /KERNEL:yes&#x0D;&#x0A;$(SolutionDir)bin\BuildUtil.exe /CMD:SignSeLowInfFiles x64&#x0D;&#x0A;"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\SeLow.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\resource.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SeLow.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SeLowCommon.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ <File
+ RelativePath=".\SeLow.rc"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/src/SeLow/SeLowCommon.h b/src/SeLow/SeLowCommon.h
new file mode 100644
index 00000000..7edfefbb
--- /dev/null
+++ b/src/SeLow/SeLowCommon.h
@@ -0,0 +1,175 @@
+// SoftEther VPN Source Code
+// SeLow - SoftEther Lightweight Network Protocol
+//
+// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
+//
+// Copyright (c) 2012-2014 Daiyuu Nobori.
+// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan.
+// Copyright (c) 2012-2014 SoftEther Corporation.
+//
+// All Rights Reserved.
+//
+// http://www.softether.org/
+//
+// Author: Daiyuu Nobori
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// 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 version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// SeLowCommon.h
+// Common Header for Kernel Mode / User Mode
+
+//// Version number
+// Change this number every time functions are added or modified on the driver.
+// As long as this number does not change, installation of SeLow during the update
+// installation of the VPN Server / VPN Client / VPN Bridge is skipped.
+#define SL_VER 42
+
+// Constants
+#define SL_MAX_PACKET_SIZE 1560
+#define SL_MAX_PACKET_SIZE_ANNOUNCE 1514
+#define SL_MIN_PACKET_SIZE 14
+#define SL_PACKET_HEADER_SIZE 14
+#define SL_MAX_FRAME_SIZE (SL_MAX_PACKET_SIZE - SL_MIN_PACKET_SIZE)
+
+#define SL_PROTOCOL_NAME "SeLow"
+#define SL_EVENT_NAME_SIZE 128
+
+#define SL_ENUM_COMPLETE_GIVEUP_TICK (15 * 1000)
+
+// IOCTL
+#define SL_IOCTL_GET_EVENT_NAME CTL_CODE(0x8000, 1, METHOD_NEITHER, FILE_ANY_ACCESS)
+
+// IOCTL data structure
+typedef struct SL_IOCTL_EVENT_NAME
+{
+ char EventNameWin32[SL_EVENT_NAME_SIZE]; // Event name
+} SL_IOCTL_EVENT_NAME;
+
+// Device ID
+#define SL_BASIC_DEVICE_NAME "\\Device\\SELOW_BASIC_DEVICE"
+#define SL_BASIC_DEVICE_NAME_SYMBOLIC "\\DosDevices\\Global\\SELOW_BASIC_DEVICE"
+#define SL_BASIC_DEVICE_FILENAME_WIN32 "\\\\.\\SELOW_BASIC_DEVICE"
+#define SL_ADAPTER_ID_PREFIX "SELOW_A_"
+#define SL_ADAPTER_ID_PREFIX_W L"SELOW_A_"
+#define SL_ADAPTER_DEVICE_NAME "\\Device\\SELOW_A_{00000000-0000-0000-0000-000000000000}"
+#define SL_ADAPTER_DEVICE_NAME_SYMBOLIC "\\DosDevices\\Global\\SELOW_A_{00000000-0000-0000-0000-000000000000}"
+#define SL_ADAPTER_DEVICE_FILENAME_WIN32 "\\\\.\\%s"
+
+// Event name
+#define SL_EVENT_NAME "\\BaseNamedObjects\\SELOW_EVENT_%u_%u"
+#define SL_EVENT_NAME_WIN32 "Global\\SELOW_EVENT_%u_%u"
+
+// Registry key
+#define SL_REG_KEY_NAME "SYSTEM\\CurrentControlSet\\services\\SeLow"
+#define SL_REG_VER_VALUE "SlVersion"
+
+// Adapter data
+#define SL_ADAPTER_ID_LEN 64
+typedef struct SL_ADAPTER_INFO
+{
+ wchar_t AdapterId[SL_ADAPTER_ID_LEN]; // Adapter ID
+ UCHAR MacAddress[6]; // MAC address
+ UCHAR Padding1[2];
+ UINT MtuSize; // MTU size
+ char FriendlyName[256]; // Display name
+ UCHAR Reserved[256]; // Reserved area
+} SL_ADAPTER_INFO;
+
+#define SL_MAX_ADAPTER_INFO_LIST_ENTRY 256
+#define SL_SIGNATURE 0xDEADBEEF
+
+typedef struct SL_ADAPTER_INFO_LIST
+{
+ UINT Signature; // Signature
+ UINT SeLowVersion; // Version of SeLow
+ UINT EnumCompleted; // Enumeration completion flag
+ UINT NumAdapters; // The total number of adapter
+ SL_ADAPTER_INFO Adapters[SL_MAX_ADAPTER_INFO_LIST_ENTRY]; // Array of adapter
+} SL_ADAPTER_INFO_LIST;
+
+
+// Packet data exchange related
+#define SL_MAX_PACKET_EXCHANGE 256 // Number of packets that can be exchanged at a time
+#define SL_MAX_PACKET_QUEUED 4096 // Maximum number of packets that can be queued
+#define SL_EX_SIZEOF_NUM_PACKET 4 // Packet count data (UINT)
+#define SL_EX_SIZEOF_LENGTH_PACKET 4 // Length data of the packet data (UINT)
+#define SL_EX_SIZEOF_LEFT_FLAG 4 // Flag to indicate that the packet is left
+#define SL_EX_SIZEOF_ONE_PACKET 1600 // Data area occupied by a packet data
+#define SL_EXCHANGE_BUFFER_SIZE (SL_EX_SIZEOF_NUM_PACKET + SL_EX_SIZEOF_LEFT_FLAG + \
+ (SL_EX_SIZEOF_LENGTH_PACKET + SL_EX_SIZEOF_ONE_PACKET) * (SL_MAX_PACKET_EXCHANGE + 1))
+#define SL_NUM_PACKET(buf) (*((UINT *)((UCHAR *)buf + 0)))
+#define SL_SIZE_OF_PACKET(buf, i) (*((UINT *)((UCHAR *)buf + SL_EX_SIZEOF_NUM_PACKET + \
+ (i * (SL_EX_SIZEOF_LENGTH_PACKET + SL_EX_SIZEOF_ONE_PACKET)))))
+#define SL_ADDR_OF_PACKET(buf, i) (((UINT *)((UCHAR *)buf + SL_EX_SIZEOF_NUM_PACKET + \
+ SL_EX_SIZEOF_LENGTH_PACKET + \
+ (i * (SL_EX_SIZEOF_LENGTH_PACKET + SL_EX_SIZEOF_ONE_PACKET)))))
+#define SL_LEFT_FLAG(buf) SL_SIZE_OF_PACKET(buf, SL_MAX_PACKET_EXCHANGE)
+
+
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/SeLow/resource.h b/src/SeLow/resource.h
new file mode 100644
index 00000000..1fdda11a
--- /dev/null
+++ b/src/SeLow/resource.h
@@ -0,0 +1,84 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by Neo.rc
+//
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// 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 version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 101
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/