1 // SoftEther VPN Source Code - Developer Edition Master Branch
2 // Kernel Device Driver
3 
4 
5 // NDIS6.c
6 // Windows NDIS 6.2 Routine
7 
8 #include <GlobalConst.h>
9 
10 #define	NEO_DEVICE_DRIVER
11 
12 #include "Neo6.h"
13 
14 static UINT64 max_speed = NEO_MAX_SPEED_DEFAULT;
15 static bool keep_link = false;
16 static UINT reg_if_type = IF_TYPE_ETHERNET_CSMACD;
17 
18 BOOLEAN
19 PsGetVersion(
20 			 PULONG MajorVersion OPTIONAL,
21 			 PULONG MinorVersion OPTIONAL,
22 			 PULONG BuildNumber OPTIONAL,
23 			 PUNICODE_STRING CSDVersion OPTIONAL
24 			 );
25 
26 // Memory related
27 static NDIS_PHYSICAL_ADDRESS HighestAcceptableMax = NDIS_PHYSICAL_ADDRESS_CONST(-1, -1);
28 NDIS_HANDLE ndis_miniport_driver_handle = NULL;
29 
30 // Flag for whether Windows 8
31 bool g_is_win8 = false;
32 
33 // Win32 driver entry point
DriverEntry(DRIVER_OBJECT * DriverObject,UNICODE_STRING * RegistryPath)34 NDIS_STATUS DriverEntry(DRIVER_OBJECT *DriverObject, UNICODE_STRING *RegistryPath)
35 {
36 	NDIS_MINIPORT_DRIVER_CHARACTERISTICS miniport;
37 	ULONG os_major_ver = 0, os_minor_ver = 0;
38 	NDIS_STATUS ret;
39 
40 	// Initialize the Neo library
41 	if (NeoInit() == FALSE)
42 	{
43 		// Initialization Failed
44 		return STATUS_UNSUCCESSFUL;
45 	}
46 
47 	g_is_win8 = false;
48 
49 	// Get the OS version
50 	PsGetVersion(&os_major_ver, &os_minor_ver, NULL, NULL);
51 
52 	if (os_major_ver >= 7 || (os_major_ver == 6 && os_minor_ver >= 2))
53 	{
54 		// Windows 8
55 		g_is_win8 = true;
56 	}
57 
58 	// Register a NDIS miniport driver
59 	NeoZero(&miniport, sizeof(NDIS_MINIPORT_DRIVER_CHARACTERISTICS));
60 
61 	miniport.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_DRIVER_CHARACTERISTICS;
62 	miniport.Header.Revision = NDIS_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_2;
63 	miniport.Header.Size = NDIS_SIZEOF_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_2;
64 
65 	miniport.MajorNdisVersion = NEO_NDIS_MAJOR_VERSION;
66 	miniport.MinorNdisVersion = NEO_NDIS_MINOR_VERSION;
67 
68 	// Register the handler
69 	miniport.InitializeHandlerEx = NeoNdisInitEx;
70 	miniport.HaltHandlerEx = NeoNdisHaltEx;
71 	miniport.OidRequestHandler = NeoNdisOidRequest;
72 	miniport.ResetHandlerEx = NeoNdisResetEx;
73 	miniport.CheckForHangHandlerEx = NeoNdisCheckForHangEx;
74 	miniport.UnloadHandler = NeoNdisDriverUnload;
75 	miniport.SendNetBufferListsHandler = NeoNdisSendNetBufferLists;
76 
77 	miniport.SetOptionsHandler = NeoNdisSetOptions;
78 	miniport.PauseHandler = NeoNdisPause;
79 	miniport.RestartHandler = NeoNdisRestart;
80 	miniport.ReturnNetBufferListsHandler = NeoNdisReturnNetBufferLists;
81 	miniport.CancelSendHandler = NeoNdisCancelSend;
82 	miniport.DevicePnPEventNotifyHandler = NeoNdisDevicePnPEventNotify;
83 	miniport.ShutdownHandlerEx = NeoNdisShutdownEx;
84 	miniport.CancelOidRequestHandler = NeoNdisCancelOidRequest;
85 
86 	ret = NdisMRegisterMiniportDriver(DriverObject, RegistryPath,
87 		NULL, &miniport, &ndis_miniport_driver_handle);
88 
89 	if (NG(ret))
90 	{
91 		// Registration failure
92 		return STATUS_UNSUCCESSFUL;
93 	}
94 
95 	// Initialization success
96 	return STATUS_SUCCESS;
97 }
98 
NeoNdisSetOptions(NDIS_HANDLE NdisDriverHandle,NDIS_HANDLE DriverContext)99 NDIS_STATUS NeoNdisSetOptions(NDIS_HANDLE NdisDriverHandle, NDIS_HANDLE DriverContext)
100 {
101 	return NDIS_STATUS_SUCCESS;
102 }
103 
NeoNdisPause(NDIS_HANDLE MiniportAdapterContext,PNDIS_MINIPORT_PAUSE_PARAMETERS MiniportPauseParameters)104 NDIS_STATUS NeoNdisPause(NDIS_HANDLE MiniportAdapterContext, PNDIS_MINIPORT_PAUSE_PARAMETERS MiniportPauseParameters)
105 {
106 	UINT counter_dbg = 0;
107 
108 	ctx->Paused = true;
109 
110 	NeoLockPacketQueue();
111 	NeoUnlockPacketQueue();
112 
113 	// Wait for complete all tasks
114 	while (ctx->NumCurrentDispatch != 0)
115 	{
116 		NdisMSleep(10000);
117 		counter_dbg++;
118 		if (counter_dbg >= 1500)
119 		{
120 			break;
121 		}
122 	}
123 
124 	return NDIS_STATUS_SUCCESS;
125 }
126 
NeoNdisRestart(NDIS_HANDLE MiniportAdapterContext,PNDIS_MINIPORT_RESTART_PARAMETERS MiniportRestartParameters)127 NDIS_STATUS NeoNdisRestart(NDIS_HANDLE MiniportAdapterContext, PNDIS_MINIPORT_RESTART_PARAMETERS MiniportRestartParameters)
128 {
129 	ctx->Paused = false;
130 
131 	return NDIS_STATUS_SUCCESS;
132 }
133 
NeoNdisReturnNetBufferLists(NDIS_HANDLE MiniportAdapterContext,PNET_BUFFER_LIST NetBufferLists,ULONG ReturnFlags)134 void NeoNdisReturnNetBufferLists(NDIS_HANDLE MiniportAdapterContext, PNET_BUFFER_LIST NetBufferLists, ULONG ReturnFlags)
135 {
136 }
137 
NeoNdisCancelSend(NDIS_HANDLE MiniportAdapterContext,PVOID CancelId)138 void NeoNdisCancelSend(NDIS_HANDLE MiniportAdapterContext, PVOID CancelId)
139 {
140 	//NeoNdisCrash2(__LINE__, __LINE__, __LINE__, __LINE__);
141 }
142 
NeoNdisDevicePnPEventNotify(NDIS_HANDLE MiniportAdapterContext,PNET_DEVICE_PNP_EVENT NetDevicePnPEvent)143 void NeoNdisDevicePnPEventNotify(NDIS_HANDLE MiniportAdapterContext, PNET_DEVICE_PNP_EVENT NetDevicePnPEvent)
144 {
145 }
146 
NeoNdisShutdownEx(NDIS_HANDLE MiniportAdapterContext,NDIS_SHUTDOWN_ACTION ShutdownAction)147 void NeoNdisShutdownEx(NDIS_HANDLE MiniportAdapterContext, NDIS_SHUTDOWN_ACTION ShutdownAction)
148 {
149 }
150 
NeoNdisCancelOidRequest(NDIS_HANDLE MiniportAdapterContext,PVOID RequestId)151 void NeoNdisCancelOidRequest(NDIS_HANDLE MiniportAdapterContext, PVOID RequestId)
152 {
153 	//NeoNdisCrash2(__LINE__, __LINE__, __LINE__, __LINE__);
154 }
155 
156 // Initialization handler of adapter
NeoNdisInitEx(NDIS_HANDLE MiniportAdapterHandle,NDIS_HANDLE MiniportDriverContext,PNDIS_MINIPORT_INIT_PARAMETERS MiniportInitParameters)157 NDIS_STATUS NeoNdisInitEx(NDIS_HANDLE MiniportAdapterHandle,
158 						  NDIS_HANDLE MiniportDriverContext,
159 						  PNDIS_MINIPORT_INIT_PARAMETERS MiniportInitParameters)
160 {
161 	NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES attr;
162 	NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES gen;
163 	NDIS_PM_CAPABILITIES pnpcap;
164 
165 	if (ctx == NULL)
166 	{
167 		return NDIS_STATUS_FAILURE;
168 	}
169 
170 	if (ctx->NdisMiniportDriverHandle == NULL)
171 	{
172 		ctx->NdisMiniportDriverHandle = ndis_miniport_driver_handle;
173 	}
174 
175 	// Prevention of multiple start
176 	if (ctx->Initing != FALSE)
177 	{
178 		// Multiple started
179 		return NDIS_STATUS_FAILURE;
180 	}
181 	ctx->Initing = TRUE;
182 
183 	// Examine whether it has already been initialized
184 	if (ctx->Inited != FALSE)
185 	{
186 		// Driver is started on another instance already.
187 		// VPN driver can start only one instance per one service.
188 		// User can start multiple drivers with different instance ID
189 		return NDIS_STATUS_FAILURE;
190 	}
191 
192 	// Current value of the packet filter
193 	ctx->CurrentPacketFilter = NDIS_PACKET_TYPE_ALL_LOCAL | NDIS_PACKET_TYPE_BROADCAST | NDIS_PACKET_TYPE_DIRECTED | NDIS_PACKET_TYPE_ALL_FUNCTIONAL;
194 
195 	// Initialize the adapter information
196 	ctx->NdisMiniport = MiniportAdapterHandle;
197 	ctx->NdisContext = ctx;
198 	ctx->HardwareStatus = NdisHardwareStatusReady;
199 	ctx->Halting = FALSE;
200 	ctx->Connected = ctx->ConnectedOld = FALSE;
201 
202 	//if (keep_link == false)
203 	{
204 		ctx->ConnectedForce = TRUE;
205 	}
206 
207 	// Read the information from the registry
208 	if (NeoLoadRegistry() == FALSE)
209 	{
210 		// Failure
211 		ctx->Initing = FALSE;
212 		return NDIS_STATUS_FAILURE;
213 	}
214 
215 	// Register the device attributes
216 	NeoZero(&attr, sizeof(attr));
217 	attr.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES;
218 	attr.Header.Revision = NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;
219 	attr.Header.Size = sizeof(NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES);
220 	attr.AttributeFlags = NDIS_MINIPORT_ATTRIBUTES_NO_HALT_ON_SUSPEND;
221 	attr.InterfaceType = NdisInterfaceInternal;
222 	attr.MiniportAdapterContext = ctx->NdisContext;
223 
224 	NdisMSetMiniportAttributes(ctx->NdisMiniport, (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&attr);
225 
226 	NeoZero(&pnpcap, sizeof(pnpcap));
227 
228 	NeoZero(&gen, sizeof(gen));
229 	gen.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES;
230 	gen.Header.Revision = NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_2;
231 	gen.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_2;
232 	gen.MediaType = NdisMedium802_3;
233 	gen.PhysicalMediumType = NdisPhysicalMedium802_3;
234 	gen.MtuSize = NEO_MAX_PACKET_SIZE_ANNOUNCE - NEO_MIN_PACKET_SIZE;
235 	gen.MaxXmitLinkSpeed = gen.MaxRcvLinkSpeed = max_speed;
236 	gen.RcvLinkSpeed = gen.XmitLinkSpeed = max_speed;
237 	gen.MediaConnectState = MediaConnectStateDisconnected;
238 	gen.LookaheadSize = NEO_MAX_PACKET_SIZE_ANNOUNCE - NEO_MIN_PACKET_SIZE;
239 	gen.MacOptions = NDIS_MAC_OPTION_TRANSFERS_NOT_PEND | NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA | NDIS_MAC_OPTION_NO_LOOPBACK;
240 	gen.SupportedPacketFilters = NDIS_PACKET_TYPE_ALL_LOCAL | NDIS_PACKET_TYPE_BROADCAST | NDIS_PACKET_TYPE_DIRECTED | NDIS_PACKET_TYPE_ALL_FUNCTIONAL;
241 	gen.MaxMulticastListSize = NEO_MAX_MULTICASE;
242 	gen.MacAddressLength = NEO_MAC_ADDRESS_SIZE;
243 	NeoCopy(gen.PermanentMacAddress, ctx->MacAddress, NEO_MAC_ADDRESS_SIZE);
244 	NeoCopy(gen.CurrentMacAddress, ctx->MacAddress, NEO_MAC_ADDRESS_SIZE);
245 	gen.AccessType = NET_IF_ACCESS_BROADCAST;
246 	gen.DirectionType = NET_IF_DIRECTION_SENDRECEIVE;
247 	gen.ConnectionType = NET_IF_CONNECTION_DEDICATED;
248 	gen.IfType = reg_if_type;
249 	gen.IfConnectorPresent = FALSE;
250 	gen.SupportedStatistics =
251 		NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_RCV |
252 		NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_RCV |
253 		NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_RCV |
254 		NDIS_STATISTICS_FLAGS_VALID_BYTES_RCV |
255 		NDIS_STATISTICS_FLAGS_VALID_RCV_DISCARDS |
256 		NDIS_STATISTICS_FLAGS_VALID_RCV_ERROR |
257 		NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_XMIT |
258 		NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_XMIT |
259 		NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_XMIT |
260 		NDIS_STATISTICS_FLAGS_VALID_BYTES_XMIT |
261 		NDIS_STATISTICS_FLAGS_VALID_XMIT_ERROR |
262 		NDIS_STATISTICS_FLAGS_VALID_XMIT_DISCARDS |
263 		NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_RCV |
264 		NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_RCV |
265 		NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_RCV |
266 		NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_XMIT |
267 		NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_XMIT |
268 		NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_XMIT;
269 	gen.SupportedPauseFunctions = NdisPauseFunctionsUnsupported;
270 	gen.AutoNegotiationFlags = NDIS_LINK_STATE_XMIT_LINK_SPEED_AUTO_NEGOTIATED |
271 		NDIS_LINK_STATE_RCV_LINK_SPEED_AUTO_NEGOTIATED |
272 		NDIS_LINK_STATE_DUPLEX_AUTO_NEGOTIATED |
273 		NDIS_LINK_STATE_PAUSE_FUNCTIONS_AUTO_NEGOTIATED;
274 	gen.SupportedOidList = SupportedOids;
275 	gen.SupportedOidListLength = sizeof(SupportedOids);
276 
277 	NeoZero(&pnpcap, sizeof(pnpcap));
278 	pnpcap.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
279 	pnpcap.Header.Revision = NDIS_PM_CAPABILITIES_REVISION_1;
280 	pnpcap.Header.Size = NDIS_SIZEOF_NDIS_PM_CAPABILITIES_REVISION_1;
281 	pnpcap.MinMagicPacketWakeUp = NdisDeviceStateUnspecified;
282 	pnpcap.MinPatternWakeUp  = NdisDeviceStateUnspecified;
283 	pnpcap.MinLinkChangeWakeUp = NdisDeviceStateUnspecified;
284 	gen.PowerManagementCapabilitiesEx = &pnpcap;
285 
286 	NdisMSetMiniportAttributes(ctx->NdisMiniport, (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&gen);
287 
288 	// Initialize the received packet array
289 	NeoInitPacketArray();
290 
291 	// Initialize the control device
292 	NeoInitControlDevice();
293 
294 	// Start the adapter
295 	NeoStartAdapter();
296 
297 	// Flag setting
298 	ctx->Initing = FALSE;
299 	ctx->Inited = TRUE;
300 
301 	// Notify the connection state
302 	NeoSetConnectState(FALSE);
303 
304 	return NDIS_STATUS_SUCCESS;
305 }
306 
307 // Open the device
NeoNdisOnOpen(IRP * irp,IO_STACK_LOCATION * stack)308 BOOL NeoNdisOnOpen(IRP *irp, IO_STACK_LOCATION *stack)
309 {
310 	char name[MAX_SIZE];
311 
312 	if (ctx == NULL)
313 	{
314 		return FALSE;
315 	}
316 
317 	if (ctx->Opened)
318 	{
319 		// Another client is connected already
320 		return FALSE;
321 	}
322 	ctx->Opened = TRUE;
323 
324 	// Initialize the event name
325 	sprintf(name, NDIS_NEO_EVENT_NAME, ctx->HardwareID);
326 
327 	// Register a Event
328 	ctx->Event = NeoNewEvent(name);
329 	if (ctx->Event == NULL)
330 	{
331 		ctx->Opened = FALSE;
332 		return FALSE;
333 	}
334 
335 	// Set the connection state
336 	NeoSetConnectState(TRUE);
337 
338 	return TRUE;
339 }
340 
341 // Close the device
NeoNdisOnClose(IRP * irp,IO_STACK_LOCATION * stack)342 BOOL NeoNdisOnClose(IRP *irp, IO_STACK_LOCATION *stack)
343 {
344 	NEO_EVENT *free_event = NULL;
345 	if (ctx == NULL)
346 	{
347 		return FALSE;
348 	}
349 
350 	if (ctx->Opened == FALSE)
351 	{
352 		// Client is not connected
353 		return FALSE;
354 	}
355 	ctx->Opened = FALSE;
356 
357 	NeoLockPacketQueue();
358 	{
359 		// Release the event
360 		free_event = ctx->Event;
361 		ctx->Event = NULL;
362 
363 		// Release all packets
364 		NeoClearPacketQueue(true);
365 	}
366 	NeoUnlockPacketQueue();
367 
368 	if (free_event != NULL)
369 	{
370 		NeoFreeEvent(free_event);
371 	}
372 
373 	NeoSetConnectState(FALSE);
374 
375 	return TRUE;
376 }
377 
378 // Crash 2
NeoNdisCrash2(UINT a,UINT b,UINT c,UINT d)379 void NeoNdisCrash2(UINT a, UINT b, UINT c, UINT d)
380 {
381 	KeBugCheckEx(0x00000061, (ULONG_PTR)a, (ULONG_PTR)b, (ULONG_PTR)c, (ULONG_PTR)d);
382 }
383 
384 // Crash
NeoNdisCrash()385 void NeoNdisCrash()
386 {
387 	NEO_QUEUE *q;
388 	q = (NEO_QUEUE *)0xACACACAC;
389 	q->Size = 128;
390 	NeoCopy(q->Buf, "ABCDEFG", 8);
391 }
392 
393 // Dispatch table for control
NeoNdisDispatch(DEVICE_OBJECT * DeviceObject,IRP * Irp)394 NTSTATUS NeoNdisDispatch(DEVICE_OBJECT *DeviceObject, IRP *Irp)
395 {
396 	NTSTATUS status;
397 	IO_STACK_LOCATION *stack;
398 	void *buf;
399 	BOOL ok;
400 	status = STATUS_SUCCESS;
401 
402 	if (ctx == NULL)
403 	{
404 		return NDIS_STATUS_FAILURE;
405 	}
406 
407 	InterlockedIncrement(&ctx->NumCurrentDispatch);
408 
409 	// Get the IRP stack
410 	stack = IoGetCurrentIrpStackLocation(Irp);
411 
412 	// Initialize the number of bytes
413 	Irp->IoStatus.Information = 0;
414 	Irp->IoStatus.Status = STATUS_SUCCESS;
415 
416 	buf = Irp->UserBuffer;
417 
418 	if (ctx->Halting != FALSE)
419 	{
420 		// Device driver is terminating
421 		Irp->IoStatus.Information = STATUS_UNSUCCESSFUL;
422 		InterlockedDecrement(&ctx->NumCurrentDispatch);
423 
424 		IoCompleteRequest(Irp, IO_NO_INCREMENT);
425 
426 		return STATUS_SUCCESS;
427 	}
428 
429 	// Branch to each operation
430 	switch (stack->MajorFunction)
431 	{
432 	case IRP_MJ_CREATE:
433 		// Device is opened
434 		if (NeoNdisOnOpen(Irp, stack) == FALSE)
435 		{
436 			Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
437 			status = STATUS_UNSUCCESSFUL;
438 		}
439 		break;
440 
441 	case IRP_MJ_CLOSE:
442 		// Device is closed
443 		if (NeoNdisOnClose(Irp, stack) == FALSE)
444 		{
445 			Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
446 			status = STATUS_UNSUCCESSFUL;
447 		}
448 		break;
449 
450 	case IRP_MJ_READ:
451 		// Read (Reading of the received packet)
452 		ok = false;
453 		if (buf != NULL)
454 		{
455 			if (ctx->Opened && ctx->Inited)
456 			{
457 				if (stack->Parameters.Read.Length == NEO_EXCHANGE_BUFFER_SIZE)
458 				{
459 					// Address check
460 					bool check_ok = true;
461 					__try
462 					{
463 						ProbeForWrite(buf, NEO_EXCHANGE_BUFFER_SIZE, 1);
464 					}
465 					__except (EXCEPTION_EXECUTE_HANDLER)
466 					{
467 						check_ok = false;
468 					}
469 
470 					if (check_ok)
471 					{
472 						// Address check
473 						MDL *mdl = IoAllocateMdl(buf, NEO_EXCHANGE_BUFFER_SIZE, false, false, NULL);
474 
475 						if (mdl != NULL)
476 						{
477 							MmProbeAndLockPages(mdl, KernelMode, IoWriteAccess);
478 						}
479 
480 						// Read
481 						NeoRead(buf);
482 						Irp->IoStatus.Information = NEO_EXCHANGE_BUFFER_SIZE;
483 						ok = true;
484 
485 						if (mdl != NULL)
486 						{
487 							MmUnlockPages(mdl);
488 							IoFreeMdl(mdl);
489 						}
490 					}
491 				}
492 			}
493 		}
494 		if (ok == FALSE)
495 		{
496 			// An error occurred
497 			Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
498 			status = STATUS_UNSUCCESSFUL;
499 		}
500 		break;
501 
502 	case IRP_MJ_WRITE:
503 		// Write (Writing of a transmission packet)
504 		ok = false;
505 		if (buf != NULL)
506 		{
507 			if (ctx->Opened && ctx->Inited)
508 			{
509 				if (stack->Parameters.Write.Length == NEO_EXCHANGE_BUFFER_SIZE)
510 				{
511 					// Address check
512 					bool check_ok = true;
513 					__try
514 					{
515 						ProbeForRead(buf, NEO_EXCHANGE_BUFFER_SIZE, 1);
516 					}
517 					__except (EXCEPTION_EXECUTE_HANDLER)
518 					{
519 						check_ok = false;
520 					}
521 
522 					if (check_ok)
523 					{
524 						// Address check
525 						MDL *mdl = IoAllocateMdl(buf, NEO_EXCHANGE_BUFFER_SIZE, false, false, NULL);
526 
527 						if (mdl != NULL)
528 						{
529 							MmProbeAndLockPages(mdl, KernelMode, IoReadAccess);
530 						}
531 						__try
532 						{
533 							ProbeForRead(buf, NEO_EXCHANGE_BUFFER_SIZE, 1);
534 						}
535 						__except (EXCEPTION_EXECUTE_HANDLER)
536 						{
537 							check_ok = false;
538 						}
539 						if (check_ok) {
540 							// Write
541 							NeoWrite(buf);
542 							Irp->IoStatus.Information = stack->Parameters.Write.Length;
543 							ok = true;
544 
545 							if (mdl != NULL)
546 							{
547 							MmUnlockPages(mdl);
548 							IoFreeMdl(mdl);
549 							}
550 						}
551 					}
552 				}
553 			}
554 		}
555 		if (ok == FALSE)
556 		{
557 			// An error occurred
558 			Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
559 			status = STATUS_UNSUCCESSFUL;
560 		}
561 		break;
562 	}
563 
564 	InterlockedDecrement(&ctx->NumCurrentDispatch);
565 
566 	IoCompleteRequest(Irp, IO_NO_INCREMENT);
567 
568 	return STATUS_SUCCESS;
569 }
570 
571 // Initialize the control device
NeoInitControlDevice()572 void NeoInitControlDevice()
573 {
574 	char name_kernel[MAX_SIZE];
575 	char name_win32[MAX_SIZE];
576 	UNICODE *unicode_kernel, *unicode_win32;
577 	DEVICE_OBJECT *control_device_object;
578 	NDIS_HANDLE ndis_control_handle;
579 	NDIS_DEVICE_OBJECT_ATTRIBUTES t;
580 
581 	if (ctx == NULL)
582 	{
583 		return;
584 	}
585 
586 	// Initialize the dispatch table
587 	NeoZero(ctx->DispatchTable, sizeof(PDRIVER_DISPATCH) * IRP_MJ_MAXIMUM_FUNCTION);
588 
589 	// Register the handler
590 	ctx->DispatchTable[IRP_MJ_CREATE] =
591 		ctx->DispatchTable[IRP_MJ_CLOSE] =
592 		ctx->DispatchTable[IRP_MJ_READ] =
593 		ctx->DispatchTable[IRP_MJ_WRITE] =
594 		ctx->DispatchTable[IRP_MJ_DEVICE_CONTROL] = NeoNdisDispatch;
595 	ctx->Opened = FALSE;
596 	ctx->Paused = FALSE;
597 
598 	// Generate the device name
599 	sprintf(name_kernel, NDIS_NEO_DEVICE_NAME, ctx->HardwareID);
600 	unicode_kernel = NewUnicode(name_kernel);
601 	sprintf(name_win32, NDIS_NEO_DEVICE_NAME_WIN32, ctx->HardwareID);
602 	unicode_win32 = NewUnicode(name_win32);
603 
604 	// Register the device
605 	NeoZero(&t, sizeof(t));
606 	t.Header.Type = NDIS_OBJECT_TYPE_DEVICE_OBJECT_ATTRIBUTES;
607 	t.Header.Revision = NDIS_DEVICE_OBJECT_ATTRIBUTES_REVISION_1;
608 	t.Header.Size = NDIS_SIZEOF_DEVICE_OBJECT_ATTRIBUTES_REVISION_1;
609 	t.DeviceName = GetUnicode(unicode_kernel);
610 	t.SymbolicName = GetUnicode(unicode_win32);
611 	t.MajorFunctions = ctx->DispatchTable;
612 
613 	NdisRegisterDeviceEx(ndis_miniport_driver_handle, &t,
614 		&control_device_object,
615 		&ndis_control_handle);
616 
617 	ctx->NdisControlDevice = control_device_object;
618 	ctx->NdisControl = ndis_control_handle;
619 
620 	// Initialize the display name
621 	if (strlen(ctx->HardwareID) > 11)
622 	{
623 		sprintf(ctx->HardwarePrintableID, NDIS_NEO_HARDWARE_ID, ctx->HardwareID_Raw + 11);
624 	}
625 	else
626 	{
627 		sprintf(ctx->HardwarePrintableID, NDIS_NEO_HARDWARE_ID, ctx->HardwareID_Raw);
628 	}
629 }
630 
631 // Release the control device
NeoFreeControlDevice()632 void NeoFreeControlDevice()
633 {
634 	if (ctx == NULL)
635 	{
636 		return;
637 	}
638 
639 	if (ctx->Opened != FALSE)
640 	{
641 		// Delete the event
642 		NeoSet(ctx->Event);
643 		NeoFreeEvent(ctx->Event);
644 		ctx->Event = NULL;
645 		ctx->Opened = FALSE;
646 	}
647 
648 	// Delete the device
649 	NdisDeregisterDeviceEx(ctx->NdisControl);
650 }
651 
652 
653 // Read the information from the registry
NeoLoadRegistry()654 BOOL NeoLoadRegistry()
655 {
656 	void *buf;
657 	NDIS_STATUS ret;
658 	UINT size;
659 	NDIS_HANDLE config;
660 	NDIS_CONFIGURATION_PARAMETER *param;
661 	UNICODE *name;
662 	ANSI_STRING ansi;
663 	UNICODE_STRING *unicode;
664 	UINT64 speed;
665 	BOOL keep;
666 	NDIS_CONFIGURATION_OBJECT config_obj;
667 
668 	// Get the Config handle
669 	NeoZero(&config_obj, sizeof(config_obj));
670 	config_obj.Header.Type = NDIS_OBJECT_TYPE_CONFIGURATION_OBJECT;
671 	config_obj.Header.Revision = NDIS_CONFIGURATION_OBJECT_REVISION_1;
672 	config_obj.Header.Size = NDIS_SIZEOF_CONFIGURATION_OBJECT_REVISION_1;
673 	config_obj.NdisHandle = ctx->NdisMiniport;
674 
675 	ret = NdisOpenConfigurationEx(&config_obj, &config);
676 	if (NG(ret))
677 	{
678 		// Failure
679 		return FALSE;
680 	}
681 
682 	// Read the MAC address
683 	NdisReadNetworkAddress(&ret, &buf, &size, config);
684 	if (NG(ret))
685 	{
686 		// Failure
687 		NdisCloseConfiguration(config);
688 		return FALSE;
689 	}
690 
691 	// Copy the MAC address
692 	if (size != NEO_MAC_ADDRESS_SIZE)
693 	{
694 		// Invalid size
695 		NdisCloseConfiguration(config);
696 		return FALSE;
697 	}
698 	NeoCopy(ctx->MacAddress, buf, NEO_MAC_ADDRESS_SIZE);
699 
700 	if (ctx->MacAddress[0] == 0x00 &&
701 		ctx->MacAddress[1] == 0x00 &&
702 		ctx->MacAddress[2] == 0x01 &&
703 		ctx->MacAddress[3] == 0x00 &&
704 		ctx->MacAddress[4] == 0x00 &&
705 		ctx->MacAddress[5] == 0x01)
706 	{
707 		// Special MAC address
708 		UINT ptr32 = (UINT)((UINT64)ctx);
709 		LARGE_INTEGER current_time;
710 		UCHAR *current_time_bytes;
711 
712 		KeQuerySystemTime(&current_time);
713 
714 		current_time_bytes = (UCHAR *)&current_time;
715 
716 		ctx->MacAddress[0] = 0x00;
717 		ctx->MacAddress[1] = 0xAD;
718 		ctx->MacAddress[2] = ((UCHAR *)(&ptr32))[0];
719 		ctx->MacAddress[3] = ((UCHAR *)(&ptr32))[1];
720 		ctx->MacAddress[4] = ((UCHAR *)(&ptr32))[2];
721 		ctx->MacAddress[5] = ((UCHAR *)(&ptr32))[3];
722 
723 		ctx->MacAddress[2] ^= current_time_bytes[0];
724 		ctx->MacAddress[3] ^= current_time_bytes[1];
725 		ctx->MacAddress[4] ^= current_time_bytes[2];
726 		ctx->MacAddress[5] ^= current_time_bytes[3];
727 
728 		ctx->MacAddress[2] ^= current_time_bytes[4];
729 		ctx->MacAddress[3] ^= current_time_bytes[5];
730 		ctx->MacAddress[4] ^= current_time_bytes[6];
731 		ctx->MacAddress[5] ^= current_time_bytes[7];
732 	}
733 
734 	// Initialize the key name of the device name
735 	name = NewUnicode("MatchingDeviceId");
736 
737 	// Read the hardware ID
738 	NdisReadConfiguration(&ret, &param, config, GetUnicode(name), NdisParameterString);
739 	FreeUnicode(name);
740 	if (NG(ret))
741 	{
742 		// Failure
743 		NdisCloseConfiguration(config);
744 		return FALSE;
745 	}
746 	// Type checking
747 	if (param->ParameterType != NdisParameterString)
748 	{
749 		// Failure
750 		NdisCloseConfiguration(config);
751 		return FALSE;
752 	}
753 	unicode = &param->ParameterData.StringData;
754 
755 	// Prepare a buffer for ANSI string
756 	NeoZero(&ansi, sizeof(ANSI_STRING));
757 	ansi.MaximumLength = MAX_SIZE - 1;
758 	ansi.Buffer = NeoZeroMalloc(MAX_SIZE);
759 
760 	// Convert to ANSI string
761 	NdisUnicodeStringToAnsiString(&ansi, unicode);
762 	// Copy
763 	strcpy(ctx->HardwareID, ansi.Buffer);
764 	strcpy(ctx->HardwareID_Raw, ctx->HardwareID);
765 	// Convert to upper case
766 	_strupr(ctx->HardwareID);
767 	// Release the memory
768 	NeoFree(ansi.Buffer);
769 
770 	// Read the bit rate
771 	name = NewUnicode("MaxSpeed");
772 	NdisReadConfiguration(&ret, &param, config, GetUnicode(name), NdisParameterInteger);
773 	FreeUnicode(name);
774 
775 	if (NG(ret) || param->ParameterType != NdisParameterInteger)
776 	{
777 		speed = NEO_MAX_SPEED_DEFAULT;
778 	}
779 	else
780 	{
781 		speed = (UINT64)param->ParameterData.IntegerData * 1000000ULL;
782 	}
783 
784 	max_speed = speed;
785 
786 	// Read the link keeping flag
787 	name = NewUnicode("KeepLink");
788 	NdisReadConfiguration(&ret, &param, config, GetUnicode(name), NdisParameterInteger);
789 	FreeUnicode(name);
790 
791 	if (NG(ret) || param->ParameterType != NdisParameterInteger)
792 	{
793 		keep = false;
794 	}
795 	else
796 	{
797 		keep = (param->ParameterData.IntegerData == 0 ? false : true);
798 	}
799 
800 	keep_link = keep;
801 
802 	// Read the *IfType value
803 	name = NewUnicode("*IfType");
804 	NdisReadConfiguration(&ret, &param, config, GetUnicode(name), NdisParameterInteger);
805 	FreeUnicode(name);
806 
807 	if (NG(ret) || param->ParameterType != NdisParameterInteger)
808 	{
809 		reg_if_type = IF_TYPE_ETHERNET_CSMACD;
810 	}
811 	else
812 	{
813 		reg_if_type = param->ParameterData.IntegerData;
814 	}
815 
816 	// Close the config handle
817 	NdisCloseConfiguration(config);
818 
819 	return TRUE;
820 }
821 
822 // Unload the driver
NeoNdisDriverUnload(PDRIVER_OBJECT DriverObject)823 VOID NeoNdisDriverUnload(PDRIVER_OBJECT DriverObject)
824 {
825 	NdisMDeregisterMiniportDriver(ndis_miniport_driver_handle);
826 }
827 
828 // Stop handler of adapter
NeoNdisHaltEx(NDIS_HANDLE MiniportAdapterContext,NDIS_HALT_ACTION HaltAction)829 void NeoNdisHaltEx(NDIS_HANDLE MiniportAdapterContext, NDIS_HALT_ACTION HaltAction)
830 {
831 	NEO_EVENT *free_event = NULL;
832 	UINT counter_dbg = 0;
833 	if (ctx == NULL)
834 	{
835 		return;
836 	}
837 
838 	if (ctx->Halting != FALSE)
839 	{
840 		// That has already been stopped
841 		return;
842 	}
843 	ctx->Halting = TRUE;
844 
845 	ctx->Opened = FALSE;
846 
847 	NeoLockPacketQueue();
848 	{
849 		// Release the event
850 		free_event = ctx->Event;
851 		ctx->Event = NULL;
852 
853 		// Release all packets
854 		NeoClearPacketQueue(true);
855 	}
856 	NeoUnlockPacketQueue();
857 
858 	if (free_event != NULL)
859 	{
860 		NeoSet(free_event);
861 	}
862 
863 	// Wait for complete all tasks
864 	while (ctx->NumCurrentDispatch != 0)
865 	{
866 		NdisMSleep(10000);
867 		counter_dbg++;
868 		if (counter_dbg >= 1500)
869 		{
870 			break;
871 		}
872 	}
873 
874 	if (free_event != NULL)
875 	{
876 		NeoFreeEvent(free_event);
877 	}
878 
879 	// Delete the control device
880 	NeoFreeControlDevice();
881 
882 	// Stop the adapter
883 	NeoStopAdapter();
884 
885 	// Release the packet array
886 	NeoFreePacketArray();
887 
888 	// Complete to stop
889 	ctx->Initing = ctx->Inited = FALSE;
890 	ctx->Connected = ctx->ConnectedForce = ctx->ConnectedOld = FALSE;
891 	ctx->Halting = FALSE;
892 
893 	// Shutdown of Neo
894 	NeoShutdown();
895 }
896 
897 // Reset handler of adapter
NeoNdisResetEx(NDIS_HANDLE MiniportAdapterContext,PBOOLEAN AddressingReset)898 NDIS_STATUS NeoNdisResetEx(NDIS_HANDLE MiniportAdapterContext, PBOOLEAN AddressingReset)
899 {
900 	return NDIS_STATUS_SUCCESS;
901 }
902 
903 // Hang-up check handler of adapter
NeoNdisCheckForHangEx(NDIS_HANDLE MiniportAdapterContext)904 BOOLEAN NeoNdisCheckForHangEx(NDIS_HANDLE MiniportAdapterContext)
905 {
906 	return FALSE;
907 }
908 
909 // OID request handler
NeoNdisOidRequest(NDIS_HANDLE MiniportAdapterContext,PNDIS_OID_REQUEST OidRequest)910 NDIS_STATUS NeoNdisOidRequest(NDIS_HANDLE MiniportAdapterContext,
911 							  PNDIS_OID_REQUEST OidRequest)
912 {
913 	NDIS_STATUS ret = STATUS_UNSUCCESSFUL;
914 	ULONG dummy = 0;
915 
916 	switch (OidRequest->RequestType)
917 	{
918 	case NdisRequestQueryInformation:
919 	case NdisRequestQueryStatistics:
920 		ret = NeoNdisQuery(MiniportAdapterContext,
921 			OidRequest->DATA.QUERY_INFORMATION.Oid,
922 			OidRequest->DATA.QUERY_INFORMATION.InformationBuffer,
923 			OidRequest->DATA.QUERY_INFORMATION.InformationBufferLength,
924 			&OidRequest->DATA.QUERY_INFORMATION.BytesWritten,
925 			&OidRequest->DATA.QUERY_INFORMATION.BytesNeeded);
926 		break;
927 
928 	case NdisRequestSetInformation:
929 		ret = NeoNdisSet(MiniportAdapterContext,
930 			OidRequest->DATA.SET_INFORMATION.Oid,
931 			OidRequest->DATA.SET_INFORMATION.InformationBuffer,
932 			OidRequest->DATA.SET_INFORMATION.InformationBufferLength,
933 			&dummy,
934 			&OidRequest->DATA.SET_INFORMATION.BytesNeeded);
935 		break;
936 
937 	default:
938 		ret = NDIS_STATUS_NOT_SUPPORTED;
939 		break;
940 	}
941 
942 	return ret;
943 }
944 
945 
946 // Information acquisition handler of adapter
NeoNdisQuery(NDIS_HANDLE MiniportAdapterContext,NDIS_OID Oid,void * InformationBuffer,ULONG InformationBufferLength,ULONG * BytesWritten,ULONG * BytesNeeded)947 NDIS_STATUS NeoNdisQuery(NDIS_HANDLE MiniportAdapterContext,
948 					NDIS_OID Oid,
949 					void *InformationBuffer,
950 					ULONG InformationBufferLength,
951 					ULONG *BytesWritten,
952 					ULONG *BytesNeeded)
953 {
954 	NDIS_MEDIUM media;
955 	void *buf;
956 	UINT value32;
957 	USHORT value16;
958 	UINT size;
959 	NDIS_STATISTICS_INFO stat;
960 	NDIS_INTERRUPT_MODERATION_PARAMETERS intp;
961 
962 	if (ctx == NULL)
963 	{
964 		return NDIS_STATUS_FAILURE;
965 	}
966 
967 	// Initialization
968 	size = sizeof(UINT);
969 	value32 = value16 = 0;
970 	buf = &value32;
971 
972 	// Branch processing
973 	switch (Oid)
974 	{
975 	case OID_GEN_SUPPORTED_LIST:
976 		// Return a list of supported OID
977 		buf = SupportedOids;
978 		size = sizeof(SupportedOids);
979 		break;
980 
981 	case OID_GEN_MAC_OPTIONS:
982 		// Ethernet option
983 		value32 = NDIS_MAC_OPTION_TRANSFERS_NOT_PEND | NDIS_MAC_OPTION_RECEIVE_SERIALIZED |
984 			NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA | NDIS_MAC_OPTION_NO_LOOPBACK;
985 		break;
986 
987 	case OID_GEN_HARDWARE_STATUS:
988 		// Hardware state
989 		buf = &ctx->HardwareStatus;
990 		size = sizeof(NDIS_HARDWARE_STATUS);
991 		break;
992 
993 	case OID_GEN_MEDIA_SUPPORTED:
994 	case OID_GEN_MEDIA_IN_USE:
995 		// Type of media
996 		media = NdisMedium802_3;
997 		buf = &media;
998 		size = sizeof(NDIS_MEDIUM);
999 		break;
1000 
1001 	case OID_GEN_CURRENT_LOOKAHEAD:
1002 	case OID_GEN_MAXIMUM_LOOKAHEAD:
1003 		// Read-ahead available size
1004 		value32 = NEO_MAX_PACKET_SIZE_ANNOUNCE - NEO_MIN_PACKET_SIZE;
1005 		break;
1006 
1007 	case OID_GEN_MAXIMUM_FRAME_SIZE:
1008 		// Maximum frame size
1009 		value32 = NEO_MAX_PACKET_SIZE_ANNOUNCE - NEO_MIN_PACKET_SIZE;
1010 		break;
1011 
1012 	case OID_GEN_MAXIMUM_TOTAL_SIZE:
1013 	case OID_GEN_TRANSMIT_BLOCK_SIZE:
1014 	case OID_GEN_RECEIVE_BLOCK_SIZE:
1015 		// Maximum packet size
1016 		value32 = NEO_MAX_PACKET_SIZE_ANNOUNCE;
1017 		break;
1018 
1019 	case OID_GEN_TRANSMIT_BUFFER_SPACE:
1020 	case OID_GEN_RECEIVE_BUFFER_SPACE:
1021 		// Buffer size
1022 		value32 = NEO_MAX_PACKET_SIZE_ANNOUNCE * NEO_MAX_PACKET_EXCHANGE;
1023 		break;
1024 
1025 	case OID_GEN_LINK_SPEED:
1026 		// Communication speed
1027 		value32 = (UINT)(max_speed / 100);
1028 		break;
1029 
1030 	case OID_GEN_VENDOR_ID:
1031 		// Vendor ID
1032 		NeoCopy(&value32, ctx->MacAddress, 3);
1033 		value32 &= 0xFFFFFF00;
1034 		value32 |= 0x01;
1035 		break;
1036 
1037 	case OID_GEN_VENDOR_DESCRIPTION:
1038 		// Hardware ID
1039 		buf = ctx->HardwarePrintableID;
1040 		size = (UINT)strlen(ctx->HardwarePrintableID) + 1;
1041 		break;
1042 
1043 	case OID_GEN_DRIVER_VERSION:
1044 		// Driver version
1045 		value16 = ((USHORT)NEO_NDIS_MAJOR_VERSION << 8) | NEO_NDIS_MINOR_VERSION;
1046 		buf = &value16;
1047 		size = sizeof(USHORT);
1048 		break;
1049 
1050 	case OID_GEN_VENDOR_DRIVER_VERSION:
1051 		// Vendor driver version
1052 		value16 = ((USHORT)NEO_NDIS_MAJOR_VERSION << 8) | NEO_NDIS_MINOR_VERSION;
1053 		buf = &value16;
1054 		size = sizeof(USHORT);
1055 		break;
1056 
1057 	case OID_802_3_PERMANENT_ADDRESS:
1058 	case OID_802_3_CURRENT_ADDRESS:
1059 		// MAC address
1060 		buf = ctx->MacAddress;
1061 		size = NEO_MAC_ADDRESS_SIZE;
1062 		break;
1063 
1064 	case OID_802_3_MAXIMUM_LIST_SIZE:
1065 		// Number of multicast
1066 		value32 = NEO_MAX_MULTICASE;
1067 		break;
1068 
1069 	case OID_GEN_MAXIMUM_SEND_PACKETS:
1070 		// Number of packets that can be sent at a time
1071 		value32 = NEO_MAX_PACKET_EXCHANGE;
1072 		break;
1073 
1074 	case OID_GEN_XMIT_OK:
1075 		// Number of packets sent
1076 		value32 = ctx->Status.NumPacketSend;
1077 		break;
1078 
1079 	case OID_GEN_RCV_OK:
1080 		// Number of received packets
1081 		value32 = ctx->Status.NumPacketRecv;
1082 		break;
1083 
1084 	case OID_GEN_XMIT_ERROR:
1085 		// Number of transmission error packets
1086 		value32 = ctx->Status.NumPacketSendError;
1087 		break;
1088 
1089 	case OID_GEN_RCV_ERROR:
1090 		// Number of error packets received
1091 		value32 = ctx->Status.NumPacketRecvError;
1092 		break;
1093 
1094 	case OID_GEN_RCV_NO_BUFFER:
1095 		// Number of reception buffer shortage occurrences
1096 		value32 = ctx->Status.NumPacketRecvNoBuffer;
1097 		break;
1098 
1099 	case OID_802_3_RCV_ERROR_ALIGNMENT:
1100 		// Number of errors
1101 		value32 = 0;
1102 		break;
1103 
1104 	case OID_GEN_MEDIA_CONNECT_STATUS:
1105 		// Cable connection state
1106 		NeoCheckConnectState();
1107 		if (keep_link == false)
1108 		{
1109 			value32 = ctx->Connected ? NdisMediaStateConnected : NdisMediaStateDisconnected;
1110 		}
1111 		else
1112 		{
1113 			value32 = NdisMediaStateConnected;
1114 		}
1115 		break;
1116 
1117 	case OID_802_3_XMIT_ONE_COLLISION:
1118 	case OID_802_3_XMIT_MORE_COLLISIONS:
1119 		// Number of collisions
1120 		value32 = 0;
1121 		break;
1122 
1123 	case OID_GEN_CURRENT_PACKET_FILTER:
1124 		// Current settings of the packet filter
1125 		value32 = ctx->CurrentPacketFilter;
1126 		break;
1127 
1128 /*	case OID_GEN_PROTOCOL_OPTIONS:
1129 		// Current value of the protocol option
1130 		value32 = ctx->CurrentProtocolOptions;
1131 		break;*/
1132 
1133 	case OID_GEN_STATISTICS:
1134 		// Statistics (NDIS 6.0)
1135 		NeoZero(&stat, sizeof(stat));
1136 		buf = &stat;
1137 		size = sizeof(stat);
1138 
1139 		stat.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
1140 		stat.Header.Revision = NDIS_STATISTICS_INFO_REVISION_1;
1141 		stat.Header.Size = NDIS_SIZEOF_STATISTICS_INFO_REVISION_1;
1142 		stat.SupportedStatistics =
1143 			NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_RCV |
1144 			NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_RCV |
1145 			NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_RCV |
1146 			NDIS_STATISTICS_FLAGS_VALID_BYTES_RCV |
1147 			NDIS_STATISTICS_FLAGS_VALID_RCV_DISCARDS |
1148 			NDIS_STATISTICS_FLAGS_VALID_RCV_ERROR |
1149 			NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_XMIT |
1150 			NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_XMIT |
1151 			NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_XMIT |
1152 			NDIS_STATISTICS_FLAGS_VALID_BYTES_XMIT |
1153 			NDIS_STATISTICS_FLAGS_VALID_XMIT_ERROR |
1154 			NDIS_STATISTICS_FLAGS_VALID_XMIT_DISCARDS |
1155 			NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_RCV |
1156 			NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_RCV |
1157 			NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_RCV |
1158 			NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_XMIT |
1159 			NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_XMIT |
1160 			NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_XMIT;
1161 
1162 		stat.ifInErrors = ctx->Status.Int64NumRecvError;
1163 		stat.ifHCInOctets = ctx->Status.Int64BytesRecvTotal;
1164 		stat.ifHCInUcastPkts = ctx->Status.Int64NumRecvUnicast;
1165 		stat.ifHCInBroadcastPkts = ctx->Status.Int64NumRecvBroadcast;
1166 		stat.ifHCOutOctets = ctx->Status.Int64BytesSendTotal;
1167 		stat.ifHCOutUcastPkts = ctx->Status.Int64NumSendUnicast;
1168 		stat.ifHCOutBroadcastPkts = ctx->Status.Int64NumSendBroadcast;
1169 		stat.ifOutErrors = ctx->Status.Int64NumSendError;
1170 		stat.ifHCInUcastOctets = ctx->Status.Int64BytesRecvUnicast;
1171 		stat.ifHCInBroadcastOctets = ctx->Status.Int64BytesRecvBroadcast;
1172 		stat.ifHCOutUcastOctets = ctx->Status.Int64BytesSendUnicast;
1173 		stat.ifHCOutBroadcastOctets = ctx->Status.Int64BytesSendBroadcast;
1174 		break;
1175 
1176 	case OID_GEN_INTERRUPT_MODERATION:
1177 		// Interrupt Moderation (NDIS 6.0)
1178 		NeoZero(&intp, sizeof(intp));
1179 		buf = &intp;
1180 		size = sizeof(intp);
1181 
1182 		intp.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
1183 		intp.Header.Revision = NDIS_INTERRUPT_MODERATION_PARAMETERS_REVISION_1;
1184 		intp.Header.Size = NDIS_SIZEOF_INTERRUPT_MODERATION_PARAMETERS_REVISION_1;
1185 		intp.InterruptModeration = NdisInterruptModerationNotSupported;
1186 		break;
1187 
1188 	default:
1189 		// Unknown OID
1190 		*BytesWritten = 0;
1191 		return NDIS_STATUS_INVALID_OID;
1192 	}
1193 
1194 	if (size > InformationBufferLength)
1195 	{
1196 		// Undersize
1197 		*BytesNeeded = size;
1198 		*BytesWritten = 0;
1199 		return NDIS_STATUS_INVALID_LENGTH;
1200 	}
1201 
1202 	// Data copy
1203 	NeoCopy(InformationBuffer, buf, size);
1204 	*BytesWritten = size;
1205 
1206 	return NDIS_STATUS_SUCCESS;
1207 }
1208 
1209 // Set the cable connection state
NeoSetConnectState(BOOL connected)1210 void NeoSetConnectState(BOOL connected)
1211 {
1212 	if (ctx == NULL)
1213 	{
1214 		return;
1215 	}
1216 	ctx->Connected = connected;
1217 	NeoCheckConnectState();
1218 }
1219 
1220 // Check the cable connection state
NeoCheckConnectState()1221 void NeoCheckConnectState()
1222 {
1223 	NDIS_STATUS_INDICATION t;
1224 	NDIS_LINK_STATE state;
1225 	if (ctx == NULL || ctx->NdisMiniport == NULL)
1226 	{
1227 		return;
1228 	}
1229 
1230 	NeoZero(&t, sizeof(t));
1231 	t.Header.Type = NDIS_OBJECT_TYPE_STATUS_INDICATION;
1232 	t.Header.Revision = NDIS_STATUS_INDICATION_REVISION_1;
1233 	t.Header.Size = NDIS_SIZEOF_STATUS_INDICATION_REVISION_1;
1234 
1235 	t.SourceHandle = ctx->NdisMiniport;
1236 
1237 	NeoZero(&state, sizeof(state));
1238 	state.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
1239 	state.Header.Revision = NDIS_LINK_STATE_REVISION_1;
1240 	state.Header.Size = NDIS_SIZEOF_LINK_STATE_REVISION_1;
1241 
1242 	state.MediaDuplexState = NdisPauseFunctionsSendAndReceive;
1243 	state.XmitLinkSpeed = state.RcvLinkSpeed = max_speed;
1244 	state.PauseFunctions = NdisPauseFunctionsUnsupported;
1245 
1246 	t.StatusCode = NDIS_STATUS_LINK_STATE;
1247 	t.StatusBuffer = &state;
1248 	t.StatusBufferSize = sizeof(NDIS_LINK_STATE);
1249 
1250 	if (keep_link == false)
1251 	{
1252 		if (ctx->ConnectedOld != ctx->Connected || ctx->ConnectedForce)
1253 		{
1254 			ctx->ConnectedForce = FALSE;
1255 			ctx->ConnectedOld = ctx->Connected;
1256 			if (ctx->Halting == FALSE)
1257 			{
1258 				state.MediaConnectState = ctx->Connected ? MediaConnectStateConnected : MediaConnectStateDisconnected;
1259 				NdisMIndicateStatusEx(ctx->NdisMiniport, &t);
1260 			}
1261 		}
1262 	}
1263 	else
1264 	{
1265 		if (ctx->ConnectedForce)
1266 		{
1267 			ctx->ConnectedForce = false;
1268 
1269 			if (ctx->Halting == FALSE)
1270 			{
1271 				state.MediaConnectState = MediaConnectStateConnected;
1272 				NdisMIndicateStatusEx(ctx->NdisMiniport, &t);
1273 			}
1274 		}
1275 	}
1276 }
1277 
1278 // Information setting handler of adapter
NeoNdisSet(NDIS_HANDLE MiniportAdapterContext,NDIS_OID Oid,void * InformationBuffer,ULONG InformationBufferLength,ULONG * BytesRead,ULONG * BytesNeeded)1279 NDIS_STATUS NeoNdisSet(
1280 					NDIS_HANDLE MiniportAdapterContext,
1281 					NDIS_OID Oid,
1282 					void *InformationBuffer,
1283 					ULONG InformationBufferLength,
1284 					ULONG *BytesRead,
1285 					ULONG *BytesNeeded)
1286 {
1287 	if (ctx == NULL)
1288 	{
1289 		return STATUS_UNSUCCESSFUL;
1290 	}
1291 
1292 	// Initialization
1293 	*BytesRead = 0;
1294 	*BytesNeeded = 0;
1295 
1296 	// Branch processing
1297 	switch (Oid)
1298 	{
1299 	case OID_GEN_CURRENT_PACKET_FILTER:
1300 		/* Packet filter */
1301 		if (InformationBufferLength != 4)
1302 		{
1303 			*BytesNeeded = 4;
1304 			return NDIS_STATUS_INVALID_LENGTH;
1305 		}
1306 		*BytesRead = 4;
1307 		ctx->CurrentPacketFilter = *((UINT *)InformationBuffer);
1308 		return NDIS_STATUS_SUCCESS;
1309 
1310 //	case OID_GEN_PROTOCOL_OPTIONS:
1311 		/* Current protocol option value */
1312 /*		if (InformationBufferLength != 4)
1313 		{
1314 			*BytesNeeded = 4;
1315 			return NDIS_STATUS_INVALID_LENGTH;
1316 		}
1317 		*BytesRead = 4;
1318 		ctx->CurrentProtocolOptions = *((UINT *)InformationBuffer);
1319 		return NDIS_STATUS_SUCCESS;*/
1320 
1321 	case OID_GEN_CURRENT_LOOKAHEAD:
1322 		/* Look ahead */
1323 		if (InformationBufferLength != 4)
1324 		{
1325 			*BytesNeeded = 4;
1326 			return NDIS_STATUS_INVALID_LENGTH;
1327 		}
1328 		*BytesRead = 4;
1329 		return NDIS_STATUS_SUCCESS;
1330 
1331 	case OID_GEN_LINK_PARAMETERS:
1332 		// NDIS 6.0 Link setting
1333 		*BytesRead = InformationBufferLength;
1334 		return NDIS_STATUS_SUCCESS;
1335 
1336 	case OID_802_3_MULTICAST_LIST:
1337 		// Multicast list
1338 		*BytesRead = InformationBufferLength;
1339 
1340 		return NDIS_STATUS_SUCCESS;
1341 
1342 	case OID_PNP_SET_POWER:
1343 	case OID_PNP_QUERY_POWER:
1344 		// Power events
1345 		*BytesRead = InformationBufferLength;
1346 
1347 		return NDIS_STATUS_SUCCESS;
1348 	}
1349 
1350 	return NDIS_STATUS_INVALID_OID;
1351 }
1352 
1353 // Set status values of NET_BUFFER_LISTs
NeoNdisSetNetBufferListsStatus(NET_BUFFER_LIST * nbl,UINT status)1354 void NeoNdisSetNetBufferListsStatus(NET_BUFFER_LIST *nbl, UINT status)
1355 {
1356 	if (nbl == NULL)
1357 	{
1358 		return;
1359 	}
1360 
1361 	while (nbl != NULL)
1362 	{
1363 		NET_BUFFER_LIST_STATUS(nbl) = status;
1364 
1365 		nbl = NET_BUFFER_LIST_NEXT_NBL(nbl);
1366 	}
1367 }
1368 
1369 // Packet send handler
NeoNdisSendNetBufferLists(NDIS_HANDLE MiniportAdapterContext,NET_BUFFER_LIST * NetBufferLists,NDIS_PORT_NUMBER PortNumber,ULONG SendFlags)1370 void NeoNdisSendNetBufferLists(NDIS_HANDLE MiniportAdapterContext,
1371 							   NET_BUFFER_LIST *NetBufferLists,
1372 							   NDIS_PORT_NUMBER PortNumber,
1373 							   ULONG SendFlags)
1374 {
1375 	bool is_dispatch_level = SendFlags & NDIS_SEND_FLAGS_DISPATCH_LEVEL;
1376 	UINT send_complete_flags = 0;
1377 	if (ctx == NULL)
1378 	{
1379 		return;
1380 	}
1381 
1382 	if (is_dispatch_level)
1383 	{
1384 		send_complete_flags |= NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL;
1385 	}
1386 
1387 	InterlockedIncrement(&ctx->NumCurrentDispatch);
1388 
1389 	// Update the connection state
1390 	NeoCheckConnectState();
1391 
1392 	if (ctx->Halting != FALSE || ctx->Opened == FALSE || ctx->Paused)
1393 	{
1394 		UINT status = NDIS_STATUS_FAILURE;
1395 
1396 		if (ctx->Paused)
1397 		{
1398 			status = NDIS_STATUS_PAUSED;
1399 		}
1400 		else if (ctx->Halting)
1401 		{
1402 			status = NDIS_STATUS_FAILURE;
1403 		}
1404 		else if (ctx->Opened == false && keep_link)
1405 		{
1406 			status = NDIS_STATUS_SUCCESS;
1407 		}
1408 
1409 		NeoNdisSetNetBufferListsStatus(NetBufferLists, status);
1410 
1411 		InterlockedDecrement(&ctx->NumCurrentDispatch);
1412 
1413 		NdisMSendNetBufferListsComplete(ctx->NdisMiniport, NetBufferLists, send_complete_flags);
1414 
1415 		return;
1416 	}
1417 
1418 	// Operation of the packet queue
1419 	NeoLockPacketQueue();
1420 	{
1421 		NET_BUFFER_LIST *nbl;
1422 
1423 		if (ctx->Halting != FALSE || ctx->Opened == FALSE || ctx->Paused)
1424 		{
1425 			UINT status = NDIS_STATUS_FAILURE;
1426 
1427 			if (ctx->Paused)
1428 			{
1429 				status = NDIS_STATUS_PAUSED;
1430 			}
1431 			else if (ctx->Halting)
1432 			{
1433 				status = NDIS_STATUS_FAILURE;
1434 			}
1435 			else if (ctx->Opened == false && keep_link)
1436 			{
1437 				status = NDIS_STATUS_SUCCESS;
1438 			}
1439 
1440 			NeoUnlockPacketQueue();
1441 
1442 			NeoNdisSetNetBufferListsStatus(NetBufferLists, status);
1443 
1444 			InterlockedDecrement(&ctx->NumCurrentDispatch);
1445 
1446 			NdisMSendNetBufferListsComplete(ctx->NdisMiniport, NetBufferLists, send_complete_flags);
1447 
1448 			return;
1449 		}
1450 
1451 		nbl = NetBufferLists;
1452 
1453 		while (nbl != NULL)
1454 		{
1455 			NET_BUFFER *nb = NET_BUFFER_LIST_FIRST_NB(nbl);
1456 
1457 			NET_BUFFER_LIST_STATUS(nbl) = NDIS_STATUS_SUCCESS;
1458 
1459 			while (nb != NULL)
1460 			{
1461 				UINT size = NET_BUFFER_DATA_LENGTH(nb);
1462 
1463 				if (size >= NEO_MIN_PACKET_SIZE && size <= NEO_MAX_PACKET_SIZE)
1464 				{
1465 					UCHAR *buf = NeoMalloc(size);
1466 					void *ptr;
1467 
1468 					ptr = NdisGetDataBuffer(nb, size, buf, 1, 0);
1469 
1470 					if (ptr == NULL)
1471 					{
1472 						ctx->Status.NumPacketSendError++;
1473 						ctx->Status.Int64NumSendError++;
1474 						NeoFree(buf);
1475 					}
1476 					else
1477 					{
1478 						if (ptr != buf)
1479 						{
1480 							NeoCopy(buf, ptr, size);
1481 						}
1482 
1483 						NeoInsertQueue(buf, size);
1484 						ctx->Status.NumPacketSend++;
1485 
1486 						if (buf[0] & 0x40)
1487 						{
1488 							ctx->Status.Int64NumSendBroadcast++;
1489 							ctx->Status.Int64BytesSendBroadcast += (UINT64)size;
1490 						}
1491 						else
1492 						{
1493 							ctx->Status.Int64NumSendUnicast++;
1494 							ctx->Status.Int64BytesSendUnicast += (UINT64)size;
1495 						}
1496 
1497 						ctx->Status.Int64BytesSendTotal += (UINT64)size;
1498 					}
1499 				}
1500 				else
1501 				{
1502 					ctx->Status.NumPacketSendError++;
1503 					ctx->Status.Int64NumSendError++;
1504 				}
1505 
1506 				nb = NET_BUFFER_NEXT_NB(nb);
1507 			}
1508 
1509 			nbl = NET_BUFFER_LIST_NEXT_NBL(nbl);
1510 		}
1511 
1512 		// Reception event
1513 		NeoSet(ctx->Event);
1514 	}
1515 	NeoUnlockPacketQueue();
1516 
1517 	// Notify the transmission completion
1518 	InterlockedDecrement(&ctx->NumCurrentDispatch);
1519 	NdisMSendNetBufferListsComplete(ctx->NdisMiniport, NetBufferLists, send_complete_flags);
1520 }
1521 
1522 // Initialize the packet array
NeoInitPacketArray()1523 void NeoInitPacketArray()
1524 {
1525 	UINT i;
1526 	// Create a packet buffer
1527 	for (i = 0;i < NEO_MAX_PACKET_EXCHANGE;i++)
1528 	{
1529 		ctx->PacketBuffer[i] = NeoNewPacketBuffer();
1530 	}
1531 }
1532 
1533 // Release the packet array
NeoFreePacketArray()1534 void NeoFreePacketArray()
1535 {
1536 	UINT i;
1537 	for (i = 0;i < NEO_MAX_PACKET_EXCHANGE;i++)
1538 	{
1539 		NeoFreePacketBuffer(ctx->PacketBuffer[i]);
1540 		ctx->PacketBuffer[i] = NULL;
1541 	}
1542 }
1543 
1544 // Release the packet buffer
NeoFreePacketBuffer(PACKET_BUFFER * p)1545 void NeoFreePacketBuffer(PACKET_BUFFER *p)
1546 {
1547 	// Validate arguments
1548 	if (p == NULL)
1549 	{
1550 		return;
1551 	}
1552 
1553 	// Release the NET_BUFFER_LIST
1554 	NdisFreeNetBufferList(p->NetBufferList);
1555 	// Release the NET_BUFFER_LIST pool
1556 	NdisFreeNetBufferListPool(p->NetBufferListPool);
1557 	// Release the memory
1558 	NeoFree(p);
1559 }
1560 
1561 // Create a packet buffer
NeoNewPacketBuffer()1562 PACKET_BUFFER *NeoNewPacketBuffer()
1563 {
1564 	PACKET_BUFFER *p;
1565 	NET_BUFFER_LIST_POOL_PARAMETERS p1;
1566 
1567 	// Memory allocation
1568 	p = NeoZeroMalloc(sizeof(PACKET_BUFFER));
1569 
1570 	// Create a NET_BUFFER_LIST pool
1571 	NeoZero(&p1, sizeof(p1));
1572 	p1.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
1573 	p1.Header.Revision = NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1;
1574 	p1.Header.Size = NDIS_SIZEOF_NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1;
1575 	p1.ProtocolId = NDIS_PROTOCOL_ID_DEFAULT;
1576 	p1.fAllocateNetBuffer = TRUE;
1577 	p1.DataSize = NEO_MAX_PACKET_SIZE;
1578 	p1.PoolTag = 'SETH';
1579 	p->NetBufferListPool = NdisAllocateNetBufferListPool(NULL, &p1);
1580 
1581 	// Create a NET_BUFFER_LIST
1582 	p->NetBufferList = NdisAllocateNetBufferList(p->NetBufferListPool, 0, 0);
1583 
1584 	return p;
1585 }
1586 
1587 // Reset the event
NeoReset(NEO_EVENT * event)1588 void NeoReset(NEO_EVENT *event)
1589 {
1590 	// Validate arguments
1591 	if (event == NULL)
1592 	{
1593 		return;
1594 	}
1595 
1596 	KeResetEvent(event->event);
1597 }
1598 
1599 // Set the event
NeoSet(NEO_EVENT * event)1600 void NeoSet(NEO_EVENT *event)
1601 {
1602 	// Validate arguments
1603 	if (event == NULL)
1604 	{
1605 		return;
1606 	}
1607 
1608 	KeSetEvent(event->event, 0, FALSE);
1609 }
1610 
1611 // Release the event
NeoFreeEvent(NEO_EVENT * event)1612 void NeoFreeEvent(NEO_EVENT *event)
1613 {
1614 	// Validate arguments
1615 	if (event == NULL)
1616 	{
1617 		return;
1618 	}
1619 
1620 	ZwClose(event->event_handle);
1621 
1622 	// Release the memory
1623 	NeoFree(event);
1624 }
1625 
1626 // Create a new event
NeoNewEvent(char * name)1627 NEO_EVENT *NeoNewEvent(char *name)
1628 {
1629 	UNICODE *unicode_name;
1630 	NEO_EVENT *event;
1631 	// Validate arguments
1632 	if (name == NULL)
1633 	{
1634 		return NULL;
1635 	}
1636 
1637 	// Convert the name to Unicode
1638 	unicode_name = NewUnicode(name);
1639 	if (unicode_name == NULL)
1640 	{
1641 		return NULL;
1642 	}
1643 
1644 	// Memory allocation
1645 	event = NeoZeroMalloc(sizeof(NEO_EVENT));
1646 	if (event == NULL)
1647 	{
1648 		FreeUnicode(unicode_name);
1649 		return NULL;
1650 	}
1651 
1652 	// Create an Event
1653 	event->event = IoCreateNotificationEvent(GetUnicode(unicode_name), &event->event_handle);
1654 	if (event->event == NULL)
1655 	{
1656 		NeoFree(event);
1657 		FreeUnicode(unicode_name);
1658 		return NULL;
1659 	}
1660 
1661 	// Initialize the event
1662 	KeInitializeEvent(event->event, NotificationEvent, FALSE);
1663 	KeClearEvent(event->event);
1664 
1665 	// Release a string
1666 	FreeUnicode(unicode_name);
1667 
1668 	return event;
1669 }
1670 
1671 // Get the Unicode string
GetUnicode(UNICODE * u)1672 NDIS_STRING *GetUnicode(UNICODE *u)
1673 {
1674 	// Validate arguments
1675 	if (u == NULL)
1676 	{
1677 		return NULL;
1678 	}
1679 
1680 	return &u->String;
1681 }
1682 
1683 // Release the Unicode strings
FreeUnicode(UNICODE * u)1684 void FreeUnicode(UNICODE *u)
1685 {
1686 	// Validate arguments
1687 	if (u == NULL)
1688 	{
1689 		return;
1690 	}
1691 
1692 	// Release a string
1693 	NdisFreeString(u->String);
1694 
1695 	// Release the memory
1696 	NeoFree(u);
1697 }
1698 
1699 // Create a new Unicode string
NewUnicode(char * str)1700 UNICODE *NewUnicode(char *str)
1701 {
1702 	UNICODE *u;
1703 	// Validate arguments
1704 	if (str == NULL)
1705 	{
1706 		return NULL;
1707 	}
1708 
1709 	// Memory allocation
1710 	u = NeoZeroMalloc(sizeof(UNICODE));
1711 	if (u == NULL)
1712 	{
1713 		return NULL;
1714 	}
1715 
1716 	// String initialization
1717 	NdisInitializeString(&u->String, str);
1718 
1719 	return u;
1720 }
1721 
1722 // Release the lock
NeoFreeLock(NEO_LOCK * lock)1723 void NeoFreeLock(NEO_LOCK *lock)
1724 {
1725 	NDIS_SPIN_LOCK *spin_lock;
1726 	// Validate arguments
1727 	if (lock == NULL)
1728 	{
1729 		return;
1730 	}
1731 
1732 	spin_lock = &lock->spin_lock;
1733 	NdisFreeSpinLock(spin_lock);
1734 
1735 	// Release the memory
1736 	NeoFree(lock);
1737 }
1738 
1739 // Unlock
NeoUnlock(NEO_LOCK * lock)1740 void NeoUnlock(NEO_LOCK *lock)
1741 {
1742 	NDIS_SPIN_LOCK *spin_lock;
1743 	// Validate arguments
1744 	if (lock == NULL)
1745 	{
1746 		return;
1747 	}
1748 
1749 	spin_lock = &lock->spin_lock;
1750 	NdisReleaseSpinLock(spin_lock);
1751 }
1752 
1753 // Lock
NeoLock(NEO_LOCK * lock)1754 void NeoLock(NEO_LOCK *lock)
1755 {
1756 	NDIS_SPIN_LOCK *spin_lock;
1757 	// Validate arguments
1758 	if (lock == NULL)
1759 	{
1760 		return;
1761 	}
1762 
1763 	spin_lock = &lock->spin_lock;
1764 	NdisAcquireSpinLock(spin_lock);
1765 }
1766 
1767 // Creating a new lock
NeoNewLock()1768 NEO_LOCK *NeoNewLock()
1769 {
1770 	NDIS_SPIN_LOCK *spin_lock;
1771 
1772 	// Memory allocation
1773 	NEO_LOCK *lock = NeoZeroMalloc(sizeof(NEO_LOCK));
1774 	if (lock == NULL)
1775 	{
1776 		return NULL;
1777 	}
1778 
1779 	// Initialize spin lock
1780 	spin_lock = &lock->spin_lock;
1781 
1782 	NdisAllocateSpinLock(spin_lock);
1783 
1784 	return lock;
1785 }
1786 
1787 // Memory copy
NeoCopy(void * dst,void * src,UINT size)1788 void NeoCopy(void *dst, void *src, UINT size)
1789 {
1790 	// Validate arguments
1791 	if (dst == NULL || src == NULL || size == 0)
1792 	{
1793 		return;
1794 	}
1795 
1796 	// Copy
1797 	NdisMoveMemory(dst, src, size);
1798 }
1799 
1800 // Memory clear
NeoZero(void * dst,UINT size)1801 void NeoZero(void *dst, UINT size)
1802 {
1803 	// Validate arguments
1804 	if (dst == NULL || size == 0)
1805 	{
1806 		return;
1807 	}
1808 
1809 	// Clear
1810 	NdisZeroMemory(dst, size);
1811 }
1812 
1813 // Clear to zero by memory allocation
NeoZeroMalloc(UINT size)1814 void *NeoZeroMalloc(UINT size)
1815 {
1816 	void *p = NeoMalloc(size);
1817 	if (p == NULL)
1818 	{
1819 		// Memory allocation failure
1820 		return NULL;
1821 	}
1822 	// Clear to zero
1823 	NeoZero(p, size);
1824 	return p;
1825 }
1826 
1827 // Memory allocation
NeoMalloc(UINT size)1828 void *NeoMalloc(UINT size)
1829 {
1830 	NDIS_STATUS r;
1831 	void *p;
1832 	if (size == 0)
1833 	{
1834 		size = 1;
1835 	}
1836 
1837 	// Allocate the non-paged memory
1838 	r = NdisAllocateMemoryWithTag(&p, size, 'SETH');
1839 
1840 	if (NG(r))
1841 	{
1842 		return NULL;
1843 	}
1844 	return p;
1845 }
1846 
1847 // Release the memory
NeoFree(void * p)1848 void NeoFree(void *p)
1849 {
1850 	// Validate arguments
1851 	if (p == NULL)
1852 	{
1853 		return;
1854 	}
1855 
1856 	// Release the memory
1857 	NdisFreeMemory(p, 0, 0);
1858 }
1859 
1860 
1861