Last active
April 5, 2023 07:42
-
-
Save gvanem/d63ab3ad81883c9c5f757bb7e62a0606 to your computer and use it in GitHub Desktop.
GNU-makefile for NPcap's NPF.sys driver
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# | |
# GNU Makefile for the 'NPcap driver'. | |
# For MSVC + clang-cl, 32/64 bits. | |
# | |
# By <[email protected]> 2023. | |
# | |
TARGETS := NPcap.sys | |
THIS_FILE := Makefile.Windows | |
MAKEFLAGS += --warn-undefined-variables | |
USE_ASTYLE ?= 1 | |
PYTHON ?= py -3 | |
ifeq ($(CPU),x86) | |
BITS = 32 | |
else ifeq ($(CPU),x64) | |
BITS = 64 | |
else | |
$(error Unsupported CPU=$(CPU)) | |
endif | |
export CL= | |
GENERATED = $(OBJ_DIR)/NPcap_hacks.h | |
NPF_DIR = packetWin7/npf/npf | |
# | |
# The default install location for the 'Windows Device Driver Kit' is | |
# alongside the user-mode Windows-Kit: | |
# Kernel-mode ('KM') headers under: | |
# | |
# $(WindowsSdkDir)/Include/$(WindowsSdkVer)/km | |
# | |
# and libraries under: | |
# | |
# $(WindowsSdkDir)/Lib/$(WindowsSdkVer)/km/$(CPU) | |
# | |
KM_INCDIR = $(realpath $(WindowsSdkDir))/Include/$(WindowsSdkVer)/km | |
KM_LIBDIR = $(realpath $(WindowsSdkDir))/Lib/$(WindowsSdkVer)/km | |
TOOLS_ROOT = $(realpath $(VCToolkitInstallDir)) | |
UCRT_LIBDIR = $(realpath $(WindowsSdkDir))/Lib/$(WindowsSdkVer)/ucrt/$(CPU) | |
UM_LIBDIR = $(realpath $(WindowsSdkDir))/Lib/$(WindowsSdkVer)/um/$(CPU) | |
CRT_LIBDIR = $(TOOLS_ROOT)/lib/$(CPU) | |
define Usage | |
Usage: "make -f $(THIS_FILE) <CPU=x86|x64> CC=[cl | clang-cl] [all | clean | realclean | depend]" | |
Specify CC=cl - use MSVC | |
Specify CC=clang-cl - use clang-cl | |
endef | |
CFLAGS = -nologo -MT -Ot -GS- \ | |
-Gz -Zi -Zo -Oy- \ | |
-I$(KM_INCDIR) \ | |
-I. \ | |
-FI./$(OBJ_DIR)/NPcap_hacks.h | |
LDFLAGS = -nologo -verbose -incremental:no \ | |
-map -debug -machine:$(CPU) \ | |
-nodefaultlib:oldnames.lib \ | |
-libpath:$(UCRT_LIBDIR) \ | |
-libpath:$(CRT_LIBDIR) | |
OBJ_DIR = objects | |
ifeq ($(CC),cl) | |
_CC = $(TOOLS_ROOT)/bin/HostX86/$(CPU)/cl.exe | |
CFLAGS += -W4 | |
else ifeq ($(CC),clang-cl) | |
# | |
# The 'clang-cl.bat' (on PATH) should look like this: | |
# @echo off | |
# setlocal | |
# set CL_32=f:\ProgramFiler\LLVM-15-32bit << install base of your 32-bit Clang | |
# set CL_64=f:\ProgramFiler\LLVM-15-64bit << ditto for 64-bit | |
# if %1. == -m32. ( | |
# shift | |
# %CL_32%\bin\clang-cl.exe %* | |
# ) else if %1. == -m64. ( | |
# shift | |
# %CL_64%\bin\clang-cl.exe %* | |
# ) else ( | |
# clang-cl.exe %* | |
# ) | |
# | |
_CC = clang-cl.bat -m$(BITS) | |
CFLAGS += -Wall \ | |
-ferror-limit=5 \ | |
-fms-compatibility | |
else | |
$(error $(Usage)) | |
endif | |
vpath %.c $(NPF_DIR) | |
C_SOURCES = $(addprefix $(NPF_DIR)/, \ | |
Loopback.c \ | |
Openclos.c \ | |
Packet.c \ | |
Read.c \ | |
Write.c \ | |
win_bpf_filter.c) | |
C_OBJECTS = $(addprefix $(OBJ_DIR)/, $(notdir $(C_SOURCES:.c=.obj))) | |
all: $(GENERATED) $(TARGETS) epilogue | |
epilogue: | |
$(call green_msg, Welcome to $(BRIGHT_WHITE)$(TARGETS)) | |
WDK_LIBS = $(KM_LIBDIR)/$(CPU)/fwpkclnt.lib \ | |
$(KM_LIBDIR)/$(CPU)/ndis.lib \ | |
$(KM_LIBDIR)/$(CPU)/wdm.lib \ | |
$(KM_LIBDIR)/$(CPU)/wdmsec.lib \ | |
$(UM_LIBDIR)/kernel32.lib \ | |
$(UM_LIBDIR)/uuid.lib | |
SYS_LDFLAGS = -entry:DriverEntry \ | |
-integritycheck \ | |
-brepro \ | |
-dependentloadflag:0x800 \ | |
-subsystem:native | |
NPcap.sys: $(C_OBJECTS) $(OBJ_DIR)/npcap.res $(WDK_LIBS) | check-for-unused-libs.py | |
$(call link_SYS, $@, $(SYS_LDFLAGS) $^) | |
$(OBJ_DIR)/NPcap_hacks.h: $(THIS_FILE) | $(OBJ_DIR) | |
$(call generate_c, $@,$(NPcap_hacks_H)) | |
$(OBJ_DIR): | |
- mkdir $@ | |
$(OBJ_DIR)/%.obj: %.c | $(CC).args | |
$(call C_compile, $@, $<) | |
$(OBJ_DIR)/%.res: $(NPF_DIR)/%.rc | |
$(call make_res, $@, $<) | |
clean: | |
rm -f vc1*.pdb link.tmp link.args cl.args clang-cl.args \ | |
NPcap.{map,pdb} cpp-filter.py check-for-unused-libs.py | |
rm -fr $(OBJ_DIR) | |
$(CC).args: $(THIS_FILE) | |
$(call green_msg, All CFLAGS are in $(BRIGHT_WHITE)$@) | |
$(call create_resp_file, $@, -c $(call put_D_CFLAGS_first, $(CFLAGS))) | |
realclean vclean: clean | |
rm -f .depend.Windows $(sort $(TARGETS) $(TARGETS:.sys=.{map,pdb,exp})) | |
%.i: %.c FORCE cpp-filter.py $(GENERATED) $(CC).args | |
$(call C_preprocess, $@, $<) | |
FORCE: | |
cpp-filter.py: $(THIS_FILE) | |
$(call generate_py, $@, $(CPP_FILTER_PY)) | |
check-for-unused-libs.py: $(THIS_FILE) | |
$(call generate_py, $@, $(CHECK_FOR_UNUSED_LIBS_PY)) | |
# | |
# GNU-make macros: | |
# | |
put_D_CFLAGS_first = $(filter -D%, $(1)) \ | |
$(filter-out -D%, $(1)) | |
BRIGHT_GREEN = \e[1;32m | |
BRIGHT_WHITE = \e[1;37m | |
green_msg = @echo -e "$(BRIGHT_GREEN)$(strip $(1))\e[0m" | |
define C_compile | |
$(_CC) @$(CC).args -Fo./$(strip $(1)) $(2) | |
@echo | |
endef | |
define link_SYS | |
$(call green_msg, Linking $(1)) | |
$(call create_resp_file, link.args, $(LDFLAGS) $(2)) | |
link -out:$(strip $(1)) @link.args > link.tmp | |
@cat link.tmp >> $(1:.sys=.map) | |
@$(PYTHON) check-for-unused-libs.py link.tmp | |
endef | |
define make_res | |
rc -nologo -fo $(1) $(2) | |
@echo | |
endef | |
define create_resp_file | |
$(file > $(1)) | |
$(foreach f, $(2), $(file >> $(1),$(strip $(f))) ) | |
endef | |
define generate | |
$(call green_msg, Generating $(1).) | |
$(call Warning, $(1),$(2)) | |
endef | |
define generate_c | |
$(call generate, $(1), //) | |
$(file >> $(1),$(2)) | |
endef | |
define generate_py | |
$(call generate, $(1), #) | |
$(file >> $(1),if 1:) | |
$(file >> $(1),$(2)) | |
endef | |
define Warning | |
$(file > $(1),$(2)) | |
$(file >> $(1),$(2) This file was generated at $(shell date +%d-%B-%Y) from) | |
$(file >> $(1),$(2) $(realpath $(THIS_FILE)).) | |
$(file >> $(1),$(2) DO NOT EDIT!) | |
$(file >> $(1),$(2)) | |
endef | |
# | |
# clang-cl: /d1PP Retain macro definitions in /E mode | |
# | |
ifeq ($(CC),clang-cl) | |
d1PP = -d1PP | |
else | |
d1PP = | |
endif | |
ifeq ($(USE_ASTYLE),1) | |
C_preprocess_filter = | astyle | |
C_preprocess_comment = and AStyle'd | |
else | |
C_preprocess_filter = | |
C_preprocess_comment = raw | |
endif | |
define C_preprocess | |
$(file > $(1),/* The preprocessed $(C_preprocess_comment) output of '$(filter %.c, $(strip $(2)))':) | |
$(foreach f, $(_CC) -E $(CFLAGS) $(d1PP), $(file >> $(1), * $(f))) | |
$(file >> $(1), *) | |
$(file >> $(1), * Try compiling it with '$(strip $(_CC) -c -Tc $(1))') | |
$(file >> $(1), *---------------------------------------------------------------------) | |
$(file >> $(1), */) | |
$(_CC) -E @$(CC).args $(d1PP) $(2) | $(PYTHON) cpp-filter.py $(C_preprocess_filter) >> $(1) | |
endef | |
define NPcap_hacks_H | |
#ifndef NPcap_hacks_H | |
#define NPcap_hacks_H | |
#if defined(__clang__) | |
#define NDIS_FILTER_MAJOR_VERSION 6 | |
#define NDIS_FILTER_MINOR_VERSION 0 | |
#define NDIS_WRAPPER 1 | |
#define EXPORT | |
/* | |
* 'clang-cl -Wall' generates tons of warnings. | |
* Especially from the Windows DDK. | |
*/ | |
#pragma clang diagnostic ignored "-Wundef" | |
#pragma clang diagnostic ignored "-Wcomment" | |
#pragma clang diagnostic ignored "-Wcast-align" | |
#pragma clang diagnostic ignored "-Wcast-qual" | |
#pragma clang diagnostic ignored "-Wcast-function-type-strict" | |
#pragma clang diagnostic ignored "-Wimplicit-int-conversion" | |
#pragma clang diagnostic ignored "-Wbad-function-cast" | |
#pragma clang diagnostic ignored "-Wlanguage-extension-token" | |
#pragma clang diagnostic ignored "-Wdeclaration-after-statement" | |
#pragma clang diagnostic ignored "-Wreserved-identifier" | |
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage" | |
#pragma clang diagnostic ignored "-Wvisibility" | |
#pragma clang diagnostic ignored "-Wsizeof-array-div" | |
#pragma clang diagnostic ignored "-Wsign-compare" | |
#pragma clang diagnostic ignored "-Wsign-conversion" | |
#pragma clang diagnostic ignored "-Wpragma-pack" | |
#pragma clang diagnostic ignored "-Wfour-char-constants" | |
#pragma clang diagnostic ignored "-Wflexible-array-extensions" | |
#pragma clang diagnostic ignored "-Wdocumentation" | |
#pragma clang diagnostic ignored "-Wswitch-enum" | |
#pragma clang diagnostic ignored "-Wextra-tokens" | |
#pragma clang diagnostic ignored "-Wextra-semi" | |
#pragma clang diagnostic ignored "-Wextra-semi-stmt" | |
#pragma clang diagnostic ignored "-Wredundant-parens" | |
#pragma clang diagnostic ignored "-Wpointer-sign" | |
#pragma clang diagnostic ignored "-Wunused-macros" | |
#pragma clang diagnostic ignored "-Wunused-parameter" | |
#pragma clang diagnostic ignored "-Wunused-value" | |
#pragma clang diagnostic ignored "-Wunused-variable" | |
#pragma clang diagnostic ignored "-Wunused-but-set-variable" | |
#pragma clang diagnostic ignored "-Wunused-local-typedef" | |
#pragma clang diagnostic ignored "-Wmissing-noreturn" | |
#pragma clang diagnostic ignored "-Wmissing-prototypes" | |
#pragma clang diagnostic ignored "-Wmissing-variable-declarations" | |
#pragma clang diagnostic ignored "-Wunknown-pragmas" | |
#pragma clang diagnostic ignored "-Wstrict-prototypes" | |
#pragma clang diagnostic ignored "-Wunreachable-code-break" | |
#pragma clang diagnostic ignored "-Wint-conversion" | |
#pragma clang diagnostic ignored "-Wduplicate-enum" | |
#pragma clang diagnostic ignored "-Wint-to-void-pointer-cast" | |
#pragma clang diagnostic ignored "-Wincompatible-pointer-types" | |
#pragma clang diagnostic ignored "-Wignored-attributes" | |
#pragma clang diagnostic ignored "-Wignored-pragma-intrinsic" | |
#pragma clang diagnostic ignored "-Wmicrosoft-anon-tag" | |
#pragma clang diagnostic ignored "-Wmicrosoft-enum-value" | |
#pragma clang diagnostic ignored "-Wmicrosoft-enum-forward-reference" | |
#pragma clang diagnostic ignored "-Wmicrosoft-flexible-array" | |
#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments" | |
#if defined(i386) | |
#pragma clang diagnostic ignored "-Wmissing-prototype-for-cc" | |
#endif | |
#elif defined(_MSC_VER) | |
#pragma warning (disable:4024 4047 4057 4100 4189 4306 4324 4389) | |
#endif | |
#define HAVE_DOT11_SUPPORT 1 | |
#define HAVE_WFP_LOOPBACK_SUPPORT 1 | |
#define HAVE_RX_SUPPORT 1 | |
#define NDIS630 1 | |
#define WINVER 0x0602 | |
#define _WIN32_WINNT 0x0602 | |
#define NTDDI_VERSION 0x06020000 | |
#define _CRT_SECURE_NO_WARNINGS 1 | |
#define _CRT_NONSTDC_NO_DEPRECATE 1 | |
//#define UNICODE | |
//#define _UNICODE | |
//#define MICROSOFT_WINDOWS_WINBASE_H_DEFINE_INTERLOCKED_CPLUSPLUS_OVERLOADS 0 | |
//#define RELOCATABLE_USER_SHARED_DATA 1 | |
#define _KERNEL_MODE 1 | |
#define POOL_NX_OPTIN 1 | |
#define POOL_ZERO_DOWN_LEVEL_SUPPORT 1 | |
#define BITS $(BITS) | |
#if (BITS == 32) | |
#define _X86_ 1 | |
#define i386 1 | |
#define STD_CALL 1 | |
#elif (BITS == 64) | |
#define _WIN64 1 | |
#define _AMD64_ 1 | |
#define AMD64 1 | |
#else | |
#error "Define 'BITS' to either '32' or '64'." | |
#endif | |
#endif /* NPcap_hacks_H */ | |
endef | |
define CPP_FILTER_PY | |
import sys, os | |
empty_lines = 0 | |
while True: | |
line = sys.stdin.readline() | |
if not line: | |
break | |
line = line.rstrip() | |
if line == "": | |
empty_lines += 1 | |
continue | |
if line.lstrip().startswith("# "): | |
line = line.replace (r"# ", "#line ") | |
if line.lstrip().startswith("#line"): | |
line = line.replace (r"\\", "/") | |
print (line) | |
if line == "}" or line == "};": | |
print ("") | |
print ("Removed %d empty lines." % empty_lines, file=sys.stderr) | |
endef | |
define CHECK_FOR_UNUSED_LIBS_PY | |
import os, sys | |
map_file = sys.argv[1] | |
class State(): | |
IDLE = 0 | |
UNUSED = 1 | |
class Color(): | |
RESET = RED = WHITE = "" | |
try: | |
from colorama import init, Fore, Style | |
init() | |
Color.RESET = Style.RESET_ALL | |
Color.RED = Fore.RED + Style.BRIGHT | |
Color.WHITE = Fore.WHITE + Style.BRIGHT | |
except: | |
pass | |
def cprint (color, s): | |
print ("%s%s%s" % (color, s, Color.RESET)) | |
def report (unused): | |
num = len(unused) | |
plural = [ "library", "libraries" ] | |
if num > 0: | |
cprint (Color.RED, "%d unused %s in %s:" % (num, plural[num > 1], map_file)) | |
for u in unused: | |
print (" " + u) | |
cprint (Color.WHITE, "Done.\n") | |
def process (state): | |
unused_libs = [] | |
f = open (map_file, "rt") | |
lines = f.readlines() | |
f.close() | |
for l in lines: | |
l = l.strip() | |
if l == "Unused libraries:": | |
state = State.UNUSED | |
continue | |
if state == State.UNUSED: | |
if l == "": | |
break | |
unused_libs.append (l) | |
return unused_libs | |
report (process(State.IDLE)) | |
endef | |
DEP_CFLAGS = -MM $(filter -D% -I%, $(CFLAGS)) \ | |
-DNDIS_SUPPORT_NDIS620=1 \ | |
-D_NDIS_ \ | |
-D_NTDDK_ \ | |
-D_NTIFS_ \ | |
-D_WDMDDK_ \ | |
-DFWPSX_H | |
DEP_REPLACE = -e 's@\(.*\)\.o: @\n$$(OBJ_DIR)\/\1.obj: @' \ | |
-e 's@$(OBJ_DIR)@$$(OBJ_DIR)@' \ | |
-e 's@$(KM_INCDIR)@$$(KM_INCDIR)@' \ | |
-e 's@$(NPF_DIR)@$$(NPF_DIR)@' | |
depend: $(GENERATED) | |
$(call green_msg, Generating dependencies for $(words $(C_SOURCES)) .c-files...) | |
$(call Warning, .depend.Windows, #) | |
gcc $(DEP_CFLAGS) $(C_SOURCES) | sed $(DEP_REPLACE) >> .depend.Windows | |
-include .depend.Windows | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment