summaryrefslogtreecommitdiffstats
path: root/win
diff options
context:
space:
mode:
Diffstat (limited to 'win')
-rw-r--r--win/__init__.py0
-rw-r--r--win/autodefs.h.in31
-rw-r--r--win/build.py22
-rw-r--r--win/build_all.py59
-rw-r--r--win/build_ddk.py54
-rw-r--r--win/build_exe.py15
-rw-r--r--win/config.py18
-rw-r--r--win/config_all.py13
-rw-r--r--win/config_tap.py35
-rw-r--r--win/config_ti.py18
-rw-r--r--win/js.py10
-rw-r--r--win/make_dist.py56
-rw-r--r--win/msvc.mak.in57
-rw-r--r--win/settings.in68
-rw-r--r--win/show.py10
-rw-r--r--win/sign.py19
-rw-r--r--win/tap_span.py129
-rw-r--r--win/wb.py215
18 files changed, 829 insertions, 0 deletions
diff --git a/win/__init__.py b/win/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/win/__init__.py
diff --git a/win/autodefs.h.in b/win/autodefs.h.in
new file mode 100644
index 0000000..2edd9b6
--- /dev/null
+++ b/win/autodefs.h.in
@@ -0,0 +1,31 @@
+#ifndef AUTODEFS_H
+#define AUTODEFS_H
+
+/*
+ * Minimum TAP-Win32 version number expected by userspace
+ *
+ * The TAP-Win32 version number is defined in tap-win32/SOURCES
+ */
+#define TAP_ID "@PRODUCT_TAP_ID@"
+#define TAP_WIN32_MIN_MAJOR @PRODUCT_TAP_WIN32_MIN_MAJOR@
+#define TAP_WIN32_MIN_MINOR @PRODUCT_TAP_WIN32_MIN_MINOR@
+
+/* Friendly name for TAP driver */
+#define PRODUCT_TAP_DEVICE_DESCRIPTION "@PRODUCT_TAP_DEVICE_DESCRIPTION@"
+
+/* Version number of DDK/WDK used to build TAP driver */
+#define DDKVER_MAJOR @DDKVER_MAJOR@
+
+/* Name of package */
+#define PACKAGE "@PRODUCT_UNIX_NAME@"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "@PRODUCT_NAME@"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "@PRODUCT_UNIX_NAME@"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "@PRODUCT_VERSION@"
+
+#endif
diff --git a/win/build.py b/win/build.py
new file mode 100644
index 0000000..3a9fbc7
--- /dev/null
+++ b/win/build.py
@@ -0,0 +1,22 @@
+import os, sys
+from wb import system, config, home_fn, cd_home
+
+os.environ['PATH'] += ";%s\\VC" % (os.path.normpath(config['MSVC']),)
+
+def build_vc(cmd):
+ system('cmd /c "vcvarsall.bat x86 && %s"' % (cmd,))
+
+def main():
+ cd_home()
+ build_vc("nmake /f %s" % (home_fn('msvc.mak'),))
+
+def clean():
+ cd_home()
+ build_vc("nmake /f %s clean" % (home_fn('msvc.mak'),))
+
+# if we are run directly, and not loaded as a module
+if __name__ == "__main__":
+ if len(sys.argv) == 2 and sys.argv[1] == 'clean':
+ clean()
+ else:
+ main()
diff --git a/win/build_all.py b/win/build_all.py
new file mode 100644
index 0000000..dec3a78
--- /dev/null
+++ b/win/build_all.py
@@ -0,0 +1,59 @@
+import getopt, sys
+from config_all import main as config_all
+from build import main as build_openvpn
+from build_ddk import main as build_ddk
+from make_dist import main as make_dist
+
+def Usage():
+ '''Show usage information'''
+ print "Usage: build_all.py [OPTIONS]..."
+ print "Build OpenVPN using Visual Studio tools"
+ print
+ print " -h, --help Show this help"
+ print " -u, --unsigned Do not sign the TAP drivers"
+ sys.exit(1)
+
+def main(config):
+
+ # Do a signed build by default
+ signedBuild=True
+
+ # Parse the command line argument(s)
+ try:
+ opts, args = getopt.getopt(sys.argv[1:], "hu", ["help", "unsigned"])
+ except getopt.GetoptError:
+ Usage()
+
+ for o, a in opts:
+ if o in ("-h","--help"):
+ Usage()
+ if o in ("-u", "--unsigned"):
+ signedBuild=False
+
+
+ # Check if the SignTool module is present. This avoids ImportErrors popping
+ # up annoyingly _after_ the build.
+ if signedBuild:
+ try:
+ from signtool import SignTool
+ except (ImportError):
+ print "ERROR: SignTool python module not found! Can't do a signed build."
+ sys.exit(1)
+ else:
+ print "Doing an unsigned build as requested"
+
+ # Start the build
+ config_all(config)
+ build_openvpn()
+ build_ddk(config, 'tap', 'all')
+ build_ddk(config, 'tapinstall', 'all')
+
+ if signedBuild:
+ sign(config, 'all')
+
+ make_dist(config)
+
+# if we are run directly, and not loaded as a module
+if __name__ == "__main__":
+ from wb import config
+ main(config)
diff --git a/win/build_ddk.py b/win/build_ddk.py
new file mode 100644
index 0000000..1a0cf82
--- /dev/null
+++ b/win/build_ddk.py
@@ -0,0 +1,54 @@
+import os
+from wb import system, home_fn, choose_arch
+
+def build_ddk(config, dir, x64):
+ ddk_path = config['DDK_PATH']
+ ddk_major = int(config['DDKVER_MAJOR'])
+ debug = 'PRODUCT_TAP_DEBUG' in config
+ return build_tap(ddk_path, ddk_major, debug, dir, x64)
+
+def build_tap(ddk_path, ddk_major, debug, dir, x64):
+ setenv_bat = os.path.realpath(os.path.join(ddk_path, 'bin/setenv.bat'))
+ target = 'chk' if debug else 'fre'
+ if x64:
+ target += ' x64'
+ else:
+ target += ' x86'
+ if ddk_major >= 7600:
+ if x64:
+ target += ' wlh' # vista
+ else:
+ target += ' wnet' # server 2003
+ else:
+ if x64:
+ target += ' wnet' # server 2003
+ else:
+ target += ' w2k' # 2000
+
+ system('cmd /c "%s %s %s && cd %s && build -cef"' % (
+ setenv_bat,
+ os.path.realpath(ddk_path),
+ target,
+ dir
+ ))
+
+def main(config, proj, arch):
+ if proj == 'tap':
+ dir = home_fn('tap-win32')
+ elif proj == 'tapinstall':
+ dir = home_fn('tapinstall')
+ else:
+ raise ValueError("unknown project: %s" % (proj,))
+
+ for x64 in choose_arch(arch):
+ build_ddk(config, dir, x64)
+
+# if we are run directly, and not loaded as a module
+if __name__ == "__main__":
+ import sys
+ from wb import config
+ if len(sys.argv) >= 3:
+ main(config, sys.argv[1], sys.argv[2])
+ else:
+ print "usage: build <tap|tapinstall> <x64|x86|all>"
+ sys.exit(2)
diff --git a/win/build_exe.py b/win/build_exe.py
new file mode 100644
index 0000000..087f9a3
--- /dev/null
+++ b/win/build_exe.py
@@ -0,0 +1,15 @@
+from config import main as config_main
+from build import main as build_openvpn
+from build_ddk import main as build_ddk
+from sign import main as sign
+from make_dist import main as make_dist
+
+def main(config):
+ config_main(config)
+ build_openvpn()
+ make_dist(config, tap=False)
+
+# if we are run directly, and not loaded as a module
+if __name__ == "__main__":
+ from wb import config
+ main(config)
diff --git a/win/config.py b/win/config.py
new file mode 100644
index 0000000..cf38cac
--- /dev/null
+++ b/win/config.py
@@ -0,0 +1,18 @@
+from wb import preprocess, autogen, mod_fn, home_fn, build_autodefs, make_headers_objs, dict_def
+
+def main(config):
+ build_autodefs(config, mod_fn('autodefs.h.in'), home_fn('autodefs.h'))
+ ho = make_headers_objs(home_fn('Makefile.am'))
+
+ preprocess(dict_def(config, [('HEADERS_OBJS', ho)]),
+ in_fn=mod_fn('msvc.mak.in'),
+ out_fn=home_fn('msvc.mak'),
+ quote_begin='@',
+ quote_end='@',
+ if_prefix='!',
+ head_comment='# %s\n\n' % autogen)
+
+# if we are run directly, and not loaded as a module
+if __name__ == "__main__":
+ from wb import config
+ main(config)
diff --git a/win/config_all.py b/win/config_all.py
new file mode 100644
index 0000000..2686780
--- /dev/null
+++ b/win/config_all.py
@@ -0,0 +1,13 @@
+from config import main as config_main
+from config_tap import main as config_tap
+from config_ti import main as config_ti
+
+def main(config):
+ config_main(config)
+ config_tap(config)
+ config_ti(config)
+
+# if we are run directly, and not loaded as a module
+if __name__ == "__main__":
+ from wb import config
+ main(config)
diff --git a/win/config_tap.py b/win/config_tap.py
new file mode 100644
index 0000000..e69ee9b
--- /dev/null
+++ b/win/config_tap.py
@@ -0,0 +1,35 @@
+import os
+from wb import preprocess, home_fn, autogen, dict_def
+
+def main(config):
+ preprocess(config,
+ in_fn=home_fn('tap-win32/SOURCES.in'),
+ out_fn=home_fn('tap-win32/SOURCES'),
+ quote_begin='@@',
+ quote_end='@@',
+ head_comment='# %s\n\n' % autogen)
+
+ preprocess(config,
+ in_fn=home_fn('tap-win32/i386/OemWin2k.inf.in'),
+ out_fn=home_fn('tap-win32/i386/OemWin2k.inf'),
+ quote_begin='@@',
+ quote_end='@@',
+ if_prefix='!',
+ head_comment='; %s\n\n' % autogen)
+
+ try:
+ os.mkdir(home_fn('tap-win32/amd64'))
+ except:
+ pass
+ preprocess(dict_def(config, [('AMD64', '1')]),
+ in_fn=home_fn('tap-win32/i386/OemWin2k.inf.in'),
+ out_fn=home_fn('tap-win32/amd64/OemWin2k.inf'),
+ quote_begin='@@',
+ quote_end='@@',
+ if_prefix='!',
+ head_comment='; %s\n\n' % autogen)
+
+# if we are run directly, and not loaded as a module
+if __name__ == "__main__":
+ from wb import config
+ main(config)
diff --git a/win/config_ti.py b/win/config_ti.py
new file mode 100644
index 0000000..4facaff
--- /dev/null
+++ b/win/config_ti.py
@@ -0,0 +1,18 @@
+import os, shutil
+from wb import preprocess, home_fn, autogen
+
+def main(config):
+ src = os.path.join(home_fn(config['TISRC']), config['DDKVER_MAJOR'])
+ dest = home_fn('tapinstall')
+ shutil.rmtree(dest, ignore_errors=True)
+ shutil.copytree(src, dest)
+ preprocess(config,
+ in_fn=os.path.join(dest, 'sources.in'),
+ out_fn=os.path.join(dest, 'sources'),
+ if_prefix='!',
+ head_comment='# %s\n\n' % autogen)
+
+# if we are run directly, and not loaded as a module
+if __name__ == "__main__":
+ from wb import config
+ main(config)
diff --git a/win/js.py b/win/js.py
new file mode 100644
index 0000000..c515824
--- /dev/null
+++ b/win/js.py
@@ -0,0 +1,10 @@
+import json
+
+# usage:
+# print JSON().encode(kv)
+
+class JSON(json.JSONEncoder):
+ def __init__(self, **kwargs):
+ args = dict(sort_keys=True, indent=2)
+ args.update(kwargs)
+ json.JSONEncoder.__init__(self, **args)
diff --git a/win/make_dist.py b/win/make_dist.py
new file mode 100644
index 0000000..a6a0563
--- /dev/null
+++ b/win/make_dist.py
@@ -0,0 +1,56 @@
+import os
+from wb import home_fn, rm_rf, mkdir, cp_a, cp
+
+def main(config, tap=True):
+ dist = config['DIST']
+ assert dist
+ dist = home_fn(dist)
+ bin = os.path.join(dist, 'bin')
+ i386 = os.path.join(dist, 'i386')
+ amd64 = os.path.join(dist, 'amd64')
+
+ # build dist and subdirectories
+ rm_rf(dist)
+ mkdir(dist)
+ mkdir(bin)
+ if tap:
+ mkdir(i386)
+ mkdir(amd64)
+
+ # copy openvpn.exe and manifest
+ cp(home_fn('openvpn.exe'), bin)
+ cp(home_fn('openvpn.exe.manifest'), bin)
+
+ # copy DLL dependencies
+ cp(home_fn(config['LZO_DIR']+'/bin/lzo2.dll'), bin)
+ cp(home_fn(config['OPENSSL_DIR']+'/bin/libeay32.dll'), bin)
+ cp(home_fn(config['OPENSSL_DIR']+'/bin/ssleay32.dll'), bin)
+
+ # copy MSVC CRT
+ cp_a(home_fn(config['MSVC_CRT']), bin)
+
+ if tap:
+ # copy TAP drivers
+ for dir_name, dest in (('amd64', amd64), ('i386', i386)):
+ dir = home_fn(os.path.join('tap-win32', dir_name))
+ for dirpath, dirnames, filenames in os.walk(dir):
+ for f in filenames:
+ root, ext = os.path.splitext(f)
+ if ext in ('.inf', '.cat', '.sys'):
+ cp(os.path.join(dir, f), dest)
+ break
+
+ # copy tapinstall
+ dest = {'amd64' : amd64, 'i386' : i386}
+ for dirpath, dirnames, filenames in os.walk(home_fn('tapinstall')):
+ for f in filenames:
+ if f == 'tapinstall.exe':
+ dir_name = os.path.basename(dirpath)
+ src = os.path.join(dirpath, f)
+ if dir_name in dest:
+ cp(src, dest[dir_name])
+
+# if we are run directly, and not loaded as a module
+if __name__ == "__main__":
+ from wb import config
+ main(config)
diff --git a/win/msvc.mak.in b/win/msvc.mak.in
new file mode 100644
index 0000000..5d94a6e
--- /dev/null
+++ b/win/msvc.mak.in
@@ -0,0 +1,57 @@
+# This makefile builds the user-mode component
+# of OpenVPN for Windows in the Visual Studio 2008 environment.
+
+# To build:
+# python win\config.py
+# nmake /f msvc.mak
+
+# Each of the OPENSSL and LZO dirs should have 'lib' and 'include'
+# directories under them.
+
+OPENSSL = @OPENSSL_DIR@
+OPENSSL_DYNAMIC = libeay32.lib ssleay32.lib
+
+LZO = @LZO_DIR@
+LZO_DYNAMIC = lzo2.lib
+
+INCLUDE_DIRS = -I$(OPENSSL)/include -I$(LZO)/include
+
+LIBS = $(OPENSSL_DYNAMIC) $(LZO_DYNAMIC) ws2_32.lib crypt32.lib iphlpapi.lib winmm.lib user32.lib gdi32.lib advapi32.lib wininet.lib
+
+LIB_DIRS = -LIBPATH:$(OPENSSL)\lib -LIBPATH:$(LZO)\lib
+
+EXE = openvpn.exe
+
+CPP=cl.exe
+CPP_ARG_COMMON=/nologo /W3 -DWIN32 -DWIN32_LEAN_AND_MEAN -D_CONSOLE -D_MBCS -D_CRT_SECURE_NO_DEPRECATE $(INCLUDE_DIRS) /FD /c
+
+LINK32=link.exe
+
+!ifdef PRODUCT_OPENVPN_DEBUG
+# debug:
+CPP_PROJ=$(CPP_ARG_COMMON) /MD /Z7
+LINK32_FLAGS=/nologo /subsystem:console /incremental:no /opt:ref /opt:icf /debug /out:"$(EXE)"
+# old debug:
+#CPP_PROJ=$(CPP_ARG_COMMON) /MDd /Zi /Od -D_DEBUG
+#LINK32_FLAGS=/nologo /subsystem:console /incremental:no /debug /out:"$(EXE)"
+!else
+# release:
+CPP_PROJ=$(CPP_ARG_COMMON) /O2 /MD -DNDEBUG
+LINK32_FLAGS=/nologo /subsystem:console /incremental:no /out:"$(EXE)"
+!endif
+
+# HEADERS and OBJS definitions, automatically generated
+@HEADERS_OBJS@
+
+openvpn : $(OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LIB_DIRS) $(LIBS) $(OBJS)
+<<
+
+clean :
+ del /Q $(OBJS) $(EXE) *.idb *.pdb
+
+.c.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
diff --git a/win/settings.in b/win/settings.in
new file mode 100644
index 0000000..f8eeb20
--- /dev/null
+++ b/win/settings.in
@@ -0,0 +1,68 @@
+# Version numbers, settings, and dependencies
+# for Windows OpenVPN installer.
+
+# Branding
+!define PRODUCT_NAME "OpenVPN"
+!define PRODUCT_UNIX_NAME "openvpn"
+!define PRODUCT_FILE_EXT "ovpn"
+
+# Allow --askpass and --auth-user-pass passwords to be read from a file
+;!define ENABLE_PASSWORD_SAVE
+
+# Include the OpenVPN GUI exe in the installer.
+# May be undefined.
+!define OPENVPN_GUI_DIR "../openvpn-gui"
+!define OPENVPN_GUI "openvpn-gui-1.0.3.exe"
+
+# Prebuilt libraries. DMALLOC is optional.
+!define OPENSSL_DIR "../openssl"
+!define LZO_DIR "../lzo"
+
+# write output files here
+!define DIST "dist"
+
+# tapinstall.exe source code.
+# Not needed if DRVBINSRC is defined
+# (or if using pre-built mode).
+!define TISRC "../tapinstall"
+
+# TAP Adapter parameters. Note that PRODUCT_TAP_ID is
+# defined in version.m4.
+!define PRODUCT_TAP_DEVICE_DESCRIPTION "TAP-Win32 Adapter V9"
+!define PRODUCT_TAP_PROVIDER "TAP-Win32 Provider V9"
+!define PRODUCT_TAP_MAJOR_VER 9
+!define PRODUCT_TAP_MINOR_VER 7
+!define PRODUCT_TAP_RELDATE "04/19/2010"
+
+# TAP adapter icon -- visible=0x81 or hidden=0x89
+!define PRODUCT_TAP_CHARACTERISTICS 0x81
+
+# Build debugging version of TAP driver
+;!define PRODUCT_TAP_DEBUG
+
+# Build debugging version of openvpn.exe
+;!define PRODUCT_OPENVPN_DEBUG
+
+# DDK path -- currently Windows 7 WDK
+!define DDK_PATH "c:/winddk/7600.16385.1"
+;!define DDK_PATH "c:/winddk/6001.18002"
+
+# output path for tap_span.py
+!define TAP_DIST "tap_dist"
+
+# Visual studio path
+!define MSVC "C:/Program Files/Microsoft Visual Studio 9.0"
+
+# Visual studio C run-time library path
+!define MSVC_CRT "../Microsoft.VC90.CRT"
+
+# Code Signing.
+# If undefined, don't sign any files.
+!define SIGNTOOL "../signtool"
+!define PRODUCT_SIGN_CN "openvpn"
+
+; DEBUGGING -- set to something like "-DBG2"
+!define OUTFILE_LABEL ""
+
+; DEBUGGING -- set to something like "DEBUG2"
+!define TITLE_LABEL ""
diff --git a/win/show.py b/win/show.py
new file mode 100644
index 0000000..9558c87
--- /dev/null
+++ b/win/show.py
@@ -0,0 +1,10 @@
+from wb import get_config
+from js import JSON
+
+def main():
+ kv = get_config()
+ print JSON().encode(kv)
+
+# if we are run directly, and not loaded as a module
+if __name__ == "__main__":
+ main()
diff --git a/win/sign.py b/win/sign.py
new file mode 100644
index 0000000..ee4ae72
--- /dev/null
+++ b/win/sign.py
@@ -0,0 +1,19 @@
+import sys
+from wb import config, choose_arch, home_fn
+
+if 'SIGNTOOL' in config:
+ sys.path.append(home_fn(config['SIGNTOOL']))
+
+def main(conf, arch):
+ from signtool import SignTool
+ st = SignTool(conf)
+ for x64 in choose_arch(arch):
+ st.sign_verify(x64=x64)
+
+# if we are run directly, and not loaded as a module
+if __name__ == "__main__":
+ if len(sys.argv) >= 2:
+ main(config, sys.argv[1])
+ else:
+ print "usage: sign <x64|x86|all>"
+ sys.exit(2)
diff --git a/win/tap_span.py b/win/tap_span.py
new file mode 100644
index 0000000..9cd127b
--- /dev/null
+++ b/win/tap_span.py
@@ -0,0 +1,129 @@
+import sys, os, shutil
+from wb import config, home_fn, mod_fn, preprocess, autogen, dict_def, build_autodefs, rm_rf, mkdir_silent, cp
+if 'SIGNTOOL' in config:
+ sys.path.append(home_fn(config['SIGNTOOL']))
+from signtool import SignTool
+from build_ddk import build_tap
+
+ti_dir = "c:/src/tapinstall"
+hi = ("c:/winddk/7600.16385.1", 7600, 7600, ("i386", "amd64"))
+low = ("c:/winddk/6001.18002", 6001, 5600, ("win2k",))
+dest_top = home_fn('tap_build')
+dist = home_fn(config['TAP_DIST'])
+
+def copy_tap(src, dest, x64):
+ dir = os.path.join(src, { False : 'i386', True: 'amd64' }[x64])
+ mkdir_silent(dest)
+ for dirpath, dirnames, filenames in os.walk(dir):
+ for f in filenames:
+ root, ext = os.path.splitext(f)
+ if ext in ('.inf', '.cat', '.sys'):
+ cp(os.path.join(dir, f), dest)
+ break
+
+def copy_tapinstall(src, dest, x64):
+ base = { False : 'i386', True: 'amd64' }[x64]
+ mkdir_silent(dest)
+ for dirpath, dirnames, filenames in os.walk(home_fn(src)):
+ for f in filenames:
+ if f == 'tapinstall.exe':
+ dir_name = os.path.basename(dirpath)
+ s = os.path.join(dirpath, f)
+ if dir_name == base:
+ cp(s, dest)
+
+def main():
+ rm_rf(dest_top)
+ os.mkdir(dest_top)
+
+ rm_rf(dist)
+ os.mkdir(dist)
+
+ for ver in hi, low:
+ top = os.path.join(dest_top, str(ver[1]))
+ os.mkdir(top)
+ tap_dest = os.path.join(top, "tap-win32")
+ ti_dest = os.path.join(top, "tapinstall")
+ ti_src = os.path.join(ti_dir, str(ver[2]))
+ shutil.copytree(home_fn("tap-win32"), tap_dest)
+ shutil.copytree(ti_src, ti_dest)
+
+ i386 = os.path.join(tap_dest, "i386")
+ amd64 = os.path.join(tap_dest, "amd64")
+
+ build_amd64 = (len(ver[3]) >= 2)
+
+ build_autodefs(config, mod_fn('autodefs.h.in'), os.path.join(top, 'autodefs.h'))
+
+ st = SignTool(config, tap_dest)
+
+ preprocess(config,
+ in_fn=os.path.join(tap_dest, 'SOURCES.in'),
+ out_fn=os.path.join(tap_dest, 'SOURCES'),
+ quote_begin='@@',
+ quote_end='@@',
+ head_comment='# %s\n\n' % autogen)
+
+ preprocess(config,
+ in_fn=os.path.join(i386, 'OemWin2k.inf.in'),
+ out_fn=os.path.join(i386, 'OemWin2k.inf'),
+ quote_begin='@@',
+ quote_end='@@',
+ if_prefix='!',
+ head_comment='; %s\n\n' % autogen)
+
+ preprocess(config,
+ in_fn=os.path.join(ti_dest, 'sources.in'),
+ out_fn=os.path.join(ti_dest, 'sources'),
+ if_prefix='!',
+ head_comment='# %s\n\n' % autogen)
+
+ build_tap(ddk_path=ver[0],
+ ddk_major=ver[1],
+ debug=False,
+ dir=tap_dest,
+ x64=False)
+
+ st.sign_verify(x64=False)
+
+ build_tap(ddk_path=ver[0],
+ ddk_major=ver[1],
+ debug=False,
+ dir=ti_dest,
+ x64=False)
+
+ tap_dist = os.path.join(dist, ver[3][0])
+
+ copy_tap(tap_dest, tap_dist, x64=False)
+ copy_tapinstall(ti_dest, tap_dist, x64=False)
+
+ if build_amd64:
+ os.mkdir(amd64)
+ preprocess(dict_def(config, [('AMD64', '1')]),
+ in_fn=os.path.join(i386, 'OemWin2k.inf.in'),
+ out_fn=os.path.join(amd64, 'OemWin2k.inf'),
+ quote_begin='@@',
+ quote_end='@@',
+ if_prefix='!',
+ head_comment='; %s\n\n' % autogen)
+
+ build_tap(ddk_path=ver[0],
+ ddk_major=ver[1],
+ debug=False,
+ dir=tap_dest,
+ x64=True)
+
+ build_tap(ddk_path=ver[0],
+ ddk_major=ver[1],
+ debug=False,
+ dir=ti_dest,
+ x64=True)
+
+ st.sign_verify(x64=True)
+
+ tap_dist_x64 = os.path.join(dist, ver[3][1])
+
+ copy_tap(tap_dest, tap_dist_x64, x64=True)
+ copy_tapinstall(ti_dest, tap_dist_x64, x64=True)
+
+main()
diff --git a/win/wb.py b/win/wb.py
new file mode 100644
index 0000000..8e23684
--- /dev/null
+++ b/win/wb.py
@@ -0,0 +1,215 @@
+# Python module containing general build functions
+# for OpenVPN on Windows
+
+import os, re, shutil, stat
+
+autogen = "Automatically generated by OpenVPN Windows build system"
+
+def get_config():
+ kv = {}
+ parse_version_m4(kv, home_fn('version.m4'))
+ parse_settings_in(kv, mod_fn('settings.in'))
+
+ # config fixups
+ kv['DDKVER'] = os.path.basename(kv['DDK_PATH'])
+ kv['DDKVER_MAJOR'] = re.match(r'^(\d+)\.', kv['DDKVER']).groups()[0]
+
+ if 'VERSION_SUFFIX' in kv:
+ kv['PRODUCT_VERSION'] += kv['VERSION_SUFFIX']
+
+ return kv
+
+def mod_fn(fn, src=__file__, real=True):
+ p = os.path.join(os.path.dirname(src), os.path.normpath(fn))
+ if real:
+ p = os.path.realpath(p)
+ return p
+
+def home_fn(fn, real=True):
+ return mod_fn(os.path.join('..', fn), real=real)
+
+def cd_home():
+ os.chdir(os.path.join(os.path.dirname(__file__), '..'))
+
+def system(cmd):
+ print "RUN:", cmd
+ os.system(cmd)
+
+def parse_version_m4(kv, version_m4):
+ r = re.compile(r'^define\((\w+),\[(.*)\]\)$')
+ f = open(version_m4)
+ for line in f:
+ line = line.rstrip()
+ m = re.match(r, line)
+ if m:
+ g = m.groups()
+ kv[g[0]] = g[1]
+ f.close()
+
+def parse_settings_in(kv, settings_in):
+ r = re.compile(r'^!define\s+(\w+)(?:\s+"?(.*?)"?)?$')
+ f = open(settings_in)
+ for line in f:
+ line = line.rstrip()
+ m = re.match(r, line)
+ if m:
+ g = m.groups()
+ kv[g[0]] = g[1] or ''
+ f.close()
+
+def dict_def(dict, newdefs):
+ ret = dict.copy()
+ ret.update(newdefs)
+ return ret
+
+def build_autodefs(kv, autodefs_in, autodefs_out):
+ preprocess(kv,
+ in_fn=autodefs_in,
+ out_fn=autodefs_out,
+ quote_begin='@',
+ quote_end='@',
+ head_comment='/* %s */\n\n' % autogen)
+
+def preprocess(kv, in_fn, out_fn, quote_begin=None, quote_end=None, if_prefix=None, head_comment=None):
+ def repfn(m):
+ var, = m.groups()
+ return kv.get(var, '')
+
+ re_macro = re_ifdef = None
+
+ if quote_begin and quote_end:
+ re_macro = re.compile(r'%s(\w+)%s' % (re.escape(quote_begin), re.escape(quote_end)))
+
+ if if_prefix:
+ re_ifdef = re.compile(r'^\s*%sifdef\s+(\w+)\b' % (re.escape(if_prefix),))
+ re_else = re.compile(r'^\s*%selse\b' % (re.escape(if_prefix),))
+ re_endif = re.compile(r'^\s*%sendif\b' % (re.escape(if_prefix),))
+
+ if_stack = []
+ fin = open(in_fn)
+ fout = open(out_fn, 'w')
+ if head_comment:
+ fout.write(head_comment)
+ for line in fin:
+ if re_ifdef:
+ m = re.match(re_ifdef, line)
+ if m:
+ var, = m.groups()
+ if_stack.append(int(var in kv))
+ continue
+ elif re.match(re_else, line):
+ if_stack[-1] ^= 1
+ continue
+ elif re.match(re_endif, line):
+ if_stack.pop()
+ continue
+ if not if_stack or min(if_stack):
+ if re_macro:
+ line = re.sub(re_macro, repfn, line)
+ fout.write(line)
+ assert not if_stack
+ fin.close()
+ fout.close()
+
+def print_key_values(kv):
+ for k, v in sorted(kv.items()):
+ print "%s%s%s" % (k, ' '*(32-len(k)), repr(v))
+
+def get_sources(makefile_am):
+ c = set()
+ h = set()
+ f = open(makefile_am)
+ state = False
+ for line in f:
+ line = line.rstrip()
+ if line == 'openvpn_SOURCES = \\':
+ state = True
+ elif not line:
+ state = False
+ elif state:
+ for sf in line.split():
+ if sf.endswith('.c'):
+ c.add(sf[:-2])
+ elif sf.endswith('.h'):
+ h.add(sf[:-2])
+ elif sf == '\\':
+ pass
+ else:
+ print >>sys.stderr, "Unrecognized filename:", sf
+ f.close()
+ return [ sorted(list(s)) for s in (c, h) ]
+
+def output_mak_list(title, srclist, ext):
+ ret = "%s =" % (title,)
+ for x in srclist:
+ ret += " \\\n\t%s.%s" % (x, ext)
+ ret += '\n\n'
+ return ret
+
+def make_headers_objs(makefile_am):
+ c, h = get_sources(makefile_am)
+ ret = output_mak_list('HEADERS', h, 'h')
+ ret += output_mak_list('OBJS', c, 'obj')
+ return ret
+
+def choose_arch(arch_name):
+ if arch_name == 'x64':
+ return (True,)
+ elif arch_name == 'x86':
+ return (False,)
+ elif arch_name == 'all':
+ return (True, False)
+ else:
+ raise ValueError("architecture ('%s') must be x86, x64, or all" % (arch_name,))
+
+def rm_rf(dir):
+ print "REMOVE", dir
+ shutil.rmtree(dir, ignore_errors=True)
+
+def mkdir(dir):
+ print "MKDIR", dir
+ os.mkdir(dir)
+
+def cp_a(src, dest, dest_is_dir=True):
+ if dest_is_dir:
+ dest = os.path.join(dest, os.path.basename(src))
+ print "COPY_DIR %s %s" % (src, dest)
+ shutil.copytree(src, dest)
+
+def cp(src, dest, dest_is_dir=True):
+ if dest_is_dir:
+ dest = os.path.join(dest, os.path.basename(src))
+ print "COPY %s %s" % (src, dest)
+ shutil.copyfile(src, dest)
+
+def rm_rf(path):
+ try:
+ shutil.rmtree(path, onerror=onerror)
+ except:
+ pass
+
+def onerror(func, path, exc_info):
+ """
+ Error handler for ``shutil.rmtree``.
+
+ If the error is due to an access error (read only file)
+ it attempts to add write permission and then retries.
+
+ If the error is for another reason it re-raises the error.
+
+ Usage : ``shutil.rmtree(path, onerror=onerror)``
+ """
+ if not os.access(path, os.W_OK):
+ # Is the error an access error ?
+ os.chmod(path, stat.S_IWUSR)
+ func(path)
+ else:
+ raise
+
+def mkdir_silent(dir):
+ try:
+ os.mkdir(dir)
+ except:
+ pass
+
+config = get_config()