diff --git a/Makefile b/Makefile
index e1af715ffa8cc6317579dac5137995b0c6eab113..000b755625d5cf2bc74e8d747521b0f45f07a459 100644
--- a/Makefile
+++ b/Makefile
@@ -8,6 +8,7 @@
 XBUILD ?= no
 SKIP_CACHECK ?= no
 PROVIDER ?= $(shell grep ^'provider =' branding/config/vendor.conf | cut -d '=' -f 2 | tr -d "[:space:]")
+TARGET ?= bitmask
 PROVIDER_CONFIG ?= branding/config/vendor.conf
 DEFAULT_PROVIDER = branding/assets/default/
 VERSION ?= $(shell git describe)
@@ -20,11 +21,12 @@ SOURCE_GOLIB=gui/backend.go
 # detect OS, we use it for dependencies
 UNAME = $(shell uname -s)
 PLATFORM ?= $(shell echo ${UNAME} | awk "{print tolower(\$$0)}")
+WININST_DATA = branding/qtinstaller/packages/root.win_x86_64/data/
 
 TEMPLATES = branding/templates
 SCRIPTS = branding/scripts
 
-all: icon locales build
+all: icon locales helper build
 
 
 #########################################################################
@@ -66,7 +68,7 @@ else ifeq (${XBUILD}, osx)
 	$(MAKE) build_cross_osx
 	$(MAKE) _build_done
 else
-	$(MAKE) _buildparts
+	@gui/build.sh
 endif
 
 
@@ -224,8 +226,9 @@ package_deb:
 	@make -C build/${PROVIDER} pkg_deb
 
 installer_win:
-	cp qtbuild/release/bitmask.exe branding/qtinstaller/packages/root.win_x86_64/data/${PROVIDER}-vpn.exe
-	windeployqt --qmldir gui/qml branding/qtinstaller/packages/root.win_x86_64/data/${PROVIDER}-vpn.exe
+	cp helper.exe ${WININST_DATA}
+	cp qtbuild/release/${TARGET}.exe ${WININST_DATA}${PROVIDER}-vpn.exe
+	windeployqt --qmldir gui/qml ${WININST_DATA}${PROVIDER}-vpn.exe
 	"/c/Qt/QtIFW-3.2.2/bin/binarycreator.exe" -c ./branding/qtinstaller/config/config.xml -p ./branding/qtinstaller/packages build/${PROVIDER}-vpn-${VERSION}-installer.exe
 
 # FIXME --- old nsis installer. deprecate, but probably we need something similar to sign all the binaries (helper, main app, installer...)
diff --git a/branding/qtinstaller/config/config.xml b/branding/qtinstaller/config/config.xml
index 4469d65a8a2cd4e033906c425d180e392c23ff14..8ce9b2e031259454d7ae05b068b59902b91cb7a8 100644
--- a/branding/qtinstaller/config/config.xml
+++ b/branding/qtinstaller/config/config.xml
@@ -1,9 +1,14 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Installer>
-	<Name>DemoLibVPN</Name>
+	<Name>DemoLibVPN-0.0.1</Name>
 	<Version>0.0.1</Version>
 	<Title>DemoLibVPN Installer</Title>
 	<Publisher>LEAP Encryption Access Project</Publisher>
-	<StartMenuDir>DemoLibVPN</StartMenuDir>
 	<TargetDir>@ApplicationsDir@/DemoLibVPN</TargetDir>
+	<RunProgram>@TargetDir@/demolib-vpn.exe</RunProgram>
+	<RunProgramArguments>
+	</RunProgramArguments>
+        <StartMenuDir>DemoLibVPN</StartMenuDir>
+        <MaintenanceToolName>Uninstall-DemoLibVPN</MaintenanceToolName>
+        <AllowNonAsciiCharacters>false</AllowNonAsciiCharacters>
 </Installer>
diff --git a/branding/qtinstaller/packages/root.win_x86_64/meta/installscript.js b/branding/qtinstaller/packages/root.win_x86_64/meta/installscript.js
index 691d1a4c0f28cb4ea9526fe81040a8b00b946159..1598458cf850d57a32708ee710a4dc946708bd3e 100644
--- a/branding/qtinstaller/packages/root.win_x86_64/meta/installscript.js
+++ b/branding/qtinstaller/packages/root.win_x86_64/meta/installscript.js
@@ -69,7 +69,9 @@ Component.prototype.createOperations = function()
         if (systemInfo.productType === "windows") {
              console.log("Adding shortcut entries");
              component.addElevatedOperation("Mkdir", "@StartMenuDir@");
-             component.addElevatedOperation("CreateShortcut", "@TargetDir@/demolib-vpn.exe", "@StartMenuDir@/DemoLibVPN.lnk", "workingDirectory=@TargetDir@", "iconPath=%SystemRoot%/system32/SHELL32.dll", "iconId=2", "description=Start DemoLibVPN");
-             component.addElevatedOperation("CreateShortcut", "@TargetDir@/maintenancetool.exe", "@StartMenuDir@/uninstall.lnk", "workingDirectory=@TargetDir@", "iconPath=%SystemRoot%/system32/SHELL32.dll", "iconId=2", "description=Uninstall application");
+             component.addElevatedOperation("CreateShortcut", "@TargetDir@/demolib-vpn.exe", "@StartMenuDir@/DemoLibVPN.lnk", "workingDirectory=@TargetDir@", "iconPath=@TargetDir@/icon.ico", "description=Start DemoLibVPN");
+
+	     // TODO I think this one is not being created because the path doesn't exist yet. We might want to do this by hooking on the installation finished signal instead.
+             component.addElevatedOperation("CreateShortcut", "@TargetDir@/Uninstall-DemoLibVPN.exe", "@StartMenuDir@/Uninstall.lnk");
         }
 }
diff --git a/docs/build.windows.rst b/docs/build.windows.rst
new file mode 100644
index 0000000000000000000000000000000000000000..a0c7a565ef5c790dd23008397eca38110120773f
--- /dev/null
+++ b/docs/build.windows.rst
@@ -0,0 +1,9 @@
+windows build notes (still some manual steps needed, this should be further automated).
+=======================================================================================
+
+PROVIDER=DemoLib make helper
+INSTALLER_DATA=branding/qtinstaller/packages/root.win_x86_64/data/
+mkdir -p INSTALLER_DATA
+mv main.exe ${INSTALLER_DATA}/helper.exe
+TARGET=demolib-vpn make build
+TARGET=demolib-vpn make installer_win
diff --git a/build.sh b/gui/build.sh
old mode 100755
new mode 100644
similarity index 100%
rename from build.sh
rename to gui/build.sh
diff --git a/pkg/helper/helper.go b/pkg/helper/helper.go
index 9d0b330475439229eba38d79ee75d80d2cd605dc..691fc6e144dffc5340d1ee442c75dfdf98a198d4 100644
--- a/pkg/helper/helper.go
+++ b/pkg/helper/helper.go
@@ -29,9 +29,9 @@ import (
 )
 
 var (
-	AppName = "DemoLibVPN"
+	AppName    = "DemoLibVPN"
 	BinaryName = "bitmask"
-	Version = "git"
+	Version    = "git"
 )
 
 type openvpnT struct {
diff --git a/pkg/helper/windows.go b/pkg/helper/windows.go
index ef4f2719fef3eab566ff996de759a22e613dd12a..44ac6f50fc53c85d91a5dfab19ea954fdccdfbd6 100644
--- a/pkg/helper/windows.go
+++ b/pkg/helper/windows.go
@@ -33,8 +33,10 @@ import (
 
 var (
 	svcName          = BinaryName + `-helper-v2`
+
+	// XXX this is set to c:\WINDOWS\system32 on initialization. Do not use it, use a function call instead.
 	appPath          = getExecDir()
-	LogFolder        = appPath
+	LogFolder        = getExecDir()
 	openvpnPath      = path.Join(appPath, "openvpn.exe")
 	chocoOpenvpnPath = `C:\Program Files\OpenVPN\bin\openvpn.exe`
 	platformOpenvpnFlags = []string{
@@ -47,9 +49,11 @@ var (
 func getExecDir() string {
 	ex, err := os.Executable()
 	if err != nil {
-		log.Fatal("Cannot find executable path")
+		log.Println("Cannot find executable path")
+		return ""
 	}
-	return path.Dir(ex)
+	/* XXX filepath.Abs is buggy, maybe because of spaces in the path. fuck it, this is good enough for now */
+	return strings.Replace(ex, "\\helper.exe", "", 1)
 }
 
 type httpConf struct {
@@ -131,11 +135,15 @@ func daemonize() {}
 func runServer(port int) {}
 
 func getOpenvpnPath() string {
-	if _, err := os.Stat(openvpnPath); !os.IsNotExist(err) {
-		return openvpnPath
+	openvpn := path.Join(getExecDir(), "openvpn.exe")
+	if _, err := os.Stat(openvpn); !os.IsNotExist(err) {
+		log.Println("DEBUG: openvpnpath found,", openvpnPath)
+		return openvpn
 	} else if _, err := os.Stat(chocoOpenvpnPath); !os.IsNotExist(err) {
+		log.Println("DEBUG: choco openvpn found,", chocoOpenvpnPath)
 		return chocoOpenvpnPath
 	}
+	log.Println("DEBUG: did not find system-wide openvpn...")
 	return "openvpn.exe"
 }