1 // SoftEther VPN Source Code - Stable Edition Repository
2 // Windows Filtering Platform Callout Driver for Capturing IPsec Packets on Windows Vista / 7 / Server 2008
3 //
4 // SoftEther VPN Server, Client and Bridge are free software under the Apache License, Version 2.0.
5 //
6 // Copyright (c) Daiyuu Nobori.
7 // Copyright (c) SoftEther VPN Project, University of Tsukuba, Japan.
8 // Copyright (c) SoftEther Corporation.
9 // Copyright (c) all contributors on SoftEther VPN project in GitHub.
10 //
11 // All Rights Reserved.
12 //
13 // http://www.softether.org/
14 //
15 // This stable branch is officially managed by Daiyuu Nobori, the owner of SoftEther VPN Project.
16 // Pull requests should be sent to the Developer Edition Master Repository on https://github.com/SoftEtherVPN/SoftEtherVPN
17 //
18 // License: The Apache License, Version 2.0
19 // https://www.apache.org/licenses/LICENSE-2.0
20 //
21 // DISCLAIMER
22 // ==========
23 //
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 // SOFTWARE.
31 //
32 // THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN, UNDER
33 // JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY, MERGE, PUBLISH,
34 // DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS SOFTWARE, THAT ANY
35 // JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS SOFTWARE OR ITS CONTENTS,
36 // AGAINST US (SOFTETHER PROJECT, SOFTETHER CORPORATION, DAIYUU NOBORI OR OTHER
37 // SUPPLIERS), OR ANY JURIDICAL DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND
38 // OF USING, COPYING, MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING,
39 // AND/OR SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
40 // CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO EXCLUSIVE
41 // JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO, JAPAN. YOU MUST WAIVE
42 // ALL DEFENSES OF LACK OF PERSONAL JURISDICTION AND FORUM NON CONVENIENS.
43 // PROCESS MAY BE SERVED ON EITHER PARTY IN THE MANNER AUTHORIZED BY APPLICABLE
44 // LAW OR COURT RULE.
45 //
46 // USE ONLY IN JAPAN. DO NOT USE THIS SOFTWARE IN ANOTHER COUNTRY UNLESS YOU HAVE
47 // A CONFIRMATION THAT THIS SOFTWARE DOES NOT VIOLATE ANY CRIMINAL LAWS OR CIVIL
48 // RIGHTS IN THAT PARTICULAR COUNTRY. USING THIS SOFTWARE IN OTHER COUNTRIES IS
49 // COMPLETELY AT YOUR OWN RISK. THE SOFTETHER VPN PROJECT HAS DEVELOPED AND
50 // DISTRIBUTED THIS SOFTWARE TO COMPLY ONLY WITH THE JAPANESE LAWS AND EXISTING
51 // CIVIL RIGHTS INCLUDING PATENTS WHICH ARE SUBJECTS APPLY IN JAPAN. OTHER
52 // COUNTRIES' LAWS OR CIVIL RIGHTS ARE NONE OF OUR CONCERNS NOR RESPONSIBILITIES.
53 // WE HAVE NEVER INVESTIGATED ANY CRIMINAL REGULATIONS, CIVIL LAWS OR
54 // INTELLECTUAL PROPERTY RIGHTS INCLUDING PATENTS IN ANY OF OTHER 200+ COUNTRIES
55 // AND TERRITORIES. BY NATURE, THERE ARE 200+ REGIONS IN THE WORLD, WITH
56 // DIFFERENT LAWS. IT IS IMPOSSIBLE TO VERIFY EVERY COUNTRIES' LAWS, REGULATIONS
57 // AND CIVIL RIGHTS TO MAKE THE SOFTWARE COMPLY WITH ALL COUNTRIES' LAWS BY THE
58 // PROJECT. EVEN IF YOU WILL BE SUED BY A PRIVATE ENTITY OR BE DAMAGED BY A
59 // PUBLIC SERVANT IN YOUR COUNTRY, THE DEVELOPERS OF THIS SOFTWARE WILL NEVER BE
60 // LIABLE TO RECOVER OR COMPENSATE SUCH DAMAGES, CRIMINAL OR CIVIL
61 // RESPONSIBILITIES. NOTE THAT THIS LINE IS NOT LICENSE RESTRICTION BUT JUST A
62 // STATEMENT FOR WARNING AND DISCLAIMER.
63 //
64 // READ AND UNDERSTAND THE 'WARNING.TXT' FILE BEFORE USING THIS SOFTWARE.
65 // SOME SOFTWARE PROGRAMS FROM THIRD PARTIES ARE INCLUDED ON THIS SOFTWARE WITH
66 // LICENSE CONDITIONS WHICH ARE DESCRIBED ON THE 'THIRD_PARTY.TXT' FILE.
67 //
68 //
69 // SOURCE CODE CONTRIBUTION
70 // ------------------------
71 //
72 // Your contribution to SoftEther VPN Project is much appreciated.
73 // Please send patches to us through GitHub.
74 // Read the SoftEther VPN Patch Acceptance Policy in advance:
75 // http://www.softether.org/5-download/src/9.patch
76 //
77 //
78 // DEAR SECURITY EXPERTS
79 // ---------------------
80 //
81 // If you find a bug or a security vulnerability please kindly inform us
82 // about the problem immediately so that we can fix the security problem
83 // to protect a lot of users around the world as soon as possible.
84 //
85 // Our e-mail address for security reports is:
86 // softether-vpn-security [at] softether.org
87 //
88 // Please note that the above e-mail address is not a technical support
89 // inquiry address. If you need technical assistance, please visit
90 // http://www.softether.org/ and ask your question on the users forum.
91 //
92 // Thank you for your cooperation.
93 //
94 //
95 // NO MEMORY OR RESOURCE LEAKS
96 // ---------------------------
97 //
98 // The memory-leaks and resource-leaks verification under the stress
99 // test has been passed before release this source code.
100 
101 
102 // Wfp.c
103 // WFP Callout Driver
104 
105 #include <GlobalConst.h>
106 
107 #define	WFP_DEVICE_DRIVER
108 
109 #include "WfpInner.h"
110 #include "Wfp.h"
111 
112 static WFP_CTX *wfp = NULL;
113 static bool g_is_win8 = false;
114 static POOL_TYPE g_pool_type = NonPagedPool;
115 
116 // Dispatch function
DriverDispatch(DEVICE_OBJECT * device_object,IRP * irp)117 NTSTATUS DriverDispatch(DEVICE_OBJECT *device_object, IRP *irp)
118 {
119 	NTSTATUS ret = STATUS_SUCCESS;
120 	IO_STACK_LOCATION *stack;
121 	void *buf;
122 	bool ok;
123 	// Validate arguments
124 	if (wfp == NULL || device_object == NULL || irp == NULL || wfp->Halting)
125 	{
126 		return NDIS_STATUS_FAILURE;
127 	}
128 
129 	// Get the IRP stack
130 	stack = IoGetCurrentIrpStackLocation(irp);
131 
132 	// Initialize the number of bytes
133 	irp->IoStatus.Information = 0;
134 	irp->IoStatus.Status = STATUS_SUCCESS;
135 
136 	buf = irp->UserBuffer;
137 
138 	if (wfp->Halting != FALSE)
139 	{
140 		// Device driver is terminating
141 		irp->IoStatus.Information = STATUS_UNSUCCESSFUL;
142 		IoCompleteRequest(irp, IO_NO_INCREMENT);
143 		return STATUS_UNSUCCESSFUL;
144 	}
145 
146 	ok = false;
147 
148 	// Branch to each operation
149 	switch (stack->MajorFunction)
150 	{
151 	case IRP_MJ_CREATE:	// Open
152 		ok = true;
153 		break;
154 
155 	case IRP_MJ_CLOSE:	// Close
156 		ok = true;
157 		break;
158 
159 	case IRP_MJ_READ:	// Read
160 		ResetEvent(wfp->Event);
161 		break;
162 
163 	case IRP_MJ_WRITE:	// Write
164 		if ((stack->Parameters.Write.Length % sizeof(WFP_LOCAL_IP)) == 0)
165 		{
166 			// Address check
167 			bool check_ok = true;
168 			__try
169 			{
170 				ProbeForRead(buf, stack->Parameters.Write.Length, 1);
171 			}
172 			__except (EXCEPTION_EXECUTE_HANDLER)
173 			{
174 				check_ok = false;
175 			}
176 
177 			if (check_ok)
178 			{
179 				MDL *mdl = IoAllocateMdl(buf, stack->Parameters.Write.Length, false, false, NULL);
180 				UINT size = MIN(WFP_MAX_LOCAL_IP_COUNT * sizeof(WFP_LOCAL_IP), stack->Parameters.Write.Length);
181 				UCHAR *copied_buf = Malloc(size);
182 				UCHAR *old_buf;
183 
184 				if (mdl != NULL)
185 				{
186 					MmProbeAndLockPages(mdl, KernelMode, IoWriteAccess);
187 				}
188 
189 				Copy(copied_buf, buf, size);
190 
191 				SpinLock(wfp->LocalIPListLock);
192 				{
193 					old_buf = wfp->LocalIPListData;
194 					wfp->LocalIPListData = copied_buf;
195 					wfp->LocalIPListSize = size;
196 				}
197 				SpinUnlock(wfp->LocalIPListLock);
198 
199 				if (old_buf != NULL)
200 				{
201 					Free(old_buf);
202 				}
203 
204 				if (mdl != NULL)
205 				{
206 					MmUnlockPages(mdl);
207 					IoFreeMdl(mdl);
208 				}
209 			}
210 		}
211 		irp->IoStatus.Information = stack->Parameters.Write.Length;
212 		ok = true;
213 		break;
214 	}
215 
216 	if (ok == false)
217 	{
218 		irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
219 		ret = STATUS_UNSUCCESSFUL;
220 	}
221 
222 	IoCompleteRequest(irp, IO_NO_INCREMENT);
223 
224 	return ret;
225 }
226 
227 // Function to finish the insertion of the packet
CalloutInjectionCompleted(void * context,NET_BUFFER_LIST * net_buffer_list,BOOLEAN dispatch_level)228 void NTAPI CalloutInjectionCompleted(void *context, NET_BUFFER_LIST *net_buffer_list, BOOLEAN dispatch_level)
229 {
230 	WFP_INJECTED_PACKET_CONTEXT *ctx = (WFP_INJECTED_PACKET_CONTEXT *)context;
231 
232 	if (ctx == NULL)
233 	{
234 		return;
235 	}
236 
237 	FreeInjectionCtx(ctx);
238 }
239 
240 // Release the injection data
FreeInjectionCtx(WFP_INJECTED_PACKET_CONTEXT * ctx)241 void FreeInjectionCtx(WFP_INJECTED_PACKET_CONTEXT *ctx)
242 {
243 	// Validate arguments
244 	if (ctx == NULL)
245 	{
246 		return;
247 	}
248 
249 	if (ctx->CurrentNetBuffer != NULL)
250 	{
251 		Copy(ctx->CurrentNetBuffer, &ctx->OriginalNetBufferData, sizeof(NET_BUFFER));
252 	}
253 
254 	if (ctx->AllocatedNetBufferList != NULL)
255 	{
256 		FwpsFreeCloneNetBufferList0(ctx->AllocatedNetBufferList, 0);
257 	}
258 
259 	if (ctx->AllocatedMdl != NULL)
260 	{
261 		NdisFreeMdl(ctx->AllocatedMdl);
262 	}
263 
264 	if (ctx->AllocatedMemory != NULL)
265 	{
266 		Free(ctx->AllocatedMemory);
267 	}
268 
269 	Free(ctx);
270 }
271 
272 // Calculate the checksum
IpChecksum(void * buf,UINT size)273 USHORT IpChecksum(void *buf, UINT size)
274 {
275 	int sum = 0;
276 	USHORT *addr = (USHORT *)buf;
277 	int len = (int)size;
278 	USHORT *w = addr;
279 	int nleft = len;
280 	USHORT answer = 0;
281 
282 	while (nleft > 1)
283 	{
284 		sum += *w++;
285 		nleft -= 2;
286 	}
287 
288 	if (nleft == 1)
289 	{
290 		*(UCHAR *)(&answer) = *(UCHAR *)w;
291 		sum += answer;
292 	}
293 
294 	sum = (sum >> 16) + (sum & 0xffff);
295 	sum += (sum >> 16);
296 
297 	answer = ~sum;
298 
299 	return answer;
300 }
301 
302 // Modify the IPsec ESP packet
ModificationOfIPsecESPPacket(UCHAR * ip_packet,UINT ip_packet_size,UINT ip_header_size,UINT * dst_size_ptr,bool isv6)303 UCHAR *ModificationOfIPsecESPPacket(UCHAR *ip_packet, UINT ip_packet_size, UINT ip_header_size, UINT *dst_size_ptr, bool isv6)
304 {
305 	UINT ip_and_udp_header_size = ip_header_size + sizeof(WFP_UDP_HEADER);
306 	UINT udp_packet_size;
307 	UINT udp_payload_size;
308 	UINT dst_udp_payload_size;
309 	WFP_UDP_HEADER *src_udp;
310 	WFP_UDP_HEADER *dst_udp;
311 	UCHAR *src_udp_payload;
312 	UCHAR *dst_data;
313 	UINT dst_size;
314 	// Validate arguments
315 	if (ip_packet == NULL || ip_packet == 0 || ip_header_size == 0 || dst_size_ptr == NULL)
316 	{
317 		return NULL;
318 	}
319 
320 	if (ip_packet_size <= ip_and_udp_header_size)
321 	{
322 		// There is no UDP header
323 		return NULL;
324 	}
325 
326 	// Get the UDP header
327 	src_udp = (WFP_UDP_HEADER *)(ip_packet + ip_header_size);
328 	udp_packet_size = Endian16(src_udp->PacketLength);
329 	if (udp_packet_size < sizeof(WFP_UDP_HEADER))
330 	{
331 		// There is no UDP payload
332 		return NULL;
333 	}
334 
335 	// Get the UDP payload size
336 	udp_payload_size = udp_packet_size - sizeof(WFP_UDP_HEADER);
337 
338 	if (ip_packet_size < (ip_and_udp_header_size + udp_payload_size))
339 	{
340 		// There is no UDP payload
341 		return NULL;
342 	}
343 
344 	// Get the UDP payload
345 	src_udp_payload = ip_packet + ip_and_udp_header_size;
346 
347 	if (udp_payload_size < sizeof(UINT))
348 	{
349 		// The size of the UDP payload is less than 5 bytes
350 		return NULL;
351 	}
352 
353 	dst_udp_payload_size = udp_payload_size + sizeof(UINT) * 3;
354 	if ((dst_udp_payload_size + sizeof(WFP_UDP_HEADER)) > 0xffff)
355 	{
356 		// UDP payload size overflows the 16bit
357 		return NULL;
358 	}
359 
360 	// Build a new packet
361 	dst_size = ip_and_udp_header_size + sizeof(UINT) * 3 + udp_payload_size;
362 	if (dst_size > 0xffff)
363 	{
364 		// IP total size overflows the 16bit
365 		return NULL;
366 	}
367 
368 	dst_data = Malloc(dst_size);
369 	if (dst_data == NULL)
370 	{
371 		// Memory allocation failure
372 		return NULL;
373 	}
374 
375 	// Copy the IP header + UDP header
376 	Copy(dst_data, ip_packet, ip_and_udp_header_size);
377 
378 	// Copy the original payload
379 	Copy(dst_data + ip_and_udp_header_size + sizeof(UINT) * 3, src_udp_payload, udp_payload_size);
380 
381 	// Insert a tag
382 	*((UINT *)(dst_data + ip_and_udp_header_size + sizeof(UINT) * 0)) = 0;
383 	*((UINT *)(dst_data + ip_and_udp_header_size + sizeof(UINT) * 1)) = WFP_ESP_PACKET_TAG_1;
384 	*((UINT *)(dst_data + ip_and_udp_header_size + sizeof(UINT) * 2)) = WFP_ESP_PACKET_TAG_2;
385 
386 	// Adjust the new IP header
387 	if (isv6 == false)
388 	{
389 		WFP_IPV4_HEADER *ip = (WFP_IPV4_HEADER *)dst_data;
390 
391 		ip->TotalLength = Endian16(dst_size);
392 		ip->Checksum = 0;
393 		ip->Checksum = IpChecksum(ip, ip_header_size);
394 	}
395 	else
396 	{
397 		WFP_IPV6_HEADER *ip = (WFP_IPV6_HEADER *)dst_data;
398 
399 		ip->PayloadLength = Endian16(dst_size);
400 	}
401 
402 	// Adjust the new UDP header
403 	dst_udp = (WFP_UDP_HEADER *)(dst_data + ip_header_size);
404 	dst_udp->Checksum = 0;
405 	dst_udp->PacketLength = Endian16((USHORT)(dst_udp_payload_size + sizeof(WFP_UDP_HEADER)));
406 
407 	*dst_size_ptr = dst_size;
408 	return dst_data;
409 }
410 
411 // Insert the packet into the stack
InjectPacket(HANDLE hInjection,NET_BUFFER_LIST * nbl,UCHAR * dst_data,UINT dst_size,const FWPS_INCOMING_VALUES0 * inFixedValues,const FWPS_INCOMING_METADATA_VALUES0 * inMetaValues)412 bool InjectPacket(HANDLE hInjection, NET_BUFFER_LIST *nbl, UCHAR *dst_data, UINT dst_size, const FWPS_INCOMING_VALUES0* inFixedValues, const FWPS_INCOMING_METADATA_VALUES0* inMetaValues)
413 {
414 	WFP_INJECTED_PACKET_CONTEXT *ctx;
415 	bool block = false;
416 	// Validate arguments
417 	if (hInjection == NULL || nbl == NULL || dst_data == NULL || dst_size == 0 || inMetaValues == NULL || inFixedValues == NULL)
418 	{
419 		return false;
420 	}
421 
422 	ctx = ZeroMalloc(sizeof(WFP_INJECTED_PACKET_CONTEXT));
423 
424 	if (ctx != NULL)
425 	{
426 		// Generate a modified packet
427 		ctx->AllocatedMemory = dst_data;
428 
429 		if (dst_data != NULL)
430 		{
431 			NET_BUFFER_LIST *net_buffer_list;
432 			NTSTATUS ret;
433 
434 			// Clone the original NET_BUFFER_LIST
435 			ret = FwpsAllocateCloneNetBufferList0(nbl, NULL, NULL, 0, &net_buffer_list);
436 
437 			if (OK(ret) && net_buffer_list != NULL)
438 			{
439 				NET_BUFFER *net_buffer = NET_BUFFER_LIST_FIRST_NB(net_buffer_list);
440 
441 				ctx->AllocatedNetBufferList = net_buffer_list;
442 				ctx->CurrentNetBuffer = net_buffer;
443 
444 				if (net_buffer != NULL)
445 				{
446 					MDL *mdl = NdisAllocateMdl(wfp->hNdis, dst_data, dst_size);
447 					if (mdl != NULL)
448 					{
449 						NTSTATUS ret;
450 
451 						ctx->AllocatedMdl = mdl;
452 
453 						Copy(&ctx->OriginalNetBufferData, net_buffer, sizeof(NET_BUFFER));
454 
455 						NET_BUFFER_FIRST_MDL(net_buffer) = mdl;
456 						NET_BUFFER_DATA_LENGTH(net_buffer) = dst_size;
457 						NET_BUFFER_DATA_OFFSET(net_buffer) = 0;
458 						NET_BUFFER_CURRENT_MDL(net_buffer) = mdl;
459 						NET_BUFFER_CURRENT_MDL_OFFSET(net_buffer) = 0;
460 
461 						// Insert packets of receiving direction
462 						ret = FwpsInjectNetworkReceiveAsync0(hInjection, NULL,
463 							0,
464 							(inMetaValues->currentMetadataValues & FWPS_METADATA_FIELD_COMPARTMENT_ID ? inMetaValues->compartmentId : UNSPECIFIED_COMPARTMENT_ID),
465 							inFixedValues->incomingValue[FWPS_FIELD_INBOUND_IPPACKET_V4_INTERFACE_INDEX].value.uint32,
466 							inFixedValues->incomingValue[FWPS_FIELD_INBOUND_IPPACKET_V4_SUB_INTERFACE_INDEX].value.uint32,
467 							net_buffer_list,
468 							CalloutInjectionCompleted,
469 							(HANDLE)ctx);
470 
471 						if (NG(ret))
472 						{
473 							//CRUSH_WHERE;
474 						}
475 						else
476 						{
477 							block = true;
478 						}
479 					}
480 					else
481 					{
482 						//CRUSH_WHERE;
483 					}
484 				}
485 				else
486 				{
487 					//CRUSH_WHERE;
488 				}
489 			}
490 			else
491 			{
492 				//CRUSH_WHERE;
493 			}
494 		}
495 		else
496 		{
497 			//CRUSH_WHERE;
498 		}
499 
500 		if (block == false)
501 		{
502 			FreeInjectionCtx(ctx);
503 		}
504 	}
505 
506 	return block;
507 }
508 
509 // Function to be notified of arriving packet
CalloutClassify(const FWPS_INCOMING_VALUES0 * inFixedValues,const FWPS_INCOMING_METADATA_VALUES0 * inMetaValues,void * layerData,const FWPS_FILTER0 * filter,UINT64 flowContext,FWPS_CLASSIFY_OUT0 * classifyOut)510 void NTAPI CalloutClassify(const FWPS_INCOMING_VALUES0* inFixedValues,
511 						   const FWPS_INCOMING_METADATA_VALUES0* inMetaValues,
512 						   void* layerData,
513 						   const FWPS_FILTER0* filter,
514 						   UINT64 flowContext,
515 						   FWPS_CLASSIFY_OUT0* classifyOut)
516 {
517 	NET_BUFFER_LIST *nbl = layerData;
518 	FWPS_PACKET_INJECTION_STATE injecton_state;
519 	bool block = false;
520 	HANDLE hInjection = NULL;
521 	UINT ip_header_len = 0;
522 	bool isv6 = false;
523 
524 	if (wfp->Halting || nbl == NULL)
525 	{
526 		classifyOut->actionType = FWP_ACTION_CONTINUE;
527 		return;
528 	}
529 
530 	switch (inFixedValues->layerId)
531 	{
532 	case FWPS_LAYER_INBOUND_IPPACKET_V4:
533 		hInjection = wfp->hInjectionIPv4;
534 		ip_header_len = sizeof(WFP_IPV4_HEADER);
535 		break;
536 
537 	case FWPS_LAYER_INBOUND_IPPACKET_V6:
538 		hInjection = wfp->hInjectionIPv6;
539 		ip_header_len = sizeof(WFP_IPV6_HEADER);
540 		isv6 = true;
541 		break;
542 	}
543 
544 	if (hInjection != NULL)
545 	{
546 		injecton_state = FwpsQueryPacketInjectionState0(hInjection, nbl, NULL);
547 
548 		if (injecton_state == FWPS_PACKET_INJECTED_BY_SELF || injecton_state == FWPS_PACKET_PREVIOUSLY_INJECTED_BY_SELF)
549 		{
550 			//SetEvent(wfp->Event);
551 			classifyOut->actionType = FWP_ACTION_CONTINUE; // continue
552 			return;
553 		}
554 
555 		if (nbl != NULL && NET_BUFFER_LIST_NEXT_NBL(nbl) == NULL)
556 		{
557 			NET_BUFFER *nb = NET_BUFFER_LIST_FIRST_NB(nbl);
558 
559 			if (nb != NULL && NET_BUFFER_NEXT_NB(nb) == NULL && (NET_BUFFER_DATA_OFFSET(nb) >= inMetaValues->ipHeaderSize))
560 			{
561 				if (OK(NdisRetreatNetBufferDataStart(nb, inMetaValues->ipHeaderSize, 0, NULL)))
562 				{
563 					WFP_IPV4_HEADER *ipv4;
564 					WFP_IPV6_HEADER *ipv6;
565 					UCHAR *alloc_buf = Malloc(ip_header_len);
566 
567 					ipv4 = NdisGetDataBuffer(nb, ip_header_len, alloc_buf, 1, 0);
568 					ipv6 = (WFP_IPV6_HEADER *)ipv4;
569 
570 					if (ipv4 != NULL)
571 					{
572 						if ((isv6 == false && ipv4->Protocol == WFP_ESP_RAW_PROTOCOL_ID))
573 						{
574 							if (IsIPv4AddressInList(&ipv4->DstIP))
575 							{
576 								UINT src_size = NET_BUFFER_DATA_LENGTH(nb);
577 								UCHAR *src_data = Malloc(src_size);
578 
579 								if (src_data != NULL)
580 								{
581 									UCHAR *src_ptr = NdisGetDataBuffer(nb, src_size, src_data, 1, 0);
582 
583 									if (src_ptr != NULL)
584 									{
585 										UINT dst_size = src_size;
586 										UCHAR *dst_data = Malloc(dst_size);
587 
588 										if (dst_data != NULL)
589 										{
590 											WFP_IPV4_HEADER *ipv4;
591 
592 											Copy(dst_data, src_ptr, dst_size);
593 											ipv4 = (WFP_IPV4_HEADER *)dst_data;
594 
595 											ipv4->Protocol = WFP_ESP_RAW_PROTOCOL_ID_DST;
596 											ipv4->Checksum = 0;
597 											ipv4->Checksum = IpChecksum(ipv4, inMetaValues->ipHeaderSize);
598 
599 											block = InjectPacket(hInjection, nbl, dst_data, dst_size, inFixedValues, inMetaValues);
600 										}
601 									}
602 
603 									Free(src_data);
604 								}
605 							}
606 						}
607 						else if ((isv6 && ipv6->NextHeader == WFP_ESP_RAW_PROTOCOL_ID))
608 						{
609 							if (IsIPv6AddressInList(&ipv6->DestAddress))
610 							{
611 								UINT src_size = NET_BUFFER_DATA_LENGTH(nb);
612 								UCHAR *src_data = Malloc(src_size);
613 
614 								if (src_data != NULL)
615 								{
616 									UCHAR *src_ptr = NdisGetDataBuffer(nb, src_size, src_data, 1, 0);
617 
618 									if (src_ptr != NULL)
619 									{
620 										UINT dst_size = src_size;
621 										UCHAR *dst_data = Malloc(dst_size);
622 
623 										if (dst_data != NULL)
624 										{
625 											WFP_IPV6_HEADER *ipv6;
626 
627 											Copy(dst_data, src_ptr, dst_size);
628 											ipv6 = (WFP_IPV6_HEADER *)dst_data;
629 
630 											ipv6->NextHeader = WFP_ESP_RAW_PROTOCOL_ID_DST;
631 
632 											block = InjectPacket(hInjection, nbl, dst_data, dst_size, inFixedValues, inMetaValues);
633 										}
634 									}
635 
636 									Free(src_data);
637 								}
638 							}
639 						}
640 
641 						if ((isv6 == false && ipv4->Protocol == WFP_IP_PROTO_UDP) ||
642 							(isv6 && ipv6->NextHeader == WFP_IP_PROTO_UDP))
643 						{
644 							UINT ip_and_udp_header_len = inMetaValues->ipHeaderSize + sizeof(WFP_UDP_HEADER);
645 							UCHAR *ptr;
646 							UCHAR *alloc_buf = Malloc(ip_and_udp_header_len);
647 
648 							ptr = NdisGetDataBuffer(nb, ip_and_udp_header_len, alloc_buf, 1, 0);
649 							if (ptr != NULL)
650 							{
651 								WFP_UDP_HEADER *udp = (WFP_UDP_HEADER *)(ptr + inMetaValues->ipHeaderSize);
652 
653 								if (Endian16(udp->DstPort) == 4500)
654 								{
655 									if ((isv6 == false && IsIPv4AddressInList(&ipv4->DstIP)) ||
656 										(isv6 && IsIPv6AddressInList(&ipv6->DestAddress)))
657 									{
658 										UINT packet_size = NET_BUFFER_DATA_LENGTH(nb);
659 										UCHAR *packet_buf_allocated = Malloc(packet_size);
660 										UCHAR *packet_data = NdisGetDataBuffer(nb, packet_size, packet_buf_allocated, 1, 0);
661 
662 										if (packet_data != NULL)
663 										{
664 											UCHAR *udp_payload = packet_data + ip_and_udp_header_len;
665 											UINT udp_payload_size = packet_size - ip_and_udp_header_len;
666 
667 											if (udp_payload_size >= 4)
668 											{
669 												UINT *i = (UINT *)udp_payload;
670 												if (*i != 0)
671 												{
672 													// Generate a modified packet
673 													UINT dst_size;
674 													UCHAR *dst_data = ModificationOfIPsecESPPacket(packet_data, packet_size,
675 														inMetaValues->ipHeaderSize, &dst_size, isv6);
676 
677 													block = InjectPacket(hInjection, nbl, dst_data, dst_size, inFixedValues, inMetaValues);
678 												}
679 											}
680 										}
681 										else
682 										{
683 											//CRUSH_WHERE;
684 										}
685 
686 										Free(packet_buf_allocated);
687 									}
688 								}
689 							}
690 							else
691 							{
692 								//CRUSH_WHERE;
693 							}
694 
695 							Free(alloc_buf);
696 						}
697 					}
698 
699 					Free(alloc_buf);
700 
701 					NdisAdvanceNetBufferDataStart(nb, inMetaValues->ipHeaderSize, false, NULL);
702 				}
703 				else
704 				{
705 					//CRUSH_WHERE;
706 				}
707 
708 				nb = NET_BUFFER_NEXT_NB(nb);
709 			}
710 
711 			nbl = NET_BUFFER_LIST_NEXT_NBL(nbl);
712 		}
713 	}
714 
715 	classifyOut->actionType = FWP_ACTION_CONTINUE;
716 
717 	if (block)
718 	{
719 		// Block the packet
720 		classifyOut->actionType = FWP_ACTION_BLOCK;
721 		classifyOut->rights &= ~FWPS_RIGHT_ACTION_WRITE;
722 		classifyOut->flags |= FWPS_CLASSIFY_OUT_FLAG_ABSORB;
723 		//SetEvent(wfp->Event);
724 	}
725 }
726 
727 // Function to receive notification from the WFP
CalloutNotify(FWPS_CALLOUT_NOTIFY_TYPE notifyType,const GUID * filterKey,FWPS_FILTER0 * filter)728 NTSTATUS NTAPI CalloutNotify(FWPS_CALLOUT_NOTIFY_TYPE notifyType,
729 							  const GUID* filterKey, FWPS_FILTER0* filter)
730 {
731 	//Crush(1,0,0,0);
732 	return 0;
733 }
734 
735 // Scan whether the specified IP address is in the local IP address list
IsIPAddressInList(struct WFP_LOCAL_IP * ip)736 bool IsIPAddressInList(struct WFP_LOCAL_IP *ip)
737 {
738 	bool ret = false;
739 	// Validate arguments
740 	if (ip == NULL)
741 	{
742 		return false;
743 	}
744 
745 	SpinLock(wfp->LocalIPListLock);
746 	{
747 		if (wfp->LocalIPListData != NULL)
748 		{
749 			UINT num = wfp->LocalIPListSize / sizeof(WFP_LOCAL_IP);
750 			WFP_LOCAL_IP *o = (WFP_LOCAL_IP *)wfp->LocalIPListData;
751 			UINT i;
752 
753 			for (i = 0;i < num;i++)
754 			{
755 				if (Cmp(&o[i], ip, sizeof(WFP_LOCAL_IP)) == 0)
756 				{
757 					ret = true;
758 					break;
759 				}
760 			}
761 		}
762 	}
763 	SpinUnlock(wfp->LocalIPListLock);
764 
765 	return ret;
766 }
IsIPv4AddressInList(void * addr)767 bool IsIPv4AddressInList(void *addr)
768 {
769 	WFP_LOCAL_IP ip;
770 	// Validate arguments
771 	if (addr == NULL)
772 	{
773 		return false;
774 	}
775 
776 	Zero(&ip, sizeof(ip));
777 	ip.IpVersion = 4;
778 	Copy(ip.IpAddress.IPv4Address, addr, 4);
779 
780 	return IsIPAddressInList(&ip);
781 }
IsIPv6AddressInList(void * addr)782 bool IsIPv6AddressInList(void *addr)
783 {
784 	WFP_LOCAL_IP ip;
785 	// Validate arguments
786 	if (addr == NULL)
787 	{
788 		return false;
789 	}
790 
791 	Zero(&ip, sizeof(ip));
792 	ip.IpVersion = 6;
793 	Copy(ip.IpAddress.IPv6Address, addr, 16);
794 
795 	return IsIPAddressInList(&ip);
796 }
797 
798 // Win32 driver entry point
DriverEntry(DRIVER_OBJECT * driver_object,UNICODE_STRING * registry_path)799 NTSTATUS DriverEntry(DRIVER_OBJECT *driver_object, UNICODE_STRING *registry_path)
800 {
801 	NTSTATUS ret;
802 	FWPM_SESSION0 t;
803 	ULONG os_ver1 = 0, os_ver2 = 0;
804 
805 	if (wfp != NULL)
806 	{
807 		return STATUS_UNSUCCESSFUL;
808 	}
809 
810 	g_is_win8 = false;
811 	g_pool_type = NonPagedPool;
812 
813 	PsGetVersion(&os_ver1, &os_ver2, NULL, NULL);
814 
815 	if ((os_ver1 == 6 && os_ver2 >= 2) || (os_ver1 >= 7))
816 	{
817 		g_is_win8 = true;
818 		g_pool_type = 512;
819 	}
820 
821 	wfp = ZeroMalloc(sizeof(WFP_CTX));
822 
823 	RtlInitUnicodeString(&wfp->DeviceName, WFP_DEVICE_NAME);
824 	RtlInitUnicodeString(&wfp->DeviceNameWin32, WFP_DEVICE_NAME_WIN32);
825 	// Create a device
826 	ret = IoCreateDevice(driver_object, 0, &wfp->DeviceName, FILE_DEVICE_NETWORK, 0, false, &wfp->DeviceObject);
827 	if (NG(ret))
828 	{
829 		return ret;
830 	}
831 
832 	// Open the NDIS handle
833 	wfp->hNdis = NdisAllocateGenericObject(driver_object, MEMPOOL_TAG, 0);
834 	if (wfp->hNdis == NULL)
835 	{
836 		DriverUnload(driver_object);
837 		return STATUS_UNSUCCESSFUL;
838 	}
839 
840 	// Create a symbolic device for Win32
841 	ret = IoCreateSymbolicLink(&wfp->DeviceNameWin32, &wfp->DeviceName);
842 	if (NG(ret))
843 	{
844 		DriverUnload(driver_object);
845 		return ret;
846 	}
847 
848 	driver_object->DriverUnload = DriverUnload;
849 
850 	// Create an Event
851 	wfp->Event = NewEvent(WFP_EVENT_NAME);
852 	if (wfp->Event == NULL)
853 	{
854 		DriverUnload(driver_object);
855 		return STATUS_UNSUCCESSFUL;
856 	}
857 
858 	// Open the WFP engine
859 	Zero(&t, sizeof(t));
860 	t.flags = FWPM_SESSION_FLAG_DYNAMIC;
861 	ret = FwpmEngineOpen0(NULL, RPC_C_AUTHN_DEFAULT, NULL, &t, &wfp->hEngine);
862 	if (NG(ret))
863 	{
864 		DriverUnload(driver_object);
865 		return ret;
866 	}
867 	else
868 	{
869 		// Register itself as a Callout Driver
870 		FWPS_CALLOUT0 s;
871 //		FWPM_CALLOUT0 callout;
872 
873 		Zero(&s, sizeof(s));
874 		s.calloutKey = GUID_WFP_CALLOUT_DRIVER_V4;
875 		s.classifyFn = CalloutClassify;
876 		s.notifyFn = CalloutNotify;
877 
878 		ret = FwpsCalloutRegister0(wfp->DeviceObject, &s, &wfp->CalloutIdIPv4);
879 		if (NG(ret))
880 		{
881 			DriverUnload(driver_object);
882 			return ret;
883 		}
884 
885 		Zero(&s, sizeof(s));
886 		s.calloutKey = GUID_WFP_CALLOUT_DRIVER_V6;
887 		s.classifyFn = CalloutClassify;
888 		s.notifyFn = CalloutNotify;
889 
890 		ret = FwpsCalloutRegister0(wfp->DeviceObject, &s, &wfp->CalloutIdIPv6);
891 		if (NG(ret))
892 		{
893 			DriverUnload(driver_object);
894 			return ret;
895 		}
896 
897 		/*// Create the Callout Driver (IPv4)
898 		Zero(&callout, sizeof(callout));
899 		callout.calloutKey = GUID_WFP_CALLOUT_DRIVER_V4;
900 		callout.applicableLayer = FWPM_LAYER_INBOUND_IPPACKET_V4;
901 		callout.displayData.name = WFP_DRIVER_TITLE_V4;
902 		ret = FwpmCalloutAdd0(wfp->hEngine, &callout, NULL, &wfp->CalloutObjIdIPv4);
903 
904 		// Create the Callout Driver (IPv6)
905 		Zero(&callout, sizeof(callout));
906 		callout.calloutKey = GUID_WFP_CALLOUT_DRIVER_V6;
907 		callout.applicableLayer = FWPM_LAYER_INBOUND_IPPACKET_V6;
908 		callout.displayData.name = WFP_DRIVER_TITLE_V6;
909 		ret = FwpmCalloutAdd0(wfp->hEngine, &callout, NULL, &wfp->CalloutObjIdIPv6);*/
910 
911 		// Create an injection handle
912 		FwpsInjectionHandleCreate0(AF_INET, FWPS_INJECTION_TYPE_NETWORK, &wfp->hInjectionIPv4);
913 		if (NG(ret))
914 		{
915 			wfp->hInjectionIPv4 = NULL;
916 		}
917 		ret = FwpsInjectionHandleCreate0(AF_INET6, FWPS_INJECTION_TYPE_NETWORK,&wfp->hInjectionIPv6);
918 		if (NG(ret))
919 		{
920 			wfp->hInjectionIPv6 = NULL;
921 		}
922 	}
923 
924 	// Create a lock
925 	wfp->LocalIPListLock = NewSpinLock();
926 
927 	// Specify a service function
928 	driver_object->MajorFunction[IRP_MJ_CREATE] =
929 		driver_object->MajorFunction[IRP_MJ_CLOSE] =
930 		driver_object->MajorFunction[IRP_MJ_READ] =
931 		driver_object->MajorFunction[IRP_MJ_WRITE] = DriverDispatch;
932 
933 	return STATUS_SUCCESS;
934 }
935 
936 // Unload the driver
DriverUnload(DRIVER_OBJECT * driver_object)937 void DriverUnload(DRIVER_OBJECT *driver_object)
938 {
939 	// Validate arguments
940 	if (wfp == NULL || driver_object == NULL)
941 	{
942 		return;
943 	}
944 
945 	wfp->Halting = true;
946 
947 	// Delete the lock
948 	FreeSpinLock(wfp->LocalIPListLock);
949 
950 	// Delete the injection handle
951 	if (wfp->hInjectionIPv4 != NULL)
952 	{
953 		FwpsInjectionHandleDestroy0(wfp->hInjectionIPv4);
954 	}
955 	if (wfp->hInjectionIPv6 != NULL)
956 	{
957 		FwpsInjectionHandleDestroy0(wfp->hInjectionIPv6);
958 	}
959 
960 	// Delete the Callout Object
961 	if (wfp->hEngine != NULL)
962 	{
963 		//FwpmCalloutDeleteByKey0(wfp->hEngine, &GUID_WFP_CALLOUT_DRIVER_V4);
964 		//FwpmCalloutDeleteByKey0(wfp->hEngine, &GUID_WFP_CALLOUT_DRIVER_V6);
965 	}
966 
967 	if (wfp->CalloutIdIPv4 != 0)
968 	{
969 		// Delete the registration of Callout Driver (IPv4)
970 		FwpsCalloutUnregisterById0(wfp->CalloutIdIPv4);
971 	}
972 
973 	if (wfp->CalloutIdIPv6 != 0)
974 	{
975 		// Delete the registration of Callout Driver (IPv6)
976 		FwpsCalloutUnregisterById0(wfp->CalloutIdIPv6);
977 	}
978 
979 	FreeEvent(wfp->Event);
980 
981 	IoDeleteSymbolicLink(&wfp->DeviceNameWin32);
982 
983 	if (wfp->DeviceObject != NULL)
984 	{
985 		IoDeleteDevice(wfp->DeviceObject);
986 	}
987 
988 	if (wfp->hEngine != NULL)
989 	{
990 		FwpmEngineClose0(wfp->hEngine);
991 	}
992 
993 	if (wfp->LocalIPListData != NULL)
994 	{
995 		Free(wfp->LocalIPListData);
996 	}
997 
998 	// Close the NDIS handle
999 	if (wfp->hNdis != NULL)
1000 	{
1001 		NdisFreeGenericObject(wfp->hNdis);
1002 	}
1003 
1004 	Free(wfp);
1005 
1006 	wfp = NULL;
1007 }
1008 
1009 // Create an Event
NewEvent(wchar_t * name)1010 EVENT *NewEvent(wchar_t *name)
1011 {
1012 	EVENT *e;
1013 	KEVENT *ke;
1014 	HANDLE h;
1015 	UNICODE_STRING name_str;
1016 	// Validate arguments
1017 	if (name == NULL)
1018 	{
1019 		return NULL;
1020 	}
1021 
1022 	RtlInitUnicodeString(&name_str, name);
1023 
1024 	ke = IoCreateNotificationEvent(&name_str, &h);
1025 	if (ke == NULL)
1026 	{
1027 		return NULL;
1028 	}
1029 
1030 	KeInitializeEvent(ke, NotificationEvent, false);
1031 	KeClearEvent(ke);
1032 
1033 	e = ZeroMalloc(sizeof(EVENT));
1034 
1035 	e->EventObj = ke;
1036 	e->Handle = h;
1037 
1038 	return e;
1039 }
1040 
1041 // Delete the event
FreeEvent(EVENT * e)1042 void FreeEvent(EVENT *e)
1043 {
1044 	// Validate arguments
1045 	if (e == NULL)
1046 	{
1047 		return;
1048 	}
1049 
1050 	ZwClose(e->Handle);
1051 
1052 	Free(e);
1053 }
1054 
1055 // Set the event
SetEvent(EVENT * e)1056 void SetEvent(EVENT *e)
1057 {
1058 	// Validate arguments
1059 	if (e == NULL)
1060 	{
1061 		return;
1062 	}
1063 
1064 	KeSetEvent(e->EventObj, 0, false);
1065 }
1066 
1067 // Reset the event
ResetEvent(EVENT * e)1068 void ResetEvent(EVENT *e)
1069 {
1070 	// Validate arguments
1071 	if (e == NULL)
1072 	{
1073 		return;
1074 	}
1075 
1076 	KeResetEvent(e->EventObj);
1077 }
1078 
1079 // Allocate the memory
Malloc(UINT size)1080 void *Malloc(UINT size)
1081 {
1082 	void *p;
1083 
1084 	p = ExAllocatePoolWithTag(g_pool_type, size + sizeof(UINT), MEMPOOL_TAG);
1085 	*((UINT *)p) = size;
1086 
1087 	return ((UCHAR *)p) + sizeof(UINT);
1088 }
ZeroMalloc(UINT size)1089 void *ZeroMalloc(UINT size)
1090 {
1091 	void *p = Malloc(size);
1092 	Zero(p, size);
1093 	return p;
1094 }
1095 
1096 // Change the memory block size
ReAlloc(void * p,UINT size)1097 void *ReAlloc(void *p, UINT size)
1098 {
1099 	void *ret;
1100 	UINT oldsize;
1101 	// Validate arguments
1102 	if (p == NULL)
1103 	{
1104 		return NULL;
1105 	}
1106 
1107 	ret = Malloc(size);
1108 	if (ret == NULL)
1109 	{
1110 		Free(p);
1111 		return NULL;
1112 	}
1113 
1114 	oldsize = GetMemSize(p);
1115 
1116 	Copy(ret, p, MIN(size, oldsize));
1117 
1118 	Free(p);
1119 
1120 	return ret;
1121 }
1122 
1123 // Copy memory
Copy(void * dst,void * src,UINT size)1124 void Copy(void *dst, void *src, UINT size)
1125 {
1126 	// Validate arguments
1127 	if (dst == NULL || src == NULL || size == 0)
1128 	{
1129 		return;
1130 	}
1131 
1132 	memcpy(dst, src, size);
1133 }
1134 
1135 // Get the memory block size
GetMemSize(void * p)1136 UINT GetMemSize(void *p)
1137 {
1138 	// Validate arguments
1139 	if (p == NULL)
1140 	{
1141 		return 0;
1142 	}
1143 
1144 	return *(UINT *)(((UCHAR *)p) - sizeof(UINT));
1145 }
1146 
1147 // Release the memory
Free(void * p)1148 void Free(void *p)
1149 {
1150 	// Validate arguments
1151 	if (p == NULL)
1152 	{
1153 		return;
1154 	}
1155 
1156 	p = ((UCHAR *)p) - sizeof(UINT);
1157 
1158 	ExFreePoolWithTag(p, MEMPOOL_TAG);
1159 }
1160 
1161 // Clear the memory to zero
Zero(void * p,UINT size)1162 void Zero(void *p, UINT size)
1163 {
1164 	// Validate arguments
1165 	if (p == NULL || size == 0)
1166 	{
1167 		return;
1168 	}
1169 
1170 	memset(p, 0, size);
1171 }
1172 
1173 // Comparison of memory
Cmp(void * p1,void * p2,UINT size)1174 UINT Cmp(void *p1, void *p2, UINT size)
1175 {
1176 	UCHAR *c1 = (UCHAR *)p1;
1177 	UCHAR *c2 = (UCHAR *)p2;
1178 	UINT i;
1179 
1180 	for (i = 0;i < size;i++)
1181 	{
1182 		if (c1[i] != c2[i])
1183 		{
1184 			if (c1[i] > c2[i])
1185 			{
1186 				return 1;
1187 			}
1188 			else
1189 			{
1190 				return -1;
1191 			}
1192 		}
1193 	}
1194 
1195 	return 0;
1196 }
1197 
1198 // Create a spin lock
NewSpinLock()1199 SPINLOCK *NewSpinLock()
1200 {
1201 	SPINLOCK *s = ZeroMalloc(sizeof(SPINLOCK));
1202 
1203 	KeInitializeSpinLock(&s->SpinLock);
1204 
1205 	return s;
1206 }
1207 
1208 // Lock
SpinLock(SPINLOCK * s)1209 void SpinLock(SPINLOCK *s)
1210 {
1211 	// Validate arguments
1212 	if (s == NULL)
1213 	{
1214 		return;
1215 	}
1216 
1217 	KeAcquireSpinLock(&s->SpinLock, &s->OldIrql);
1218 }
1219 
1220 // Unlock
SpinUnlock(SPINLOCK * s)1221 void SpinUnlock(SPINLOCK *s)
1222 {
1223 	// Validate arguments
1224 	if (s == NULL)
1225 	{
1226 		return;
1227 	}
1228 
1229 	KeReleaseSpinLock(&s->SpinLock, s->OldIrql);
1230 }
1231 
1232 // Release the spin lock
FreeSpinLock(SPINLOCK * s)1233 void FreeSpinLock(SPINLOCK *s)
1234 {
1235 	// Validate arguments
1236 	if (s == NULL)
1237 	{
1238 		return;
1239 	}
1240 
1241 	Free(s);
1242 }
1243 
1244 // Sleep
Sleep(int milliSeconds)1245 void Sleep(int milliSeconds)
1246 {
1247 	PKTIMER timer = ZeroMalloc(sizeof(KTIMER));
1248 	LARGE_INTEGER duetime;
1249 
1250 	duetime.QuadPart = (__int64)milliSeconds * -10000;
1251 	KeInitializeTimerEx(timer, NotificationTimer);
1252 	KeSetTimerEx(timer, duetime, 0, NULL);
1253 
1254 	KeWaitForSingleObject (timer, Executive, KernelMode, FALSE, NULL);
1255 
1256 	Free(timer);
1257 }
1258 
1259 // 16-bit swap
Swap16(USHORT value)1260 USHORT Swap16(USHORT value)
1261 {
1262 	USHORT r;
1263 	((BYTE *)&r)[0] = ((BYTE *)&value)[1];
1264 	((BYTE *)&r)[1] = ((BYTE *)&value)[0];
1265 	return r;
1266 }
1267 
1268 // 32-bit swap
Swap32(UINT value)1269 UINT Swap32(UINT value)
1270 {
1271 	UINT r;
1272 	((BYTE *)&r)[0] = ((BYTE *)&value)[3];
1273 	((BYTE *)&r)[1] = ((BYTE *)&value)[2];
1274 	((BYTE *)&r)[2] = ((BYTE *)&value)[1];
1275 	((BYTE *)&r)[3] = ((BYTE *)&value)[0];
1276 	return r;
1277 }
1278 
1279 // 64-bit swap
Swap64(UINT64 value)1280 UINT64 Swap64(UINT64 value)
1281 {
1282 	UINT64 r;
1283 	((BYTE *)&r)[0] = ((BYTE *)&value)[7];
1284 	((BYTE *)&r)[1] = ((BYTE *)&value)[6];
1285 	((BYTE *)&r)[2] = ((BYTE *)&value)[5];
1286 	((BYTE *)&r)[3] = ((BYTE *)&value)[4];
1287 	((BYTE *)&r)[4] = ((BYTE *)&value)[3];
1288 	((BYTE *)&r)[5] = ((BYTE *)&value)[2];
1289 	((BYTE *)&r)[6] = ((BYTE *)&value)[1];
1290 	((BYTE *)&r)[7] = ((BYTE *)&value)[0];
1291 	return r;
1292 }
1293 
1294 // Endian conversion 16bit
Endian16(USHORT src)1295 USHORT Endian16(USHORT src)
1296 {
1297 	int x = 1;
1298 	if (*((char *)&x))
1299 	{
1300 		return Swap16(src);
1301 	}
1302 	else
1303 	{
1304 		return src;
1305 	}
1306 }
1307 
1308 // Endian conversion 32bit
Endian32(UINT src)1309 UINT Endian32(UINT src)
1310 {
1311 	int x = 1;
1312 	if (*((char *)&x))
1313 	{
1314 		return Swap32(src);
1315 	}
1316 	else
1317 	{
1318 		return src;
1319 	}
1320 }
1321 
1322 // Endian conversion 64bit
Endian64(UINT64 src)1323 UINT64 Endian64(UINT64 src)
1324 {
1325 	int x = 1;
1326 	if (*((char *)&x))
1327 	{
1328 		return Swap64(src);
1329 	}
1330 	else
1331 	{
1332 		return src;
1333 	}
1334 }
1335 
1336 // Crash
Crush(UINT a,UINT b,UINT c,UINT d)1337 void Crush(UINT a, UINT b, UINT c, UINT d)
1338 {
1339 	KeBugCheckEx(0x00000061, (ULONG_PTR)a, (ULONG_PTR)b, (ULONG_PTR)c, (ULONG_PTR)d);
1340 }
1341