Merge pull request #2 from ebarboni/initcommit

Initial commit preserving history
diff --git a/src/main/cpp/build.properties b/src/main/cpp/build.properties
new file mode 100644
index 0000000..5959d93
--- /dev/null
+++ b/src/main/cpp/build.properties
@@ -0,0 +1,68 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# 
+
+#ignore.native=
+
+native.dist.dir=dist
+
+native.jnilib.dir=jnilib
+native.launcher.dir=launcher
+native.cleaner.dir=cleaner
+
+# Native Library properties
+native.jnilib.dir.windows=${native.jnilib.dir}/windows
+native.jnilib.dir.linux=${native.jnilib.dir}/linux
+native.jnilib.dir.solaris-x86=${native.jnilib.dir}/solaris-x86
+native.jnilib.dir.solaris-sparc=${native.jnilib.dir}/solaris-sparc
+native.jnilib.dir.macosx=${native.jnilib.dir}/macosx
+
+native.jnilib.file.windows.i386=windows-x86.dll
+native.jnilib.file.windows.amd64=windows-x64.dll
+native.jnilib.file.windows.ia64=windows-ia64.dll
+native.jnilib.file.linux.i386=linux.so
+native.jnilib.file.linux.amd64=linux-amd64.so
+native.jnilib.file.solaris-x86=solaris-x86.so
+native.jnilib.file.solaris-sparc=solaris-sparc.so
+native.jnilib.file.solaris-amd64=solaris-amd64.so
+native.jnilib.file.solaris-sparcv9=solaris-sparcv9.so
+native.jnilib.file.macosx=macosx.dylib
+
+
+# Native Launcher Properties
+native.launcher.windows.dir=${native.launcher.dir}/windows
+native.launcher.windows.stub.file=nlw.exe
+native.launcher.windows.stub.src=${native.launcher.windows.dir}/dist/${native.launcher.windows.stub.file}
+native.launcher.windows.stub.dst.dir=${native.launcher.windows.dir}
+native.launcher.windows.i18n.dir=${native.launcher.windows.dir}/i18n
+
+native.launcher.unix.dir=${native.launcher.dir}/unix
+native.launcher.unix.stub.file=launcher.sh
+native.launcher.unix.stub.src=${native.launcher.unix.dir}/src/${native.launcher.unix.stub.file}
+native.launcher.unix.stub.dst.dir=${native.launcher.unix.dir}
+native.launcher.unix.i18n.dir=${native.launcher.unix.dir}/i18n
+
+
+# Native on-exit cleaner properties
+native.cleaner.windows.dir=${native.cleaner.dir}/windows
+native.cleaner.windows.srcdir=${native.cleaner.windows.dir}/dist
+native.cleaner.windows.file=cleaner.exe
+
+native.cleaner.unix.dir=${native.cleaner.dir}/unix
+native.cleaner.unix.srcdir=${native.cleaner.unix.dir}/src
+native.cleaner.unix.file=cleaner.sh
diff --git a/src/main/cpp/build.xml b/src/main/cpp/build.xml
new file mode 100644
index 0000000..58c97a6
--- /dev/null
+++ b/src/main/cpp/build.xml
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+
+<project name="native" default="default" basedir=".">
+    <property file="build.properties"/>
+    
+    <!-- =======================================================================
+        NetBeans Installer engine specific targets
+    ======================================================================== -->
+
+    <!-- =======================================================================
+        Build native library
+    ======================================================================== -->
+    <target name="jnilib-init" depends="define-platform,init-platform"/>
+    <target name="jnilib-clean" depends="jnilib-init" unless="ignore.native">
+        <exec executable="make" dir="${jnilib.dir}">
+            <arg value="clean"/>
+        </exec>    
+    </target>    
+    
+    <target name="jnilib-compile" depends="jnilib-init,jnilib-clean" unless="ignore.native">
+        <exec executable="make" dir="${jnilib.dir}">
+            <arg value="build"/>
+        </exec>
+    </target>    
+    <target name="jnilib-build"   depends="jnilib-init,jnilib-compile"/>
+
+    <!-- =======================================================================
+        Build launcher
+    ======================================================================== -->
+    <target name="launcher-init" depends="define-platform,init-platform"/>
+    <target name="launcher-clean" depends="launcher-init" unless="ignore.native">
+        <exec executable="make" dir="${launcher.dir}">
+            <arg value="clean"/>
+        </exec>    
+    </target>    
+    
+    <target name="launcher-compile" depends="launcher-init,launcher-clean" if="is.windows" unless="ignore.native">
+        <exec executable="make" dir="${launcher.dir}">
+            <arg value="build"/>
+        </exec>
+    </target>
+    <target name="launcher-build" depends="launcher-init,launcher-compile"/>
+
+
+
+<!-- =======================================================================
+        Build cleaner
+    ======================================================================== -->
+    <target name="cleaner-init" depends="define-platform,init-platform"/>
+    <target name="cleaner-clean" depends="cleaner-init" unless="ignore.native">
+        <exec executable="make" dir="${cleaner.dir}">
+            <arg value="clean"/>
+        </exec>    
+    </target>    
+    
+    <target name="cleaner-compile" depends="cleaner-init,cleaner-clean" if="is.windows" unless="ignore.native">
+        <exec executable="make" dir="${cleaner.dir}">
+            <arg value="build"/>
+        </exec>
+    </target>
+    <target name="cleaner-build" depends="cleaner-init,cleaner-compile"/>
+
+
+<!-- =======================================================================
+        Build all native resources
+    ======================================================================== -->
+
+    <target name="native-clean" depends="jnilib-clean,launcher-clean,cleaner-clean"/>
+    <target name="native-compile" depends="jnilib-compile,launcher-compile,cleaner-compile"/>
+    <target name="native-build" depends="jnilib-build,launcher-build,cleaner-build"/>
+
+    <target name="define-platform">
+        <condition property="is.windows">
+            <os family="windows"/>
+        </condition>
+        <condition property="is.linux">
+            <os name="Linux"/>
+        </condition>
+        <condition property="is.solaris-x86">
+            <os name="SunOS" arch="x86"/>
+        </condition>
+        <condition property="is.solaris-sparc">
+            <os name="SunOS" arch="sparc"/>
+        </condition>
+        <condition property="is.macosx">
+            <and>
+                <os family="mac"/>
+                <os family="unix"/>
+            </and>
+        </condition>
+    </target>
+    
+    <target name="init-platform" depends="init-windows,init-linux,init-solaris-x86,init-solaris-sparc,init-macosx"/>
+    
+    <target name="init-windows" if="is.windows">
+        <property name="jnilib.dir"   value="${native.jnilib.dir.windows}"/>
+        <property name="jnilib.file"  value="${native.jnilib.file.windows}"/>
+	<property name="launcher.dir" value="${native.launcher.windows.dir}"/>
+	<property name="cleaner.dir"  value="${native.cleaner.windows.dir}"/>
+    </target>
+    <target name="init-linux" if="is.linux">
+        <property name="jnilib.dir"   value="${native.jnilib.dir.linux}"/>
+        <property name="jnilib.file"  value="${native.jnilib.file.linux}"/>
+	<property name="launcher.dir" value="${native.launcher.unix.dir}"/>
+	<property name="cleaner.dir"  value="${native.cleaner.unix.dir}"/>
+    </target>
+    <target name="init-solaris-x86" if="is.solaris-x86">
+        <property name="jnilib.dir"   value="${native.jnilib.dir.solaris-x86}"/>
+        <property name="jnilib.file"  value="${native.jnilib.file.solaris-x86}"/>
+	<property name="launcher.dir" value="${native.launcher.unix.dir}"/>
+	<property name="cleaner.dir"  value="${native.cleaner.unix.dir}"/>
+    </target>
+    <target name="init-solaris-sparc" if="is.solaris-sparc">
+        <property name="jnilib.dir"   value="${native.jnilib.dir.solaris-sparc}"/>
+        <property name="jnilib.file"  value="${native.jnilib.file.solaris-sparc}"/>
+	<property name="launcher.dir" value="${native.launcher.unix.dir}"/>
+	<property name="cleaner.dir"  value="${native.cleaner.unix.dir}"/>
+    </target>
+    <target name="init-macosx" if="is.macosx">
+        <property name="jnilib.dir"   value="${native.jnilib.dir.macosx}"/>
+        <property name="jnilib.file"  value="${native.jnilib.file.macosx}"/>
+	<property name="launcher.dir" value="${native.launcher.unix.dir}"/>
+	<property name="cleaner.dir"  value="${native.cleaner.unix.dir}"/>
+    </target>
+    
+</project>
diff --git a/src/main/cpp/cleaner/unix/src/cleaner.sh b/src/main/cpp/cleaner/unix/src/cleaner.sh
new file mode 100644
index 0000000..cfae216
--- /dev/null
+++ b/src/main/cpp/cleaner/unix/src/cleaner.sh
@@ -0,0 +1,92 @@
+#!/bin/sh
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# 
+
+deleteFiles() {
+        testSymlinkErr=`test -L / > /dev/null`
+        if [ -z "$testSymlinkErr" ] ; then
+            isSymlink=-L
+        else
+            isSymlink=-h
+        fi
+
+	#wait for main thread to finish...
+	sleep 3
+	waitOnError=1
+	tryTimes=3
+	list="$1"
+	if [ -n "$list" ] && [ -f "$list" ] ; then
+		#echo "Using list file : $list"
+		itemsNumber=`wc -l $list | sed "s/^\ *//;s/\ .*//" 2>/dev/null`
+		#echo "Total items : $itemsNumber"
+		counter=1
+		try=$tryTimes
+		allitems=`cat "$list" 2>/dev/null`
+		if [ -f "$list" ] ; then 
+			#echo "... remove cleaner list $list"
+			rm -f "$list"
+		fi
+		while [ $counter -le $itemsNumber ] ; do			
+			file=`echo "$allitems" | sed -n "${counter}p" 2>/dev/null`
+			#echo "entry : $file"
+			result=1
+			if [ -n "$file" ] ; then
+				#echo "... file not zero"
+				if [ $isSymlink "$file" ] || [ -f "$file" ] ; then
+					# file or symlink
+					#echo "deleting [F] $file"
+					rm -f "$file" 2>/dev/null 1>&2
+					if [ $? -ne 0 ] ; then
+						#echo "... can't delete $file"
+						result=0
+					fi 
+				elif [ -d "$file" ] ; then
+					# directory
+					#echo "deleting [D] $file"
+					rmdir "$file" 2>/dev/null 1>&2
+					if [ $? -ne 0 ] ; then 
+						result=0
+						#echo "... can't delete $file"
+					fi
+				fi
+			fi
+			if [ 0 -eq $result ] ; then
+				# try to remove it again after a short wait
+				if [ $try -gt 0 ] ; then	
+					try=`expr "$try" - 1`
+					sleep $waitOnError
+				else
+					#can`t delete.. skip it
+					result=1
+				fi
+				
+			fi
+			if [ 1 -eq $result ] ; then
+				counter=`expr "$counter" + 1`
+				try=$tryTimes
+			fi		
+		done				
+	fi
+	if [ -f "$0" ] ; then 
+		#echo "... remove cleaner itself $0"
+		rm -f "$0"
+	fi
+}
+
+deleteFiles "$@"
diff --git a/src/main/cpp/cleaner/windows/Makefile b/src/main/cpp/cleaner/windows/Makefile
new file mode 100644
index 0000000..98cf53c
--- /dev/null
+++ b/src/main/cpp/cleaner/windows/Makefile
@@ -0,0 +1,79 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# 
+
+# Environment 
+MKDIR=mkdir
+CP=cp
+CCADMIN=CCadmin
+RANLIB=ranlib
+
+
+# build
+build: .build-pre .build-impl .build-post
+
+.build-pre:
+# Add your pre 'build' code here...
+
+.build-post:
+# Add your post 'build' code here...
+
+
+# clean
+clean: .clean-pre .clean-impl .clean-post
+
+.clean-pre:
+# Add your pre 'clean' code here...
+
+.clean-post:
+# Add your post 'clean' code here...
+
+
+# clobber
+clobber: .clobber-pre .clobber-impl .clobber-post
+
+.clobber-pre:
+# Add your pre 'clobber' code here...
+
+.clobber-post:
+# Add your post 'clobber' code here...
+
+
+# all
+all: .all-pre .all-impl .all-post
+
+.all-pre:
+# Add your pre 'all' code here...
+
+.all-post:
+# Add your post 'all' code here...
+
+
+# help
+help: .help-pre .help-impl .help-post
+
+.help-pre:
+# Add your pre 'help' code here...
+
+.help-post:
+# Add your post 'help' code here...
+
+
+
+# include project implementation makefile
+include nbproject/Makefile-impl.mk
diff --git a/src/main/cpp/cleaner/windows/Makefile-vc b/src/main/cpp/cleaner/windows/Makefile-vc
new file mode 100644
index 0000000..b9edda9
--- /dev/null
+++ b/src/main/cpp/cleaner/windows/Makefile-vc
@@ -0,0 +1,59 @@
+#
+#
+
+
+!include <$(PLATFORM_SDK)/include/win32.mak>
+
+# define the compiler and linker for all the platforms
+CC32="$(VC_2005)\Bin\cl.exe"
+L32="$(VC_2005)\Bin\link.exe"
+
+BUILD_DIR32=.\build\32bit
+OUTPUT_FILE32=.\dist\cleaner.exe
+
+CC32_OPTS=/O1 /Os \
+	/I "$(VC_2005)\include" \
+	/D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_CRT_SECURE_NO_DEPRECATE" \
+	/FD /GS-\
+	/Fo"$(BUILD_DIR32)\\"  /Fd"$(BUILD_DIR32)\vc80.pdb" \
+	/W3 /nologo /c /Wp64 /TC /errorReport:prompt
+
+LINKING_LIBRARIES=\
+	shell32.lib \
+	kernel32.lib
+
+L32_OPTS=\
+	/OUT:$(OUTPUT_FILE32) \
+	/INCREMENTAL:NO \
+	/LIBPATH:"$(PLATFORM_SDK)\Lib" \
+	/MANIFEST:NO \
+	/NODEFAULTLIB \
+	/SUBSYSTEM:WINDOWS \
+	/OPT:REF /OPT:ICF \
+	/MACHINE:X86 \
+	/ERRORREPORT:PROMPT \
+	/ENTRY:WinMain \
+	$(LINKING_LIBRARIES)
+	
+all: init build-32
+
+clean:
+  
+
+init:
+  - md $(BUILD_DIR32)
+  - md .\dist
+
+  del /Q /S $(BUILD_DIR32)
+  del /Q  $(OUTPUT_FILE32)  
+
+build-32: 
+  Set CPU=i386
+  Set Lib=%VC_2005%\Lib;%PLATFORM_SDK%\Lib;%Lib%
+  Set Include=%PLATFORM_SDK%\Include;%Include%
+  Set Path=%PLATFORM_SDK%\Bin;%PLATFORM_SDK%\Bin\WinNT;%VC_2005_PATH%;%path%
+  Set APPVER=5.01
+  Set TARGETOS=WINNT
+  
+  $(CC32) $(CC32_OPTS) .\src\main.c
+  $(L32) $(L32_OPTS) $(BUILD_DIR32)\main.obj
diff --git a/src/main/cpp/cleaner/windows/nbproject/configurations.xml b/src/main/cpp/cleaner/windows/nbproject/configurations.xml
new file mode 100644
index 0000000..b16b628
--- /dev/null
+++ b/src/main/cpp/cleaner/windows/nbproject/configurations.xml
@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+
+<configurationDescriptor version="35">
+  <logicalFolder name="root" displayName="root" projectFiles="true">
+    <logicalFolder name="SourceFiles"
+                   displayName="Source Files"
+                   projectFiles="true">
+      <itemPath>src/main.c</itemPath>
+    </logicalFolder>
+    <logicalFolder name="HeaderFiles"
+                   displayName="Header Files"
+                   projectFiles="true">
+    </logicalFolder>
+    <logicalFolder name="ResourceFiles"
+                   displayName="Resource Files"
+                   projectFiles="true">
+    </logicalFolder>
+    <logicalFolder name="ExternalFiles"
+                   displayName="Important Files"
+                   projectFiles="false">
+      <itemPath>Makefile</itemPath>
+    </logicalFolder>
+  </logicalFolder>
+  <projectmakefile>Makefile</projectmakefile>
+  <defaultConf>0</defaultConf>
+  <confs>
+    <conf name="Debug" type="1">
+      <toolsSet>
+        <compilerSet>Cygwin</compilerSet>
+        <cRequired>true</cRequired>
+        <cppRequired>true</cppRequired>
+        <fortranRequired>false</fortranRequired>
+        <platform>3</platform>
+      </toolsSet>
+      <compileType>
+        <linkerTool>
+          <output>dist/cleaner</output>
+          <stripSymbols>true</stripSymbols>
+          <linkerLibItems>
+            <linkerOptionItem>-lshell32 -lkernel32</linkerOptionItem>
+          </linkerLibItems>
+          <commandLine>-mno-cygwin -mwindows</commandLine>
+        </linkerTool>
+      </compileType>
+      <item path="src/main.c">
+        <itemTool>0</itemTool>
+      </item>
+    </conf>
+    <conf name="Release" type="1">
+      <toolsSet>
+        <compilerSet>Cygwin</compilerSet>
+        <cRequired>true</cRequired>
+        <cppRequired>true</cppRequired>
+        <fortranRequired>false</fortranRequired>
+        <platform>3</platform>
+      </toolsSet>
+      <compileType>
+        <cCompilerTool>
+          <developmentMode>5</developmentMode>
+        </cCompilerTool>
+        <ccCompilerTool>
+          <developmentMode>5</developmentMode>
+        </ccCompilerTool>
+        <fortranCompilerTool>
+          <developmentMode>5</developmentMode>
+        </fortranCompilerTool>
+        <linkerTool>
+          <linkerLibItems>
+          </linkerLibItems>
+        </linkerTool>
+      </compileType>
+      <item path="src/main.c">
+        <itemTool>0</itemTool>
+      </item>
+    </conf>
+  </confs>
+</configurationDescriptor>
diff --git a/src/main/cpp/cleaner/windows/nbproject/project.properties b/src/main/cpp/cleaner/windows/nbproject/project.properties
new file mode 100644
index 0000000..3807b67
--- /dev/null
+++ b/src/main/cpp/cleaner/windows/nbproject/project.properties
@@ -0,0 +1,20 @@
+
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# 
+
diff --git a/src/main/cpp/cleaner/windows/nbproject/project.xml b/src/main/cpp/cleaner/windows/nbproject/project.xml
new file mode 100644
index 0000000..ded3e3c
--- /dev/null
+++ b/src/main/cpp/cleaner/windows/nbproject/project.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+
+<project xmlns="http://www.netbeans.org/ns/project/1">
+    <type>org.netbeans.modules.cnd.makeproject</type>
+    <configuration>
+        <data xmlns="http://www.netbeans.org/ns/make-project/1">
+            <name>NBI Native Cleaner : Windows</name>
+            <make-project-type>0</make-project-type>
+        </data>
+    </configuration>
+</project>
diff --git a/src/main/cpp/cleaner/windows/src/main.c b/src/main/cpp/cleaner/windows/src/main.c
new file mode 100644
index 0000000..43271ff
--- /dev/null
+++ b/src/main/cpp/cleaner/windows/src/main.c
@@ -0,0 +1,482 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <windows.h>
+#include <wchar.h>
+
+
+/*
+ * cleaner.exe
+ * 
+ * Deletes a list of files/folders.
+ * 
+ * The command line syntax is:
+ * 
+ *    arg1:   File name containing a list of files/folders to delete.
+ * 
+ * Requirements for arg1:
+ *  - The arg1 file name MUST be fully qualified. (or be in the same directory
+ *       as the cleaner.exe executable)
+ *  - The file MUST use Windows line ending (CRLF)
+ *  - The file MUST be encoded in UTF-16. The NBI Engine will produce
+ *    this file in Java charset "UNICODE" which effectively means
+ *    UCS-2 BigEndian BOM. Such file will work just fine.
+ *  - Each line in the file is expected to contain a fully qualified file
+ *    or folder name. The entry can be 
+ *        - a local file/folder name, e.g. "C:\foo\bar", up to a maximum of 32767 
+ *          chars and thus not subject to the original Windows limitation 
+ *          of 260 chars for a path name.
+ *        - a UNC, e.g. "\\servername\sharename\foo\bar", subject to a
+ *          restriction of 260 chars.
+ *  - The list MUST be ordered so that the files in a folder are listed before 
+ *    the folder itself. (it is not possible to delete a non-empty folder)
+ * 
+ * Method of working:
+ * 
+ * 1. After launch the content of command line arg1 is read into memory 
+ *    as one big string.
+ * 2. The string is chopped into a list by separating at the LINE_SEPARATOR.
+ * 3. Sleep for 2 seconds to allow the launching process (the JVM) to exit.
+ * 4. Loop over the list of files/folder to delete. Each file-delete operation 
+ *    is spawned into a thread of its own up to a maximum of 64 threads. 
+ *    Therefore the delete operations happens in parallel rather than in sequence. 
+ *    If 64 threads have been spawned then wait for a thread to exit before
+ *    spawning a new one. (therefore never more than 64 threads)
+ *    For each file delete operation do the following:
+ *       - Check to see if the file exists (by getting its attributes)
+ *       - If file: delete file, if directory: delete directory (these are two 
+ *            different calls in the Win32 API).
+ *       - Attempt to delete each file/dir up to 15 times sleeping for 200 ms 
+ *            between each attempt.
+ * 5. Wait for all file-delete threads to exit.
+ * 6. Delete self, i.e. the "cleaner.exe" executable.
+ * 7. End
+ *
+ * The arg1 file is not deleted. However it can be part of the list itself 
+ * if need be.
+ * 
+ * Author:  Dmitry Lipin, 2007
+ * 
+ *
+ *  
+ * Changes after transition to Apache:
+ * 
+ *   14-SEP-2019 Lars Bruun-Hansen (lbruun@apache.org) :   
+ *         Function comment headers added. 
+ *         Main comment header added.
+ *  
+ */
+
+
+// Retry functionality: 
+//   SLEEP_DELAY : millis between each attempt at a file delete
+//   MAX_ATTEMPTS : how many times to attempt to delete a file
+const DWORD SLEEP_DELAY   = 200;
+const DWORD MAX_ATTEMPTS   = 15;
+const DWORD THREAD_FINISHED = 100;
+
+// Number of milliseconds to sleep at launch of the application.
+const DWORD INITIAL_DELAY = 2000; // 2 seconds seems to be enough to finish java process
+
+const WCHAR * LINE_SEPARATOR = L"\r\n";
+const WCHAR * UNC_PREFIX     = L"\\\\?\\"; // Prefix for extended-length path in Win32 API
+const WCHAR * UNC_STD_PREFIX = L"\\\\";  // Prefix for UNC paths, for example: \\servername\share\foo\bar
+const DWORD UNC_PREFIX_LENGTH = 4;
+
+#ifdef _MSC_VER
+#define ZERO(x,y) SecureZeroMemory((x),(y));
+#else
+#define ZERO(x,y) ZeroMemory((x),(y));
+#endif
+
+
+/*
+ * Search for the first occurrence of wcs2 within wcs1.
+ * Returns a pointer to the first occurrence if found.
+ * If not found, NULL is returned.
+ */
+WCHAR * search( const WCHAR * wcs1, const WCHAR * wcs2) {
+    WCHAR *cp = (WCHAR *) wcs1;
+    WCHAR *s1, *s2;
+    
+    if ( !*wcs2) {
+        return (WCHAR *)wcs1;
+    }
+    
+    while (*cp) {
+        s1 = cp;
+        s2 = (WCHAR *) wcs2;
+        
+        while ( *s1 && *s2 && !(*s1-*s2) ) {
+            s1++, s2++;
+        }
+        if (!*s2) {
+            return(cp);
+        }
+        cp++;
+    }
+    return(NULL);
+}
+
+
+typedef struct _list {
+    WCHAR * item;
+    struct _list * next;
+} LIST;
+
+
+WCHAR * toWCHAR(char * charBuffer, DWORD size) {
+    DWORD i=0;
+    WCHAR * buffer;
+    BOOL hasBOM        = (*charBuffer == '\xFF' && *(charBuffer+1) == '\xFE');
+    BOOL hasReverseBOM = (*charBuffer == '\xFE' && *(charBuffer+1) == '\xFF');
+    
+    char * realStringPtr = charBuffer;
+    if (hasBOM || hasReverseBOM) {
+        size-= 2;
+        realStringPtr+= 2;
+        if(hasReverseBOM) {
+            char c;
+            for (i = 0 ; i < size/2 ; i++) {
+                c = charBuffer [2 * i] ;
+                charBuffer [2 * i] = charBuffer [2 * i + 1] ;
+                charBuffer [2 * i + 1] = c;
+            }
+        }
+    }
+    
+    buffer = (WCHAR*) LocalAlloc(LPTR, sizeof(WCHAR) * (size/2+1));
+    ZERO(buffer, sizeof(WCHAR) * (size/2+1));
+    for(i=0;i<size/2;i++) {
+        realStringPtr[2*i] = (realStringPtr[2*i]) & 0xFF;
+        realStringPtr[2*i+1] = (realStringPtr[2*i+1])& 0xFF;
+        buffer [i] = ((unsigned char)realStringPtr[2*i]) + (((unsigned char)realStringPtr[2*i+1]) << 8);
+    }
+    
+    return buffer;
+}
+
+/*
+ * Gets the number of lines in the input. 
+ * (lines are expected to be separated by LINE_SEPARATOR) 
+ */
+DWORD getLinesNumber(WCHAR *str) {
+    DWORD result = 0;
+    WCHAR *ptr = str;
+    WCHAR *ptr2 = str;
+    DWORD sepLength = lstrlenW(LINE_SEPARATOR);
+    if(ptr!=NULL) {
+        while((ptr2 = search(ptr, LINE_SEPARATOR))!=NULL) {
+            ptr = ptr2 + sepLength;
+            result++;
+            
+            if(ptr==NULL)  break;
+        }
+        if(ptr!=NULL && lstrlenW(ptr) > 0) {
+            result ++;
+        }
+    }
+    return result;
+}
+
+/*
+ * Produces a string array, 'list', from 'str' by splitting the string
+ * at each occurrence of LINE_SEPARATOR.
+ * 
+ * [IN] str:      the input
+ * [OUT] list:    string array
+ * [OUT] number:  number of elements in 'list' 
+ *
+ */
+void getLines(WCHAR *str, WCHAR *** list, DWORD * number) {
+    WCHAR *ptr = str;
+    WCHAR *ptr2 = NULL;
+    DWORD length = 0;
+    DWORD sepLength = lstrlenW(LINE_SEPARATOR);
+    DWORD counter = 0;
+    *number = getLinesNumber(str);
+    *list = (WCHAR**) LocalAlloc(LPTR, sizeof(WCHAR*) * (*number));
+    
+    if(ptr!=NULL) {
+        while(counter < (*number)) {
+            DWORD i = 0 ;
+            if((ptr2 = search(ptr, LINE_SEPARATOR))!=NULL) {
+                ptr2 = search(ptr, LINE_SEPARATOR) + sepLength;
+                length = lstrlenW(ptr) - lstrlenW(ptr2) - sepLength;
+                (*list) [counter ] = (WCHAR*) LocalAlloc(LPTR, sizeof(WCHAR*)*(length+1));
+                ZERO((*list) [counter ], sizeof(WCHAR*)*(length+1));
+                for(i=0;i<length;i++) {
+                    (*list) [counter ][i]=ptr[i];
+                }
+                ptr = ptr2;
+            } else if((length = lstrlenW(ptr)) > 0) {
+                (*list)[counter ] = (WCHAR*) LocalAlloc(LPTR, sizeof(WCHAR*)*(length+1));
+                ZERO((*list) [counter ], sizeof(WCHAR*)*(length+1));
+                for(i=0;i<length;i++) {
+                    (*list) [counter ][i]=ptr[i];
+                }
+                ptr = NULL;
+            }
+            counter++;
+            if(ptr==NULL)  break;
+        }
+    }
+}
+
+/*
+ *  Read file into memory. 
+ */
+void readStringList(HANDLE fileHandle, WCHAR *** list, DWORD *number) {
+    DWORD size = GetFileSize(fileHandle, NULL); // hope it much less than 2GB
+    DWORD read = 0;
+    char * charBuffer = (char*) LocalAlloc(LPTR, sizeof(char) * (size + 2));
+    ZERO(charBuffer, sizeof(char) * (size + 2));
+    
+    if(ReadFile(fileHandle, charBuffer, size, &read, 0) && read >=2) {
+        WCHAR * buffer = toWCHAR(charBuffer, size + 2);
+        getLines(buffer, list, number);
+        LocalFree(buffer);
+    }
+    LocalFree(charBuffer);
+}
+
+void deleteFile(WCHAR * filePath) {
+    BOOL canDelete = TRUE;
+    DWORD count = 0 ;
+    WIN32_FILE_ATTRIBUTE_DATA attrs;
+    DWORD filePathLength = lstrlenW(filePath);
+    DWORD prefixLength = (filePath == search(filePath, UNC_STD_PREFIX)) ? 0 : UNC_PREFIX_LENGTH;
+    DWORD length = filePathLength + prefixLength + 1;
+    WCHAR * file = (WCHAR*) LocalAlloc(LPTR, sizeof(WCHAR) * length);
+    DWORD i=0;
+    for(i=0;i<prefixLength;i++) {
+        file[i]=UNC_PREFIX[i];
+    }
+    for(i=0;i<filePathLength;i++) {
+        file[i+prefixLength] = filePath[i];
+    }
+
+    // Implementation note:
+    // GetFileAttributesExW() is used not only to get file attributes
+    // but also as a way to check if the file/dir (still) exist.
+
+    if(GetFileAttributesExW(file, GetFileExInfoStandard, &attrs)) {
+      if (attrs.dwFileAttributes & FILE_ATTRIBUTE_READONLY) { // if read-only attrib is set
+            if (SetFileAttributesW(file, FILE_ATTRIBUTE_NORMAL) == 0) { // remove read-only attrib
+                // The read-only attrib could not be deleted. No point in continuing.
+                canDelete = FALSE;
+            }
+        }
+        if (canDelete) {
+            if (attrs.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
+                while ((!RemoveDirectoryW(file) || GetFileAttributesExW(file, GetFileExInfoStandard, &attrs)) &&
+                        ((count++) < MAX_ATTEMPTS)) {
+                    Sleep(SLEEP_DELAY);
+                }
+            } else {
+                while ((!DeleteFileW(file) || GetFileAttributesExW(file, GetFileExInfoStandard, &attrs)) &&
+                        ((count++) < MAX_ATTEMPTS)) {
+                    Sleep(SLEEP_DELAY);
+                }
+            }
+        }
+    }
+    LocalFree(file);
+}
+
+DWORD WINAPI deleteFileThread(void * ptr) {
+    WCHAR * file = (WCHAR*) ptr;
+    deleteFile(file);
+    return THREAD_FINISHED;
+}
+
+void getFreeIndexForNextThread(HANDLE * list, DWORD max, DWORD * counter) {
+    DWORD code = 0;
+    DWORD maxReached = 0;
+    
+    while(1) {
+        if((*counter)==max) {
+            maxReached = 1;
+            *counter = 0;
+        }
+        code = 0;
+        if(list[*counter]==INVALID_HANDLE_VALUE) {
+            break;
+        } else if(GetExitCodeThread(list[*counter], &code)!=0 && code==THREAD_FINISHED) {
+            break;
+        } else {
+            *counter = (*counter) + 1;
+            if((*counter)==max && maxReached == 1) {
+                *counter = WaitForMultipleObjects(max, list, FALSE, INFINITE) - WAIT_OBJECT_0;
+            }
+        }
+    }
+}
+
+/*
+ * Deletes the the current executable. This is done by spawning a small
+ * .bat file which does the job. The .bat file even deletes itself when 
+ * finished.
+ */
+#define BUFSIZE 512
+void removeItselfUsingCmd() {
+    char * currentFile = LocalAlloc(LPTR, sizeof(char) * BUFSIZE);    
+    if (GetModuleFileNameA(0, currentFile, MAX_PATH)) {
+        char * tempFile = LocalAlloc(LPTR, sizeof(char) * BUFSIZE);    
+        HANDLE hTempFile;
+        int index = 0;
+        int i = 0;
+        char cleanerSuffix [] = ".bat";
+        for( i = 0; i < (lstrlenA(currentFile) - lstrlenA(cleanerSuffix)); i++) {
+            tempFile[index++] = currentFile[i];
+        }
+        for(i=0;i<lstrlenA(cleanerSuffix);i++) {
+            tempFile[index++] = cleanerSuffix[i];
+        }
+        hTempFile = CreateFileA(tempFile, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);        
+        if (hTempFile != INVALID_HANDLE_VALUE) {
+            char * command = LocalAlloc(LPTR, sizeof(char) * (lstrlenA(tempFile) + lstrlenA(currentFile) + 6));
+            DWORD bytesNumber = 0 ;
+            STARTUPINFO si;
+            PROCESS_INFORMATION pi;   
+            
+            char * strings [4] = {
+                ":Repeat\n",
+                "del %1\n",
+                "if exist %1 goto Repeat\n",
+                "del %0\n",                
+            };
+            for(i=0;i<4;i++) {
+                WriteFile(hTempFile, strings[i], lstrlenA(strings[i]), &bytesNumber, NULL);
+            }
+            
+            CloseHandle(hTempFile);
+            
+            ZERO( &si, sizeof(si) );
+            si.cb = sizeof(si);
+            ZERO( &pi, sizeof(pi) );
+            index=0;
+            command [index++]= '"';
+            for(i=0;i<lstrlenA(tempFile);i++) {
+                command [index++] = tempFile[i];
+            }
+            command[index++]= '"';
+            command[index++]= ' ';
+            command[index++]= '"';
+            for(i=0;i<lstrlenA(currentFile);i++) {
+                command [index++] = currentFile[i];
+            }
+            command[index++]= '"';
+            command[index++]= 0;
+
+            CreateProcess(0, command, 0, 0, FALSE, CREATE_NO_WINDOW | IDLE_PRIORITY_CLASS, 0, 0, &si, &pi);
+            LocalFree(command);
+            CloseHandle( pi.hProcess );
+            CloseHandle( pi.hThread );            
+        }
+        LocalFree(tempFile);
+    }
+    LocalFree(currentFile);
+    
+}
+
+/*
+ * Changes directory to the directory where the currently executing
+ * executable is located.
+ */ 
+void changeCurrentDirectory() {
+    WCHAR * currentFile = LocalAlloc(LPTR, sizeof(WCHAR) * MAX_PATH);    
+    if (GetModuleFileNameW(0, currentFile, MAX_PATH)) {
+        WCHAR * ptr = currentFile;
+        DWORD i=0;
+        DWORD len=0;
+        WCHAR * parent;
+        while(search(ptr, L"\\")!=NULL) {
+            ptr = search(ptr, L"\\") + 1;
+        }
+        len = lstrlenW(currentFile) - lstrlenW(ptr) - 1;
+        parent = LocalAlloc(LPTR, sizeof(WCHAR) * (len + 1));
+        for(i=0;i<len;i++) {
+            parent[i] = currentFile[i];
+        }
+        parent[len] = 0;
+        SetCurrentDirectoryW(parent);
+        LocalFree(parent);
+    }
+    LocalFree(currentFile);
+}
+
+// should be less or equals to MAXIMUM_WAIT_OBJECTS
+#define MAXIMUM_THREADS MAXIMUM_WAIT_OBJECTS
+
+int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hi, PSTR pszCmdLine, int nCmdShow) {
+//int main(void) {
+    int argumentsNumber = 0;
+    DWORD i=0;
+    DWORD  threadCounter = 0;
+    DWORD dwThread;
+    WCHAR ** commandLine = CommandLineToArgvW(GetCommandLineW(), &argumentsNumber);
+    HANDLE * runningThreads = (HANDLE *) LocalAlloc(LPTR, sizeof(HANDLE) * MAXIMUM_THREADS);
+    
+    for(i=0;i<MAXIMUM_THREADS;i++) {
+        runningThreads[i] = INVALID_HANDLE_VALUE;
+    }
+    changeCurrentDirectory();
+    
+    if(argumentsNumber==2) {
+        WCHAR * filename = commandLine[1];
+        HANDLE fileList = CreateFileW(filename, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, 0);
+        if(fileList!=0) {
+            WCHAR ** files = NULL;
+            DWORD number = 0;
+            DWORD allThreadsUsed=0;
+            readStringList(fileList, &files, &number);
+            CloseHandle(fileList);
+            
+            if(files!=NULL) {
+                Sleep(INITIAL_DELAY);
+                for(i=0;i<number;i++) {
+                    WCHAR * file = files[i];
+                    if(file!=NULL) {
+                        if(lstrlenW(file)>0)  {
+                            getFreeIndexForNextThread(runningThreads, MAXIMUM_THREADS, &threadCounter);
+                            runningThreads [threadCounter] = CreateThread( NULL, 0, &deleteFileThread, (LPVOID) file, 0, &dwThread );
+                            threadCounter++;
+                            if(threadCounter==MAXIMUM_THREADS) allThreadsUsed = 1;
+                        }
+                    }
+                }
+                
+                WaitForMultipleObjects(allThreadsUsed ? MAXIMUM_THREADS : threadCounter,
+                        runningThreads, TRUE, INFINITE);
+                
+                for(i=0;i<number;i++) {
+                    if(files[i]!=NULL) LocalFree(files[i]);
+                }
+                
+                LocalFree(files);
+            }
+        }
+    }
+    LocalFree(commandLine);
+    LocalFree(runningThreads);
+    //removeItself();
+    removeItselfUsingCmd();
+    return 0;
+}
diff --git a/src/main/cpp/cleaner/windows/vcproject/NBI Native Cleaner.ncb b/src/main/cpp/cleaner/windows/vcproject/NBI Native Cleaner.ncb
new file mode 100644
index 0000000..9057eba
--- /dev/null
+++ b/src/main/cpp/cleaner/windows/vcproject/NBI Native Cleaner.ncb
@@ -0,0 +1 @@
+Microsoft C/C++ MSF 7.00
diff --git a/src/main/cpp/cleaner/windows/vcproject/NBI Native Cleaner.sln b/src/main/cpp/cleaner/windows/vcproject/NBI Native Cleaner.sln
new file mode 100644
index 0000000..659a421
--- /dev/null
+++ b/src/main/cpp/cleaner/windows/vcproject/NBI Native Cleaner.sln
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual C++ Express 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NBI Native Cleaner", "NBI Native Cleaner.vcproj", "{0DB81F65-E9E6-4506-BE27-C020AAD1B04A}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Win32 = Debug|Win32
+		Release|Win32 = Release|Win32
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{0DB81F65-E9E6-4506-BE27-C020AAD1B04A}.Debug|Win32.ActiveCfg = Debug|Win32
+		{0DB81F65-E9E6-4506-BE27-C020AAD1B04A}.Debug|Win32.Build.0 = Debug|Win32
+		{0DB81F65-E9E6-4506-BE27-C020AAD1B04A}.Release|Win32.ActiveCfg = Release|Win32
+		{0DB81F65-E9E6-4506-BE27-C020AAD1B04A}.Release|Win32.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/src/main/cpp/cleaner/windows/vcproject/NBI Native Cleaner.suo b/src/main/cpp/cleaner/windows/vcproject/NBI Native Cleaner.suo
new file mode 100644
index 0000000..189f7a2
--- /dev/null
+++ b/src/main/cpp/cleaner/windows/vcproject/NBI Native Cleaner.suo
Binary files differ
diff --git a/src/main/cpp/cleaner/windows/vcproject/NBI Native Cleaner.vcproj b/src/main/cpp/cleaner/windows/vcproject/NBI Native Cleaner.vcproj
new file mode 100644
index 0000000..dd72b1f
--- /dev/null
+++ b/src/main/cpp/cleaner/windows/vcproject/NBI Native Cleaner.vcproj
@@ -0,0 +1,209 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8,00"
+	Name="NBI Native Cleaner"
+	ProjectGUID="{0DB81F65-E9E6-4506-BE27-C020AAD1B04A}"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="Debug"
+			IntermediateDirectory="Debug"
+			ConfigurationType="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				LinkIncremental="2"
+				GenerateDebugInformation="true"
+				SubSystem="2"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="Release"
+			IntermediateDirectory="Release"
+			ConfigurationType="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="1"
+				FavorSizeOrSpeed="2"
+				AdditionalIncludeDirectories="C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Include"
+				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE"
+				ExceptionHandling="0"
+				BasicRuntimeChecks="0"
+				RuntimeLibrary="0"
+				BufferSecurityCheck="false"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				SuppressStartupBanner="true"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="0"
+				CompileAs="1"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="Shell32.lib"
+				OutputFile="..\dist\cleaner.exe"
+				LinkIncremental="1"
+				SuppressStartupBanner="false"
+				AdditionalLibraryDirectories="C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Lib"
+				GenerateManifest="false"
+				IgnoreAllDefaultLibraries="true"
+				GenerateDebugInformation="false"
+				SubSystem="2"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				EntryPointSymbol="WinMain"
+				TargetMachine="1"
+				ErrorReporting="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+			>
+		</Filter>
+		<Filter
+			Name="Resource Files"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+			>
+		</Filter>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath="..\src\main.c"
+				>
+			</File>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
diff --git a/src/main/cpp/cleaner/windows/vcproject/NBI Native Cleaner.vcproj.user b/src/main/cpp/cleaner/windows/vcproject/NBI Native Cleaner.vcproj.user
new file mode 100644
index 0000000..a5ca4f9
--- /dev/null
+++ b/src/main/cpp/cleaner/windows/vcproject/NBI Native Cleaner.vcproj.user
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="utf-8"?><VisualStudioUserFile ProjectType="Visual C++" Version="8.00" ShowAllFiles="true"></VisualStudioUserFile>
\ No newline at end of file
diff --git a/src/main/cpp/jnilib/.common/src/CommonUtils.c b/src/main/cpp/jnilib/.common/src/CommonUtils.c
new file mode 100644
index 0000000..b66eccd
--- /dev/null
+++ b/src/main/cpp/jnilib/.common/src/CommonUtils.c
@@ -0,0 +1,384 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <jni.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+#include "CommonUtils.h"
+
+jbyteArray getStringBytes(JNIEnv* jEnv, jstring jString) {
+    jbyteArray result = NULL;
+    
+    if (jString != NULL) {
+        jmethodID jGetBytesMethod = (*jEnv)->GetMethodID(jEnv, (*jEnv)->GetObjectClass(jEnv, jString), "getBytes", "()[B");
+        
+        if (jGetBytesMethod != NULL) {
+            jbyteArray jBuffer = (jbyteArray) (*jEnv)->CallObjectMethod(jEnv, jString, jGetBytesMethod);
+            
+            if (jBuffer != NULL) {
+                jsize jLength = (*jEnv)->GetArrayLength(jEnv, jBuffer);
+                
+                result = (*jEnv)->NewByteArray(jEnv, jLength + 1);
+                if (jLength != 0) {
+                    jbyte* jChars = (*jEnv)->GetByteArrayElements(jEnv, jBuffer, NULL);
+                    (*jEnv)->SetByteArrayRegion(jEnv, result, 0, jLength, jChars);
+                    (*jEnv)->ReleaseByteArrayElements(jEnv, jBuffer, jChars, JNI_ABORT);
+                }
+                (*jEnv)->DeleteLocalRef(jEnv, jBuffer);
+            }
+            //(*jEnv)->DeleteLocalRef(jEnv, getBytesMethod);
+        }
+    }
+    
+    return result;
+}
+
+
+jstring newStringFromJByteArray(JNIEnv* jEnv, jbyteArray jByteArray, int length) {
+    jstring result = NULL;
+    
+    jclass jStringClass = (*jEnv)->FindClass(jEnv, "java/lang/String");
+    if (jStringClass != NULL) {
+        jmethodID jStringConstructor = (*jEnv)->GetMethodID(jEnv, jStringClass, "<init>", "([BII)V");
+        
+        if (jStringConstructor != NULL) {
+            result = (jstring) (*jEnv)->NewObject(jEnv, jStringClass, jStringConstructor, jByteArray, 0, length);
+            //(*jEnv)->DeleteLocalRef(jEnv, stringConstructor);
+        }
+        (*jEnv)->DeleteLocalRef(jEnv, jStringClass);
+    }
+    
+    return result;
+}
+
+
+jstring newStringFromJCharArray(JNIEnv* jEnv, jcharArray jCharArray, int length) {
+    jstring result = NULL;
+    
+    jclass jStringClass = (*jEnv)->FindClass(jEnv, "java/lang/String");
+    if (jStringClass != NULL) {
+        jmethodID jStringConstructor = (*jEnv)->GetMethodID(jEnv, jStringClass, "<init>", "([CII)V");
+        
+        if (jStringConstructor != NULL) {
+            result = (jstring) (*jEnv)->NewObject(jEnv, jStringClass, jStringConstructor, jCharArray, 0, length);            
+        }
+        (*jEnv)->DeleteLocalRef(jEnv, jStringClass);
+    }
+    
+    return result;
+}
+
+jstring getString(JNIEnv* jEnv, const char* chars) {
+    return (jstring) getStringWithLength(jEnv, chars, (int) STRLEN(chars));
+}
+
+jstring getStringW(JNIEnv* jEnv, const wchar_t * chars) {
+    return (jstring) getStringWithLengthW(jEnv, chars, (int) WCSLEN(chars));
+}
+
+jstring getStringWithLength(JNIEnv* jEnv, const char* chars, int length) {
+    jstring result = NULL;
+    
+    if (chars != NULL) {
+        if (length == 0) {
+            result = (*jEnv)->NewString(jEnv, (const jchar *) L"", 0);
+        } else {
+            jbyteArray jByteArray = (*jEnv)->NewByteArray(jEnv, length);
+            
+            if (jByteArray != NULL) {
+                (*jEnv)->SetByteArrayRegion(jEnv, jByteArray, 0, length, (jbyte*) chars);
+                result = newStringFromJByteArray(jEnv, jByteArray, length);
+                (*jEnv)->DeleteLocalRef(jEnv, jByteArray);
+            }
+        }
+    }
+    
+    return result;
+}
+
+
+jstring getStringWithLengthW(JNIEnv* jEnv, const wchar_t* chars, int length) {
+    jstring result = NULL;
+    
+    if (chars != NULL) {
+        if (length == 0) {
+            result = (*jEnv)->NewString(jEnv, (const jchar *) L"", 0);
+        } else {
+            jcharArray jCharArray = (*jEnv)->NewCharArray(jEnv, length);
+            
+            if (jCharArray != NULL) {
+                (*jEnv)->SetCharArrayRegion(jEnv, jCharArray, 0, length, (jchar*) chars);
+                result = newStringFromJCharArray(jEnv, jCharArray, length);
+                (*jEnv)->DeleteLocalRef(jEnv, jCharArray);
+            }
+        }
+    }
+    
+    return result;
+}
+
+
+char* getChars(JNIEnv* jEnv, jstring jString) {
+    char* result = NULL;
+    
+    jbyteArray jByteArray = getStringBytes(jEnv, jString);
+    if (jByteArray != NULL) {
+        jbyte* jBytes = (*jEnv)->GetByteArrayElements(jEnv, jByteArray, NULL);
+        
+        long index = 0;
+        if (jBytes != NULL) {
+            int length = (int) STRLEN((char*) jBytes);
+            
+            result = (char*) MALLOC(sizeof(char) * (length + 1));
+            if (result != NULL) {
+                ZERO(result, length);
+                STRNCPY(result, (char*) jBytes, length);
+                result[length] = 0;
+            }
+            (*jEnv)->ReleaseByteArrayElements(jEnv, jByteArray, jBytes, JNI_ABORT);
+        }
+        (*jEnv)->DeleteLocalRef(jEnv, jByteArray);
+    }
+    
+    return result;
+}
+
+char* getStringFromMethod(JNIEnv* jEnv, jobject object, const char* methodName) {
+    char* result = NULL;
+    
+    jclass clazz = (*jEnv)->GetObjectClass(jEnv, object);
+    if (clazz != NULL) {
+        jmethodID method = (*jEnv)->GetMethodID(jEnv, clazz, methodName, "()Ljava/lang/String;");
+        if (method != NULL) {
+            jstring string = (jstring) (*jEnv)->CallObjectMethod(jEnv, object, method);
+            if (string != NULL) {
+                result = getChars(jEnv, string);
+                (*jEnv)->DeleteLocalRef(jEnv, string);
+            }
+            //(*jEnv)->DeleteLocalRef(jEnv, method);
+        }
+        (*jEnv)->DeleteLocalRef(jEnv, clazz);
+    }
+    
+    return result;
+}
+
+wchar_t * getWideStringFromMethod(JNIEnv* jEnv, jobject object, const char* methodName) {
+    wchar_t* result = NULL;
+    
+    jclass clazz = (*jEnv)->GetObjectClass(jEnv, object);
+    if (clazz != NULL) {
+        jmethodID method = (*jEnv)->GetMethodID(jEnv, clazz, methodName, "()Ljava/lang/String;");
+        if (method != NULL) {
+            jstring string = (jstring) (*jEnv)->CallObjectMethod(jEnv, object, method);
+            if (string != NULL) {
+                result = getWideChars(jEnv, string);
+                (*jEnv)->DeleteLocalRef(jEnv, string);
+            }
+            //(*jEnv)->DeleteLocalRef(jEnv, method);
+        }
+        (*jEnv)->DeleteLocalRef(jEnv, clazz);
+    }
+    
+    return result;
+}
+
+jboolean isInstanceOf(JNIEnv* jEnv, jobject object, const char* className) {
+    jboolean result = 0;
+    jclass clazz = clazz = (*jEnv)->FindClass(jEnv, className);
+    
+    if (clazz != NULL) {
+        result = (*jEnv)->IsInstanceOf(jEnv, object, clazz);
+        (*jEnv)->DeleteLocalRef(jEnv, clazz);
+    }
+    return result;
+}
+
+jint getIntFromMethod(JNIEnv* jEnv, jobject object, const char* methodName) {
+    jint value = 0;
+    
+    jclass clazz = (*jEnv)->GetObjectClass(jEnv, object);
+    if (clazz != NULL) {
+        jmethodID method = (*jEnv)->GetMethodID(jEnv, clazz, methodName, "()I");
+        if (method != NULL) {
+            value = (*jEnv)->CallIntMethod(jEnv, object, method);
+        }
+        (*jEnv)->DeleteLocalRef(jEnv, clazz);
+    }
+    
+    return value;
+}
+
+void throwException(JNIEnv* jEnv, const char* message) {
+    jclass clazz = (*jEnv)->FindClass(jEnv, "org/netbeans/installer/utils/exceptions/NativeException");
+    if (clazz != NULL) {
+        (*jEnv)->ThrowNew(jEnv, clazz, message);
+        (*jEnv)->DeleteLocalRef(jEnv, clazz);
+    }
+}
+
+void writeLog(JNIEnv* jEnv, int level, const char* message) {
+    const char* prefix = "[jni] ";
+    
+    jclass clazz = (*jEnv)->FindClass(jEnv, "org/netbeans/installer/utils/LogManager");
+    if (clazz != NULL) {
+        jmethodID method = (*jEnv)->GetStaticMethodID(jEnv, clazz, "log", "(ILjava/lang/String;)V");
+        if (method != NULL) {
+            jstring jMessage = NULL;
+            int prefix_length = STRLEN(prefix);
+            int message_length = STRLEN(message);
+            char* string = (char*) MALLOC(sizeof(char) * (prefix_length + message_length + 1));
+            int i = 0;
+            for(i=0;i<prefix_length;i++) {
+               string[i]=prefix[i];
+            }
+            
+            for(i=0;i<message_length;i++) {
+               string[i + prefix_length]=message[i];
+            }
+            string[i+prefix_length + message_length] = '\0';
+
+            
+            jMessage = getString(jEnv, string);
+            
+            if (jMessage != NULL) {
+                (*jEnv)->CallStaticVoidMethod(jEnv, clazz, method, (jint) level, jMessage);
+                (*jEnv)->DeleteLocalRef(jEnv, jMessage);
+            }
+            
+            FREE(string);
+            //(*jEnv)->DeleteLocalRef(jEnv, method);
+        }
+        (*jEnv)->DeleteLocalRef(jEnv, clazz);
+    }
+}
+
+int createDirs(JNIEnv* jEnv, jstring jPath) {
+    int result = 0;
+    jclass jFileClass = (*jEnv)->FindClass(jEnv, "java/io/File");
+    if (jFileClass != NULL) {
+        jmethodID jFileConstructor     = (*jEnv)->GetMethodID(jEnv, jFileClass, "<init>", "(Ljava/lang/String;)V");
+        jmethodID jGetParentFileMethod = (*jEnv)->GetMethodID(jEnv, jFileClass, "getParentFile", "()Ljava/io/File;");
+        jmethodID jExistsMethod        = (*jEnv)->GetMethodID(jEnv, jFileClass, "exists", "()Z");
+        jmethodID jMkdirsMethod        = (*jEnv)->GetMethodID(jEnv, jFileClass, "mkdirs", "()Z");
+        
+        if ((jFileConstructor != NULL) && (jGetParentFileMethod != NULL) && (jExistsMethod != NULL) && (jMkdirsMethod != NULL)) {            
+            jobject jFile = (*jEnv)->NewObject(jEnv, jFileClass, jFileConstructor, jPath);
+            if (jFile != NULL ) {
+                if(!((*jEnv)->CallBooleanMethod(jEnv, jFile, jExistsMethod))) {
+                    jobject jParent = (*jEnv)->CallObjectMethod(jEnv, jFile, jGetParentFileMethod);
+                    if (jParent != NULL) {
+                        result = (*jEnv)->CallBooleanMethod(jEnv, jParent, jExistsMethod);
+                        if (!result) {
+                            result = (*jEnv)->CallBooleanMethod(jEnv, jParent, jMkdirsMethod);
+                        }
+                        (*jEnv)->DeleteLocalRef(jEnv, jParent);
+                    }
+                } else {
+                    result = 1;
+                }
+                (*jEnv)->DeleteLocalRef(jEnv, jFile);
+            }
+        }
+        (*jEnv)->DeleteLocalRef(jEnv, jFileClass);
+    }
+    return result;
+}
+
+int mkdirs(JNIEnv* jEnv, const char *path) {
+    int result = 1;
+    jstring jPath  = getString(jEnv, path);
+    if (jPath != NULL) {
+        result = createDirs(jEnv, jPath);
+        (*jEnv)->DeleteLocalRef(jEnv, jPath);
+    }
+    return result;
+}
+
+
+int mkdirsW(JNIEnv* jEnv, const wchar_t *path) {
+    int result = 1;
+    jstring jPath  = getStringW(jEnv, path);
+    if (jPath != NULL) {        
+        result = createDirs(jEnv, jPath);
+        (*jEnv)->DeleteLocalRef(jEnv, jPath);
+    }
+    
+    return result;
+}
+
+
+
+unsigned char* getByteFromMultiString(JNIEnv *jEnv, jobjectArray jObjectArray, unsigned long* size) {
+    unsigned short * result = NULL;
+    
+    int     totalLength = 0;
+    unsigned int arrayLength = (*jEnv)->GetArrayLength(jEnv, jObjectArray);
+    jstring jString     = NULL;
+    
+    unsigned int i, j; // just counters
+    
+    for (i = 0; i < arrayLength; i++) {
+        jString = (jstring) (*jEnv)->GetObjectArrayElement(jEnv, jObjectArray, i);
+        totalLength += (*jEnv)->GetStringLength(jEnv, jString) + 1;
+    }
+    totalLength++; // add null to the end of array
+      
+    result = (unsigned short*) MALLOC(sizeof(unsigned short) * totalLength);
+    if (result != NULL) {
+        int index = 0 ; 
+        
+        for (i = 0; i < arrayLength; i++) {
+            jString = (jstring) (*jEnv)->GetObjectArrayElement(jEnv, jObjectArray, i);
+            
+            if (jString != NULL) {
+                wchar_t * chars = getWideChars(jEnv, jString);
+                if (chars != NULL) {
+                    for (j = 0; j < (WCSLEN(chars)); j++) {
+                        result[index++] = chars[j];
+                    }
+                    
+                    FREE(chars);
+                }
+            }
+            result[index++] = '\0';            
+        }
+        result[index++] = '\0'; //double \0 at the end        
+    }    
+    * size = sizeof(unsigned short) * totalLength;
+    return (unsigned char*)result;
+}
+
+wchar_t * getWideChars(JNIEnv *jEnv, jstring jString) {
+    if(jString==NULL) {
+        return NULL;
+    } else {
+        long length = (*jEnv)->GetStringLength( jEnv, jString);
+        const jchar * unicodeStr = (*jEnv)->GetStringChars( jEnv, jString, 0 );
+        wchar_t * copy = (wchar_t *) MALLOC(sizeof(wchar_t) * (length + 1));
+        ZERO(copy, sizeof(wchar_t)*(length + 1));        
+        WCSNCPY(copy, (const wchar_t *) unicodeStr, length + 1);
+        (*jEnv)->ReleaseStringChars( jEnv, jString, unicodeStr);
+        return copy;
+    }
+    
+}
diff --git a/src/main/cpp/jnilib/.common/src/CommonUtils.h b/src/main/cpp/jnilib/.common/src/CommonUtils.h
new file mode 100644
index 0000000..8824351
--- /dev/null
+++ b/src/main/cpp/jnilib/.common/src/CommonUtils.h
@@ -0,0 +1,122 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <jni.h>
+#include <wchar.h>
+#include <stdlib.h>
+#ifdef _MSC_VER 
+#include <windows.h>
+#endif
+
+#ifndef _CommonUtils_H
+#define	_CommonUtils_H
+
+
+#ifdef _MSC_VER 
+#define FREE(x) { if((x)!=NULL) { LocalFree(x); (x)=NULL;}}
+#else  
+#define FREE(x) { if((x)!=NULL) {      free(x); (x)=NULL;}}
+#endif
+
+#ifdef _MSC_VER 
+#define MALLOC(x) LocalAlloc(LPTR, x)
+#else  
+#define MALLOC(x) malloc(x)
+#endif
+
+
+#ifdef _MSC_VER
+#define ZERO(x,y) SecureZeroMemory((x),(y))
+#else
+#define ZERO(x,y) memset((x),0,(y))
+#endif
+
+
+#ifdef _MSC_VER
+#define STRLEN(x) lstrlenA(x)
+#else
+#define STRLEN(x) strlen(x)
+#endif
+
+
+#ifdef _MSC_VER
+#define WCSLEN(x) ((unsigned long)lstrlenW(x))
+#else
+#define WCSLEN(x) ((unsigned long)wcslen(x))
+#endif
+
+
+#ifdef _MSC_VER
+#define STRNCPY(x,y,z) lstrcpynA((x),(y),(z))
+#else
+#define STRNCPY(x,y,z) strncpy((x),(y),(z))
+#endif
+
+#ifdef _MSC_VER
+#define WCSNCPY(x,y,z) lstrcpynW((x),(y),(z))
+#else
+#define WCSNCPY(x,y,z) wcsncpy((x),(y),(z))
+#endif
+
+
+#define LOG_DEBUG    4
+#define LOG_MESSAGE  3
+#define LOG_WARNING  2
+#define LOG_ERROR    1
+#define LOG_CRITICAL 0
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+    
+jbyteArray getStringBytes(JNIEnv* jEnv, jstring jString);
+
+jstring newStringFromJByteArray(JNIEnv* jEnv, jbyteArray jByteArray, int length);
+jstring newStringFromJCharArray(JNIEnv* jEnv, jcharArray jCharArray, int length);
+
+jstring getString (JNIEnv* jEnv, const char* chars);
+jstring getStringW(JNIEnv* jEnv, const wchar_t * chars);
+
+
+jstring getStringWithLength(JNIEnv* jEnv, const char* chars, int length);
+jstring getStringWithLengthW(JNIEnv* jEnv, const wchar_t * chars, int length);
+
+char* getChars(JNIEnv* jEnv, jstring jString);
+wchar_t * getWideChars(JNIEnv *jEnv, jstring str);
+
+char* getStringFromMethod(JNIEnv* jEnv, jobject object, const char* methodName);
+wchar_t* getWideStringFromMethod(JNIEnv* jEnv, jobject object, const char* methodName) ;
+
+jint getIntFromMethod(JNIEnv* jEnv, jobject object, const char* methodName);
+
+jboolean isInstanceOf(JNIEnv* jEnv, jobject object, const char* className);
+
+void throwException(JNIEnv* jEnv, const char* message);
+
+void writeLog(JNIEnv* jEnv, int level, const char* message);
+
+int mkdirs (JNIEnv* jEnv, const char *path);
+int mkdirsW(JNIEnv* jEnv, const wchar_t *path);
+
+unsigned char* getByteFromMultiString(JNIEnv *jEnv, jobjectArray jObjectArray, unsigned long* size);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _CommonUtils_H */
diff --git a/src/main/cpp/jnilib/.unix/src/jni_UnixNativeUtils.c b/src/main/cpp/jnilib/.unix/src/jni_UnixNativeUtils.c
new file mode 100644
index 0000000..437e270
--- /dev/null
+++ b/src/main/cpp/jnilib/.unix/src/jni_UnixNativeUtils.c
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <jni.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/statvfs.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../../.common/src/CommonUtils.h"
+#include "jni_UnixNativeUtils.h"
+
+
+jboolean statMode(const char *path, int *mode) {
+    struct stat sb;
+    if (stat(path, &sb) == 0) {
+        *mode = sb.st_mode;
+        return 1;
+    } else {
+        return 0;
+    }
+}
+
+
+JNIEXPORT jlong JNICALL Java_org_netbeans_installer_utils_system_UnixNativeUtils_getFreeSpace0(JNIEnv* jEnv, jobject jObject, jstring jPath) {
+    char* path   = getChars(jEnv, jPath);
+    jlong result = 0;
+    
+    struct statvfs fsstat;
+    if(memset(&fsstat, 0, sizeof(struct statvfs)) != NULL) {
+        if(statvfs(path, &fsstat) == 0) {
+            result = (jlong) fsstat.f_frsize;
+            result *= (jlong) fsstat.f_bfree;
+        }
+    }
+    
+    
+    FREE(path);
+    return result;
+}
+
+
+JNIEXPORT void JNICALL Java_org_netbeans_installer_utils_system_UnixNativeUtils_setPermissions0(JNIEnv *jEnv, jobject jObject, jstring jPath, jint jMode, jint jChange) {
+    char* path = getChars(jEnv, jPath);    
+    int currentMode = 0 ;
+    char * msg = NULL;
+    if(statMode(path, &currentMode)) {
+        switch (jChange) {
+            case MODE_CHANGE_SET:
+                currentMode |= (S_IRWXU | S_IRWXG | S_IRWXO);
+                currentMode &= jMode;
+                break;
+            case MODE_CHANGE_ADD:
+                currentMode |= jMode;
+                break;
+            case MODE_CHANGE_REMOVE:
+                currentMode &= ~jMode;
+                break;
+            default:     
+                msg = (char*) malloc(sizeof(char) * 60);
+                memset(msg, 0, sizeof(char) * 60);
+                sprintf(msg, "Selected change mode (%ld) is not supported", jChange);
+                throwException(jEnv, msg);
+                FREE(msg);
+                FREE(path);                
+                return;                
+        }
+        chmod(path, currentMode);
+    } else {
+        throwException(jEnv, "Can`t get file current permissions");
+    }
+    FREE(path);
+}
+
+
+JNIEXPORT jint JNICALL Java_org_netbeans_installer_utils_system_UnixNativeUtils_getPermissions0(JNIEnv *jEnv, jobject jObject, jstring jPath) {
+    char* path = getChars(jEnv, jPath);
+    int currentMode;
+    if(statMode(path, &currentMode)) {
+        return currentMode & (S_IRWXU | S_IRWXG | S_IRWXO);
+    } else {
+        throwException(jEnv, "Can`t get file current permissions");
+    }
+    
+    FREE(path);
+}
+
+JNIEXPORT jboolean JNICALL Java_org_netbeans_installer_utils_system_UnixNativeUtils_isCurrentUserAdmin0 (JNIEnv *jEnv, jobject jObject) {
+    return (geteuid()==0);
+}
diff --git a/src/main/cpp/jnilib/.unix/src/jni_UnixNativeUtils.h b/src/main/cpp/jnilib/.unix/src/jni_UnixNativeUtils.h
new file mode 100644
index 0000000..989e05d
--- /dev/null
+++ b/src/main/cpp/jnilib/.unix/src/jni_UnixNativeUtils.h
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <jni.h>
+/* Header for class org_netbeans_installer_utils_system_UnixNativeUtils */
+
+#ifndef _Included_org_netbeans_installer_utils_system_UnixNativeUtils
+#define _Included_org_netbeans_installer_utils_system_UnixNativeUtils
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define MODE_RU 1L
+#define MODE_WU 2L
+#define MODE_EU 4L
+#define MODE_RG 8L
+#define MODE_WG 16L
+#define MODE_EG 32L
+#define MODE_RO 64L
+#define MODE_WO 128L
+#define MODE_EO 256L
+    
+#define MODE_CHANGE_SET 1L
+#define MODE_CHANGE_ADD 2L
+#define MODE_CHANGE_REMOVE 4L
+        
+    
+
+/*
+ * Class:     org_netbeans_installer_utils_system_UnixNativeUtils
+ * Method:    getFreeSpace0
+ * Signature: (Ljava/lang/String;)J
+ */
+JNIEXPORT jlong JNICALL Java_org_netbeans_installer_utils_system_UnixNativeUtils_getFreeSpace0
+  (JNIEnv *, jobject, jstring);
+
+/*
+ * Class:     org_netbeans_installer_utils_system_UnixNativeUtils
+ * Method:    setPermission0
+ * Signature: (Ljava/lang/String;II)V
+ */
+JNIEXPORT void JNICALL Java_org_netbeans_installer_utils_system_UnixNativeUtils_setPermissions0
+  (JNIEnv *, jobject, jstring, jint, jint);
+
+/*
+ * Class:     org_netbeans_installer_utils_system_UnixNativeUtils
+ * Method:    getPermissions0
+ * Signature: (Ljava/lang/String;)I
+ */
+JNIEXPORT jint JNICALL Java_org_netbeans_installer_utils_system_UnixNativeUtils_getPermissions0
+  (JNIEnv *, jobject, jstring);
+
+/*
+ * Class:     org_netbeans_installer_utils_system_UnixNativeUtils
+ * Method:    isCurrentUserAdmin0
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_org_netbeans_installer_utils_system_UnixNativeUtils_isCurrentUserAdmin0
+  (JNIEnv *, jobject);
+
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/main/cpp/jnilib/linux/Makefile b/src/main/cpp/jnilib/linux/Makefile
new file mode 100644
index 0000000..516847d
--- /dev/null
+++ b/src/main/cpp/jnilib/linux/Makefile
@@ -0,0 +1,109 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# 
+
+#
+#  There exist several targets which are by default empty and which can be 
+#  used for execution of your targets. These targets are usually executed 
+#  before and after some main targets. They are: 
+#
+#     .build-pre:              called before 'build' target
+#     .build-post:             called after 'build' target
+#     .clean-pre:              called before 'clean' target
+#     .clean-post:             called after 'clean' target
+#     .clobber-pre:            called before 'clobber' target
+#     .clobber-post:           called after 'clobber' target
+#     .all-pre:                called before 'all' target
+#     .all-post:               called after 'all' target
+#     .help-pre:                called before 'help' target
+#     .help-post:               called after 'help' target
+#
+#  Targets beginning with '.' are not intended to be called on their own.
+#
+#  Main targets can be executed directly, and they are:
+#  
+#     build                    build a specific configuration
+#     clean                    remove built files from a configuration
+#     clobber                  remove all built files
+#     all                      build all configurations
+#     help                     print help mesage
+#  
+#  Targets .build-impl, .clean-impl, .clobber-impl, .all-impl, and
+#  .help-impl are implemented in nbproject/makefile-impl.mk.
+#
+
+# Environment 
+MKDIR=mkdir
+CP=cp
+CCADMIN=CCadmin
+RANLIB=ranlib
+
+
+# build
+build: .build-pre .build-impl .build-post
+
+.build-pre:
+# Add your pre 'build' code here...
+
+.build-post:
+# Add your post 'build' code here...
+
+
+# clean
+clean: .clean-pre .clean-impl .clean-post
+
+.clean-pre:
+# Add your pre 'clean' code here...
+
+.clean-post:
+# Add your post 'clean' code here...
+
+
+# clobber
+clobber: .clobber-pre .clobber-impl .clobber-post
+
+.clobber-pre:
+# Add your pre 'clobber' code here...
+
+.clobber-post:
+# Add your post 'clobber' code here...
+
+
+# all
+all: .all-pre .all-impl .all-post
+
+.all-pre:
+# Add your pre 'all' code here...
+
+.all-post:
+# Add your post 'all' code here...
+
+
+# help
+help: .help-pre .help-impl .help-post
+
+.help-pre:
+# Add your pre 'help' code here...
+
+.help-post:
+# Add your post 'help' code here...
+
+
+
+# include project implementation makefile
+include nbproject/Makefile-impl.mk
diff --git a/src/main/cpp/jnilib/linux/nbproject/configurations.xml b/src/main/cpp/jnilib/linux/nbproject/configurations.xml
new file mode 100644
index 0000000..9e8e8b1
--- /dev/null
+++ b/src/main/cpp/jnilib/linux/nbproject/configurations.xml
@@ -0,0 +1,183 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+
+<configurationDescriptor version="35">
+  <logicalFolder name="root" displayName="root" projectFiles="true">
+    <logicalFolder name="SourceFiles"
+                   displayName="Source Files"
+                   projectFiles="true">
+      <itemPath>../.common/src/CommonUtils.c</itemPath>
+      <itemPath>../.unix/src/jni_UnixNativeUtils.c</itemPath>
+    </logicalFolder>
+    <logicalFolder name="HeaderFiles"
+                   displayName="Header Files"
+                   projectFiles="true">
+      <itemPath>../.common/src/CommonUtils.h</itemPath>
+      <itemPath>../.unix/src/jni_UnixNativeUtils.h</itemPath>
+    </logicalFolder>
+    <logicalFolder name="ResourceFiles"
+                   displayName="Resource Files"
+                   projectFiles="true">
+    </logicalFolder>
+    <logicalFolder name="ExternalFiles"
+                   displayName="Important Files"
+                   projectFiles="false">
+      <itemPath>Makefile</itemPath>
+    </logicalFolder>
+  </logicalFolder>
+  <projectmakefile>Makefile</projectmakefile>
+  <defaultConf>0</defaultConf>
+  <confs>
+    <conf name="Debug" type="2">
+      <toolsSet>
+        <compilerSet>GNU</compilerSet>
+        <cRequired>true</cRequired>
+        <cppRequired>true</cppRequired>
+        <fortranRequired>false</fortranRequired>
+        <platform>2</platform>
+      </toolsSet>
+      <compileType>
+        <cCompilerTool>
+          <developmentMode>0</developmentMode>
+          <stripSymbols>true</stripSymbols>
+          <includeDirectories>
+            <directoryPath>/usr/java/include</directoryPath>
+            <directoryPath>/usr/java/include/linux</directoryPath>
+          </includeDirectories>
+          <commandLine>-shared -m32 -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE</commandLine>
+        </cCompilerTool>
+        <ccCompilerTool>
+          <developmentMode>0</developmentMode>
+          <stripSymbols>true</stripSymbols>
+          <includeDirectories>
+            <directoryPath>/usr/java/include</directoryPath>
+            <directoryPath>/usr/java/include/linux</directoryPath>
+          </includeDirectories>
+          <commandLine>-shared -m32 -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE</commandLine>
+        </ccCompilerTool>
+        <linkerTool>
+          <output>dist/linux.so</output>
+          <stripSymbols>true</stripSymbols>
+          <linkerLibItems>
+          </linkerLibItems>
+        </linkerTool>
+      </compileType>
+      <item path="../.common/src/CommonUtils.c">
+        <itemTool>0</itemTool>
+      </item>
+      <item path="../.common/src/CommonUtils.h">
+        <itemTool>3</itemTool>
+      </item>
+      <item path="../.unix/src/jni_UnixNativeUtils.c">
+        <itemTool>0</itemTool>
+      </item>
+      <item path="../.unix/src/jni_UnixNativeUtils.h">
+        <itemTool>3</itemTool>
+      </item>
+    </conf>
+    <conf name="Release" type="2">
+      <toolsSet>
+        <compilerSet>GNU</compilerSet>
+        <cRequired>true</cRequired>
+        <cppRequired>true</cppRequired>
+        <fortranRequired>false</fortranRequired>
+        <platform>2</platform>
+      </toolsSet>
+      <compileType>
+        <cCompilerTool>
+          <developmentMode>5</developmentMode>
+        </cCompilerTool>
+        <ccCompilerTool>
+          <developmentMode>5</developmentMode>
+        </ccCompilerTool>
+        <fortranCompilerTool>
+          <developmentMode>5</developmentMode>
+        </fortranCompilerTool>
+        <linkerTool>
+          <linkerLibItems>
+          </linkerLibItems>
+        </linkerTool>
+      </compileType>
+      <item path="../.common/src/CommonUtils.c">
+        <itemTool>0</itemTool>
+      </item>
+      <item path="../.common/src/CommonUtils.h">
+        <itemTool>3</itemTool>
+      </item>
+      <item path="../.unix/src/jni_UnixNativeUtils.c">
+        <itemTool>0</itemTool>
+      </item>
+      <item path="../.unix/src/jni_UnixNativeUtils.h">
+        <itemTool>3</itemTool>
+      </item>
+    </conf>
+    <conf name="Debug_amd64" type="2">
+      <toolsSet>
+        <compilerSet>GNU</compilerSet>
+        <cRequired>true</cRequired>
+        <cppRequired>true</cppRequired>
+        <fortranRequired>false</fortranRequired>
+        <platform>2</platform>
+      </toolsSet>
+      <compileType>
+        <cCompilerTool>
+          <developmentMode>0</developmentMode>
+          <stripSymbols>true</stripSymbols>
+          <sixtyfourBits>true</sixtyfourBits>
+          <includeDirectories>
+            <directoryPath>/usr/java/include</directoryPath>
+            <directoryPath>/usr/java/include/linux</directoryPath>
+          </includeDirectories>
+          <commandLine>-shared -fPIC  -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE</commandLine>
+        </cCompilerTool>
+        <ccCompilerTool>
+          <developmentMode>0</developmentMode>
+          <stripSymbols>true</stripSymbols>
+          <sixtyfourBits>true</sixtyfourBits>
+          <includeDirectories>
+            <directoryPath>/usr/java/include</directoryPath>
+            <directoryPath>/usr/java/include/linux</directoryPath>
+          </includeDirectories>
+          <commandLine>-shared -fPIC  -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE</commandLine>
+        </ccCompilerTool>
+        <linkerTool>
+          <output>dist/linux-amd64.so</output>
+          <stripSymbols>true</stripSymbols>
+          <linkerLibItems>
+          </linkerLibItems>
+        </linkerTool>
+      </compileType>
+      <item path="../.common/src/CommonUtils.c">
+        <itemTool>0</itemTool>
+      </item>
+      <item path="../.common/src/CommonUtils.h">
+        <itemTool>3</itemTool>
+      </item>
+      <item path="../.unix/src/jni_UnixNativeUtils.c">
+        <itemTool>0</itemTool>
+      </item>
+      <item path="../.unix/src/jni_UnixNativeUtils.h">
+        <itemTool>3</itemTool>
+      </item>
+    </conf>
+  </confs>
+</configurationDescriptor>
diff --git a/src/main/cpp/jnilib/linux/nbproject/project.properties b/src/main/cpp/jnilib/linux/nbproject/project.properties
new file mode 100644
index 0000000..3807b67
--- /dev/null
+++ b/src/main/cpp/jnilib/linux/nbproject/project.properties
@@ -0,0 +1,20 @@
+
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# 
+
diff --git a/src/main/cpp/jnilib/linux/nbproject/project.xml b/src/main/cpp/jnilib/linux/nbproject/project.xml
new file mode 100644
index 0000000..4e61d3b
--- /dev/null
+++ b/src/main/cpp/jnilib/linux/nbproject/project.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+
+<project xmlns="http://www.netbeans.org/ns/project/1">
+    <type>org.netbeans.modules.cnd.makeproject</type>
+    <configuration>
+        <data xmlns="http://www.netbeans.org/ns/make-project/1">
+            <name>NBI Native Library: Linux</name>
+            <make-project-type>0</make-project-type>
+        </data>
+    </configuration>
+</project>
diff --git a/src/main/cpp/jnilib/macosx/Makefile b/src/main/cpp/jnilib/macosx/Makefile
new file mode 100644
index 0000000..516847d
--- /dev/null
+++ b/src/main/cpp/jnilib/macosx/Makefile
@@ -0,0 +1,109 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# 
+
+#
+#  There exist several targets which are by default empty and which can be 
+#  used for execution of your targets. These targets are usually executed 
+#  before and after some main targets. They are: 
+#
+#     .build-pre:              called before 'build' target
+#     .build-post:             called after 'build' target
+#     .clean-pre:              called before 'clean' target
+#     .clean-post:             called after 'clean' target
+#     .clobber-pre:            called before 'clobber' target
+#     .clobber-post:           called after 'clobber' target
+#     .all-pre:                called before 'all' target
+#     .all-post:               called after 'all' target
+#     .help-pre:                called before 'help' target
+#     .help-post:               called after 'help' target
+#
+#  Targets beginning with '.' are not intended to be called on their own.
+#
+#  Main targets can be executed directly, and they are:
+#  
+#     build                    build a specific configuration
+#     clean                    remove built files from a configuration
+#     clobber                  remove all built files
+#     all                      build all configurations
+#     help                     print help mesage
+#  
+#  Targets .build-impl, .clean-impl, .clobber-impl, .all-impl, and
+#  .help-impl are implemented in nbproject/makefile-impl.mk.
+#
+
+# Environment 
+MKDIR=mkdir
+CP=cp
+CCADMIN=CCadmin
+RANLIB=ranlib
+
+
+# build
+build: .build-pre .build-impl .build-post
+
+.build-pre:
+# Add your pre 'build' code here...
+
+.build-post:
+# Add your post 'build' code here...
+
+
+# clean
+clean: .clean-pre .clean-impl .clean-post
+
+.clean-pre:
+# Add your pre 'clean' code here...
+
+.clean-post:
+# Add your post 'clean' code here...
+
+
+# clobber
+clobber: .clobber-pre .clobber-impl .clobber-post
+
+.clobber-pre:
+# Add your pre 'clobber' code here...
+
+.clobber-post:
+# Add your post 'clobber' code here...
+
+
+# all
+all: .all-pre .all-impl .all-post
+
+.all-pre:
+# Add your pre 'all' code here...
+
+.all-post:
+# Add your post 'all' code here...
+
+
+# help
+help: .help-pre .help-impl .help-post
+
+.help-pre:
+# Add your pre 'help' code here...
+
+.help-post:
+# Add your post 'help' code here...
+
+
+
+# include project implementation makefile
+include nbproject/Makefile-impl.mk
diff --git a/src/main/cpp/jnilib/macosx/nbproject/configurations.xml b/src/main/cpp/jnilib/macosx/nbproject/configurations.xml
new file mode 100644
index 0000000..50ab41e
--- /dev/null
+++ b/src/main/cpp/jnilib/macosx/nbproject/configurations.xml
@@ -0,0 +1,125 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+<configurationDescriptor version="45">
+  <logicalFolder name="root" displayName="root" projectFiles="true">
+    <logicalFolder name="HeaderFiles"
+                   displayName="Header Files"
+                   projectFiles="true">
+      <itemPath>../.common/src/CommonUtils.h</itemPath>
+      <itemPath>../.unix/src/jni_UnixNativeUtils.h</itemPath>
+    </logicalFolder>
+    <logicalFolder name="ResourceFiles"
+                   displayName="Resource Files"
+                   projectFiles="true">
+    </logicalFolder>
+    <logicalFolder name="SourceFiles"
+                   displayName="Source Files"
+                   projectFiles="true">
+      <itemPath>../.common/src/CommonUtils.c</itemPath>
+      <itemPath>../.unix/src/jni_UnixNativeUtils.c</itemPath>
+    </logicalFolder>
+    <logicalFolder name="ExternalFiles"
+                   displayName="Important Files"
+                   projectFiles="false">
+      <itemPath>Makefile</itemPath>
+    </logicalFolder>
+  </logicalFolder>
+  <sourceEncoding>UTF-8</sourceEncoding>
+  <projectmakefile>Makefile</projectmakefile>
+  <confs>
+    <conf name="Debug" type="2">
+      <toolsSet>
+        <compilerSet>GNU|GNU</compilerSet>
+        <platform>4</platform>
+      </toolsSet>
+      <compileType>
+        <cCompilerTool>
+          <developmentMode>0</developmentMode>
+          <stripSymbols>true</stripSymbols>
+          <includeDirectories>
+            <directoryPath>/Library/Java/Home/include</directoryPath>
+          </includeDirectories>
+          <commandLine>-arch i386 -arch ppc -arch ppc64 -arch x86_64 -isysroot /Developer/SDKs/MacOSX10.4u.sdk -dynamiclib</commandLine>
+        </cCompilerTool>
+        <ccCompilerTool>
+          <developmentMode>0</developmentMode>
+          <stripSymbols>true</stripSymbols>
+          <includeDirectories>
+            <directoryPath>/Library/Java/Home/include</directoryPath>
+          </includeDirectories>
+          <commandLine>-arch i386 -arch ppc -arch ppc64 -arch x86_64 -isysroot /Developer/SDKs/MacOSX10.4u.sdk -dynamiclib</commandLine>
+        </ccCompilerTool>
+        <linkerTool>
+          <output>dist/macosx.dylib</output>
+          <linkerLibItems>
+          </linkerLibItems>
+          <commandLine>-Wl,-syslibroot /Developer/SDKs/MacOSX10.4u.sdk -arch i386 -arch ppc -arch ppc64 -arch x86_64</commandLine>
+        </linkerTool>
+      </compileType>
+      <item path="../.common/src/CommonUtils.c">
+        <itemTool>0</itemTool>
+      </item>
+      <item path="../.common/src/CommonUtils.h">
+        <itemTool>3</itemTool>
+      </item>
+      <item path="../.unix/src/jni_UnixNativeUtils.c">
+        <itemTool>0</itemTool>
+      </item>
+      <item path="../.unix/src/jni_UnixNativeUtils.h">
+        <itemTool>3</itemTool>
+      </item>
+    </conf>
+    <conf name="Release" type="2">
+      <toolsSet>
+        <compilerSet>GNU|GNU</compilerSet>
+        <platform>4</platform>
+      </toolsSet>
+      <compileType>
+        <cCompilerTool>
+          <developmentMode>5</developmentMode>
+        </cCompilerTool>
+        <ccCompilerTool>
+          <developmentMode>5</developmentMode>
+        </ccCompilerTool>
+        <fortranCompilerTool>
+          <developmentMode>5</developmentMode>
+        </fortranCompilerTool>
+        <linkerTool>
+          <linkerLibItems>
+          </linkerLibItems>
+        </linkerTool>
+      </compileType>
+      <item path="../.common/src/CommonUtils.c">
+        <itemTool>0</itemTool>
+      </item>
+      <item path="../.common/src/CommonUtils.h">
+        <itemTool>3</itemTool>
+      </item>
+      <item path="../.unix/src/jni_UnixNativeUtils.c">
+        <itemTool>0</itemTool>
+      </item>
+      <item path="../.unix/src/jni_UnixNativeUtils.h">
+        <itemTool>3</itemTool>
+      </item>
+    </conf>
+  </confs>
+</configurationDescriptor>
diff --git a/src/main/cpp/jnilib/macosx/nbproject/project.properties b/src/main/cpp/jnilib/macosx/nbproject/project.properties
new file mode 100644
index 0000000..3807b67
--- /dev/null
+++ b/src/main/cpp/jnilib/macosx/nbproject/project.properties
@@ -0,0 +1,20 @@
+
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# 
+
diff --git a/src/main/cpp/jnilib/macosx/nbproject/project.xml b/src/main/cpp/jnilib/macosx/nbproject/project.xml
new file mode 100644
index 0000000..1825876
--- /dev/null
+++ b/src/main/cpp/jnilib/macosx/nbproject/project.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+<project xmlns="http://www.netbeans.org/ns/project/1">
+    <type>org.netbeans.modules.cnd.makeproject</type>
+    <configuration>
+        <data xmlns="http://www.netbeans.org/ns/make-project/1">
+            <name>NBI Native Library: MacOS X</name>
+            <make-project-type>0</make-project-type>
+            <make-dep-projects/>
+        </data>
+    </configuration>
+</project>
diff --git a/src/main/cpp/jnilib/solaris-sparc/Makefile b/src/main/cpp/jnilib/solaris-sparc/Makefile
new file mode 100644
index 0000000..516847d
--- /dev/null
+++ b/src/main/cpp/jnilib/solaris-sparc/Makefile
@@ -0,0 +1,109 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# 
+
+#
+#  There exist several targets which are by default empty and which can be 
+#  used for execution of your targets. These targets are usually executed 
+#  before and after some main targets. They are: 
+#
+#     .build-pre:              called before 'build' target
+#     .build-post:             called after 'build' target
+#     .clean-pre:              called before 'clean' target
+#     .clean-post:             called after 'clean' target
+#     .clobber-pre:            called before 'clobber' target
+#     .clobber-post:           called after 'clobber' target
+#     .all-pre:                called before 'all' target
+#     .all-post:               called after 'all' target
+#     .help-pre:                called before 'help' target
+#     .help-post:               called after 'help' target
+#
+#  Targets beginning with '.' are not intended to be called on their own.
+#
+#  Main targets can be executed directly, and they are:
+#  
+#     build                    build a specific configuration
+#     clean                    remove built files from a configuration
+#     clobber                  remove all built files
+#     all                      build all configurations
+#     help                     print help mesage
+#  
+#  Targets .build-impl, .clean-impl, .clobber-impl, .all-impl, and
+#  .help-impl are implemented in nbproject/makefile-impl.mk.
+#
+
+# Environment 
+MKDIR=mkdir
+CP=cp
+CCADMIN=CCadmin
+RANLIB=ranlib
+
+
+# build
+build: .build-pre .build-impl .build-post
+
+.build-pre:
+# Add your pre 'build' code here...
+
+.build-post:
+# Add your post 'build' code here...
+
+
+# clean
+clean: .clean-pre .clean-impl .clean-post
+
+.clean-pre:
+# Add your pre 'clean' code here...
+
+.clean-post:
+# Add your post 'clean' code here...
+
+
+# clobber
+clobber: .clobber-pre .clobber-impl .clobber-post
+
+.clobber-pre:
+# Add your pre 'clobber' code here...
+
+.clobber-post:
+# Add your post 'clobber' code here...
+
+
+# all
+all: .all-pre .all-impl .all-post
+
+.all-pre:
+# Add your pre 'all' code here...
+
+.all-post:
+# Add your post 'all' code here...
+
+
+# help
+help: .help-pre .help-impl .help-post
+
+.help-pre:
+# Add your pre 'help' code here...
+
+.help-post:
+# Add your post 'help' code here...
+
+
+
+# include project implementation makefile
+include nbproject/Makefile-impl.mk
diff --git a/src/main/cpp/jnilib/solaris-sparc/nbproject/configurations.xml b/src/main/cpp/jnilib/solaris-sparc/nbproject/configurations.xml
new file mode 100644
index 0000000..98c3b5c
--- /dev/null
+++ b/src/main/cpp/jnilib/solaris-sparc/nbproject/configurations.xml
@@ -0,0 +1,283 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+
+<configurationDescriptor version="35">
+  <logicalFolder name="root" displayName="root" projectFiles="true">
+    <logicalFolder name="SourceFiles"
+                   displayName="Source Files"
+                   projectFiles="true">
+      <itemPath>../.common/src/CommonUtils.c</itemPath>
+      <itemPath>../.unix/src/jni_UnixNativeUtils.c</itemPath>
+    </logicalFolder>
+    <logicalFolder name="HeaderFiles"
+                   displayName="Header Files"
+                   projectFiles="true">
+      <itemPath>../.common/src/CommonUtils.h</itemPath>
+      <itemPath>../.unix/src/jni_UnixNativeUtils.h</itemPath>
+    </logicalFolder>
+    <logicalFolder name="ResourceFiles"
+                   displayName="Resource Files"
+                   projectFiles="true">
+    </logicalFolder>
+    <logicalFolder name="ExternalFiles"
+                   displayName="Important Files"
+                   projectFiles="false">
+      <itemPath>Makefile</itemPath>
+    </logicalFolder>
+  </logicalFolder>
+  <projectmakefile>Makefile</projectmakefile>
+  <defaultConf>0</defaultConf>
+  <confs>
+    <conf name="Debug" type="2">
+      <toolsSet>
+        <compilerSet>Sun12</compilerSet>
+        <cRequired>true</cRequired>
+        <cppRequired>true</cppRequired>
+        <fortranRequired>false</fortranRequired>
+        <platform>0</platform>
+      </toolsSet>
+      <compileType>
+        <cCompilerTool>
+          <developmentMode>0</developmentMode>
+          <stripSymbols>true</stripSymbols>
+          <includeDirectories>
+            <directoryPath>/usr/java/include</directoryPath>
+            <directoryPath>/usr/java/include/solaris</directoryPath>
+          </includeDirectories>
+          <commandLine>-m32 -shared -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -xO2 -Xa</commandLine>
+        </cCompilerTool>
+        <ccCompilerTool>
+          <developmentMode>0</developmentMode>
+          <stripSymbols>true</stripSymbols>
+          <includeDirectories>
+            <directoryPath>/usr/java/include</directoryPath>
+            <directoryPath>/usr/java/include/solaris</directoryPath>
+          </includeDirectories>
+          <commandLine>-m32 -shared -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -xO2 -Xa</commandLine>
+        </ccCompilerTool>
+        <linkerTool>
+          <output>dist/solaris-sparc.so</output>
+          <stripSymbols>true</stripSymbols>
+          <linkerNorunpath>false</linkerNorunpath>
+          <linkerLibItems>
+          </linkerLibItems>
+        </linkerTool>
+      </compileType>
+      <item path="../.common/src/CommonUtils.c">
+        <itemTool>0</itemTool>
+      </item>
+      <item path="../.common/src/CommonUtils.h">
+        <itemTool>3</itemTool>
+      </item>
+      <item path="../.unix/src/jni_UnixNativeUtils.c">
+        <itemTool>0</itemTool>
+      </item>
+      <item path="../.unix/src/jni_UnixNativeUtils.h">
+        <itemTool>3</itemTool>
+      </item>
+    </conf>
+    <conf name="Release" type="2">
+      <toolsSet>
+        <compilerSet>GNU</compilerSet>
+        <cRequired>true</cRequired>
+        <cppRequired>true</cppRequired>
+        <fortranRequired>false</fortranRequired>
+        <platform>0</platform>
+      </toolsSet>
+      <compileType>
+        <cCompilerTool>
+          <developmentMode>5</developmentMode>
+        </cCompilerTool>
+        <ccCompilerTool>
+          <developmentMode>5</developmentMode>
+        </ccCompilerTool>
+        <fortranCompilerTool>
+          <developmentMode>5</developmentMode>
+        </fortranCompilerTool>
+        <linkerTool>
+          <linkerLibItems>
+          </linkerLibItems>
+        </linkerTool>
+      </compileType>
+      <item path="../.common/src/CommonUtils.c">
+        <itemTool>0</itemTool>
+      </item>
+      <item path="../.common/src/CommonUtils.h">
+        <itemTool>3</itemTool>
+      </item>
+      <item path="../.unix/src/jni_UnixNativeUtils.c">
+        <itemTool>0</itemTool>
+      </item>
+      <item path="../.unix/src/jni_UnixNativeUtils.h">
+        <itemTool>3</itemTool>
+      </item>
+    </conf>
+    <conf name="Debug_x64" type="2">
+      <toolsSet>
+        <compilerSet>Sun12</compilerSet>
+        <cRequired>true</cRequired>
+        <cppRequired>true</cppRequired>
+        <fortranRequired>false</fortranRequired>
+        <platform>0</platform>
+      </toolsSet>
+      <compileType>
+        <cCompilerTool>
+          <developmentMode>0</developmentMode>
+          <stripSymbols>true</stripSymbols>
+          <sixtyfourBits>true</sixtyfourBits>
+          <includeDirectories>
+            <directoryPath>/usr/java/include</directoryPath>
+            <directoryPath>/usr/java/include/solaris</directoryPath>
+          </includeDirectories>
+          <commandLine>-fPIC -shared -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -xO2 -Xa</commandLine>
+        </cCompilerTool>
+        <ccCompilerTool>
+          <developmentMode>0</developmentMode>
+          <stripSymbols>true</stripSymbols>
+          <sixtyfourBits>true</sixtyfourBits>
+          <includeDirectories>
+            <directoryPath>/usr/java/include</directoryPath>
+            <directoryPath>/usr/java/include/solaris</directoryPath>
+          </includeDirectories>
+          <commandLine>-fPIC -shared -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -xO2 -Xa</commandLine>
+        </ccCompilerTool>
+        <linkerTool>
+          <output>dist/solaris-sparcv9.so</output>
+          <stripSymbols>true</stripSymbols>
+          <linkerNorunpath>false</linkerNorunpath>
+          <linkerLibItems>
+          </linkerLibItems>
+        </linkerTool>
+      </compileType>
+      <item path="../.common/src/CommonUtils.c">
+        <itemTool>0</itemTool>
+      </item>
+      <item path="../.common/src/CommonUtils.h">
+        <itemTool>3</itemTool>
+      </item>
+      <item path="../.unix/src/jni_UnixNativeUtils.c">
+        <itemTool>0</itemTool>
+      </item>
+      <item path="../.unix/src/jni_UnixNativeUtils.h">
+        <itemTool>3</itemTool>
+      </item>
+    </conf>
+    <conf name="Debug_gnu" type="2">
+      <toolsSet>
+        <compilerSet>GNU</compilerSet>
+        <cRequired>true</cRequired>
+        <cppRequired>true</cppRequired>
+        <fortranRequired>false</fortranRequired>
+        <platform>0</platform>
+      </toolsSet>
+      <compileType>
+        <cCompilerTool>
+          <developmentMode>0</developmentMode>
+          <stripSymbols>true</stripSymbols>
+          <includeDirectories>
+            <directoryPath>/usr/java/include</directoryPath>
+            <directoryPath>/usr/java/include/solaris</directoryPath>
+          </includeDirectories>
+          <commandLine>-m32 -fPIC -shared -static-libgcc -mimpure-text -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE</commandLine>
+        </cCompilerTool>
+        <ccCompilerTool>
+          <developmentMode>0</developmentMode>
+          <stripSymbols>true</stripSymbols>
+          <includeDirectories>
+            <directoryPath>/usr/java/include</directoryPath>
+            <directoryPath>/usr/java/include/solaris</directoryPath>
+          </includeDirectories>
+          <commandLine>-m32 -fPIC -shared -static-libgcc -mimpure-text -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE</commandLine>
+        </ccCompilerTool>
+        <linkerTool>
+          <output>dist/solaris-sparc.so</output>
+          <stripSymbols>true</stripSymbols>
+          <linkerNorunpath>false</linkerNorunpath>
+          <linkerLibItems>
+          </linkerLibItems>
+        </linkerTool>
+      </compileType>
+      <item path="../.common/src/CommonUtils.c">
+        <itemTool>0</itemTool>
+      </item>
+      <item path="../.common/src/CommonUtils.h">
+        <itemTool>3</itemTool>
+      </item>
+      <item path="../.unix/src/jni_UnixNativeUtils.c">
+        <itemTool>0</itemTool>
+      </item>
+      <item path="../.unix/src/jni_UnixNativeUtils.h">
+        <itemTool>3</itemTool>
+      </item>
+    </conf>
+    <conf name="Debug_x64_gnu" type="2">
+      <toolsSet>
+        <compilerSet>GNU</compilerSet>
+        <cRequired>true</cRequired>
+        <cppRequired>true</cppRequired>
+        <fortranRequired>false</fortranRequired>
+        <platform>0</platform>
+      </toolsSet>
+      <compileType>
+        <cCompilerTool>
+          <developmentMode>0</developmentMode>
+          <stripSymbols>true</stripSymbols>
+          <sixtyfourBits>true</sixtyfourBits>
+          <includeDirectories>
+            <directoryPath>/usr/java/include</directoryPath>
+            <directoryPath>/usr/java/include/solaris</directoryPath>
+          </includeDirectories>
+          <commandLine>-fPIC -shared -static-libgcc -mimpure-text -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE</commandLine>
+        </cCompilerTool>
+        <ccCompilerTool>
+          <developmentMode>0</developmentMode>
+          <stripSymbols>true</stripSymbols>
+          <sixtyfourBits>true</sixtyfourBits>
+          <includeDirectories>
+            <directoryPath>/usr/java/include</directoryPath>
+            <directoryPath>/usr/java/include/solaris</directoryPath>
+          </includeDirectories>
+          <commandLine>-fPIC -shared -static-libgcc -mimpure-text -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE</commandLine>
+        </ccCompilerTool>
+        <linkerTool>
+          <output>dist/solaris-sparcv9.so</output>
+          <stripSymbols>true</stripSymbols>
+          <linkerNorunpath>false</linkerNorunpath>
+          <linkerLibItems>
+          </linkerLibItems>
+        </linkerTool>
+      </compileType>
+      <item path="../.common/src/CommonUtils.c">
+        <itemTool>0</itemTool>
+      </item>
+      <item path="../.common/src/CommonUtils.h">
+        <itemTool>3</itemTool>
+      </item>
+      <item path="../.unix/src/jni_UnixNativeUtils.c">
+        <itemTool>0</itemTool>
+      </item>
+      <item path="../.unix/src/jni_UnixNativeUtils.h">
+        <itemTool>3</itemTool>
+      </item>
+    </conf>
+  </confs>
+</configurationDescriptor>
diff --git a/src/main/cpp/jnilib/solaris-sparc/nbproject/project.properties b/src/main/cpp/jnilib/solaris-sparc/nbproject/project.properties
new file mode 100644
index 0000000..3807b67
--- /dev/null
+++ b/src/main/cpp/jnilib/solaris-sparc/nbproject/project.properties
@@ -0,0 +1,20 @@
+
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# 
+
diff --git a/src/main/cpp/jnilib/solaris-sparc/nbproject/project.xml b/src/main/cpp/jnilib/solaris-sparc/nbproject/project.xml
new file mode 100644
index 0000000..c6febe0
--- /dev/null
+++ b/src/main/cpp/jnilib/solaris-sparc/nbproject/project.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+
+<project xmlns="http://www.netbeans.org/ns/project/1">
+    <type>org.netbeans.modules.cnd.makeproject</type>
+    <configuration>
+        <data xmlns="http://www.netbeans.org/ns/make-project/1">
+            <name>NBI Native Library: Solaris Sparc</name>
+            <make-project-type>0</make-project-type>
+        </data>
+    </configuration>
+</project>
diff --git a/src/main/cpp/jnilib/solaris-x86/Makefile b/src/main/cpp/jnilib/solaris-x86/Makefile
new file mode 100644
index 0000000..516847d
--- /dev/null
+++ b/src/main/cpp/jnilib/solaris-x86/Makefile
@@ -0,0 +1,109 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# 
+
+#
+#  There exist several targets which are by default empty and which can be 
+#  used for execution of your targets. These targets are usually executed 
+#  before and after some main targets. They are: 
+#
+#     .build-pre:              called before 'build' target
+#     .build-post:             called after 'build' target
+#     .clean-pre:              called before 'clean' target
+#     .clean-post:             called after 'clean' target
+#     .clobber-pre:            called before 'clobber' target
+#     .clobber-post:           called after 'clobber' target
+#     .all-pre:                called before 'all' target
+#     .all-post:               called after 'all' target
+#     .help-pre:                called before 'help' target
+#     .help-post:               called after 'help' target
+#
+#  Targets beginning with '.' are not intended to be called on their own.
+#
+#  Main targets can be executed directly, and they are:
+#  
+#     build                    build a specific configuration
+#     clean                    remove built files from a configuration
+#     clobber                  remove all built files
+#     all                      build all configurations
+#     help                     print help mesage
+#  
+#  Targets .build-impl, .clean-impl, .clobber-impl, .all-impl, and
+#  .help-impl are implemented in nbproject/makefile-impl.mk.
+#
+
+# Environment 
+MKDIR=mkdir
+CP=cp
+CCADMIN=CCadmin
+RANLIB=ranlib
+
+
+# build
+build: .build-pre .build-impl .build-post
+
+.build-pre:
+# Add your pre 'build' code here...
+
+.build-post:
+# Add your post 'build' code here...
+
+
+# clean
+clean: .clean-pre .clean-impl .clean-post
+
+.clean-pre:
+# Add your pre 'clean' code here...
+
+.clean-post:
+# Add your post 'clean' code here...
+
+
+# clobber
+clobber: .clobber-pre .clobber-impl .clobber-post
+
+.clobber-pre:
+# Add your pre 'clobber' code here...
+
+.clobber-post:
+# Add your post 'clobber' code here...
+
+
+# all
+all: .all-pre .all-impl .all-post
+
+.all-pre:
+# Add your pre 'all' code here...
+
+.all-post:
+# Add your post 'all' code here...
+
+
+# help
+help: .help-pre .help-impl .help-post
+
+.help-pre:
+# Add your pre 'help' code here...
+
+.help-post:
+# Add your post 'help' code here...
+
+
+
+# include project implementation makefile
+include nbproject/Makefile-impl.mk
diff --git a/src/main/cpp/jnilib/solaris-x86/nbproject/configurations.xml b/src/main/cpp/jnilib/solaris-x86/nbproject/configurations.xml
new file mode 100644
index 0000000..18c1468
--- /dev/null
+++ b/src/main/cpp/jnilib/solaris-x86/nbproject/configurations.xml
@@ -0,0 +1,283 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+
+<configurationDescriptor version="35">
+  <logicalFolder name="root" displayName="root" projectFiles="true">
+    <logicalFolder name="SourceFiles"
+                   displayName="Source Files"
+                   projectFiles="true">
+      <itemPath>../.common/src/CommonUtils.c</itemPath>
+      <itemPath>../.unix/src/jni_UnixNativeUtils.c</itemPath>
+    </logicalFolder>
+    <logicalFolder name="HeaderFiles"
+                   displayName="Header Files"
+                   projectFiles="true">
+      <itemPath>../.common/src/CommonUtils.h</itemPath>
+      <itemPath>../.unix/src/jni_UnixNativeUtils.h</itemPath>
+    </logicalFolder>
+    <logicalFolder name="ResourceFiles"
+                   displayName="Resource Files"
+                   projectFiles="true">
+    </logicalFolder>
+    <logicalFolder name="ExternalFiles"
+                   displayName="Important Files"
+                   projectFiles="false">
+      <itemPath>Makefile</itemPath>
+    </logicalFolder>
+  </logicalFolder>
+  <projectmakefile>Makefile</projectmakefile>
+  <defaultConf>0</defaultConf>
+  <confs>
+    <conf name="Debug" type="2">
+      <toolsSet>
+        <compilerSet>Sun12</compilerSet>
+        <cRequired>true</cRequired>
+        <cppRequired>true</cppRequired>
+        <fortranRequired>false</fortranRequired>
+        <platform>1</platform>
+      </toolsSet>
+      <compileType>
+        <cCompilerTool>
+          <developmentMode>0</developmentMode>
+          <stripSymbols>true</stripSymbols>
+          <includeDirectories>
+            <directoryPath>/usr/java/include</directoryPath>
+            <directoryPath>/usr/java/include/solaris</directoryPath>
+          </includeDirectories>
+          <commandLine>-m32 -fPIC -shared -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -xO2 -Xa</commandLine>
+        </cCompilerTool>
+        <ccCompilerTool>
+          <developmentMode>0</developmentMode>
+          <stripSymbols>true</stripSymbols>
+          <includeDirectories>
+            <directoryPath>/usr/java/include</directoryPath>
+            <directoryPath>/usr/java/include/solaris</directoryPath>
+          </includeDirectories>
+          <commandLine>-m32 -fPIC -shared -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -xO2 -Xa</commandLine>
+        </ccCompilerTool>
+        <linkerTool>
+          <output>dist/solaris-x86.so</output>
+          <stripSymbols>true</stripSymbols>
+          <linkerNorunpath>false</linkerNorunpath>
+          <linkerLibItems>
+          </linkerLibItems>
+        </linkerTool>
+      </compileType>
+      <item path="../.common/src/CommonUtils.c">
+        <itemTool>0</itemTool>
+      </item>
+      <item path="../.common/src/CommonUtils.h">
+        <itemTool>3</itemTool>
+      </item>
+      <item path="../.unix/src/jni_UnixNativeUtils.c">
+        <itemTool>0</itemTool>
+      </item>
+      <item path="../.unix/src/jni_UnixNativeUtils.h">
+        <itemTool>3</itemTool>
+      </item>
+    </conf>
+    <conf name="Release" type="2">
+      <toolsSet>
+        <compilerSet>GNU</compilerSet>
+        <cRequired>true</cRequired>
+        <cppRequired>true</cppRequired>
+        <fortranRequired>false</fortranRequired>
+        <platform>0</platform>
+      </toolsSet>
+      <compileType>
+        <cCompilerTool>
+          <developmentMode>5</developmentMode>
+        </cCompilerTool>
+        <ccCompilerTool>
+          <developmentMode>5</developmentMode>
+        </ccCompilerTool>
+        <fortranCompilerTool>
+          <developmentMode>5</developmentMode>
+        </fortranCompilerTool>
+        <linkerTool>
+          <linkerLibItems>
+          </linkerLibItems>
+        </linkerTool>
+      </compileType>
+      <item path="../.common/src/CommonUtils.c">
+        <itemTool>0</itemTool>
+      </item>
+      <item path="../.common/src/CommonUtils.h">
+        <itemTool>3</itemTool>
+      </item>
+      <item path="../.unix/src/jni_UnixNativeUtils.c">
+        <itemTool>0</itemTool>
+      </item>
+      <item path="../.unix/src/jni_UnixNativeUtils.h">
+        <itemTool>3</itemTool>
+      </item>
+    </conf>
+    <conf name="Debug_x64" type="2">
+      <toolsSet>
+        <compilerSet>Sun12</compilerSet>
+        <cRequired>true</cRequired>
+        <cppRequired>true</cppRequired>
+        <fortranRequired>false</fortranRequired>
+        <platform>1</platform>
+      </toolsSet>
+      <compileType>
+        <cCompilerTool>
+          <developmentMode>0</developmentMode>
+          <stripSymbols>true</stripSymbols>
+          <sixtyfourBits>true</sixtyfourBits>
+          <includeDirectories>
+            <directoryPath>/usr/java/include</directoryPath>
+            <directoryPath>/usr/java/include/solaris</directoryPath>
+          </includeDirectories>
+          <commandLine>-KPIC -shared -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -xO2 -Xa</commandLine>
+        </cCompilerTool>
+        <ccCompilerTool>
+          <developmentMode>0</developmentMode>
+          <stripSymbols>true</stripSymbols>
+          <sixtyfourBits>true</sixtyfourBits>
+          <includeDirectories>
+            <directoryPath>/usr/java/include</directoryPath>
+            <directoryPath>/usr/java/include/solaris</directoryPath>
+          </includeDirectories>
+          <commandLine>-KPIC -shared -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -xO2 -Xa</commandLine>
+        </ccCompilerTool>
+        <linkerTool>
+          <output>dist/solaris-amd64.so</output>
+          <stripSymbols>true</stripSymbols>
+          <linkerNorunpath>false</linkerNorunpath>
+          <linkerLibItems>
+          </linkerLibItems>
+        </linkerTool>
+      </compileType>
+      <item path="../.common/src/CommonUtils.c">
+        <itemTool>0</itemTool>
+      </item>
+      <item path="../.common/src/CommonUtils.h">
+        <itemTool>3</itemTool>
+      </item>
+      <item path="../.unix/src/jni_UnixNativeUtils.c">
+        <itemTool>0</itemTool>
+      </item>
+      <item path="../.unix/src/jni_UnixNativeUtils.h">
+        <itemTool>3</itemTool>
+      </item>
+    </conf>
+    <conf name="Debug_gnu" type="2">
+      <toolsSet>
+        <compilerSet>GNU</compilerSet>
+        <cRequired>true</cRequired>
+        <cppRequired>true</cppRequired>
+        <fortranRequired>false</fortranRequired>
+        <platform>1</platform>
+      </toolsSet>
+      <compileType>
+        <cCompilerTool>
+          <developmentMode>0</developmentMode>
+          <stripSymbols>true</stripSymbols>
+          <includeDirectories>
+            <directoryPath>/usr/java/include</directoryPath>
+            <directoryPath>/usr/java/include/solaris</directoryPath>
+          </includeDirectories>
+          <commandLine>-m32 -fPIC -static-libgcc -shared -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE</commandLine>
+        </cCompilerTool>
+        <ccCompilerTool>
+          <developmentMode>0</developmentMode>
+          <stripSymbols>true</stripSymbols>
+          <includeDirectories>
+            <directoryPath>/usr/java/include</directoryPath>
+            <directoryPath>/usr/java/include/solaris</directoryPath>
+          </includeDirectories>
+          <commandLine>-m32 -fPIC -static-libgcc -shared -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE</commandLine>
+        </ccCompilerTool>
+        <linkerTool>
+          <output>dist/solaris-x86.so</output>
+          <stripSymbols>true</stripSymbols>
+          <linkerNorunpath>false</linkerNorunpath>
+          <linkerLibItems>
+          </linkerLibItems>
+        </linkerTool>
+      </compileType>
+      <item path="../.common/src/CommonUtils.c">
+        <itemTool>0</itemTool>
+      </item>
+      <item path="../.common/src/CommonUtils.h">
+        <itemTool>3</itemTool>
+      </item>
+      <item path="../.unix/src/jni_UnixNativeUtils.c">
+        <itemTool>0</itemTool>
+      </item>
+      <item path="../.unix/src/jni_UnixNativeUtils.h">
+        <itemTool>3</itemTool>
+      </item>
+    </conf>
+    <conf name="Debug_x64_gnu" type="2">
+      <toolsSet>
+        <compilerSet>GNU</compilerSet>
+        <cRequired>true</cRequired>
+        <cppRequired>true</cppRequired>
+        <fortranRequired>false</fortranRequired>
+        <platform>1</platform>
+      </toolsSet>
+      <compileType>
+        <cCompilerTool>
+          <developmentMode>0</developmentMode>
+          <stripSymbols>true</stripSymbols>
+          <sixtyfourBits>true</sixtyfourBits>
+          <includeDirectories>
+            <directoryPath>/usr/java/include</directoryPath>
+            <directoryPath>/usr/java/include/solaris</directoryPath>
+          </includeDirectories>
+          <commandLine>-fPIC -static-libgcc -shared -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE</commandLine>
+        </cCompilerTool>
+        <ccCompilerTool>
+          <developmentMode>0</developmentMode>
+          <stripSymbols>true</stripSymbols>
+          <sixtyfourBits>true</sixtyfourBits>
+          <includeDirectories>
+            <directoryPath>/usr/java/include</directoryPath>
+            <directoryPath>/usr/java/include/solaris</directoryPath>
+          </includeDirectories>
+          <commandLine>-fPIC -static-libgcc -shared -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE</commandLine>
+        </ccCompilerTool>
+        <linkerTool>
+          <output>dist/solaris-amd64.so</output>
+          <stripSymbols>true</stripSymbols>
+          <linkerNorunpath>false</linkerNorunpath>
+          <linkerLibItems>
+          </linkerLibItems>
+        </linkerTool>
+      </compileType>
+      <item path="../.common/src/CommonUtils.c">
+        <itemTool>0</itemTool>
+      </item>
+      <item path="../.common/src/CommonUtils.h">
+        <itemTool>3</itemTool>
+      </item>
+      <item path="../.unix/src/jni_UnixNativeUtils.c">
+        <itemTool>0</itemTool>
+      </item>
+      <item path="../.unix/src/jni_UnixNativeUtils.h">
+        <itemTool>3</itemTool>
+      </item>
+    </conf>
+  </confs>
+</configurationDescriptor>
diff --git a/src/main/cpp/jnilib/solaris-x86/nbproject/project.properties b/src/main/cpp/jnilib/solaris-x86/nbproject/project.properties
new file mode 100644
index 0000000..3807b67
--- /dev/null
+++ b/src/main/cpp/jnilib/solaris-x86/nbproject/project.properties
@@ -0,0 +1,20 @@
+
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# 
+
diff --git a/src/main/cpp/jnilib/solaris-x86/nbproject/project.xml b/src/main/cpp/jnilib/solaris-x86/nbproject/project.xml
new file mode 100644
index 0000000..fdb4477
--- /dev/null
+++ b/src/main/cpp/jnilib/solaris-x86/nbproject/project.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+
+<project xmlns="http://www.netbeans.org/ns/project/1">
+    <type>org.netbeans.modules.cnd.makeproject</type>
+    <configuration>
+        <data xmlns="http://www.netbeans.org/ns/make-project/1">
+            <name>NBI Native Library: Solaris X86</name>
+            <make-project-type>0</make-project-type>
+        </data>
+    </configuration>
+</project>
diff --git a/src/main/cpp/jnilib/windows/Makefile b/src/main/cpp/jnilib/windows/Makefile
new file mode 100644
index 0000000..516847d
--- /dev/null
+++ b/src/main/cpp/jnilib/windows/Makefile
@@ -0,0 +1,109 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# 
+
+#
+#  There exist several targets which are by default empty and which can be 
+#  used for execution of your targets. These targets are usually executed 
+#  before and after some main targets. They are: 
+#
+#     .build-pre:              called before 'build' target
+#     .build-post:             called after 'build' target
+#     .clean-pre:              called before 'clean' target
+#     .clean-post:             called after 'clean' target
+#     .clobber-pre:            called before 'clobber' target
+#     .clobber-post:           called after 'clobber' target
+#     .all-pre:                called before 'all' target
+#     .all-post:               called after 'all' target
+#     .help-pre:                called before 'help' target
+#     .help-post:               called after 'help' target
+#
+#  Targets beginning with '.' are not intended to be called on their own.
+#
+#  Main targets can be executed directly, and they are:
+#  
+#     build                    build a specific configuration
+#     clean                    remove built files from a configuration
+#     clobber                  remove all built files
+#     all                      build all configurations
+#     help                     print help mesage
+#  
+#  Targets .build-impl, .clean-impl, .clobber-impl, .all-impl, and
+#  .help-impl are implemented in nbproject/makefile-impl.mk.
+#
+
+# Environment 
+MKDIR=mkdir
+CP=cp
+CCADMIN=CCadmin
+RANLIB=ranlib
+
+
+# build
+build: .build-pre .build-impl .build-post
+
+.build-pre:
+# Add your pre 'build' code here...
+
+.build-post:
+# Add your post 'build' code here...
+
+
+# clean
+clean: .clean-pre .clean-impl .clean-post
+
+.clean-pre:
+# Add your pre 'clean' code here...
+
+.clean-post:
+# Add your post 'clean' code here...
+
+
+# clobber
+clobber: .clobber-pre .clobber-impl .clobber-post
+
+.clobber-pre:
+# Add your pre 'clobber' code here...
+
+.clobber-post:
+# Add your post 'clobber' code here...
+
+
+# all
+all: .all-pre .all-impl .all-post
+
+.all-pre:
+# Add your pre 'all' code here...
+
+.all-post:
+# Add your post 'all' code here...
+
+
+# help
+help: .help-pre .help-impl .help-post
+
+.help-pre:
+# Add your pre 'help' code here...
+
+.help-post:
+# Add your post 'help' code here...
+
+
+
+# include project implementation makefile
+include nbproject/Makefile-impl.mk
diff --git a/src/main/cpp/jnilib/windows/Makefile-vc b/src/main/cpp/jnilib/windows/Makefile-vc
new file mode 100644
index 0000000..131aee1
--- /dev/null
+++ b/src/main/cpp/jnilib/windows/Makefile-vc
@@ -0,0 +1,76 @@
+#
+#
+
+
+!include <$(PLATFORM_SDK)/include/win32.mak>
+
+# define the compiler and linker for all the platforms
+CC32="$(VC_2005)\Bin\cl.exe"
+L32="$(VC_2005)\Bin\link.exe"
+
+CC32_OPTS=/O1 /Os /I "$(VC_2005)\include" /I "$(PLATFORM_SDK)\Include" /I "$(JAVA_HOME)\include" /I "$(JAVA_HOME)\include\win32" /D "WIN32" /D "_WINDOWS" /D "_USRDLL" /D "NBIJNILIBRARY_EXPORTS" /D "_CRT_SECURE_NO_DEPRECATE" /D "_STATIC_CPPLIB" /D "_LITTLE_ENDIAN" /D "_WINDLL" /FD /MT /Fo".\build\32bit\\" /W3 /WX /c /Wp64 /Gd /TC 
+L32_OPTS=/OUT:".\dist\windows-x86.dll" /INCREMENTAL:NO /LIBPATH:"$(PLATFORM_SDK)\Lib" /LIBPATH:"$(VC_2005)\lib" /DLL /MANIFEST:NO /IGNOREIDL /SUBSYSTEM:WINDOWS /OPT:REF /OPT:ICF /MACHINE:X86 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib
+
+
+CC64="$(PLATFORM_SDK)\Bin\win64\x86\AMD64\cl.exe"
+L64="$(PLATFORM_SDK)\Bin\win64\x86\AMD64\link.exe"
+
+CC64_OPTS=/O1 /Os /I "$(VC_2005)\include" /I "$(PLATFORM_SDK)\Include" /I "$(PLATFORM_SDK)\Include\win64\crt\amd64" /I "$(JAVA_HOME)\include" /I "$(JAVA_HOME)\include\win32" /D "WIN32" /D "_WINDOWS" /D "_USRDLL" /D "NBIJNILIBRARY_EXPORTS" /D "_CRT_SECURE_NO_DEPRECATE" /D "_STATIC_CPPLIB" /D "_LITTLE_ENDIAN" /D "_WINDLL" /FD /MT /Fo".\build\64bit\\" /W3 /c /Wp64 /Gd /TC 
+L64_OPTS=/OUT:".\dist\windows-x64.dll" /INCREMENTAL:NO /LIBPATH:"$(PLATFORM_SDK)\Lib\amd64" /LIBPATH:"$(VC_2005)\lib" /DLL /MANIFEST:NO /IGNOREIDL /SUBSYSTEM:WINDOWS /OPT:REF /OPT:ICF /MACHINE:AMD64 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib bufferoverflowU.lib
+
+CCIA64="$(PLATFORM_SDK)\Bin\win64\cl.exe"
+LIA64="$(PLATFORM_SDK)\Bin\win64\link.exe"
+
+CCIA64_OPTS=/O1 /Os /I "$(VC_2005)\include" /I "$(PLATFORM_SDK)\Include" /I "$(PLATFORM_SDK)\Include\win64\crt\amd64" /I "$(JAVA_HOME)\include" /I "$(JAVA_HOME)\include\win32" /D "WIN32" /D "_WINDOWS" /D "_USRDLL" /D "NBIJNILIBRARY_EXPORTS" /D "_CRT_SECURE_NO_DEPRECATE" /D "_STATIC_CPPLIB" /D "_LITTLE_ENDIAN" /D "_WINDLL" /FD /MT /Fo".\build\ia64\\" /W3 /c /Wp64 /Gd /TC 
+LIA64_OPTS=/OUT:".\dist\windows-ia64.dll" /INCREMENTAL:NO /LIBPATH:"$(PLATFORM_SDK)\Lib\ia64" /LIBPATH:"$(VC_2005)\lib" /DLL /MANIFEST:NO /IGNOREIDL /SUBSYSTEM:WINDOWS /OPT:REF /OPT:ICF /MACHINE:IA64 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib bufferoverflowU.lib
+
+
+all: init build-32 build-64 build-ia64
+
+init:
+  - md .\build\32bit
+  - md .\build\64bit
+  - md .\build\ia64
+  - md .\dist
+
+  del /Q /S build
+
+  del /Q .\dist\windows-x86.*
+  del /Q .\dist\windows-x64.*
+  del /Q .\dist\windows-ia64.*
+
+build-32: 
+  Set CPU=i386
+  Set Lib=%PLATFORM_SDK%\Lib;%Lib%
+  Set Include=%PLATFORM_SDK%\Include;%Include%
+  Set Path=%PLATFORM_SDK%\Bin;%PLATFORM_SDK%\Bin\WinNT;%VC_2005_PATH%;%path%
+  Set APPVER=5.01
+  Set TARGETOS=WINNT
+
+  $(CC32) $(CC32_OPTS) .\src\WindowsUtils.c .\src\jni_WindowsRegistry.c .\src\jni_WindowsNativeUtils.c .\..\.common\src\CommonUtils.c
+  $(L32) $(L32_OPTS) ".\build\32bit\WindowsUtils.obj" ".\build\32bit\jni_WindowsRegistry.obj" ".\build\32bit\jni_WindowsNativeUtils.obj" ".\build\32bit\CommonUtils.obj"
+  
+
+build-64:
+  Set CPU=AMD64
+  Set Lib=%PLATFORM_SDK%\Lib\AMD64;%PLATFORM_SDK%\Lib\AMD64\atlmfc;
+  Set Include=%PLATFORM_SDK%\Include;%PLATFORM_SDK%\Include\crt;%PLATFORM_SDK%\Include\crt\sys;%PLATFORM_SDK%\Include\mfc;%PLATFORM_SDK%\Include\atl
+  Set Path=%PLATFORM_SDK%\Bin\Win64\x86\AMD64;%PLATFORM_SDK%\Bin;%PLATFORM_SDK%\Bin\WinNT;%path%
+  Set APPVER=5.02
+  Set TARGETOS=WINNT
+
+  $(CC64) $(CC64_OPTS) .\src\WindowsUtils.c .\src\jni_WindowsRegistry.c .\src\jni_WindowsNativeUtils.c .\..\.common\src\CommonUtils.c
+  $(L64) $(L64_OPTS) ".\build\64bit\WindowsUtils.obj" ".\build\64bit\jni_WindowsRegistry.obj" ".\build\64bit\jni_WindowsNativeUtils.obj" ".\build\64bit\CommonUtils.obj"
+
+
+build-ia64:
+  Set CPU=IA64
+  Set Lib=%PLATFORM_SDK%\Lib\IA64;%PLATFORM_SDK%\Lib\IA64\atlmfc;
+  Set Include=%PLATFORM_SDK%\Include;%PLATFORM_SDK%\Include\crt;%PLATFORM_SDK%\Include\crt\sys;%PLATFORM_SDK%\Include\mfc;%PLATFORM_SDK%\Include\atl
+  Set Path=%PLATFORM_SDK%\Bin\Win64;%PLATFORM_SDK%\Bin;%PLATFORM_SDK%\Bin\WinNT;%path%
+  Set APPVER=5.02
+  Set TARGETOS=WINNT
+
+  $(CCIA64) $(CCIA64_OPTS) .\src\WindowsUtils.c .\src\jni_WindowsRegistry.c .\src\jni_WindowsNativeUtils.c .\..\.common\src\CommonUtils.c
+  $(LIA64) $(LIA64_OPTS) ".\build\ia64\WindowsUtils.obj" ".\build\ia64\jni_WindowsRegistry.obj" ".\build\ia64\jni_WindowsNativeUtils.obj" ".\build\ia64\CommonUtils.obj"
+
diff --git a/src/main/cpp/jnilib/windows/Makefile-vc-wo-crt b/src/main/cpp/jnilib/windows/Makefile-vc-wo-crt
new file mode 100644
index 0000000..e344b28
--- /dev/null
+++ b/src/main/cpp/jnilib/windows/Makefile-vc-wo-crt
@@ -0,0 +1,79 @@
+#
+#
+
+
+!include <$(PLATFORM_SDK)/include/win32.mak>
+
+# define the compiler and linker for all the platforms
+CC32="$(VC_2005)\Bin\cl.exe"
+L32="$(VC_2005)\Bin\link.exe"
+
+L32_LIBS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib
+CC32_OPTS=/GS- /O1 /Os /I "$(VC_2005)\include" /I "$(PLATFORM_SDK)\Include" /I "$(JAVA_HOME)\include" /I "$(JAVA_HOME)\include\win32" /D "WIN32" /D "_WINDOWS" /D "_USRDLL" /D "NBIJNILIBRARY_EXPORTS"  /D "_LITTLE_ENDIAN" /D "_WINDLL" /FD /MD /Fo".\build\32bit\\" /W3 /WX /c /Wp64 /Gd /TC 
+L32_OPTS=/NOENTRY /NODEFAULTLIB /OUT:".\dist\windows-x86.dll" /INCREMENTAL:NO /LIBPATH:"$(PLATFORM_SDK)\Lib" /LIBPATH:"$(VC_2005)\lib" /DLL /MANIFEST:NO /IGNOREIDL /SUBSYSTEM:WINDOWS /OPT:REF /OPT:ICF /MACHINE:X86 $(L32_LIBS)
+
+
+CC64="$(PLATFORM_SDK)\Bin\win64\x86\AMD64\cl.exe"
+L64="$(PLATFORM_SDK)\Bin\win64\x86\AMD64\link.exe"
+
+L64_LIBS=$(L32_LIBS)
+CC64_OPTS=/O1 /Os /GS- /I "$(VC_2005)\include" /I "$(PLATFORM_SDK)\Include" /I "$(PLATFORM_SDK)\Include\win64\crt\amd64" /I "$(JAVA_HOME)\include" /I "$(JAVA_HOME)\include\win32" /D "WIN32" /D "_WINDOWS" /D "_USRDLL" /D "NBIJNILIBRARY_EXPORTS" /D "_CRT_SECURE_NO_DEPRECATE"  /D "_LITTLE_ENDIAN" /D "_WINDLL" /FD /MD  /Fo".\build\64bit\\" /W3 /c /Wp64 /Gd /TC 
+L64_OPTS=/NOENTRY /NODEFAULTLIB /OUT:".\dist\windows-x64.dll" /INCREMENTAL:NO /LIBPATH:"$(PLATFORM_SDK)\Lib\amd64" /LIBPATH:"$(VC_2005)\lib" /DLL /MANIFEST:NO /IGNOREIDL /SUBSYSTEM:WINDOWS /OPT:REF /OPT:ICF /MACHINE:AMD64 $(L64_LIBS)
+
+CCIA64="$(PLATFORM_SDK)\Bin\win64\cl.exe"
+LIA64="$(PLATFORM_SDK)\Bin\win64\link.exe"
+
+LIA64_LIBS=$(L32_LIBS)
+CCIA64_OPTS=/O1 /Os /GS- /I "$(VC_2005)\include" /I "$(PLATFORM_SDK)\Include" /I "$(PLATFORM_SDK)\Include\win64\crt\amd64" /I "$(JAVA_HOME)\include" /I "$(JAVA_HOME)\include\win32" /D "WIN32" /D "_WINDOWS" /D "_USRDLL" /D "NBIJNILIBRARY_EXPORTS" /D "_CRT_SECURE_NO_DEPRECATE"  /D "_LITTLE_ENDIAN" /D "_WINDLL" /FD /MD  /Fo".\build\ia64\\" /W3 /c /Wp64 /Gd /TC 
+LIA64_OPTS=/NOENTRY /NODEFAULTLIB /OUT:".\dist\windows-ia64.dll" /INCREMENTAL:NO /LIBPATH:"$(PLATFORM_SDK)\Lib\ia64" /LIBPATH:"$(VC_2005)\lib" /DLL /MANIFEST:NO /IGNOREIDL /SUBSYSTEM:WINDOWS /OPT:REF /OPT:ICF /MACHINE:IA64 $(LIA64_LIBS)
+
+
+all: init build-32 build-64 build-ia64
+
+init:
+  - md .\build\32bit
+  - md .\build\64bit
+  - md .\build\ia64
+  - md .\dist
+
+  del /Q /S build
+
+  del /Q .\dist\windows-x86.*
+  del /Q .\dist\windows-x64.*
+  del /Q .\dist\windows-ia64.*
+
+build-32: 
+  Set CPU=i386
+  Set Lib=%PLATFORM_SDK%\Lib;%Lib%
+  Set Include=%PLATFORM_SDK%\Include;%Include%
+  Set Path=%PLATFORM_SDK%\Bin;%PLATFORM_SDK%\Bin\WinNT;%VC_2005_PATH%;%path%
+  Set APPVER=5.01
+  Set TARGETOS=WINNT
+
+  $(CC32) $(CC32_OPTS) .\src\WindowsUtils.c .\src\jni_WindowsRegistry.c .\src\jni_WindowsNativeUtils.c .\..\.common\src\CommonUtils.c
+  $(L32) $(L32_OPTS) ".\build\32bit\WindowsUtils.obj" ".\build\32bit\jni_WindowsRegistry.obj" ".\build\32bit\jni_WindowsNativeUtils.obj" ".\build\32bit\CommonUtils.obj"
+  
+
+build-64:
+  Set CPU=AMD64
+  Set Lib=%PLATFORM_SDK%\Lib\AMD64;%PLATFORM_SDK%\Lib\AMD64\atlmfc;
+  Set Include=%PLATFORM_SDK%\Include;%PLATFORM_SDK%\Include\crt;%PLATFORM_SDK%\Include\crt\sys;%PLATFORM_SDK%\Include\mfc;%PLATFORM_SDK%\Include\atl
+  Set Path=%PLATFORM_SDK%\Bin\Win64\x86\AMD64;%PLATFORM_SDK%\Bin;%PLATFORM_SDK%\Bin\WinNT;%path%
+  Set APPVER=5.02
+  Set TARGETOS=WINNT
+
+  $(CC64) $(CC64_OPTS) .\src\WindowsUtils.c .\src\jni_WindowsRegistry.c .\src\jni_WindowsNativeUtils.c .\..\.common\src\CommonUtils.c
+  $(L64) $(L64_OPTS) ".\build\64bit\WindowsUtils.obj" ".\build\64bit\jni_WindowsRegistry.obj" ".\build\64bit\jni_WindowsNativeUtils.obj" ".\build\64bit\CommonUtils.obj"
+
+
+build-ia64:
+  Set CPU=IA64
+  Set Lib=%PLATFORM_SDK%\Lib\IA64;%PLATFORM_SDK%\Lib\IA64\atlmfc;
+  Set Include=%PLATFORM_SDK%\Include;%PLATFORM_SDK%\Include\crt;%PLATFORM_SDK%\Include\crt\sys;%PLATFORM_SDK%\Include\mfc;%PLATFORM_SDK%\Include\atl
+  Set Path=%PLATFORM_SDK%\Bin\Win64;%PLATFORM_SDK%\Bin;%PLATFORM_SDK%\Bin\WinNT;%path%
+  Set APPVER=5.02
+  Set TARGETOS=WINNT
+
+  $(CCIA64) $(CCIA64_OPTS) .\src\WindowsUtils.c .\src\jni_WindowsRegistry.c .\src\jni_WindowsNativeUtils.c .\..\.common\src\CommonUtils.c
+  $(LIA64) $(LIA64_OPTS) ".\build\ia64\WindowsUtils.obj" ".\build\ia64\jni_WindowsRegistry.obj" ".\build\ia64\jni_WindowsNativeUtils.obj" ".\build\ia64\CommonUtils.obj"
+
diff --git a/src/main/cpp/jnilib/windows/nbproject/configurations.xml b/src/main/cpp/jnilib/windows/nbproject/configurations.xml
new file mode 100644
index 0000000..b7731b5
--- /dev/null
+++ b/src/main/cpp/jnilib/windows/nbproject/configurations.xml
@@ -0,0 +1,179 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+
+<configurationDescriptor version="35">
+  <logicalFolder name="root" displayName="root" projectFiles="true">
+    <logicalFolder name="SourceFiles"
+                   displayName="Source Files"
+                   projectFiles="true">
+      <itemPath>../.common/src/CommonUtils.c</itemPath>
+      <itemPath>src/jni_WindowsNativeUtils.c</itemPath>
+      <itemPath>src/jni_WindowsRegistry.c</itemPath>
+      <itemPath>src/WindowsUtils.c</itemPath>
+    </logicalFolder>
+    <logicalFolder name="HeaderFiles"
+                   displayName="Header Files"
+                   projectFiles="true">
+      <itemPath>../.common/src/CommonUtils.h</itemPath>
+      <itemPath>src/jni_WindowsNativeUtils.h</itemPath>
+      <itemPath>src/jni_WindowsRegistry.h</itemPath>
+      <itemPath>src/WindowsUtils.h</itemPath>
+    </logicalFolder>
+    <logicalFolder name="ResourceFiles"
+                   displayName="Resource Files"
+                   projectFiles="true">
+    </logicalFolder>
+    <logicalFolder name="ExternalFiles"
+                   displayName="Important Files"
+                   projectFiles="false">
+      <itemPath>Makefile</itemPath>
+    </logicalFolder>
+  </logicalFolder>
+  <projectmakefile>Makefile</projectmakefile>
+  <defaultConf>0</defaultConf>
+  <confs>
+    <conf name="Default-32bit" type="2">
+      <toolsSet>
+        <compilerSet>Cygwin</compilerSet>
+        <cRequired>true</cRequired>
+        <cppRequired>true</cppRequired>
+        <fortranRequired>false</fortranRequired>
+        <platform>3</platform>
+      </toolsSet>
+      <compileType>
+        <cCompilerTool>
+          <developmentMode>0</developmentMode>
+          <stripSymbols>true</stripSymbols>
+          <includeDirectories>
+            <directoryPath>/usr/java/include</directoryPath>
+            <directoryPath>/usr/java/include/win32</directoryPath>
+          </includeDirectories>
+          <commandLine>-mno-cygwin</commandLine>
+        </cCompilerTool>
+        <ccCompilerTool>
+          <developmentMode>0</developmentMode>
+          <stripSymbols>true</stripSymbols>
+          <includeDirectories>
+            <directoryPath>/usr/java/include</directoryPath>
+            <directoryPath>/usr/java/include\win32</directoryPath>
+          </includeDirectories>
+          <commandLine>-mno-cygwin</commandLine>
+        </ccCompilerTool>
+        <linkerTool>
+          <output>dist/windows.dll</output>
+          <stripSymbols>true</stripSymbols>
+          <linkerLibItems>
+            <linkerOptionItem>-lole32</linkerOptionItem>
+            <linkerOptionItem>-luuid</linkerOptionItem>
+          </linkerLibItems>
+          <commandLine>-Wl,--add-stdcall-alias</commandLine>
+        </linkerTool>
+      </compileType>
+      <item path="../.common/src/CommonUtils.c">
+        <itemTool>0</itemTool>
+      </item>
+      <item path="../.common/src/CommonUtils.h">
+        <itemTool>3</itemTool>
+      </item>
+      <item path="src/WindowsUtils.c">
+        <itemTool>0</itemTool>
+      </item>
+      <item path="src/WindowsUtils.h">
+        <itemTool>3</itemTool>
+      </item>
+      <item path="src/jni_WindowsNativeUtils.c">
+        <itemTool>0</itemTool>
+      </item>
+      <item path="src/jni_WindowsNativeUtils.h">
+        <itemTool>3</itemTool>
+      </item>
+      <item path="src/jni_WindowsRegistry.c">
+        <itemTool>0</itemTool>
+      </item>
+      <item path="src/jni_WindowsRegistry.h">
+        <itemTool>3</itemTool>
+      </item>
+    </conf>
+    <conf name="Default-64bit" type="2">
+      <toolsSet>
+        <compilerSet>Cygwin</compilerSet>
+        <cRequired>true</cRequired>
+        <cppRequired>true</cppRequired>
+        <fortranRequired>false</fortranRequired>
+        <platform>3</platform>
+      </toolsSet>
+      <compileType>
+        <cCompilerTool>
+          <developmentMode>0</developmentMode>
+          <stripSymbols>true</stripSymbols>
+          <includeDirectories>
+            <directoryPath>/usr/java/include</directoryPath>
+            <directoryPath>/usr/java/include/win32</directoryPath>
+          </includeDirectories>
+          <commandLine>-mno-cygwin</commandLine>
+        </cCompilerTool>
+        <ccCompilerTool>
+          <developmentMode>0</developmentMode>
+          <stripSymbols>true</stripSymbols>
+          <includeDirectories>
+            <directoryPath>/usr/java/include</directoryPath>
+            <directoryPath>/usr/java/include\win32</directoryPath>
+          </includeDirectories>
+          <commandLine>-mno-cygwin</commandLine>
+        </ccCompilerTool>
+        <linkerTool>
+          <output>dist/windows.dll</output>
+          <stripSymbols>true</stripSymbols>
+          <linkerLibItems>
+            <linkerOptionItem>-lole32</linkerOptionItem>
+            <linkerOptionItem>-luuid</linkerOptionItem>
+          </linkerLibItems>
+          <commandLine>-Wl,--add-stdcall-alias</commandLine>
+        </linkerTool>
+      </compileType>
+      <item path="../.common/src/CommonUtils.c">
+        <itemTool>0</itemTool>
+      </item>
+      <item path="../.common/src/CommonUtils.h">
+        <itemTool>3</itemTool>
+      </item>
+      <item path="src/WindowsUtils.c">
+        <itemTool>0</itemTool>
+      </item>
+      <item path="src/WindowsUtils.h">
+        <itemTool>3</itemTool>
+      </item>
+      <item path="src/jni_WindowsNativeUtils.c">
+        <itemTool>0</itemTool>
+      </item>
+      <item path="src/jni_WindowsNativeUtils.h">
+        <itemTool>3</itemTool>
+      </item>
+      <item path="src/jni_WindowsRegistry.c">
+        <itemTool>0</itemTool>
+      </item>
+      <item path="src/jni_WindowsRegistry.h">
+        <itemTool>3</itemTool>
+      </item>
+    </conf>
+  </confs>
+</configurationDescriptor>
diff --git a/src/main/cpp/jnilib/windows/nbproject/project.properties b/src/main/cpp/jnilib/windows/nbproject/project.properties
new file mode 100644
index 0000000..3807b67
--- /dev/null
+++ b/src/main/cpp/jnilib/windows/nbproject/project.properties
@@ -0,0 +1,20 @@
+
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# 
+
diff --git a/src/main/cpp/jnilib/windows/nbproject/project.xml b/src/main/cpp/jnilib/windows/nbproject/project.xml
new file mode 100644
index 0000000..1aa64eb
--- /dev/null
+++ b/src/main/cpp/jnilib/windows/nbproject/project.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+
+<project xmlns="http://www.netbeans.org/ns/project/1">
+    <type>org.netbeans.modules.cnd.makeproject</type>
+    <configuration>
+        <data xmlns="http://www.netbeans.org/ns/make-project/1">
+            <name>NBI Native Library: Windows</name>
+            <make-project-type>0</make-project-type>
+        </data>
+    </configuration>
+</project>
diff --git a/src/main/cpp/jnilib/windows/src/WindowsUtils.c b/src/main/cpp/jnilib/windows/src/WindowsUtils.c
new file mode 100644
index 0000000..fe4972d
--- /dev/null
+++ b/src/main/cpp/jnilib/windows/src/WindowsUtils.c
@@ -0,0 +1,146 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <jni.h>
+#include <windows.h>
+#include <winreg.h>
+#include <winnt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <malloc.h>
+
+#include "../../.common/src/CommonUtils.h"
+#include "WindowsUtils.h"
+#include "jni_WindowsRegistry.h"
+
+HKEY getHKEY(jint jSection) {
+    switch (jSection) {
+        case org_netbeans_installer_utils_system_windows_WindowsRegistry_HKEY_CLASSES_ROOT:
+            return HKEY_CLASSES_ROOT;
+        case org_netbeans_installer_utils_system_windows_WindowsRegistry_HKEY_CURRENT_USER:
+            return HKEY_CURRENT_USER;
+        case org_netbeans_installer_utils_system_windows_WindowsRegistry_HKEY_LOCAL_MACHINE:
+            return HKEY_LOCAL_MACHINE;
+        case org_netbeans_installer_utils_system_windows_WindowsRegistry_HKEY_USERS:
+            return HKEY_USERS;
+        case org_netbeans_installer_utils_system_windows_WindowsRegistry_HKEY_CURRENT_CONFIG:
+            return HKEY_CURRENT_CONFIG;
+        case org_netbeans_installer_utils_system_windows_WindowsRegistry_HKEY_DYN_DATA:
+            return HKEY_DYN_DATA;
+        case org_netbeans_installer_utils_system_windows_WindowsRegistry_HKEY_PERFORMANCE_DATA:
+            return HKEY_PERFORMANCE_DATA;
+        default:
+            return NULL;
+    }
+}
+
+LONG getMode(jint jmode) {
+    switch (jmode) {
+        case org_netbeans_installer_utils_system_windows_WindowsRegistry_MODE_DEFAULT:
+            return 0L;
+        case org_netbeans_installer_utils_system_windows_WindowsRegistry_MODE_32BIT:
+            return KEY_WOW64_32KEY;
+        case org_netbeans_installer_utils_system_windows_WindowsRegistry_MODE_64BIT:
+            return KEY_WOW64_64KEY;
+        default:
+            return 0L;
+    }
+}
+
+
+int queryValue(int mode, HKEY section, const unsigned short* key, const unsigned short* name, DWORD* type, DWORD* size, byte** value, int expand) {
+    int result = 1;
+    
+    HKEY hkey = 0;
+    int tempType = 0;
+    int tempSize = 0;
+    byte* tempValue = NULL;
+    
+    if (RegOpenKeyExW(section, key, 0, KEY_QUERY_VALUE | mode, &hkey) == ERROR_SUCCESS) {
+        if (RegQueryValueExW(hkey, name, NULL, (LPDWORD) &tempType, NULL, (LPDWORD) &tempSize) == ERROR_SUCCESS) {
+            tempValue = (byte*) MALLOC(tempSize + 8);
+            
+            if (tempValue != NULL) {
+                ZERO(tempValue, tempSize + 8);
+                
+                if (RegQueryValueExW(hkey, name, NULL, (LPDWORD) &tempType, tempValue, (LPDWORD) &tempSize) == ERROR_SUCCESS) {
+                    if (expand && (tempType == REG_EXPAND_SZ)) {
+                        int expandedSize = (int) WCSLEN((unsigned short*) tempValue) + 2;
+                        byte* expandedValue = (byte*) MALLOC(expandedSize * sizeof(wchar_t));
+                        int expandedCharsNumber = 0;
+                        ZERO(expandedValue, expandedSize);
+                        expandedCharsNumber = ExpandEnvironmentStringsW((unsigned short*) tempValue, (unsigned short*) expandedValue, tempSize);
+                        if (expandedCharsNumber > tempSize) {
+                            FREE(expandedValue);
+                            expandedValue       = (byte*) MALLOC(expandedCharsNumber * sizeof(wchar_t));
+                            expandedCharsNumber = ExpandEnvironmentStringsW((unsigned short*) tempValue, (unsigned short*) expandedValue, expandedCharsNumber);
+                        }
+                        
+                        FREE(tempValue);
+                        tempValue = expandedValue;
+                    }
+                } else {
+                    FREE(tempValue);
+                    result = 0;
+                }
+            }
+        } else {
+            result = 0;
+        }
+    } else {
+        result = 0;
+    }
+    
+    if (hkey != 0) {
+        RegCloseKey(hkey);
+    }
+    
+    if (type != NULL) {
+        *type = tempType;
+    }
+    if (size != NULL) {
+        *size = tempSize;
+    }
+    if ((value != NULL) && (tempValue != NULL)) {
+        *value = tempValue;
+    }
+    
+    return result;
+}
+
+int setValue(int mode, HKEY section, const unsigned short* key, const unsigned short* name, DWORD type, const byte* data, int size, int expand) {
+    int result = 1;
+    
+    HKEY hkey  = 0;
+    
+    if (RegOpenKeyExW(section, key, 0, KEY_SET_VALUE | mode, &hkey) == ERROR_SUCCESS) {
+        if (!(RegSetValueExW(hkey, name, 0, type, data, size) == ERROR_SUCCESS)) {
+            result = 0;
+        }
+    } else {
+        result = 0;
+    }
+    
+    if (hkey != 0) {
+        RegCloseKey(hkey);
+    }
+    
+    return result;
+}
diff --git a/src/main/cpp/jnilib/windows/src/WindowsUtils.h b/src/main/cpp/jnilib/windows/src/WindowsUtils.h
new file mode 100644
index 0000000..947c63e
--- /dev/null
+++ b/src/main/cpp/jnilib/windows/src/WindowsUtils.h
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <jni.h>
+#include <windows.h>
+#include <winreg.h>
+#include <winnt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <malloc.h>
+
+#include "../../.common/src/CommonUtils.h"
+
+#ifndef _WindowsUtils_H
+#define _WindowsUtils_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+HKEY getHKEY(jint jSection);
+
+int queryValue(int mode, HKEY section, const unsigned short * key, const unsigned short * name, DWORD* type, DWORD* size, byte** value, int expand);
+
+int setValue(int mode, HKEY section, const unsigned short * key, const unsigned short * name, DWORD type, const byte* data, int size, int expand);
+
+LONG getMode(jint jmode);
+#ifdef __cplusplus
+}
+#endif
+#endif // _WindowsUtils_H
diff --git a/src/main/cpp/jnilib/windows/src/jni_WindowsNativeUtils.c b/src/main/cpp/jnilib/windows/src/jni_WindowsNativeUtils.c
new file mode 100644
index 0000000..6d7c60b
--- /dev/null
+++ b/src/main/cpp/jnilib/windows/src/jni_WindowsNativeUtils.c
@@ -0,0 +1,400 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <jni.h>
+#include <windows.h>
+#include <lmcons.h>
+#include <shlguid.h>
+#include <shlobj.h>
+
+#include "../../.common/src/CommonUtils.h"
+#include "WindowsUtils.h"
+#include "jni_WindowsNativeUtils.h"
+
+////////////////////////////////////////////////////////////////////////////////
+// Functions
+
+JNIEXPORT jboolean JNICALL Java_org_netbeans_installer_utils_system_WindowsNativeUtils_isCurrentUserAdmin0(JNIEnv* jEnv, jobject jObject) {
+    BOOL result = FALSE;
+    
+    PACL pACL = NULL;
+    PSID psidAdmin = NULL;
+    HANDLE token = NULL;
+    HANDLE duplToken = NULL;
+    PSECURITY_DESCRIPTOR adminDescriptor = NULL;
+    
+    SID_IDENTIFIER_AUTHORITY SystemSidAuthority = SECURITY_NT_AUTHORITY;
+    DWORD aclSize;
+    
+    const DWORD ACCESS_READ  = 1;
+    const DWORD ACCESS_WRITE = 2;
+    
+    GENERIC_MAPPING mapping;
+    
+    PRIVILEGE_SET ps;
+    DWORD status;
+    DWORD structSize = sizeof(PRIVILEGE_SET);
+    
+    // MS KB 118626
+    while (TRUE) {
+        if (!OpenThreadToken(GetCurrentThread(), TOKEN_DUPLICATE | TOKEN_QUERY, TRUE, &token)) {
+            if (GetLastError() != ERROR_NO_TOKEN) {
+                throwException(jEnv, "Native error");
+                break;
+            }
+            
+            if (!OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE | TOKEN_QUERY, &token)) {
+                throwException(jEnv, "Native error");
+                break;
+            }
+        }
+        
+        if (!DuplicateToken(token, SecurityImpersonation, &duplToken)) {
+            throwException(jEnv, "Native error");
+            break;
+        }
+        
+        if (!AllocateAndInitializeSid(&SystemSidAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &psidAdmin)) {
+            throwException(jEnv, "Native error");
+            break;
+        }
+        
+        adminDescriptor = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
+        if (adminDescriptor == NULL) {
+            throwException(jEnv, "Native error");
+            break;
+        }
+        if (!InitializeSecurityDescriptor(adminDescriptor, SECURITY_DESCRIPTOR_REVISION)) {
+            throwException(jEnv, "Native error");
+            break;
+        }
+        
+        aclSize = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(psidAdmin) - sizeof(DWORD);
+        
+        pACL = (PACL) LocalAlloc(LPTR, aclSize);
+        if (pACL == NULL) {
+            throwException(jEnv, "Native error");
+            break;
+        }
+        if (!InitializeAcl(pACL, aclSize, ACL_REVISION2)) {
+            throwException(jEnv, "Native error");
+            break;
+        }
+        
+        if (!AddAccessAllowedAce(pACL, ACL_REVISION2, ACCESS_READ | ACCESS_WRITE , psidAdmin)) {
+            throwException(jEnv, "Native error");
+            break;
+        }
+        if (!SetSecurityDescriptorDacl(adminDescriptor, TRUE, pACL, FALSE)) {
+            throwException(jEnv, "Native error");
+            break;
+        }
+        
+        SetSecurityDescriptorGroup(adminDescriptor, psidAdmin, FALSE);
+        SetSecurityDescriptorOwner(adminDescriptor, psidAdmin, FALSE);
+        
+        if (!IsValidSecurityDescriptor(adminDescriptor)) {
+            throwException(jEnv, "Native error");
+            break;
+        }
+        
+        mapping.GenericRead    = ACCESS_READ;
+        mapping.GenericWrite   = ACCESS_WRITE;
+        mapping.GenericExecute = 0;
+        mapping.GenericAll     = ACCESS_READ | ACCESS_WRITE;
+        
+        if (!AccessCheck(adminDescriptor, duplToken, ACCESS_READ, &mapping, &ps, &structSize, &status, &result)) {
+            throwException(jEnv, "Native error");
+            break;
+        }
+        
+        break;
+    }
+    
+    if (pACL) {
+        LocalFree(pACL);
+    }
+    if (adminDescriptor) {
+        LocalFree(adminDescriptor);
+    }
+    if (psidAdmin) {
+        FreeSid(psidAdmin);
+    }
+    if (duplToken) {
+        CloseHandle(duplToken);
+    }
+    if (token) {
+        CloseHandle(token);
+    }
+    
+    return result;
+}
+
+JNIEXPORT jlong JNICALL Java_org_netbeans_installer_utils_system_WindowsNativeUtils_getFreeSpace0(JNIEnv* jEnv, jobject jObject, jstring jPath) {
+    WCHAR*  path = getWideChars(jEnv, jPath);
+    jlong  size = 0;
+    typedef struct int64s { unsigned long Low, High; } int64t;
+    int64t bytes;
+    if (GetDiskFreeSpaceExW(path, (PULARGE_INTEGER) &bytes, NULL, NULL)) {
+        unsigned long h = bytes.High;
+        // workaround of using missing _allmul function
+        // replace multiplication by sum
+        // (2^32 * high + low) = 2^32 + 2^32 + ... (bytes.High times total) + bytes.Low     
+        // can be relatively expensive on big sizes (peta bytes and more)
+        while(h > 0) {
+            h--;
+            size+=4294967296L;
+        }
+        size+= bytes.Low;
+    } else {
+        throwException(jEnv, "Native error");
+    }
+    
+    FREE(path);
+    
+    return size;
+}
+
+JNIEXPORT void JNICALL Java_org_netbeans_installer_utils_system_WindowsNativeUtils_createShortcut0(JNIEnv* jEnv, jobject jObject, jobject jShortcut) {
+    unsigned short *shortcutPath     = getWideStringFromMethod(jEnv, jShortcut, "getPath");
+    unsigned short *targetPath       = getWideStringFromMethod(jEnv, jShortcut, "getTargetPath");
+    unsigned short *description      = getWideStringFromMethod(jEnv, jShortcut, "getDescription");
+    unsigned short *iconPath         = getWideStringFromMethod(jEnv, jShortcut, "getIconPath");
+    jint            iconIndex        = getIntFromMethod       (jEnv, jShortcut, "getIconIndex");
+    unsigned short *workingDirectory = getWideStringFromMethod(jEnv, jShortcut, "getWorkingDirectoryPath");
+    unsigned short *arguments        = getWideStringFromMethod(jEnv, jShortcut, "getArgumentsString");
+    
+    HRESULT     tempResult;
+    IShellLinkW* shell;
+    
+    HRESULT comStart = CoInitialize(NULL);
+    int errorCode = 0;
+    
+    tempResult = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, &IID_IShellLinkW, (void **) &shell);
+    
+    if (SUCCEEDED(tempResult)) {
+        IPersistFile *persistFile;
+        // we will save the shell link in persistent storage
+        tempResult = shell->lpVtbl->QueryInterface(shell, &IID_IPersistFile, (void **) &persistFile);
+        
+        if (SUCCEEDED(tempResult)) {
+            tempResult = shell->lpVtbl->SetPath(shell, targetPath);
+            if (!SUCCEEDED(tempResult)) {
+                throwException(jEnv, "Native error (-2)");
+                errorCode = -2;
+            }
+            // make sure description length is less than MAX_PATH
+            if ((errorCode == 0) && (description != NULL)) {
+                if (WCSLEN(description) < MAX_PATH) {
+                    if (!SUCCEEDED(shell->lpVtbl->SetDescription(shell, description))) {
+                        throwException(jEnv, "Native error (-3)");
+                        errorCode = -3;
+                    }
+                } else {
+                    unsigned short *desc = (unsigned short *) MALLOC(sizeof(unsigned short) * MAX_PATH);
+                    ZERO(desc, sizeof(unsigned short) * MAX_PATH);
+                    desc = WCSNCPY(desc, description, MAX_PATH);
+                    if (!SUCCEEDED(shell->lpVtbl->SetDescription(shell, desc))) {
+                        throwException(jEnv, "Native error (-4)");
+                        errorCode = -4;
+                    }
+                    FREE(desc);
+                }
+            }
+            if ((errorCode == 0) && (arguments != NULL)) {
+                if (!SUCCEEDED(shell->lpVtbl->SetArguments(shell, arguments))) {
+                    throwException(jEnv, "Native error (-5)");
+                    errorCode = -5;
+                }
+            }
+            if ((errorCode == 0) && (workingDirectory != NULL)) {
+                if (!SUCCEEDED(shell->lpVtbl->SetWorkingDirectory(shell, workingDirectory))) {
+                    throwException(jEnv, "Native error (-6)");
+                    errorCode = -6;
+                }
+            }
+            if ((errorCode == 0) && (iconPath != NULL)) {
+                if (!SUCCEEDED(shell->lpVtbl->SetIconLocation(shell, iconPath, iconIndex))) {
+                    throwException(jEnv, "Native error (-7)");
+                    errorCode = -7;
+                }
+            }
+            // use normal window.
+            if (errorCode == 0) {
+                if (!SUCCEEDED(shell->lpVtbl->SetShowCmd(shell, SW_NORMAL))) {
+                    throwException(jEnv, "Native error (-8)");
+                    errorCode = -8;
+                }
+            }
+            if (errorCode == 0) {
+                if (mkdirsW(jEnv, shortcutPath)) {
+                    if (!SUCCEEDED(persistFile->lpVtbl->Save(persistFile, shortcutPath, TRUE))) {
+                        throwException(jEnv, "Native error (-9)");
+                        errorCode = -9;
+                    }
+                } else {
+                    throwException(jEnv, "Native error (-10)");
+                    errorCode = -10;
+                }
+            }
+            
+            if (errorCode == 0) {
+                persistFile->lpVtbl->Release(persistFile);
+            }
+        } else {
+            throwException(jEnv, "Native error (-11)");
+            errorCode = -11;
+        }
+        shell->lpVtbl->Release(shell);
+    } else {
+        throwException(jEnv, "Native error (-12)");
+        errorCode = -12;
+    }
+    
+    if (comStart == S_OK) {
+        CoUninitialize();
+    }
+    
+    FREE(shortcutPath);
+    FREE(targetPath);
+    FREE(description);
+    FREE(iconPath);
+    FREE(workingDirectory);
+    FREE(arguments);
+}
+
+JNIEXPORT void JNICALL Java_org_netbeans_installer_utils_system_WindowsNativeUtils_deleteFileOnReboot0(JNIEnv* jEnv, jobject jObject, jstring jPath) {
+    unsigned short * path = getWideChars(jEnv, jPath);
+    
+    if (!MoveFileExW(path, NULL, MOVEFILE_DELAY_UNTIL_REBOOT)) {
+        throwException(jEnv, "Native error");
+    }
+    
+    FREE(path);
+}
+
+JNIEXPORT void JNICALL Java_org_netbeans_installer_utils_system_WindowsNativeUtils_createProcessWithoutHandles0(JNIEnv* jEnv, jobject jObject, jstring jCommand) {
+    unsigned short * command = getWideChars(jEnv, jCommand);
+    STARTUPINFOW si;
+    PROCESS_INFORMATION pi;
+    
+    ZERO(&si, sizeof(si));
+    si.cb = sizeof(si);
+    ZERO(&pi, sizeof(pi));
+    if(!CreateProcessW(NULL,   // executable name - use command line
+            command,    // command line
+            NULL,   // process security attribute
+            NULL,   // thread security attribute
+            FALSE,   // inherits system handles
+            0,      // no creation flags
+            NULL,   // use parent's environment block
+            NULL,   // use parent's starting directory
+            &si,    // (in) startup information
+            &pi)) {   // (out) process information
+        throwException(jEnv, "Cannot create process.\n");
+    }
+    
+    
+    FREE(command);
+}
+JNIEXPORT void JNICALL Java_org_netbeans_installer_utils_system_WindowsNativeUtils_notifyAssociationChanged0(JNIEnv *jEnv, jobject jObj) {
+    SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, 0, 0);
+}
+
+JNIEXPORT jboolean JNICALL Java_org_netbeans_installer_utils_system_WindowsNativeUtils_notifyEnvironmentChanged0(JNIEnv *jEnv, jobject jObj) {
+    /* maximum 1 sec timeout for each window in the system */
+    DWORD dwReturnValue = 0;
+    LRESULT result = SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, (LPARAM) "Environment", SMTO_ABORTIFHUNG, 1000, (PDWORD_PTR) &dwReturnValue);
+    return (result!=0);
+}
+
+
+JNIEXPORT jint JNICALL Java_org_netbeans_installer_utils_system_WindowsNativeUtils_checkAccessTokenAccessLevel0(JNIEnv *jEnv, jobject jObj, jstring jPath, jint jLevel) {
+    unsigned short * path = getWideChars(jEnv, jPath);
+    PSECURITY_DESCRIPTOR    pSD;
+    DWORD nLength;
+    
+    PRIVILEGE_SET PrivilegeSet;
+    DWORD PrivSetSize = sizeof (PRIVILEGE_SET);
+    
+    HANDLE hToken;
+    
+    GENERIC_MAPPING GenericMapping;
+    DWORD DesiredAccess = (DWORD) jLevel ;
+    
+    BOOL bAccessGranted;
+    DWORD GrantedAccess;
+    
+    // create memory for storing user's security descriptor
+    GetFileSecurityW(path, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, NULL, 0, &nLength);
+    
+    pSD = (PSECURITY_DESCRIPTOR) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nLength);
+    
+    if (pSD == NULL) {
+        throwException(jEnv, "Unable to allocate memory to store security descriptor.\n");
+        return -1;
+    }
+    // Get the security descriptor
+    if (!GetFileSecurityW(path, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,  pSD, nLength, &nLength)) {
+        throwException(jEnv, "Unable to obtain security descriptor.\n");
+        FREE(path);
+        return (-3);
+    }
+    FREE(path);
+    
+    /* Perform security impersonation of the user and open */
+    /* the resulting thread token. */
+    if (!ImpersonateSelf(SecurityImpersonation)) {
+        throwException(jEnv, "Unable to perform security impersonation.\n");
+        HeapFree(GetProcessHeap(), 0, pSD);
+        return (-4);
+    }
+    
+    if (!OpenThreadToken(GetCurrentThread(), TOKEN_DUPLICATE | TOKEN_QUERY, FALSE, &hToken)) {
+        throwException(jEnv, "Unable to get current thread's token.\n");
+        HeapFree(GetProcessHeap(), 0, pSD);
+        return (-5);
+    }
+    RevertToSelf();
+    
+    ZERO(&GenericMapping, sizeof (GENERIC_MAPPING));
+    
+    DesiredAccess = DesiredAccess | STANDARD_RIGHTS_READ;
+    GenericMapping.GenericRead = FILE_GENERIC_READ;
+    
+    if(jLevel & FILE_WRITE_DATA) {
+        GenericMapping.GenericWrite = FILE_GENERIC_WRITE;
+    }
+    
+    MapGenericMask(&DesiredAccess, &GenericMapping);
+    
+    /* Perform access check using the token. */
+    if (!AccessCheck(pSD, hToken, DesiredAccess, &GenericMapping, &PrivilegeSet, &PrivSetSize, &GrantedAccess, &bAccessGranted)) {
+        throwException(jEnv, "Unable to perform access check.\n");
+        CloseHandle(hToken);
+        HeapFree(GetProcessHeap(), 0, pSD);
+        return (-6);
+    }
+    /* Clean up. */
+    HeapFree(GetProcessHeap(), 0, pSD);
+    CloseHandle(hToken);
+    return (bAccessGranted);
+}
+
+
diff --git a/src/main/cpp/jnilib/windows/src/jni_WindowsNativeUtils.h b/src/main/cpp/jnilib/windows/src/jni_WindowsNativeUtils.h
new file mode 100644
index 0000000..9ea87e7
--- /dev/null
+++ b/src/main/cpp/jnilib/windows/src/jni_WindowsNativeUtils.h
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <jni.h>
+/* Header for class org_netbeans_installer_utils_system_WindowsNativeUtils */
+
+#ifndef _Included_org_netbeans_installer_utils_system_WindowsNativeUtils
+#define _Included_org_netbeans_installer_utils_system_WindowsNativeUtils
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#undef org_netbeans_installer_utils_system_WindowsNativeUtils_MIN_UID_INDEX
+#define org_netbeans_installer_utils_system_WindowsNativeUtils_MIN_UID_INDEX 1L
+
+#undef org_netbeans_installer_utils_system_WindowsNativeUtils_MAX_UID_INDEX
+#define org_netbeans_installer_utils_system_WindowsNativeUtils_MAX_UID_INDEX 100L
+
+/*
+ * Class:     org_netbeans_installer_utils_system_WindowsNativeUtils
+ * Method:    isCurrentUserAdmin0
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_org_netbeans_installer_utils_system_WindowsNativeUtils_isCurrentUserAdmin0
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     org_netbeans_installer_utils_system_WindowsNativeUtils
+ * Method:    getFreeSpace0
+ * Signature: (Ljava/lang/String;)J
+ */
+JNIEXPORT jlong JNICALL Java_org_netbeans_installer_utils_system_WindowsNativeUtils_getFreeSpace0
+  (JNIEnv *, jobject, jstring);
+
+/*
+ * Class:     org_netbeans_installer_utils_system_WindowsNativeUtils
+ * Method:    createShortcut0
+ * Signature: (Lorg/netbeans/installer/utils/system/shortcut/FileShortcut;)V
+ */
+JNIEXPORT void JNICALL Java_org_netbeans_installer_utils_system_WindowsNativeUtils_createShortcut0
+  (JNIEnv *, jobject, jobject);
+
+
+/*
+ * Class:     org_netbeans_installer_utils_system_WindowsNativeUtils
+ * Method:    deleteFileOnReboot0
+ * Signature: (Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_org_netbeans_installer_utils_system_WindowsNativeUtils_deleteFileOnReboot0
+  (JNIEnv *, jobject, jstring);
+
+/*
+ * Class:     org_netbeans_installer_utils_system_WindowsNativeUtils
+ * Method:    createProcessWithoutHandles0
+ * Signature: (Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_org_netbeans_installer_utils_system_WindowsNativeUtils_createProcessWithoutHandles0
+  (JNIEnv *, jobject, jstring);
+
+
+/*
+ * Class:     org_netbeans_installer_utils_system_WindowsNativeUtils
+ * Method:    notifyAssociationChanged0
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_org_netbeans_installer_utils_system_WindowsNativeUtils_notifyAssociationChanged0
+  (JNIEnv *, jobject);
+
+
+/*
+ * Class:     org_netbeans_installer_utils_system_WindowsNativeUtils
+ * Method:    checkAccessTokenAccessLevel0
+ * Signature: (Ljava/lang/String;I)I
+ */
+JNIEXPORT jint JNICALL Java_org_netbeans_installer_utils_system_WindowsNativeUtils_checkAccessTokenAccessLevel0
+  (JNIEnv *, jobject, jstring, jint);
+
+
+/*
+ * Class:     org_netbeans_installer_utils_system_WindowsNativeUtils
+ * Method:    notifyEnvironmentChanged0
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_org_netbeans_installer_utils_system_WindowsNativeUtils_notifyEnvironmentChanged0
+  (JNIEnv *, jobject);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/main/cpp/jnilib/windows/src/jni_WindowsRegistry.c b/src/main/cpp/jnilib/windows/src/jni_WindowsRegistry.c
new file mode 100644
index 0000000..3608bf0
--- /dev/null
+++ b/src/main/cpp/jnilib/windows/src/jni_WindowsRegistry.c
@@ -0,0 +1,632 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <jni.h>
+#include <windows.h>
+#include <winreg.h>
+#include <winnt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <malloc.h>
+
+#include "../../.common/src/CommonUtils.h"
+#include "WindowsUtils.h"
+#include "jni_WindowsRegistry.h"
+
+////////////////////////////////////////////////////////////////////////////////
+// Globals
+
+// maximum length of a registry value
+const DWORD MAX_LEN_VALUE_NAME = 16383;
+
+////////////////////////////////////////////////////////////////////////////////
+// Functions
+
+JNIEXPORT jboolean JNICALL Java_org_netbeans_installer_utils_system_windows_WindowsRegistry_checkKeyAccess0(JNIEnv *jEnv, jobject jObject, jint jMode, jint jSection, jstring jKey, jint jLevel) {
+    HKEY  hkey = 0;
+    unsigned short * key = getWideChars(jEnv, jKey);
+    
+    jboolean result = FALSE;
+    REGSAM access = (jLevel==0) ? KEY_READ : KEY_ALL_ACCESS;
+    result = (RegOpenKeyExW(getHKEY(jSection), key, 0, access | getMode(jMode), &hkey) == ERROR_SUCCESS);
+    
+    if (hkey != 0) {
+        RegCloseKey(hkey);
+    }
+    
+    FREE(key);
+    
+    return result;
+}
+
+JNIEXPORT jboolean JNICALL Java_org_netbeans_installer_utils_system_windows_WindowsRegistry_valueExists0(JNIEnv *jEnv, jobject jObject, jint jMode, jint jSection, jstring jKey, jstring jName) {
+    HKEY  hkey  = 0;
+    unsigned short * key   = getWideChars(jEnv, jKey);
+    unsigned short * value = getWideChars(jEnv, jName);
+    jboolean result = FALSE;
+    if (RegOpenKeyExW(getHKEY(jSection), key, 0, KEY_QUERY_VALUE | getMode(jMode), &hkey) == ERROR_SUCCESS) {
+        result = (RegQueryValueExW(hkey, value, NULL, NULL, NULL, NULL) == ERROR_SUCCESS);
+    } else {
+        throwException(jEnv, "Cannot open key");
+    }
+    
+    if (hkey != 0) {
+        RegCloseKey(hkey);
+    }
+    FREE(key);
+    FREE(value);
+    
+    return result;
+}
+
+JNIEXPORT jboolean JNICALL Java_org_netbeans_installer_utils_system_windows_WindowsRegistry_keyEmpty0(JNIEnv *jEnv, jobject jObject, jint jMode, jint jSection, jstring jKey) {
+    HKEY  hkey = 0;
+    unsigned short* key = getWideChars(jEnv, jKey);
+    
+    DWORD subkeys = 1;
+    DWORD values  = 1;
+    if (RegOpenKeyExW(getHKEY(jSection), key, 0, KEY_READ | getMode(jMode), &hkey) == ERROR_SUCCESS) {
+        if (RegQueryInfoKeyW(hkey, NULL, NULL, NULL, &subkeys, NULL, NULL, &values, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) {
+            throwException(jEnv, "Cannot read key data");
+        }
+    } else {
+        throwException(jEnv, "Cannot open key");
+    }
+    
+    if (hkey != 0) {
+        RegCloseKey(hkey);
+    }
+    
+    FREE(key);
+    
+    return (values + subkeys == 0);
+}
+
+JNIEXPORT jint JNICALL Java_org_netbeans_installer_utils_system_windows_WindowsRegistry_countSubKeys0(JNIEnv *jEnv, jobject jObject, jint jMode, jint jSection, jstring jKey) {
+    HKEY  hkey = 0;
+    unsigned short* key = getWideChars(jEnv, jKey);
+    
+    DWORD count = 0;
+    if (RegOpenKeyExW(getHKEY(jSection), key, 0, KEY_READ | getMode(jMode), &hkey) == ERROR_SUCCESS) {
+        if(RegQueryInfoKeyW(hkey, NULL, NULL, NULL, &count, NULL, NULL, NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) {
+            throwException(jEnv, "Cannot read key data");
+        }
+    } else {
+        throwException(jEnv, "Cannot open key");
+    }
+    
+    if (hkey != 0) {
+        RegCloseKey(hkey);
+    }
+    
+    FREE(key);
+    
+    return count;
+}
+
+JNIEXPORT jint JNICALL Java_org_netbeans_installer_utils_system_windows_WindowsRegistry_countValues0(JNIEnv *jEnv, jobject jObject, jint jMode, jint jSection, jstring jKey) {
+    HKEY  hkey = 0;
+    unsigned short* key = getWideChars(jEnv, jKey);
+    
+    DWORD count = 0;
+    if (RegOpenKeyExW(getHKEY(jSection), key, 0, KEY_READ | getMode(jMode), &hkey) == ERROR_SUCCESS) {
+        if (RegQueryInfoKeyW(hkey, NULL, NULL, NULL, NULL, NULL, NULL, &count, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) {
+            throwException(jEnv, "Cannot read key data");
+        }
+    } else {
+        throwException(jEnv, "Cannot open key");
+    }
+    
+    if (hkey != 0) {
+        RegCloseKey(hkey);
+    }
+    
+    FREE(key);
+    
+    return count;
+}
+
+JNIEXPORT jobjectArray JNICALL Java_org_netbeans_installer_utils_system_windows_WindowsRegistry_getSubkeyNames0(JNIEnv *jEnv, jobject jObject, jint jMode, jint jSection, jstring jKey) {
+    HKEY  hkey   = 0;
+    unsigned short* key    = getWideChars(jEnv, jKey);
+    DWORD number = 0;
+    int   err    = 0;
+    int   index  = 0 ;
+    
+    unsigned short* buffer = (unsigned short*) MALLOC(sizeof(char) * MAX_LEN_VALUE_NAME);
+    
+    jobjectArray result = NULL;
+    if (RegOpenKeyExW(getHKEY(jSection), key, 0, KEY_READ | getMode(jMode), &hkey) == ERROR_SUCCESS) {
+        if (RegQueryInfoKeyW(hkey, NULL, NULL, NULL, &number, NULL, NULL, NULL, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
+            jclass stringClazz = (*jEnv)->FindClass(jEnv, "java/lang/String");
+            result = (*jEnv)->NewObjectArray(jEnv, number, stringClazz, NULL);
+            
+            do {
+                DWORD size = MAX_LEN_VALUE_NAME;
+                buffer[0]  = 0;
+                
+                err = RegEnumKeyExW(hkey, index, buffer, &size, NULL, NULL, NULL, NULL);
+                if (err == ERROR_SUCCESS) {
+                    (*jEnv)->SetObjectArrayElement(jEnv, result, index, getStringW(jEnv, buffer));
+                } else {
+                    if (err != ERROR_NO_MORE_ITEMS) {
+                        throwException(jEnv, "Cannot get key names");
+                    }
+                }
+                
+                index++;
+            } while (err == ERROR_SUCCESS);
+        } else {
+            throwException(jEnv, "Cannot read key data");
+        }
+    } else {
+        throwException(jEnv, "Cannot open key");
+    }
+    
+    if (hkey != 0) {
+        RegCloseKey(hkey);
+    }
+    
+    FREE(key);
+    FREE(buffer);
+    
+    return result;
+}
+
+JNIEXPORT jobjectArray JNICALL Java_org_netbeans_installer_utils_system_windows_WindowsRegistry_getValueNames0(JNIEnv *jEnv, jobject jObject, jint jMode, jint jSection, jstring jKey) {
+    HKEY  hkey         = 0;
+    unsigned short* key          = getWideChars(jEnv, jKey);
+    DWORD valuesCount  = 0;
+    int   err          = 0;
+    int   index        = 0;
+    
+    unsigned short* buffer = (unsigned short*) MALLOC(sizeof(char) * MAX_LEN_VALUE_NAME);
+    
+    jobjectArray result = NULL;
+    if (RegOpenKeyExW(getHKEY(jSection), key, 0, KEY_QUERY_VALUE | getMode(jMode), &hkey) == ERROR_SUCCESS) {
+        if (RegQueryInfoKeyW(hkey, NULL, NULL, NULL, NULL, NULL, NULL, &valuesCount, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
+            jclass stringClazz = (*jEnv)->FindClass(jEnv, "java/lang/String");
+            result = (*jEnv)->NewObjectArray(jEnv, valuesCount, stringClazz, NULL);
+            
+            do {
+                DWORD size = MAX_LEN_VALUE_NAME;
+                buffer[0]  = 0;
+                
+                err = RegEnumValueW(hkey, index, buffer, &size, NULL, NULL, NULL, NULL);
+                if (err == ERROR_SUCCESS) {
+                    (*jEnv)->SetObjectArrayElement(jEnv, result, index, getStringW(jEnv, buffer));
+                } else {
+                    if (err != ERROR_NO_MORE_ITEMS) {
+                        throwException(jEnv, "Cannot get value names");
+                    }
+                }
+                
+                index++;
+            } while (err == ERROR_SUCCESS);
+        } else {
+            throwException(jEnv, "Cannot read key data");
+        }
+    } else {
+        throwException(jEnv, "Cannot open key");
+    }
+    
+    if (hkey != 0) {
+        RegCloseKey(hkey);
+    }
+    
+    FREE(key);
+    FREE(buffer);
+    
+    return result;
+}
+
+JNIEXPORT jint JNICALL Java_org_netbeans_installer_utils_system_windows_WindowsRegistry_getValueType0(JNIEnv *jEnv, jobject jObject, jint jMode, jint jSection, jstring jKey, jstring jName) {
+    HKEY  hkey   =0;
+    unsigned short* key   = getWideChars(jEnv, jKey);
+    unsigned short* value = getWideChars(jEnv, jName);
+    
+    DWORD type = REG_NONE;
+    if (RegOpenKeyExW(getHKEY(jSection), key, 0, KEY_QUERY_VALUE | getMode(jMode), &hkey) == ERROR_SUCCESS) {
+        if (RegQueryValueExW(hkey, value, NULL, &type, NULL, NULL) != ERROR_SUCCESS) {
+            throwException(jEnv, "Cannot read value");
+        }
+    } else {
+        throwException(jEnv, "Cannot open key");
+    }
+    
+    if (hkey != 0) {
+        RegCloseKey(hkey);
+    }
+    
+    FREE(key);
+    FREE(value);
+    
+    return type;
+}
+
+JNIEXPORT void JNICALL Java_org_netbeans_installer_utils_system_windows_WindowsRegistry_createKey0(JNIEnv *jEnv, jobject jObject, jint jMode, jint jSection, jstring jParent, jstring jChild) {
+    HKEY  hkey   = 0;
+    HKEY  newKey = 0;
+    unsigned short* parent = getWideChars(jEnv, jParent);
+    unsigned short* child  = getWideChars(jEnv, jChild);
+    
+    if (RegOpenKeyExW(getHKEY(jSection), parent, 0, KEY_CREATE_SUB_KEY | getMode(jMode), &hkey) == ERROR_SUCCESS) {
+        LONG result = RegCreateKeyExW(hkey, child, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE | getMode(jMode), NULL, &newKey, NULL);
+        if (result == ERROR_SUCCESS) {
+            if (newKey != 0) {
+                RegCloseKey(newKey);
+            }
+        } else if (result == ERROR_ACCESS_DENIED) {
+            throwException(jEnv, "Could not create a new key (access denied)");
+        } else {
+            throwException(jEnv, "Could not create a new key");
+        }
+    } else {
+        throwException(jEnv, "Could not open the parent key");
+    }
+    
+    if (hkey != 0) {
+        RegCloseKey(hkey);
+    }
+    
+    FREE(parent);
+    FREE(child);
+}
+
+JNIEXPORT void JNICALL Java_org_netbeans_installer_utils_system_windows_WindowsRegistry_deleteKey0(JNIEnv *jEnv, jobject jObject, jint jMode, jint jSection, jstring jParent, jstring jChild) {
+    HKEY  hkey       = 0;
+    unsigned short* jParentS = getWideChars(jEnv, jParent);
+    unsigned short* jChildS  = getWideChars(jEnv, jChild);
+    
+    
+    if (RegOpenKeyExW(getHKEY(jSection), jParentS, 0, KEY_READ | KEY_WRITE | getMode(jMode), &hkey) == ERROR_SUCCESS) {
+	LONG mode = getMode(jMode);
+	if(mode==0) {
+            if (RegDeleteKeyW(hkey, jChildS) != ERROR_SUCCESS) {
+                throwException(jEnv, "Could not delete key");
+	    }
+        } else {
+             typedef LONG (WINAPI *LPFN_REGDELETEKEYEXW) (HKEY, LPCWSTR, REGSAM, DWORD);
+             LPFN_REGDELETEKEYEXW regDeleteKeyExW;
+             HMODULE hModule = GetModuleHandle(TEXT("advapi32.dll"));
+             if(hModule == NULL) {
+                 hModule = LoadLibraryA("advapi32.dll");
+             }
+             regDeleteKeyExW = (LPFN_REGDELETEKEYEXW) GetProcAddress(hModule,"RegDeleteKeyExW");
+             if (NULL != regDeleteKeyExW) {
+                 if (regDeleteKeyExW(hkey, jChildS, mode, 0) != ERROR_SUCCESS) {
+     		    throwException(jEnv, "Could not delete key");
+                 }
+             } else {
+                    throwException(jEnv, "Cannot load function RegDeleteKeyExW");
+             }
+        }
+    } else {
+        throwException(jEnv, "Could not open the parent key");
+    }
+    
+    if (hkey != 0) {
+        RegCloseKey(hkey);
+    }
+    
+    FREE(jParentS);
+    FREE(jChildS);
+}
+
+JNIEXPORT void JNICALL Java_org_netbeans_installer_utils_system_windows_WindowsRegistry_deleteValue0(JNIEnv *jEnv, jobject jObject, jint jMode, jint jSection, jstring jKey, jstring jName) {
+    HKEY  hkey   = 0;
+    unsigned short* key   = getWideChars(jEnv, jKey);
+    unsigned short* value = getWideChars(jEnv, jName);
+    
+    if (RegOpenKeyExW(getHKEY(jSection), key, 0, KEY_SET_VALUE | getMode(jMode) , &hkey) == ERROR_SUCCESS) {
+        if (RegDeleteValueW(hkey, value) != ERROR_SUCCESS) {
+            throwException(jEnv, "Cannot delete value");
+        }
+    } else {
+        throwException(jEnv, "Canont open key");
+    }
+    
+    if(hkey != 0) {
+        RegCloseKey(hkey);
+    }
+    
+    FREE(key);
+    FREE(value);
+}
+
+JNIEXPORT jstring JNICALL Java_org_netbeans_installer_utils_system_windows_WindowsRegistry_getStringValue0(JNIEnv *jEnv, jobject jObject, jint jMode, jint jSection, jstring jKey, jstring jName, jboolean jExpand) {
+    unsigned short*   key    = getWideChars(jEnv, jKey);
+    unsigned short*   name   = getWideChars(jEnv, jName);
+    DWORD   type   = REG_NONE;
+    byte*   value  = NULL;
+    
+    jstring result = NULL;
+    
+    if (queryValue(getMode(jMode), getHKEY(jSection), key, name, &type, NULL, &value, jExpand)) {
+        if (type == REG_SZ || type == REG_EXPAND_SZ) {
+            result = getStringW(jEnv, (unsigned short*) value);
+        } else {
+            throwException(jEnv, "Value has wrong type");
+        }
+    } else {
+        throwException(jEnv, "Cannot read value");
+    }
+    
+    FREE(key);
+    FREE(name);
+    FREE(value);
+    
+    return result;
+}
+
+JNIEXPORT void JNICALL Java_org_netbeans_installer_utils_system_windows_WindowsRegistry_setStringValue0(JNIEnv *jEnv, jobject jObject, jint jMode, jint jSection, jstring jKey, jstring jName, jstring jValue, jboolean jExpand) {
+    unsigned short* key   = getWideChars(jEnv, jKey);
+    unsigned short* name  = getWideChars(jEnv, jName);
+    unsigned short* value = getWideChars(jEnv, jValue);
+    
+    if (!setValue(getMode(jMode), getHKEY(jSection), key, name, jExpand ? REG_EXPAND_SZ : REG_SZ, (byte*) value, ((int) WCSLEN(value)) * sizeof(unsigned short), 0)) {
+        throwException(jEnv, "Could not set value");
+    }
+    
+    FREE(key);
+    FREE(name);
+    FREE(value);
+}
+
+JNIEXPORT jint JNICALL Java_org_netbeans_installer_utils_system_windows_WindowsRegistry_get32BitValue0(JNIEnv *jEnv, jobject jObject, jint jMode, jint jSection, jstring jKey, jstring jName) {
+    HKEY  hkey   = 0;
+    unsigned short* key   = getWideChars(jEnv, jKey);
+    unsigned short* value = getWideChars(jEnv, jName);
+    
+    jint result = -1;
+    if(RegOpenKeyExW(getHKEY(jSection), key, 0, KEY_QUERY_VALUE | getMode(jMode), &hkey) == ERROR_SUCCESS) {
+        DWORD dwType    = 0;
+        DWORD dwValue   = 0;
+        DWORD dwBufSize = sizeof(dwValue);
+        
+        if (RegQueryValueExW(hkey, value, NULL, &dwType, (LPBYTE) &dwValue, &dwBufSize) == ERROR_SUCCESS) {
+            if ((dwType == REG_DWORD) || (dwType == REG_DWORD_BIG_ENDIAN)) {
+                result = dwValue;
+            } else {
+                throwException(jEnv, "Value is of wrong type");
+            }
+        } else {
+            throwException(jEnv, "Cannot read key data");
+        }
+    } else {
+        throwException(jEnv, "Could not open key");
+    }
+    
+    if (hkey != 0) {
+        RegCloseKey(hkey);
+    }
+    
+    FREE(key);
+    FREE(value);
+    
+    return result;
+}
+
+JNIEXPORT void JNICALL Java_org_netbeans_installer_utils_system_windows_WindowsRegistry_set32BitValue0(JNIEnv *jEnv, jobject jObject, jint jMode, jint jSection, jstring jKey, jstring jName, jint jValue) {
+    unsigned short*  key       = getWideChars(jEnv, jKey);
+    unsigned short*  name      = getWideChars(jEnv, jName);
+    DWORD  dword     = (DWORD) jValue;
+    LPBYTE byteValue = (LPBYTE) &dword;
+    
+    if (!setValue(getMode(jMode),getHKEY(jSection), key, name, REG_DWORD, byteValue, sizeof(dword), 0)) {
+        throwException(jEnv, "Cannot set value");
+    }
+    
+    FREE(key);
+    FREE(name);
+}
+
+JNIEXPORT jobjectArray JNICALL Java_org_netbeans_installer_utils_system_windows_WindowsRegistry_getMultiStringValue0(JNIEnv *jEnv, jobject jObject, jint jMode, jint jSection, jstring jKey, jstring jName) {
+    HKEY  hkey   = 0;
+    unsigned short* key   = getWideChars(jEnv, jKey);
+    unsigned short* value = getWideChars(jEnv, jName);
+    
+    int	i, start, count, cnt;
+    LONG regErr = 0;
+    unsigned short* data = 0;
+    jstring string;
+    jclass strClass;
+    DWORD dwType;
+    DWORD size = 0;
+    
+    jarray result = 0;
+    if(RegOpenKeyExW(getHKEY(jSection), key, 0, KEY_QUERY_VALUE | getMode(jMode), &hkey) == ERROR_SUCCESS) {
+        if (RegQueryValueExW(hkey, value, NULL, &dwType, NULL, &size) == ERROR_SUCCESS) {
+            if (dwType == REG_MULTI_SZ) {
+                data = (unsigned short*) LocalAlloc(LPTR, size + 8);
+                
+                if (data != NULL) {
+                    if (RegQueryValueExW(hkey, value, NULL, &dwType, (byte*) data, &size) == ERROR_SUCCESS) {
+                        for (count = 0, i = 0; i < (int) size; i++) {
+                            if (data[i] == '\0') { // \0 - end of a single string
+                                count++;
+                                if (data[i + 1] == '\0') { // two \0 's in a row - end of all strings
+                                    break;
+                                }
+                            }
+                        }
+                        
+                        strClass = (*jEnv)->FindClass(jEnv, "java/lang/String");
+                        if (strClass != NULL) {
+                            result = (*jEnv)->NewObjectArray(jEnv, (jsize) count, strClass, NULL);
+                            if (result != NULL) {
+                                for (cnt = 0, start = 0, i = 0; (i < (int) size) && (cnt < count); i++) {
+                                    if (data[i] == '\0') {
+                                        string = getStringWithLengthW(jEnv, &data[start], i - start);
+                                        
+                                        if (string != NULL) {
+                                            (*jEnv)->SetObjectArrayElement(jEnv, (jobjectArray) result, (jsize) cnt++, string);
+                                            
+                                            start = i + 1;
+                                            if (data[start] == '\0') {
+                                                break;
+                                            }
+                                        } else {
+                                            throwException(jEnv, "Cannot create an array element");
+                                            break;
+                                        }
+                                    }
+                                }
+                            } else {
+                                throwException(jEnv, "Cannot create resulting array");
+                            }
+                        } else {
+                            throwException(jEnv, "Cannot find java.lang.String");
+                        }
+                    } else {
+                        throwException(jEnv, "Cannot read value data");
+                    }
+                    FREE(data);
+                } else {
+                    throwException(jEnv, "Cannot allocate memory for value");
+                }
+            } else {
+                throwException(jEnv, "Value is of wrong type");
+            }
+        } else {
+            throwException(jEnv, "Cannot read key data");
+        }
+    } else {
+        throwException(jEnv, "Cannot open key");
+    }
+    
+    if (hkey != 0) {
+        RegCloseKey(hkey);
+    }
+    
+    FREE(key);
+    FREE(value);
+    
+    return (jobjectArray) result;
+}
+
+JNIEXPORT void JNICALL Java_org_netbeans_installer_utils_system_windows_WindowsRegistry_setMultiStringValue0(JNIEnv *jEnv, jobject jObject, jint jMode, jint jSection, jstring jKey, jstring jName, jobjectArray jValue) {
+    unsigned short* key    = getWideChars(jEnv, jKey);
+    unsigned short* name   = getWideChars(jEnv, jName);
+    DWORD size   = 0;
+    BYTE* data   = getByteFromMultiString(jEnv, jValue, &size);
+    
+    if (!setValue(getMode(jMode),getHKEY(jSection), key, name, REG_MULTI_SZ, data, size, 0)) {
+        throwException(jEnv, "Cannot set value");
+    }
+    
+    FREE(key);
+    FREE(name);
+    FREE(data);
+}
+
+JNIEXPORT jbyteArray JNICALL Java_org_netbeans_installer_utils_system_windows_WindowsRegistry_getBinaryValue0(JNIEnv *jEnv, jobject jObject, jint jMode, jint jSection, jstring jKey, jstring jName) {
+    HKEY  hkey   = 0;
+    unsigned short* key   = getWideChars(jEnv, jKey);
+    unsigned short* value = getWideChars(jEnv, jName);
+    
+    jbyteArray result = NULL;
+    if (RegOpenKeyExW(getHKEY(jSection), key, 0, KEY_QUERY_VALUE | getMode(jMode), &hkey) == ERROR_SUCCESS) {
+        DWORD dwType  = 0;
+        DWORD dwValue = 0;
+        DWORD size    = 0;
+        BYTE* data    = NULL;
+        
+        if (RegQueryValueExW(hkey, value, NULL, &dwType, NULL, &size) == ERROR_SUCCESS) {
+            if (dwType == REG_BINARY || dwType == REG_NONE) {
+                data = (BYTE*) LocalAlloc(LPTR, size + 8);
+                if (RegQueryValueExW(hkey, value, NULL, &dwType, (BYTE*) data, &size) == ERROR_SUCCESS) {
+                    if (data != NULL) {
+                        result = (*jEnv)->NewByteArray(jEnv, (jsize) size);
+                        (*jEnv)->SetByteArrayRegion(jEnv, result, 0, (jsize) size, (jbyte*) data);
+                    }
+                } else {
+                    throwException(jEnv, "Could not read key data");
+                }
+                FREE(data);
+            } else {
+                throwException(jEnv, "Value is of wrong type");
+            }
+        } else {
+            throwException(jEnv, "Could not read key data");
+        }
+    } else {
+        throwException(jEnv, "Could not open key");
+    }
+    
+    if (hkey != 0) {
+        RegCloseKey(hkey);
+    }
+    
+    FREE(key);
+    FREE(value);
+    
+    return result;
+}
+
+JNIEXPORT void JNICALL Java_org_netbeans_installer_utils_system_windows_WindowsRegistry_setBinaryValue0(JNIEnv *jEnv, jobject jObject, jint jMode, jint jSection, jstring jKey, jstring jName, jbyteArray jValue) {
+    unsigned short*  key     = getWideChars(jEnv, jKey);
+    unsigned short*  name    = getWideChars(jEnv, jName);
+    BYTE*  data    = (BYTE*) (*jEnv)->GetByteArrayElements(jEnv, jValue, 0);
+    DWORD  length  = (*jEnv)->GetArrayLength(jEnv, jValue);
+    
+    if (!setValue(getMode(jMode),getHKEY(jSection), key, name, REG_BINARY, data, length, 0)) {
+        throwException(jEnv, "Cannot set value");
+    }
+    
+    FREE(key);
+    FREE(name);
+    if (data != NULL) {
+        (*jEnv)->ReleaseByteArrayElements(jEnv, jValue, (jbyte*) data, JNI_ABORT);
+    }
+}
+
+JNIEXPORT void JNICALL Java_org_netbeans_installer_utils_system_windows_WindowsRegistry_setNoneValue0(JNIEnv *jEnv, jobject jobj, jint jMode, jint jSection, jstring jKey, jstring jName, jbyteArray jValue) {
+    unsigned short*  key     = getWideChars(jEnv, jKey);
+    unsigned short*  name    = getWideChars(jEnv, jName);
+    BYTE*  data    = (BYTE*) (*jEnv)->GetByteArrayElements(jEnv, jValue, 0);
+    DWORD  length  = (*jEnv)->GetArrayLength(jEnv, jValue);
+    
+    if (!setValue(getMode(jMode),getHKEY(jSection), key, name, REG_NONE, data, length, 0)) {
+        throwException(jEnv, "Cannot set value");
+    }
+    
+    FREE(key);
+    FREE(name);
+    if (data != NULL) {
+        (*jEnv)->ReleaseByteArrayElements(jEnv, jValue, (jbyte*) data, JNI_ABORT);
+    }
+}
+
+JNIEXPORT jboolean JNICALL Java_org_netbeans_installer_utils_system_windows_WindowsRegistry_IsWow64Process0(JNIEnv *jEnv, jobject jObject) {
+    typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
+    LPFN_ISWOW64PROCESS fnIsWow64Process;
+    BOOL IsWow64 = FALSE;
+
+    fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(GetModuleHandle(TEXT("kernel32")),"IsWow64Process");
+  
+    if (NULL != fnIsWow64Process)
+    {
+        if (!fnIsWow64Process(GetCurrentProcess(),&IsWow64))
+        {
+        }
+    }
+    return IsWow64;
+}
diff --git a/src/main/cpp/jnilib/windows/src/jni_WindowsRegistry.h b/src/main/cpp/jnilib/windows/src/jni_WindowsRegistry.h
new file mode 100644
index 0000000..1bf9add
--- /dev/null
+++ b/src/main/cpp/jnilib/windows/src/jni_WindowsRegistry.h
@@ -0,0 +1,266 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <jni.h>
+/* Header for class org_netbeans_installer_utils_system_windows_WindowsRegistry */
+
+#ifndef _Included_org_netbeans_installer_utils_system_windows_WindowsRegistry
+#define _Included_org_netbeans_installer_utils_system_windows_WindowsRegistry
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef org_netbeans_installer_utils_system_windows_WindowsRegistry_HKEY_CLASSES_ROOT
+#define org_netbeans_installer_utils_system_windows_WindowsRegistry_HKEY_CLASSES_ROOT 0L
+#undef org_netbeans_installer_utils_system_windows_WindowsRegistry_HKEY_CURRENT_USER
+#define org_netbeans_installer_utils_system_windows_WindowsRegistry_HKEY_CURRENT_USER 1L
+#undef org_netbeans_installer_utils_system_windows_WindowsRegistry_HKEY_LOCAL_MACHINE
+#define org_netbeans_installer_utils_system_windows_WindowsRegistry_HKEY_LOCAL_MACHINE 2L
+#undef org_netbeans_installer_utils_system_windows_WindowsRegistry_HKEY_USERS
+#define org_netbeans_installer_utils_system_windows_WindowsRegistry_HKEY_USERS 3L
+#undef org_netbeans_installer_utils_system_windows_WindowsRegistry_HKEY_CURRENT_CONFIG
+#define org_netbeans_installer_utils_system_windows_WindowsRegistry_HKEY_CURRENT_CONFIG 4L
+#undef org_netbeans_installer_utils_system_windows_WindowsRegistry_HKEY_DYN_DATA
+#define org_netbeans_installer_utils_system_windows_WindowsRegistry_HKEY_DYN_DATA 5L
+#undef org_netbeans_installer_utils_system_windows_WindowsRegistry_HKEY_PERFORMANCE_DATA
+#define org_netbeans_installer_utils_system_windows_WindowsRegistry_HKEY_PERFORMANCE_DATA 6L
+#undef org_netbeans_installer_utils_system_windows_WindowsRegistry_HKEY_PERFORMANCE_NLSTEXT
+#define org_netbeans_installer_utils_system_windows_WindowsRegistry_HKEY_PERFORMANCE_NLSTEXT 7L
+#undef org_netbeans_installer_utils_system_windows_WindowsRegistry_HKEY_PERFORMANCE_TEXT
+#define org_netbeans_installer_utils_system_windows_WindowsRegistry_HKEY_PERFORMANCE_TEXT 8L
+#undef org_netbeans_installer_utils_system_windows_WindowsRegistry_HKCR
+#define org_netbeans_installer_utils_system_windows_WindowsRegistry_HKCR 0L
+#undef org_netbeans_installer_utils_system_windows_WindowsRegistry_HKCU
+#define org_netbeans_installer_utils_system_windows_WindowsRegistry_HKCU 1L
+#undef org_netbeans_installer_utils_system_windows_WindowsRegistry_HKLM
+#define org_netbeans_installer_utils_system_windows_WindowsRegistry_HKLM 2L
+#undef org_netbeans_installer_utils_system_windows_WindowsRegistry_REG_NONE
+#define org_netbeans_installer_utils_system_windows_WindowsRegistry_REG_NONE 0L
+#undef org_netbeans_installer_utils_system_windows_WindowsRegistry_REG_SZ
+#define org_netbeans_installer_utils_system_windows_WindowsRegistry_REG_SZ 1L
+#undef org_netbeans_installer_utils_system_windows_WindowsRegistry_REG_EXPAND_SZ
+#define org_netbeans_installer_utils_system_windows_WindowsRegistry_REG_EXPAND_SZ 2L
+#undef org_netbeans_installer_utils_system_windows_WindowsRegistry_REG_BINARY
+#define org_netbeans_installer_utils_system_windows_WindowsRegistry_REG_BINARY 3L
+#undef org_netbeans_installer_utils_system_windows_WindowsRegistry_REG_DWORD_LITTLE_ENDIAN
+#define org_netbeans_installer_utils_system_windows_WindowsRegistry_REG_DWORD_LITTLE_ENDIAN 4L
+#undef org_netbeans_installer_utils_system_windows_WindowsRegistry_REG_DWORD
+#define org_netbeans_installer_utils_system_windows_WindowsRegistry_REG_DWORD 4L
+#undef org_netbeans_installer_utils_system_windows_WindowsRegistry_REG_DWORD_BIG_ENDIAN
+#define org_netbeans_installer_utils_system_windows_WindowsRegistry_REG_DWORD_BIG_ENDIAN 5L
+#undef org_netbeans_installer_utils_system_windows_WindowsRegistry_REG_LINK
+#define org_netbeans_installer_utils_system_windows_WindowsRegistry_REG_LINK 6L
+#undef org_netbeans_installer_utils_system_windows_WindowsRegistry_REG_MULTI_SZ
+#define org_netbeans_installer_utils_system_windows_WindowsRegistry_REG_MULTI_SZ 7L
+#undef org_netbeans_installer_utils_system_windows_WindowsRegistry_REG_RESOURCE_LIST
+#define org_netbeans_installer_utils_system_windows_WindowsRegistry_REG_RESOURCE_LIST 8L
+#undef org_netbeans_installer_utils_system_windows_WindowsRegistry_REG_FULL_RESOURCE_DESCRIPTOR
+#define org_netbeans_installer_utils_system_windows_WindowsRegistry_REG_FULL_RESOURCE_DESCRIPTOR 9L
+#undef org_netbeans_installer_utils_system_windows_WindowsRegistry_REG_RESOURCE_REQUIREMENTS_LIST
+#define org_netbeans_installer_utils_system_windows_WindowsRegistry_REG_RESOURCE_REQUIREMENTS_LIST 10L
+#undef org_netbeans_installer_utils_system_windows_WindowsRegistry_REG_QWORD_LITTLE_ENDIAN
+#define org_netbeans_installer_utils_system_windows_WindowsRegistry_REG_QWORD_LITTLE_ENDIAN 11L
+#undef org_netbeans_installer_utils_system_windows_WindowsRegistry_REG_QWORD
+#define org_netbeans_installer_utils_system_windows_WindowsRegistry_REG_QWORD 11L
+#undef org_netbeans_installer_utils_system_windows_WindowsRegistry_MODE_DEFAULT
+#define org_netbeans_installer_utils_system_windows_WindowsRegistry_MODE_DEFAULT 0L
+#undef org_netbeans_installer_utils_system_windows_WindowsRegistry_MODE_32BIT
+#define org_netbeans_installer_utils_system_windows_WindowsRegistry_MODE_32BIT 1L
+#undef org_netbeans_installer_utils_system_windows_WindowsRegistry_MODE_64BIT
+#define org_netbeans_installer_utils_system_windows_WindowsRegistry_MODE_64BIT 2L
+/*
+ * Class:     org_netbeans_installer_utils_system_windows_WindowsRegistry
+ * Method:    checkKeyAccess0
+ * Signature: (IILjava/lang/String;I;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_org_netbeans_installer_utils_system_windows_WindowsRegistry_checkKeyAccess0
+  (JNIEnv *, jobject, jint, jint, jstring, jint);
+
+/*
+ * Class:     org_netbeans_installer_utils_system_windows_WindowsRegistry
+ * Method:    valueExists0
+ * Signature: (IILjava/lang/String;Ljava/lang/String;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_org_netbeans_installer_utils_system_windows_WindowsRegistry_valueExists0
+  (JNIEnv *, jobject, jint, jint, jstring, jstring);
+
+/*
+ * Class:     org_netbeans_installer_utils_system_windows_WindowsRegistry
+ * Method:    keyEmpty0
+ * Signature: (IILjava/lang/String;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_org_netbeans_installer_utils_system_windows_WindowsRegistry_keyEmpty0
+  (JNIEnv *, jobject, jint, jint, jstring);
+
+/*
+ * Class:     org_netbeans_installer_utils_system_windows_WindowsRegistry
+ * Method:    countSubKeys0
+ * Signature: (IILjava/lang/String;)I
+ */
+JNIEXPORT jint JNICALL Java_org_netbeans_installer_utils_system_windows_WindowsRegistry_countSubKeys0
+  (JNIEnv *, jobject, jint, jint, jstring);
+
+/*
+ * Class:     org_netbeans_installer_utils_system_windows_WindowsRegistry
+ * Method:    countValues0
+ * Signature: (IILjava/lang/String;)I
+ */
+JNIEXPORT jint JNICALL Java_org_netbeans_installer_utils_system_windows_WindowsRegistry_countValues0
+  (JNIEnv *, jobject, jint, jint, jstring);
+
+/*
+ * Class:     org_netbeans_installer_utils_system_windows_WindowsRegistry
+ * Method:    getSubkeyNames0
+ * Signature: (IILjava/lang/String;)[Ljava/lang/String;
+ */
+JNIEXPORT jobjectArray JNICALL Java_org_netbeans_installer_utils_system_windows_WindowsRegistry_getSubkeyNames0
+  (JNIEnv *, jobject, jint, jint, jstring);
+
+/*
+ * Class:     org_netbeans_installer_utils_system_windows_WindowsRegistry
+ * Method:    getValueNames0
+ * Signature: (IILjava/lang/String;)[Ljava/lang/String;
+ */
+JNIEXPORT jobjectArray JNICALL Java_org_netbeans_installer_utils_system_windows_WindowsRegistry_getValueNames0
+  (JNIEnv *, jobject, jint, jint, jstring);
+
+/*
+ * Class:     org_netbeans_installer_utils_system_windows_WindowsRegistry
+ * Method:    getValueType0
+ * Signature: (IILjava/lang/String;Ljava/lang/String;)I
+ */
+JNIEXPORT jint JNICALL Java_org_netbeans_installer_utils_system_windows_WindowsRegistry_getValueType0
+  (JNIEnv *, jobject, jint, jint, jstring, jstring);
+
+/*
+ * Class:     org_netbeans_installer_utils_system_windows_WindowsRegistry
+ * Method:    createKey0
+ * Signature: (IILjava/lang/String;Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_org_netbeans_installer_utils_system_windows_WindowsRegistry_createKey0
+  (JNIEnv *, jobject, jint, jint, jstring, jstring);
+
+/*
+ * Class:     org_netbeans_installer_utils_system_windows_WindowsRegistry
+ * Method:    deleteKey0
+ * Signature: (IILjava/lang/String;Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_org_netbeans_installer_utils_system_windows_WindowsRegistry_deleteKey0
+  (JNIEnv *, jobject, jint, jint, jstring, jstring);
+
+/*
+ * Class:     org_netbeans_installer_utils_system_windows_WindowsRegistry
+ * Method:    deleteValue0
+ * Signature: (IILjava/lang/String;Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_org_netbeans_installer_utils_system_windows_WindowsRegistry_deleteValue0
+  (JNIEnv *, jobject, jint, jint, jstring, jstring);
+
+/*
+ * Class:     org_netbeans_installer_utils_system_windows_WindowsRegistry
+ * Method:    getStringValue0
+ * Signature: (IILjava/lang/String;Ljava/lang/String;Z)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_org_netbeans_installer_utils_system_windows_WindowsRegistry_getStringValue0
+  (JNIEnv *, jobject, jint, jint, jstring, jstring, jboolean);
+
+/*
+ * Class:     org_netbeans_installer_utils_system_windows_WindowsRegistry
+ * Method:    setStringValue0
+ * Signature: (IILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)V
+ */
+JNIEXPORT void JNICALL Java_org_netbeans_installer_utils_system_windows_WindowsRegistry_setStringValue0
+  (JNIEnv *, jobject, jint, jint, jstring, jstring, jstring, jboolean);
+
+/*
+ * Class:     org_netbeans_installer_utils_system_windows_WindowsRegistry
+ * Method:    get32BitValue0
+ * Signature: (IILjava/lang/String;Ljava/lang/String;)I
+ */
+JNIEXPORT jint JNICALL Java_org_netbeans_installer_utils_system_windows_WindowsRegistry_get32BitValue0
+  (JNIEnv *, jobject, jint, jint, jstring, jstring);
+
+/*
+ * Class:     org_netbeans_installer_utils_system_windows_WindowsRegistry
+ * Method:    set32BitValue0
+ * Signature: (IILjava/lang/String;Ljava/lang/String;I)V
+ */
+JNIEXPORT void JNICALL Java_org_netbeans_installer_utils_system_windows_WindowsRegistry_set32BitValue0
+  (JNIEnv *, jobject, jint, jint, jstring, jstring, jint);
+
+/*
+ * Class:     org_netbeans_installer_utils_system_windows_WindowsRegistry
+ * Method:    getMultiStringValue0
+ * Signature: (IILjava/lang/String;Ljava/lang/String;)[Ljava/lang/String;
+ */
+JNIEXPORT jobjectArray JNICALL Java_org_netbeans_installer_utils_system_windows_WindowsRegistry_getMultiStringValue0
+  (JNIEnv *, jobject, jint, jint, jstring, jstring);
+
+/*
+ * Class:     org_netbeans_installer_utils_system_windows_WindowsRegistry
+ * Method:    setMultiStringValue0
+ * Signature: (IILjava/lang/String;Ljava/lang/String;[Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_org_netbeans_installer_utils_system_windows_WindowsRegistry_setMultiStringValue0
+  (JNIEnv *, jobject, jint, jint, jstring, jstring, jobjectArray);
+
+/*
+ * Class:     org_netbeans_installer_utils_system_windows_WindowsRegistry
+ * Method:    getBinaryValue0
+ * Signature: (IILjava/lang/String;Ljava/lang/String;)[B
+ */
+JNIEXPORT jbyteArray JNICALL Java_org_netbeans_installer_utils_system_windows_WindowsRegistry_getBinaryValue0
+  (JNIEnv *, jobject, jint, jint, jstring, jstring);
+
+/*
+ * Class:     org_netbeans_installer_utils_system_windows_WindowsRegistry
+ * Method:    setBinaryValue0
+ * Signature: (IILjava/lang/String;Ljava/lang/String;[B)V
+ */
+JNIEXPORT void JNICALL Java_org_netbeans_installer_utils_system_windows_WindowsRegistry_setBinaryValue0
+  (JNIEnv *, jobject, jint, jint, jstring, jstring, jbyteArray);
+
+/*
+ * Class:     org_netbeans_installer_utils_system_windows_WindowsRegistry
+ * Method:    setNoneValue0
+ * Signature: (IILjava/lang/String;Ljava/lang/String;[B)V
+ */
+JNIEXPORT void JNICALL Java_org_netbeans_installer_utils_system_windows_WindowsRegistry_setNoneValue0
+  (JNIEnv *, jobject, jint, jint, jstring, jstring, jbyteArray);
+
+/*
+ * Class:     org_netbeans_installer_utils_system_windows_WindowsRegistry
+ * Method:    IsWow64Process0
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_org_netbeans_installer_utils_system_windows_WindowsRegistry_IsWow64Process0
+  (JNIEnv *, jobject);
+
+
+#ifndef KEY_WOW64_32KEY
+#define KEY_WOW64_32KEY 0x0200
+#endif
+#ifndef KEY_WOW64_64KEY
+#define KEY_WOW64_64KEY 0x0100
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/main/cpp/jnilib/windows/vcproject/NBI JNI Library.ncb b/src/main/cpp/jnilib/windows/vcproject/NBI JNI Library.ncb
new file mode 100644
index 0000000..9057eba
--- /dev/null
+++ b/src/main/cpp/jnilib/windows/vcproject/NBI JNI Library.ncb
@@ -0,0 +1 @@
+Microsoft C/C++ MSF 7.00
diff --git a/src/main/cpp/jnilib/windows/vcproject/NBI JNI Library.sln b/src/main/cpp/jnilib/windows/vcproject/NBI JNI Library.sln
new file mode 100644
index 0000000..4410e6f
--- /dev/null
+++ b/src/main/cpp/jnilib/windows/vcproject/NBI JNI Library.sln
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual C++ Express 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NBI JNI Library", "NBI JNI Library.vcproj", "{AF9FBB45-6887-41CE-8DC2-915C5FB2AD45}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Default-32bit|Windows = Default-32bit|Windows
+		Default-64bit|Windows = Default-64bit|Windows
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{AF9FBB45-6887-41CE-8DC2-915C5FB2AD45}.Default-32bit|Windows.ActiveCfg = Default-32bit|Win32
+		{AF9FBB45-6887-41CE-8DC2-915C5FB2AD45}.Default-32bit|Windows.Build.0 = Default-32bit|Win32
+		{AF9FBB45-6887-41CE-8DC2-915C5FB2AD45}.Default-64bit|Windows.ActiveCfg = Default-32bit|Win32
+		{AF9FBB45-6887-41CE-8DC2-915C5FB2AD45}.Default-64bit|Windows.Build.0 = Default-32bit|Win32
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/src/main/cpp/jnilib/windows/vcproject/NBI JNI Library.suo b/src/main/cpp/jnilib/windows/vcproject/NBI JNI Library.suo
new file mode 100644
index 0000000..8a45057
--- /dev/null
+++ b/src/main/cpp/jnilib/windows/vcproject/NBI JNI Library.suo
Binary files differ
diff --git a/src/main/cpp/jnilib/windows/vcproject/NBI JNI Library.vcproj b/src/main/cpp/jnilib/windows/vcproject/NBI JNI Library.vcproj
new file mode 100644
index 0000000..4cbd1b7
--- /dev/null
+++ b/src/main/cpp/jnilib/windows/vcproject/NBI JNI Library.vcproj
@@ -0,0 +1,261 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8,00"
+	Name="NBI JNI Library"
+	ProjectGUID="{AF9FBB45-6887-41CE-8DC2-915C5FB2AD45}"
+	RootNamespace="NBI JNI Library"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Default-32bit|Win32"
+			OutputDirectory="Default-32bit"
+			IntermediateDirectory="Default-32bit"
+			ConfigurationType="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				UseUnicodeResponseFiles="true"
+				Optimization="1"
+				FavorSizeOrSpeed="2"
+				AdditionalIncludeDirectories="&quot;C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Include&quot;;&quot;C:\Program Files\Java\jdk1.5.0_11\include&quot;;&quot;C:\Program Files\Java\jdk1.5.0_11\include\win32&quot;"
+				PreprocessorDefinitions="WIN32;_WINDOWS;_USRDLL;NBIJNILIBRARY_EXPORTS;_CRT_SECURE_NO_DEPRECATE;_STATIC_CPPLIB;_LITTLE_ENDIAN"
+				MinimalRebuild="false"
+				ExceptionHandling="0"
+				BasicRuntimeChecks="0"
+				RuntimeLibrary="0"
+				DisableLanguageExtensions="false"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				WarnAsError="true"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="0"
+				CallingConvention="0"
+				CompileAs="1"
+				ShowIncludes="false"
+				OmitDefaultLibName="false"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				LinkLibraryDependencies="false"
+				UseLibraryDependencyInputs="false"
+				ShowProgress="1"
+				OutputFile="..\dist\windows-x86.dll"
+				LinkIncremental="1"
+				AdditionalLibraryDirectories="&quot;C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Lib&quot;"
+				GenerateManifest="false"
+				IgnoreEmbeddedIDL="true"
+				GenerateDebugInformation="false"
+				SubSystem="2"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Default-64bit|Win32"
+			OutputDirectory="$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)"
+			ConfigurationType="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				UseUnicodeResponseFiles="true"
+				Optimization="1"
+				FavorSizeOrSpeed="2"
+				AdditionalIncludeDirectories="&quot;C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Include&quot;;&quot;C:\Program Files\Java\jdk1.5.0_11\include&quot;;&quot;C:\Program Files\Java\jdk1.5.0_11\include\win32&quot;"
+				PreprocessorDefinitions="WIN32;_WINDOWS;_USRDLL;NBIJNILIBRARY_EXPORTS;_CRT_SECURE_NO_DEPRECATE;_STATIC_CPPLIB;_LITTLE_ENDIAN"
+				MinimalRebuild="false"
+				ExceptionHandling="0"
+				BasicRuntimeChecks="0"
+				RuntimeLibrary="0"
+				DisableLanguageExtensions="false"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				WarnAsError="true"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="0"
+				CallingConvention="0"
+				CompileAs="1"
+				ShowIncludes="false"
+				OmitDefaultLibName="false"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				LinkLibraryDependencies="false"
+				UseLibraryDependencyInputs="false"
+				ShowProgress="0"
+				OutputFile="..\dist\windows-x64.dll"
+				LinkIncremental="1"
+				AdditionalLibraryDirectories="&quot;C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Lib&quot;"
+				GenerateManifest="false"
+				IgnoreEmbeddedIDL="true"
+				GenerateDebugInformation="false"
+				SubSystem="2"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="17"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+			>
+			<File
+				RelativePath="..\..\.common\src\CommonUtils.h"
+				>
+			</File>
+			<File
+				RelativePath="..\src\jni_WindowsNativeUtils.h"
+				>
+			</File>
+			<File
+				RelativePath="..\src\jni_WindowsRegistry.h"
+				>
+			</File>
+			<File
+				RelativePath="..\src\WindowsUtils.h"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Resource Files"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+			>
+		</Filter>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath="..\..\.common\src\CommonUtils.c"
+				>
+			</File>
+			<File
+				RelativePath="..\src\jni_WindowsNativeUtils.c"
+				>
+			</File>
+			<File
+				RelativePath="..\src\jni_WindowsRegistry.c"
+				>
+			</File>
+			<File
+				RelativePath="..\src\WindowsUtils.c"
+				>
+			</File>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
diff --git a/src/main/cpp/jnilib/windows/vcproject/NBI JNI Library.vcproj.user b/src/main/cpp/jnilib/windows/vcproject/NBI JNI Library.vcproj.user
new file mode 100644
index 0000000..a5ca4f9
--- /dev/null
+++ b/src/main/cpp/jnilib/windows/vcproject/NBI JNI Library.vcproj.user
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="utf-8"?><VisualStudioUserFile ProjectType="Visual C++" Version="8.00" ShowAllFiles="true"></VisualStudioUserFile>
\ No newline at end of file
diff --git a/src/main/cpp/jnilib/windows/vcproject/vc80.idb b/src/main/cpp/jnilib/windows/vcproject/vc80.idb
new file mode 100644
index 0000000..3169052
--- /dev/null
+++ b/src/main/cpp/jnilib/windows/vcproject/vc80.idb
Binary files differ
diff --git a/src/main/cpp/launcher/unix/i18n/launcher.properties b/src/main/cpp/launcher/unix/i18n/launcher.properties
new file mode 100644
index 0000000..73e6c6e
--- /dev/null
+++ b/src/main/cpp/launcher/unix/i18n/launcher.properties
@@ -0,0 +1,51 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# 
+
+nlu.jvm.notfoundmessage=Java SE Development Kit (JDK) was not found on this computer\nJDK 8 is required for installing the NetBeans IDE. Make sure that the JDK is properly installed and run installer again.\nYou can specify valid JDK location using {0} installer argument.\n\nTo download the JDK, visit http://www.oracle.com/technetwork/java/javase/downloads
+nlu.jvm.usererror=Java Runtime Environment (JRE) was not found at the specified location {0}
+nlu.jvm.uncompatible=Unsupported JVM version at {0}.\nTry to specify another JVM location using parameter {1}
+nlu.freespace=There is not enough free disk space to extract installation data\n{0} MB of free disk space is required in a temporary folder.\nClean up the disk space and run installer again. You can specify a temporary folder with sufficient disk space using {1} installer argument
+nlu.integrity=\nInstaller file {0} seems to be corrupted
+nlu.missing.external.resource=Can`t run NetBeans Installer.\nAn external file with necessary data is required but missing:\n{0}
+nlu.cannot.create.tmpdir=Cannot create temporary directory {0}
+nlu.cannot.extract.bundled.jvm=Cannot prepare bundled JVM to run the installer.\nMost probably the bundled JVM is not compatible with the current platform.\nSee FAQ at http://wiki.netbeans.org/FaqUnableToPrepareBundledJdk for more information.
+nlu.cannot.unpack.jvm.file=Cannot unpack file {0}
+nlu.error.verify.bundled.jvm=Cannot verify bundled JVM, try to search JVM on the system
+
+nlu.running=Running the installer wizard...
+nlu.starting=Configuring the installer...
+nlu.extracting=Extracting installation data...
+nlu.prepare.jvm=Preparing bundled JVM ...
+nlu.jvm.search=Searching for JVM on the system...
+
+nlu.msg.usage=\nUsage:
+nlu.arg.javahome=\t{0}\t<dir>\tUsing java from <dir> for running application
+nlu.arg.verbose=\t{0}\t\tUse verbose output
+nlu.arg.output=\t{0}\t<out>\tRedirect all output to file <out>
+nlu.arg.disable.space.check=\t{0}\t\tDisable free space check
+nlu.arg.extract=\t{0}\t[dir]\tExtract all bundled data to <dir>.\n\t\t\t\tIf <dir> is not specified then extract to the current directory
+nlu.arg.tempdir=\t{0}\t<dir>\tUse <dir> for extracting temporary data
+nlu.arg.cpa=\t{0} <cp>\tAppend classpath with <cp>
+nlu.arg.cpp=\t{0} <cp>\tPrepend classpath with <cp>
+nlu.arg.locale=\t{0}\t<locale>\tOverride default locale with specified <locale>
+nlu.arg.silent=\t{0}\t\tRun installer silently
+nlu.arg.help=\t{0}\t\tShow this help
+
+
+nlu.java.application.name.macosx=NetBeans IDE Installer
diff --git a/src/main/cpp/launcher/unix/src/launcher.sh b/src/main/cpp/launcher/unix/src/launcher.sh
new file mode 100644
index 0000000..5a6fc13
--- /dev/null
+++ b/src/main/cpp/launcher/unix/src/launcher.sh
@@ -0,0 +1,1665 @@
+#!/bin/sh
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# 
+
+ARG_JAVAHOME="--javahome"
+ARG_VERBOSE="--verbose"
+ARG_OUTPUT="--output"
+ARG_EXTRACT="--extract"
+ARG_JAVA_ARG_PREFIX="-J"
+ARG_TEMPDIR="--tempdir"
+ARG_CLASSPATHA="--classpath-append"
+ARG_CLASSPATHP="--classpath-prepend"
+ARG_HELP="--help"
+ARG_SILENT="--silent"
+ARG_NOSPACECHECK="--nospacecheck"
+ARG_LOCALE="--locale"
+
+USE_DEBUG_OUTPUT=0
+PERFORM_FREE_SPACE_CHECK=1
+SILENT_MODE=0
+EXTRACT_ONLY=0
+SHOW_HELP_ONLY=0
+LOCAL_OVERRIDDEN=0
+APPEND_CP=
+PREPEND_CP=
+LAUNCHER_APP_ARGUMENTS=
+LAUNCHER_JVM_ARGUMENTS=
+ERROR_OK=0
+ERROR_TEMP_DIRECTORY=2
+ERROR_TEST_JVM_FILE=3
+ERROR_JVM_NOT_FOUND=4
+ERROR_JVM_UNCOMPATIBLE=5
+ERROR_EXTRACT_ONLY=6
+ERROR_INPUTOUPUT=7
+ERROR_FREESPACE=8
+ERROR_INTEGRITY=9
+ERROR_MISSING_RESOURCES=10
+ERROR_JVM_EXTRACTION=11
+ERROR_JVM_UNPACKING=12
+ERROR_VERIFY_BUNDLED_JVM=13
+
+VERIFY_OK=1
+VERIFY_NOJAVA=2
+VERIFY_UNCOMPATIBLE=3
+
+MSG_ERROR_JVM_NOT_FOUND="nlu.jvm.notfoundmessage"
+MSG_ERROR_USER_ERROR="nlu.jvm.usererror"
+MSG_ERROR_JVM_UNCOMPATIBLE="nlu.jvm.uncompatible"
+MSG_ERROR_INTEGRITY="nlu.integrity"
+MSG_ERROR_FREESPACE="nlu.freespace"
+MSG_ERROP_MISSING_RESOURCE="nlu.missing.external.resource"
+MSG_ERROR_TMPDIR="nlu.cannot.create.tmpdir"
+
+MSG_ERROR_EXTRACT_JVM="nlu.cannot.extract.bundled.jvm"
+MSG_ERROR_UNPACK_JVM_FILE="nlu.cannot.unpack.jvm.file"
+MSG_ERROR_VERIFY_BUNDLED_JVM="nlu.error.verify.bundled.jvm"
+
+MSG_RUNNING="nlu.running"
+MSG_STARTING="nlu.starting"
+MSG_EXTRACTING="nlu.extracting"
+MSG_PREPARE_JVM="nlu.prepare.jvm"
+MSG_JVM_SEARCH="nlu.jvm.search"
+MSG_ARG_JAVAHOME="nlu.arg.javahome"
+MSG_ARG_VERBOSE="nlu.arg.verbose"
+MSG_ARG_OUTPUT="nlu.arg.output"
+MSG_ARG_EXTRACT="nlu.arg.extract"
+MSG_ARG_TEMPDIR="nlu.arg.tempdir"
+MSG_ARG_CPA="nlu.arg.cpa"
+MSG_ARG_CPP="nlu.arg.cpp"
+MSG_ARG_DISABLE_FREE_SPACE_CHECK="nlu.arg.disable.space.check"
+MSG_ARG_LOCALE="nlu.arg.locale"
+MSG_ARG_SILENT="nlu.arg.silent"
+MSG_ARG_HELP="nlu.arg.help"
+MSG_USAGE="nlu.msg.usage"
+
+isSymlink=
+
+entryPoint() {
+        initSymlinkArgument        
+	CURRENT_DIRECTORY=`pwd`
+	LAUNCHER_NAME=`echo $0`
+	parseCommandLineArguments "$@"
+	initializeVariables            
+	setLauncherLocale	
+	debugLauncherArguments "$@"
+	if [ 1 -eq $SHOW_HELP_ONLY ] ; then
+		showHelp
+	fi
+	
+        message "$MSG_STARTING"
+        createTempDirectory
+	checkFreeSpace "$TOTAL_BUNDLED_FILES_SIZE" "$LAUNCHER_EXTRACT_DIR"	
+
+        extractJVMData
+	if [ 0 -eq $EXTRACT_ONLY ] ; then 
+            searchJava
+	fi
+
+	extractBundledData
+	verifyIntegrity
+
+	if [ 0 -eq $EXTRACT_ONLY ] ; then 
+	    executeMainClass
+	else 
+	    exitProgram $ERROR_OK
+	fi
+}
+
+initSymlinkArgument() {
+        testSymlinkErr=`test -L / 2>&1 > /dev/null`
+        if [ -z "$testSymlinkErr" ] ; then
+            isSymlink=-L
+        else
+            isSymlink=-h
+        fi
+}
+
+debugLauncherArguments() {
+	debug "Launcher Command : $0"
+	argCounter=1
+        while [ $# != 0 ] ; do
+		debug "... argument [$argCounter] = $1"
+		argCounter=`expr "$argCounter" + 1`
+		shift
+	done
+}
+isLauncherCommandArgument() {
+	case "$1" in
+	    $ARG_VERBOSE | $ARG_NOSPACECHECK | $ARG_OUTPUT | $ARG_HELP | $ARG_JAVAHOME | $ARG_TEMPDIR | $ARG_EXTRACT | $ARG_SILENT | $ARG_LOCALE | $ARG_CLASSPATHP | $ARG_CLASSPATHA)
+	    	echo 1
+		;;
+	    *)
+		echo 0
+		;;
+	esac
+}
+
+parseCommandLineArguments() {
+	while [ $# != 0 ]
+	do
+		case "$1" in
+		$ARG_VERBOSE)
+                        USE_DEBUG_OUTPUT=1;;
+		$ARG_NOSPACECHECK)
+                        PERFORM_FREE_SPACE_CHECK=0
+                        parseJvmAppArgument "$1"
+                        ;;
+                $ARG_OUTPUT)
+			if [ -n "$2" ] ; then
+                        	OUTPUT_FILE="$2"
+				if [ -f "$OUTPUT_FILE" ] ; then
+					# clear output file first
+					rm -f "$OUTPUT_FILE" > /dev/null 2>&1
+					touch "$OUTPUT_FILE"
+				fi
+                        	shift
+			fi
+			;;
+		$ARG_HELP)
+			SHOW_HELP_ONLY=1
+			;;
+		$ARG_JAVAHOME)
+			if [ -n "$2" ] ; then
+				LAUNCHER_JAVA="$2"
+				shift
+			fi
+			;;
+		$ARG_TEMPDIR)
+			if [ -n "$2" ] ; then
+				LAUNCHER_JVM_TEMP_DIR="$2"
+				shift
+			fi
+			;;
+		$ARG_EXTRACT)
+			EXTRACT_ONLY=1
+			if [ -n "$2" ] && [ `isLauncherCommandArgument "$2"` -eq 0 ] ; then
+				LAUNCHER_EXTRACT_DIR="$2"
+				shift
+			else
+				LAUNCHER_EXTRACT_DIR="$CURRENT_DIRECTORY"				
+			fi
+			;;
+		$ARG_SILENT)
+			SILENT_MODE=1
+			parseJvmAppArgument "$1"
+			;;
+		$ARG_LOCALE)
+			SYSTEM_LOCALE="$2"
+			LOCAL_OVERRIDDEN=1			
+			parseJvmAppArgument "$1"
+			;;
+		$ARG_CLASSPATHP)
+			if [ -n "$2" ] ; then
+				if [ -z "$PREPEND_CP" ] ; then
+					PREPEND_CP="$2"
+				else
+					PREPEND_CP="$2":"$PREPEND_CP"
+				fi
+				shift
+			fi
+			;;
+		$ARG_CLASSPATHA)
+			if [ -n "$2" ] ; then
+				if [ -z "$APPEND_CP" ] ; then
+					APPEND_CP="$2"
+				else
+					APPEND_CP="$APPEND_CP":"$2"
+				fi
+				shift
+			fi
+			;;
+
+		*)
+			parseJvmAppArgument "$1"
+		esac
+                shift
+	done
+}
+
+setLauncherLocale() {
+	if [ 0 -eq $LOCAL_OVERRIDDEN ] ; then		
+        	SYSTEM_LOCALE="$LANG"
+		debug "Setting initial launcher locale from the system : $SYSTEM_LOCALE"
+	else	
+		debug "Setting initial launcher locale using command-line argument : $SYSTEM_LOCALE"
+	fi
+
+	LAUNCHER_LOCALE="$SYSTEM_LOCALE"
+	
+	if [ -n "$LAUNCHER_LOCALE" ] ; then
+		# check if $LAUNCHER_LOCALE is in UTF-8
+		if [ 0 -eq $LOCAL_OVERRIDDEN ] ; then
+			removeUTFsuffix=`echo "$LAUNCHER_LOCALE" | sed "s/\.UTF-8//"`
+			isUTF=`ifEquals "$removeUTFsuffix" "$LAUNCHER_LOCALE"`
+			if [ 1 -eq $isUTF ] ; then
+				#set launcher locale to the default if the system locale name doesn`t containt  UTF-8
+				LAUNCHER_LOCALE=""
+			fi
+		fi
+
+        	localeChanged=0	
+		localeCounter=0
+		while [ $localeCounter -lt $LAUNCHER_LOCALES_NUMBER ] ; do		
+		    localeVar="$""LAUNCHER_LOCALE_NAME_$localeCounter"
+		    arg=`eval "echo \"$localeVar\""`		
+                    if [ -n "$arg" ] ; then 
+                        # if not a default locale			
+			# $comp length shows the difference between $SYSTEM_LOCALE and $arg
+  			# the less the length the less the difference and more coincedence
+
+                        comp=`echo "$SYSTEM_LOCALE" | sed -e "s/^${arg}//"`				
+			length1=`getStringLength "$comp"`
+                        length2=`getStringLength "$LAUNCHER_LOCALE"`
+                        if [ $length1 -lt $length2 ] ; then	
+				# more coincidence between $SYSTEM_LOCALE and $arg than between $SYSTEM_LOCALE and $arg
+                                compare=`ifLess "$comp" "$LAUNCHER_LOCALE"`
+				
+                                if [ 1 -eq $compare ] ; then
+                                        LAUNCHER_LOCALE="$arg"
+                                        localeChanged=1
+                                        debug "... setting locale to $arg"
+                                fi
+                                if [ -z "$comp" ] ; then
+					# means that $SYSTEM_LOCALE equals to $arg
+                                        break
+                                fi
+                        fi   
+                    else 
+                        comp="$SYSTEM_LOCALE"
+                    fi
+		    localeCounter=`expr "$localeCounter" + 1`
+       		done
+		if [ $localeChanged -eq 0 ] ; then 
+                	#set default
+                	LAUNCHER_LOCALE=""
+        	fi
+        fi
+
+        
+        debug "Final Launcher Locale : $LAUNCHER_LOCALE"	
+}
+
+escapeBackslash() {
+	echo "$1" | sed "s/\\\/\\\\\\\/g"
+}
+
+ifLess() {
+	arg1=`escapeBackslash "$1"`
+	arg2=`escapeBackslash "$2"`
+	compare=`awk 'END { if ( a < b ) { print 1 } else { print 0 } }' a="$arg1" b="$arg2" < /dev/null`
+	echo $compare
+}
+
+formatVersion() {
+        formatted=`echo "$1" | sed "s/-ea//g;s/-rc[0-9]*//g;s/-beta[0-9]*//g;s/-preview[0-9]*//g;s/-dp[0-9]*//g;s/-alpha[0-9]*//g;s/-fcs//g;s/_/./g;s/-/\./g"`
+        formatted=`echo "$formatted" | sed "s/^\(\([0-9][0-9]*\)\.\([0-9][0-9]*\)\.\([0-9][0-9]*\)\)\.b\([0-9][0-9]*\)/\1\.0\.\5/g"`
+        formatted=`echo "$formatted" | sed "s/\.b\([0-9][0-9]*\)/\.\1/g"`
+	echo "$formatted"
+
+}
+
+compareVersions() {
+        current1=`formatVersion "$1"`
+        current2=`formatVersion "$2"`
+	compresult=
+	#0 - equals
+	#-1 - less
+	#1 - more
+
+	while [ -z "$compresult" ] ; do
+		value1=`echo "$current1" | sed "s/\..*//g"`
+		value2=`echo "$current2" | sed "s/\..*//g"`
+
+
+		removeDots1=`echo "$current1" | sed "s/\.//g"`
+		removeDots2=`echo "$current2" | sed "s/\.//g"`
+
+		if [ 1 -eq `ifEquals "$current1" "$removeDots1"` ] ; then
+			remainder1=""
+		else
+			remainder1=`echo "$current1" | sed "s/^$value1\.//g"`
+		fi
+		if [ 1 -eq `ifEquals "$current2" "$removeDots2"` ] ; then
+			remainder2=""
+		else
+			remainder2=`echo "$current2" | sed "s/^$value2\.//g"`
+		fi
+
+		current1="$remainder1"
+		current2="$remainder2"
+		
+		if [ -z "$value1" ] || [ 0 -eq `ifNumber "$value1"` ] ; then 
+			value1=0 
+		fi
+		if [ -z "$value2" ] || [ 0 -eq `ifNumber "$value2"` ] ; then 
+			value2=0 
+		fi
+		if [ "$value1" -gt "$value2" ] ; then 
+			compresult=1
+			break
+		elif [ "$value2" -gt "$value1" ] ; then 
+			compresult=-1
+			break
+		fi
+
+		if [ -z "$current1" ] && [ -z "$current2" ] ; then	
+			compresult=0
+			break
+		fi
+	done
+	echo $compresult
+}
+
+ifVersionLess() {
+	compareResult=`compareVersions "$1" "$2"`
+        if [ -1 -eq $compareResult ] ; then
+            echo 1
+        else
+            echo 0
+        fi
+}
+
+ifVersionGreater() {
+	compareResult=`compareVersions "$1" "$2"`
+        if [ 1 -eq $compareResult ] ; then
+            echo 1
+        else
+            echo 0
+        fi
+}
+
+ifGreater() {
+	arg1=`escapeBackslash "$1"`
+	arg2=`escapeBackslash "$2"`
+
+	compare=`awk 'END { if ( a > b ) { print 1 } else { print 0 } }' a="$arg1" b="$arg2" < /dev/null`
+	echo $compare
+}
+
+ifEquals() {
+	arg1=`escapeBackslash "$1"`
+	arg2=`escapeBackslash "$2"`
+
+	compare=`awk 'END { if ( a == b ) { print 1 } else { print 0 } }' a="$arg1" b="$arg2" < /dev/null`
+	echo $compare
+}
+
+ifNumber() 
+{
+	result=0
+	if  [ -n "$1" ] ; then 
+		num=`echo "$1" | sed 's/[0-9]*//g' 2>/dev/null`
+		if [ -z "$num" ] ; then
+			result=1
+		fi
+	fi 
+	echo $result
+}
+getStringLength() {
+    strlength=`awk 'END{ print length(a) }' a="$1" < /dev/null`
+    echo $strlength
+}
+
+resolveRelativity() {
+	if [ 1 -eq `ifPathRelative "$1"` ] ; then
+		echo "$CURRENT_DIRECTORY"/"$1" | sed 's/\"//g' 2>/dev/null
+	else 
+		echo "$1"
+	fi
+}
+
+ifPathRelative() {
+	param="$1"
+	removeRoot=`echo "$param" | sed "s/^\\\///" 2>/dev/null`
+	echo `ifEquals "$param" "$removeRoot"` 2>/dev/null
+}
+
+
+initializeVariables() {	
+	debug "Launcher name is $LAUNCHER_NAME"
+	systemName=`uname`
+	debug "System name is $systemName"
+	isMacOSX=`ifEquals "$systemName" "Darwin"`	
+	isSolaris=`ifEquals "$systemName" "SunOS"`
+	if [ 1 -eq $isSolaris ] ; then
+		POSSIBLE_JAVA_EXE_SUFFIX="$POSSIBLE_JAVA_EXE_SUFFIX_SOLARIS"
+	else
+		POSSIBLE_JAVA_EXE_SUFFIX="$POSSIBLE_JAVA_EXE_SUFFIX_COMMON"
+	fi
+        if [ 1 -eq $isMacOSX ] ; then
+                # set default userdir and cachedir on MacOS
+                DEFAULT_USERDIR_ROOT="${HOME}/Library/Application Support/NetBeans"
+                DEFAULT_CACHEDIR_ROOT="${HOME}/Library/Caches/NetBeans"
+        else
+                # set default userdir and cachedir on unix systems
+                DEFAULT_USERDIR_ROOT=${HOME}/.netbeans
+                DEFAULT_CACHEDIR_ROOT=${HOME}/.cache/netbeans
+        fi
+	systemInfo=`uname -a 2>/dev/null`
+	debug "System Information:"
+	debug "$systemInfo"             
+	debug ""
+	DEFAULT_DISK_BLOCK_SIZE=512
+	LAUNCHER_TRACKING_SIZE=$LAUNCHER_STUB_SIZE
+	LAUNCHER_TRACKING_SIZE_BYTES=`expr "$LAUNCHER_STUB_SIZE" \* "$FILE_BLOCK_SIZE"`
+	getLauncherLocation
+}
+
+parseJvmAppArgument() {
+        param="$1"
+	arg=`echo "$param" | sed "s/^-J//"`
+	argEscaped=`escapeString "$arg"`
+
+	if [ "$param" = "$arg" ] ; then
+	    LAUNCHER_APP_ARGUMENTS="$LAUNCHER_APP_ARGUMENTS $argEscaped"
+	else
+	    LAUNCHER_JVM_ARGUMENTS="$LAUNCHER_JVM_ARGUMENTS $argEscaped"
+	fi	
+}
+
+getLauncherLocation() {
+	# if file path is relative then prepend it with current directory
+	LAUNCHER_FULL_PATH=`resolveRelativity "$LAUNCHER_NAME"`
+	debug "... normalizing full path"
+	LAUNCHER_FULL_PATH=`normalizePath "$LAUNCHER_FULL_PATH"`
+	debug "... getting dirname"
+	LAUNCHER_DIR=`dirname "$LAUNCHER_FULL_PATH"`
+	debug "Full launcher path = $LAUNCHER_FULL_PATH"
+	debug "Launcher directory = $LAUNCHER_DIR"
+}
+
+getLauncherSize() {
+	lsOutput=`ls -l --block-size=1 "$LAUNCHER_FULL_PATH" 2>/dev/null`
+	if [ $? -ne 0 ] ; then
+	    #default block size
+	    lsOutput=`ls -l "$LAUNCHER_FULL_PATH" 2>/dev/null`
+	fi
+	echo "$lsOutput" | awk ' { print $5 }' 2>/dev/null
+}
+
+verifyIntegrity() {
+	size=`getLauncherSize`
+	extractedSize=$LAUNCHER_TRACKING_SIZE_BYTES
+	if [ 1 -eq `ifNumber "$size"` ] ; then
+		debug "... check integrity"
+		debug "... minimal size : $extractedSize"
+		debug "... real size    : $size"
+
+        	if [ $size -lt $extractedSize ] ; then
+			debug "... integration check FAILED"
+			message "$MSG_ERROR_INTEGRITY" `normalizePath "$LAUNCHER_FULL_PATH"`
+			exitProgram $ERROR_INTEGRITY
+		fi
+		debug "... integration check OK"
+	fi
+}
+showHelp() {
+	msg0=`message "$MSG_USAGE"`
+	msg1=`message "$MSG_ARG_JAVAHOME $ARG_JAVAHOME"`
+	msg2=`message "$MSG_ARG_TEMPDIR $ARG_TEMPDIR"`
+	msg3=`message "$MSG_ARG_EXTRACT $ARG_EXTRACT"`
+	msg4=`message "$MSG_ARG_OUTPUT $ARG_OUTPUT"`
+	msg5=`message "$MSG_ARG_VERBOSE $ARG_VERBOSE"`
+	msg6=`message "$MSG_ARG_CPA $ARG_CLASSPATHA"`
+	msg7=`message "$MSG_ARG_CPP $ARG_CLASSPATHP"`
+	msg8=`message "$MSG_ARG_DISABLE_FREE_SPACE_CHECK $ARG_NOSPACECHECK"`
+        msg9=`message "$MSG_ARG_LOCALE $ARG_LOCALE"`
+        msg10=`message "$MSG_ARG_SILENT $ARG_SILENT"`
+	msg11=`message "$MSG_ARG_HELP $ARG_HELP"`
+	out "$msg0"
+	out "$msg1"
+	out "$msg2"
+	out "$msg3"
+	out "$msg4"
+	out "$msg5"
+	out "$msg6"
+	out "$msg7"
+	out "$msg8"
+	out "$msg9"
+	out "$msg10"
+	out "$msg11"
+	exitProgram $ERROR_OK
+}
+
+exitProgram() {
+	if [ 0 -eq $EXTRACT_ONLY ] ; then
+	    if [ -n "$LAUNCHER_EXTRACT_DIR" ] && [ -d "$LAUNCHER_EXTRACT_DIR" ]; then		
+		debug "Removing directory $LAUNCHER_EXTRACT_DIR"
+		rm -rf "$LAUNCHER_EXTRACT_DIR" > /dev/null 2>&1
+	    fi
+	fi
+	debug "exitCode = $1"
+	exit $1
+}
+
+debug() {
+        if [ $USE_DEBUG_OUTPUT -eq 1 ] ; then
+		timestamp=`date '+%Y-%m-%d %H:%M:%S'`
+                out "[$timestamp]> $1"
+        fi
+}
+
+out() {
+	
+        if [ -n "$OUTPUT_FILE" ] ; then
+                printf "%s\n" "$@" >> "$OUTPUT_FILE"
+        elif [ 0 -eq $SILENT_MODE ] ; then
+                printf "%s\n" "$@"
+	fi
+}
+
+message() {        
+        msg=`getMessage "$@"`
+        out "$msg"
+}
+
+
+createTempDirectory() {
+	if [ 0 -eq $EXTRACT_ONLY ] ; then
+            if [ -z "$LAUNCHER_JVM_TEMP_DIR" ] ; then
+		if [ 0 -eq $EXTRACT_ONLY ] ; then
+                    if [ -n "$TEMP" ] && [ -d "$TEMP" ] ; then
+                        debug "TEMP var is used : $TEMP"
+                        LAUNCHER_JVM_TEMP_DIR="$TEMP"
+                    elif [ -n "$TMP" ] && [ -d "$TMP" ] ; then
+                        debug "TMP var is used : $TMP"
+                        LAUNCHER_JVM_TEMP_DIR="$TMP"
+                    elif [ -n "$TEMPDIR" ] && [ -d "$TEMPDIR" ] ; then
+                        debug "TEMPDIR var is used : $TEMPDIR"
+                        LAUNCHER_JVM_TEMP_DIR="$TEMPDIR"
+                    elif [ -d "/tmp" ] ; then
+                        debug "Using /tmp for temp"
+                        LAUNCHER_JVM_TEMP_DIR="/tmp"
+                    else
+                        debug "Using home dir for temp"
+                        LAUNCHER_JVM_TEMP_DIR="$HOME"
+                    fi
+		else
+		    #extract only : to the curdir
+		    LAUNCHER_JVM_TEMP_DIR="$CURRENT_DIRECTORY"		    
+		fi
+            fi
+            # if temp dir does not exist then try to create it
+            if [ ! -d "$LAUNCHER_JVM_TEMP_DIR" ] ; then
+                mkdir -p "$LAUNCHER_JVM_TEMP_DIR" > /dev/null 2>&1
+                if [ $? -ne 0 ] ; then                        
+                        message "$MSG_ERROR_TMPDIR" "$LAUNCHER_JVM_TEMP_DIR"
+                        exitProgram $ERROR_TEMP_DIRECTORY
+                fi
+            fi		
+            debug "Launcher TEMP ROOT = $LAUNCHER_JVM_TEMP_DIR"
+            subDir=`date '+%u%m%M%S'`
+            subDir=`echo ".nbi-$subDir.tmp"`
+            LAUNCHER_EXTRACT_DIR="$LAUNCHER_JVM_TEMP_DIR/$subDir"
+	else
+	    #extracting to the $LAUNCHER_EXTRACT_DIR
+            debug "Launcher Extracting ROOT = $LAUNCHER_EXTRACT_DIR"
+	fi
+
+        if [ ! -d "$LAUNCHER_EXTRACT_DIR" ] ; then
+                mkdir -p "$LAUNCHER_EXTRACT_DIR" > /dev/null 2>&1
+                if [ $? -ne 0 ] ; then                        
+                        message "$MSG_ERROR_TMPDIR"  "$LAUNCHER_EXTRACT_DIR"
+                        exitProgram $ERROR_TEMP_DIRECTORY
+                fi
+        else
+                debug "$LAUNCHER_EXTRACT_DIR is directory and exist"
+        fi
+        debug "Using directory $LAUNCHER_EXTRACT_DIR for extracting data"
+}
+extractJVMData() {
+	debug "Extracting testJVM file data..."
+        extractTestJVMFile
+	debug "Extracting bundled JVMs ..."
+	extractJVMFiles        
+	debug "Extracting JVM data done"
+}
+extractBundledData() {
+	message "$MSG_EXTRACTING"
+	debug "Extracting bundled jars  data..."
+	extractJars		
+	debug "Extracting other  data..."
+	extractOtherData
+	debug "Extracting bundled data finished..."
+}
+
+setTestJVMClasspath() {
+	testjvmname=`basename "$TEST_JVM_PATH"`
+	removeClassSuffix=`echo "$testjvmname" | sed 's/\.class$//'`
+	notClassFile=`ifEquals "$testjvmname" "$removeClassSuffix"`
+		
+	if [ -d "$TEST_JVM_PATH" ] ; then
+		TEST_JVM_CLASSPATH="$TEST_JVM_PATH"
+		debug "... testJVM path is a directory"
+	elif [ $isSymlink "$TEST_JVM_PATH" ] && [ $notClassFile -eq 1 ] ; then
+		TEST_JVM_CLASSPATH="$TEST_JVM_PATH"
+		debug "... testJVM path is a link but not a .class file"
+	else
+		if [ $notClassFile -eq 1 ] ; then
+			debug "... testJVM path is a jar/zip file"
+			TEST_JVM_CLASSPATH="$TEST_JVM_PATH"
+		else
+			debug "... testJVM path is a .class file"
+			TEST_JVM_CLASSPATH=`dirname "$TEST_JVM_PATH"`
+		fi        
+	fi
+	debug "... testJVM classpath is : $TEST_JVM_CLASSPATH"
+}
+
+extractTestJVMFile() {
+        TEST_JVM_PATH=`resolveResourcePath "TEST_JVM_FILE"`
+	extractResource "TEST_JVM_FILE"
+	setTestJVMClasspath
+        
+}
+
+installJVM() {
+	message "$MSG_PREPARE_JVM"	
+	jvmFile=`resolveRelativity "$1"`
+	jvmDir=`dirname "$jvmFile"`/_jvm
+	debug "JVM Directory : $jvmDir"
+	mkdir "$jvmDir" > /dev/null 2>&1
+	if [ $? != 0 ] ; then
+		message "$MSG_ERROR_EXTRACT_JVM"
+		exitProgram $ERROR_JVM_EXTRACTION
+	fi
+        chmod +x "$jvmFile" > /dev/null  2>&1
+	jvmFileEscaped=`escapeString "$jvmFile"`
+        jvmDirEscaped=`escapeString "$jvmDir"`
+	cd "$jvmDir"
+        runCommand "$jvmFileEscaped"
+	ERROR_CODE=$?
+
+        cd "$CURRENT_DIRECTORY"
+
+	if [ $ERROR_CODE != 0 ] ; then		
+	        message "$MSG_ERROR_EXTRACT_JVM"
+		exitProgram $ERROR_JVM_EXTRACTION
+	fi
+	
+	files=`find "$jvmDir" -name "*.jar.pack.gz" -print`
+	debug "Packed files : $files"
+	f="$files"
+	fileCounter=1;
+	while [ -n "$f" ] ; do
+		f=`echo "$files" | sed -n "${fileCounter}p" 2>/dev/null`
+		debug "... next file is $f"				
+		if [ -n "$f" ] ; then
+			debug "... packed file  = $f"
+			unpacked=`echo "$f" | sed s/\.pack\.gz//`
+			debug "... unpacked file = $unpacked"
+			fEsc=`escapeString "$f"`
+			uEsc=`escapeString "$unpacked"`
+			cmd="$jvmDirEscaped/bin/unpack200 -r $fEsc $uEsc"
+			runCommand "$cmd"
+			if [ $? != 0 ] ; then
+			    message "$MSG_ERROR_UNPACK_JVM_FILE" "$f"
+			    exitProgram $ERROR_JVM_UNPACKING
+			fi		
+		fi					
+		fileCounter=`expr "$fileCounter" + 1`
+	done
+		
+	verifyJVM "$jvmDir"
+	if [ -z "$LAUNCHER_JAVA_EXE" ] ; then
+		message "$MSG_ERROR_VERIFY_BUNDLED_JVM"
+		exitProgram $ERROR_VERIFY_BUNDLED_JVM
+	fi
+}
+
+resolveResourcePath() {
+	resourcePrefix="$1"
+	resourceVar="$""$resourcePrefix""_PATH"
+	resourceName=`eval "echo \"$resourceVar\""`
+	resourcePath=`resolveString "$resourceName"`
+    	echo "$resourcePath"
+
+}
+
+resolveResourceSize() {
+	resourcePrefix="$1"
+	resourceVar="$""$resourcePrefix""_SIZE"
+	resourceSize=`eval "echo \"$resourceVar\""`
+    	echo "$resourceSize"
+}
+
+resolveResourceMd5() {
+	resourcePrefix="$1"
+	resourceVar="$""$resourcePrefix""_MD5"
+	resourceMd5=`eval "echo \"$resourceVar\""`
+    	echo "$resourceMd5"
+}
+
+resolveResourceType() {
+	resourcePrefix="$1"
+	resourceVar="$""$resourcePrefix""_TYPE"
+	resourceType=`eval "echo \"$resourceVar\""`
+	echo "$resourceType"
+}
+
+extractResource() {	
+	debug "... extracting resource" 
+        resourcePrefix="$1"
+	debug "... resource prefix id=$resourcePrefix"	
+	resourceType=`resolveResourceType "$resourcePrefix"`
+	debug "... resource type=$resourceType"	
+	if [ $resourceType -eq 0 ] ; then
+                resourceSize=`resolveResourceSize "$resourcePrefix"`
+		debug "... resource size=$resourceSize"
+            	resourcePath=`resolveResourcePath "$resourcePrefix"`
+	    	debug "... resource path=$resourcePath"
+            	extractFile "$resourceSize" "$resourcePath"
+                resourceMd5=`resolveResourceMd5 "$resourcePrefix"`
+	    	debug "... resource md5=$resourceMd5"
+                checkMd5 "$resourcePath" "$resourceMd5"
+		debug "... done"
+	fi
+	debug "... extracting resource finished"	
+        
+}
+
+extractJars() {
+        counter=0
+	while [ $counter -lt $JARS_NUMBER ] ; do
+		extractResource "JAR_$counter"
+		counter=`expr "$counter" + 1`
+	done
+}
+
+extractOtherData() {
+        counter=0
+	while [ $counter -lt $OTHER_RESOURCES_NUMBER ] ; do
+		extractResource "OTHER_RESOURCE_$counter"
+		counter=`expr "$counter" + 1`
+	done
+}
+
+extractJVMFiles() {
+	javaCounter=0
+	debug "... total number of JVM files : $JAVA_LOCATION_NUMBER"
+	while [ $javaCounter -lt $JAVA_LOCATION_NUMBER ] ; do		
+		extractResource "JAVA_LOCATION_$javaCounter"
+		javaCounter=`expr "$javaCounter" + 1`
+	done
+}
+
+
+processJarsClasspath() {
+	JARS_CLASSPATH=""
+	jarsCounter=0
+	while [ $jarsCounter -lt $JARS_NUMBER ] ; do
+		resolvedFile=`resolveResourcePath "JAR_$jarsCounter"`
+		debug "... adding jar to classpath : $resolvedFile"
+		if [ ! -f "$resolvedFile" ] && [ ! -d "$resolvedFile" ] && [ ! $isSymlink "$resolvedFile" ] ; then
+				message "$MSG_ERROP_MISSING_RESOURCE" "$resolvedFile"
+				exitProgram $ERROR_MISSING_RESOURCES
+		else
+			if [ -z "$JARS_CLASSPATH" ] ; then
+				JARS_CLASSPATH="$resolvedFile"
+			else				
+				JARS_CLASSPATH="$JARS_CLASSPATH":"$resolvedFile"
+			fi
+		fi			
+			
+		jarsCounter=`expr "$jarsCounter" + 1`
+	done
+	debug "Jars classpath : $JARS_CLASSPATH"
+}
+
+extractFile() {
+        start=$LAUNCHER_TRACKING_SIZE
+        size=$1 #absolute size
+        name="$2" #relative part        
+        fullBlocks=`expr $size / $FILE_BLOCK_SIZE`
+        fullBlocksSize=`expr "$FILE_BLOCK_SIZE" \* "$fullBlocks"`
+        oneBlocks=`expr  $size - $fullBlocksSize`
+	oneBlocksStart=`expr "$start" + "$fullBlocks"`
+
+	checkFreeSpace $size "$name"	
+	LAUNCHER_TRACKING_SIZE_BYTES=`expr "$LAUNCHER_TRACKING_SIZE" \* "$FILE_BLOCK_SIZE"`
+
+	if [ 0 -eq $diskSpaceCheck ] ; then
+		dir=`dirname "$name"`
+		message "$MSG_ERROR_FREESPACE" "$size" "$ARG_TEMPDIR"	
+		exitProgram $ERROR_FREESPACE
+	fi
+
+        if [ 0 -lt "$fullBlocks" ] ; then
+                # file is larger than FILE_BLOCK_SIZE
+                dd if="$LAUNCHER_FULL_PATH" of="$name" \
+                        bs="$FILE_BLOCK_SIZE" count="$fullBlocks" skip="$start"\
+			> /dev/null  2>&1
+		LAUNCHER_TRACKING_SIZE=`expr "$LAUNCHER_TRACKING_SIZE" + "$fullBlocks"`
+		LAUNCHER_TRACKING_SIZE_BYTES=`expr "$LAUNCHER_TRACKING_SIZE" \* "$FILE_BLOCK_SIZE"`
+        fi
+        if [ 0 -lt "$oneBlocks" ] ; then
+		dd if="$LAUNCHER_FULL_PATH" of="$name.tmp.tmp" bs="$FILE_BLOCK_SIZE" count=1\
+			skip="$oneBlocksStart"\
+			 > /dev/null 2>&1
+
+		dd if="$name.tmp.tmp" of="$name" bs=1 count="$oneBlocks" seek="$fullBlocksSize"\
+			 > /dev/null 2>&1
+
+		rm -f "$name.tmp.tmp"
+		LAUNCHER_TRACKING_SIZE=`expr "$LAUNCHER_TRACKING_SIZE" + 1`
+
+		LAUNCHER_TRACKING_SIZE_BYTES=`expr "$LAUNCHER_TRACKING_SIZE_BYTES" + "$oneBlocks"`
+        fi        
+}
+
+md5_program=""
+no_md5_program_id="no_md5_program"
+
+initMD5program() {
+    if [ -z "$md5_program" ] ; then 
+        type digest >> /dev/null 2>&1
+        if [ 0 -eq $? ] ; then
+            md5_program="digest -a md5"
+        else
+            type md5sum >> /dev/null 2>&1
+            if [ 0 -eq $? ] ; then
+                md5_program="md5sum"
+            else 
+                type gmd5sum >> /dev/null 2>&1
+                if [ 0 -eq $? ] ; then
+                    md5_program="gmd5sum"
+                else
+                    type md5 >> /dev/null 2>&1
+                    if [ 0 -eq $? ] ; then
+                        md5_program="md5 -q"
+                    else 
+                        md5_program="$no_md5_program_id"
+                    fi
+                fi
+            fi
+        fi
+        debug "... program to check: $md5_program"
+    fi
+}
+
+checkMd5() {
+     name="$1"
+     md5="$2"     
+     if [ 32 -eq `getStringLength "$md5"` ] ; then
+         #do MD5 check         
+         initMD5program            
+         if [ 0 -eq `ifEquals "$md5_program" "$no_md5_program_id"` ] ; then
+            debug "... check MD5 of file : $name"           
+            debug "... expected md5: $md5"
+            realmd5=`$md5_program "$name" 2>/dev/null | sed "s/ .*//g"`
+            debug "... real md5 : $realmd5"
+            if [ 32 -eq `getStringLength "$realmd5"` ] ; then
+                if [ 0 -eq `ifEquals "$md5" "$realmd5"` ] ; then
+                        debug "... integration check FAILED"
+			message "$MSG_ERROR_INTEGRITY" `normalizePath "$LAUNCHER_FULL_PATH"`
+			exitProgram $ERROR_INTEGRITY
+                fi
+            else
+                debug "... looks like not the MD5 sum"
+            fi
+         fi
+     fi   
+}
+searchJavaEnvironment() {
+     if [ -z "$LAUNCHER_JAVA_EXE" ] ; then
+		    # search java in the environment
+		
+            	    ptr="$POSSIBLE_JAVA_ENV"
+            	    while [ -n "$ptr" ] && [ -z "$LAUNCHER_JAVA_EXE" ] ; do
+			argJavaHome=`echo "$ptr" | sed "s/:.*//"`
+			back=`echo "$argJavaHome" | sed "s/\\\//\\\\\\\\\//g"`
+		    	end=`echo "$ptr"       | sed "s/${back}://"`
+			argJavaHome=`echo "$back" | sed "s/\\\\\\\\\//\\\//g"`
+			ptr="$end"
+                        eval evaluated=`echo \\$$argJavaHome` > /dev/null
+                        if [ -n "$evaluated" ] ; then
+                                debug "EnvVar $argJavaHome=$evaluated"				
+                                verifyJVM "$evaluated"
+                        fi
+            	    done
+     fi
+}
+
+installBundledJVMs() {
+	if [ -z "$LAUNCHER_JAVA_EXE" ] ; then
+	    # search bundled java in the common list
+	    javaCounter=0
+    	    while [ $javaCounter -lt $JAVA_LOCATION_NUMBER ] && [ -z "$LAUNCHER_JAVA_EXE" ] ; do
+	    	fileType=`resolveResourceType "JAVA_LOCATION_$javaCounter"`
+		
+		if [ $fileType -eq 0 ] ; then # bundled->install
+			argJavaHome=`resolveResourcePath "JAVA_LOCATION_$javaCounter"`
+			installJVM  "$argJavaHome"				
+        	fi
+		javaCounter=`expr "$javaCounter" + 1`
+    	    done
+	fi
+}
+
+searchJavaOnMacOs() {
+        if [ -x "/usr/libexec/java_home" ]; then
+            javaOnMacHome=`/usr/libexec/java_home --failfast`
+        fi
+
+        if [ ! -x "$javaOnMacHome/bin/java" -a -f "/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/bin/java" ] ; then
+            javaOnMacHome=`echo "/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home"`
+        fi
+
+        verifyJVM "$javaOnMacHome"
+}
+
+searchJavaSystemDefault() {
+        if [ -z "$LAUNCHER_JAVA_EXE" ] ; then
+            debug "... check default java in the path"
+            java_bin=`which java 2>&1`
+            if [ $? -eq 0 ] && [ -n "$java_bin" ] ; then
+                remove_no_java_in=`echo "$java_bin" | sed "s/no java in//g"`
+                if [ 1 -eq `ifEquals "$remove_no_java_in" "$java_bin"` ] && [ -f "$java_bin" ] ; then
+                    debug "... java in path found: $java_bin"
+                    # java is in path
+                    java_bin=`resolveSymlink "$java_bin"`
+                    debug "... java real path: $java_bin"
+                    parentDir=`dirname "$java_bin"`
+                    if [ -n "$parentDir" ] ; then
+                        parentDir=`dirname "$parentDir"`
+                        if [ -n "$parentDir" ] ; then
+                            debug "... java home path: $parentDir"
+                            parentDir=`resolveSymlink "$parentDir"`
+                            debug "... java home real path: $parentDir"
+                            verifyJVM "$parentDir"
+                        fi
+                    fi
+                fi
+            fi
+	fi
+}
+
+searchJavaSystemPaths() {
+	if [ -z "$LAUNCHER_JAVA_EXE" ] ; then
+	    # search java in the common system paths
+	    javaCounter=0
+    	    while [ $javaCounter -lt $JAVA_LOCATION_NUMBER ] && [ -z "$LAUNCHER_JAVA_EXE" ] ; do
+	    	fileType=`resolveResourceType "JAVA_LOCATION_$javaCounter"`
+	    	argJavaHome=`resolveResourcePath "JAVA_LOCATION_$javaCounter"`
+
+	    	debug "... next location $argJavaHome"
+		
+		if [ $fileType -ne 0 ] ; then # bundled JVMs have already been proceeded
+			argJavaHome=`escapeString "$argJavaHome"`
+			locations=`ls -d -1 $argJavaHome 2>/dev/null`
+			nextItem="$locations"
+			itemCounter=1
+			while [ -n "$nextItem" ] && [ -z "$LAUNCHER_JAVA_EXE" ] ; do
+				nextItem=`echo "$locations" | sed -n "${itemCounter}p" 2>/dev/null`
+				debug "... next item is $nextItem"				
+				nextItem=`removeEndSlashes "$nextItem"`
+				if [ -n "$nextItem" ] ; then
+					if [ -d "$nextItem" ] || [ $isSymlink "$nextItem" ] ; then
+	               				debug "... checking item : $nextItem"
+						verifyJVM "$nextItem"
+					fi
+				fi					
+				itemCounter=`expr "$itemCounter" + 1`
+			done
+		fi
+		javaCounter=`expr "$javaCounter" + 1`
+    	    done
+	fi
+}
+
+searchJavaUserDefined() {
+	if [ -z "$LAUNCHER_JAVA_EXE" ] ; then
+        	if [ -n "$LAUNCHER_JAVA" ] ; then
+                	verifyJVM "$LAUNCHER_JAVA"
+		
+			if [ $VERIFY_UNCOMPATIBLE -eq $verifyResult ] ; then
+		    		message "$MSG_ERROR_JVM_UNCOMPATIBLE" "$LAUNCHER_JAVA" "$ARG_JAVAHOME"
+		    		exitProgram $ERROR_JVM_UNCOMPATIBLE
+			elif [ $VERIFY_NOJAVA -eq $verifyResult ] ; then
+				message "$MSG_ERROR_USER_ERROR" "$LAUNCHER_JAVA"
+		    		exitProgram $ERROR_JVM_NOT_FOUND
+			fi
+        	fi
+	fi
+}
+
+searchJavaInstallFolder() {
+        installFolder="`dirname \"$0\"`"
+        installFolder="`( cd \"$installFolder\" && pwd )`"
+        installFolder="$installFolder/bin/jre"
+        tempJreFolder="$TEST_JVM_CLASSPATH/_jvm"
+
+        if [ -d "$installFolder" ] ; then
+            #copy nested JRE to temp folder
+            cp -r "$installFolder" "$tempJreFolder"
+
+            verifyJVM "$tempJreFolder"
+        fi
+}
+
+searchJava() {
+	message "$MSG_JVM_SEARCH"
+        if [ ! -f "$TEST_JVM_CLASSPATH" ] && [ ! $isSymlink "$TEST_JVM_CLASSPATH" ] && [ ! -d "$TEST_JVM_CLASSPATH" ]; then
+                debug "Cannot find file for testing JVM at $TEST_JVM_CLASSPATH"
+		message "$MSG_ERROR_JVM_NOT_FOUND" "$ARG_JAVAHOME"
+                exitProgram $ERROR_TEST_JVM_FILE
+        else	
+                searchJavaInstallFolder
+		searchJavaUserDefined
+		installBundledJVMs
+		searchJavaEnvironment
+		searchJavaSystemDefault
+		searchJavaSystemPaths
+                if [ 1 -eq $isMacOSX ] ; then
+                    searchJavaOnMacOs
+                fi
+        fi
+
+	if [ -z "$LAUNCHER_JAVA_EXE" ] ; then
+		message "$MSG_ERROR_JVM_NOT_FOUND" "$ARG_JAVAHOME"
+		exitProgram $ERROR_JVM_NOT_FOUND
+	fi
+}
+
+normalizePath() {	
+	argument="$1"
+  
+  # replace all /./ to /
+	while [ 0 -eq 0 ] ; do	
+		testArgument=`echo "$argument" | sed 's/\/\.\//\//g' 2> /dev/null`
+		if [ -n "$testArgument" ] && [ 0 -eq `ifEquals "$argument" "$testArgument"` ] ; then
+		  # something changed
+			argument="$testArgument"
+		else
+			break
+		fi	
+	done
+
+	# replace XXX/../YYY to 'dirname XXX'/YYY
+	while [ 0 -eq 0 ] ; do	
+		beforeDotDot=`echo "$argument" | sed "s/\/\.\.\/.*//g" 2> /dev/null`
+      if [ 0 -eq `ifEquals "$beforeDotDot" "$argument"` ] && [ 0 -eq `ifEquals "$beforeDotDot" "."` ] && [ 0 -eq `ifEquals "$beforeDotDot" ".."` ] ; then
+        esc=`echo "$beforeDotDot" | sed "s/\\\//\\\\\\\\\//g"`
+        afterDotDot=`echo "$argument" | sed "s/^$esc\/\.\.//g" 2> /dev/null` 
+        parent=`dirname "$beforeDotDot"`
+        argument=`echo "$parent""$afterDotDot"`
+		else 
+      break
+		fi	
+	done
+
+	# replace XXX/.. to 'dirname XXX'
+	while [ 0 -eq 0 ] ; do	
+		beforeDotDot=`echo "$argument" | sed "s/\/\.\.$//g" 2> /dev/null`
+    if [ 0 -eq `ifEquals "$beforeDotDot" "$argument"` ] && [ 0 -eq `ifEquals "$beforeDotDot" "."` ] && [ 0 -eq `ifEquals "$beforeDotDot" ".."` ] ; then
+		  argument=`dirname "$beforeDotDot"`
+		else 
+      break
+		fi	
+	done
+
+  # remove /. a the end (if the resulting string is not zero)
+	testArgument=`echo "$argument" | sed 's/\/\.$//' 2> /dev/null`
+	if [ -n "$testArgument" ] ; then
+		argument="$testArgument"
+	fi
+
+	# replace more than 2 separators to 1
+	testArgument=`echo "$argument" | sed 's/\/\/*/\//g' 2> /dev/null`
+	if [ -n "$testArgument" ] ; then
+		argument="$testArgument"
+	fi
+	
+	echo "$argument"	
+}
+
+resolveSymlink() {  
+    pathArg="$1"	
+    while [ $isSymlink "$pathArg" ] ; do
+        ls=`ls -ld "$pathArg"`
+        link=`expr "$ls" : '^.*-> \(.*\)$' 2>/dev/null`
+    
+        if expr "$link" : '^/' 2> /dev/null >/dev/null; then
+		pathArg="$link"
+        else
+		pathArg="`dirname "$pathArg"`"/"$link"
+        fi
+	pathArg=`normalizePath "$pathArg"` 
+    done
+    echo "$pathArg"
+}
+
+verifyJVM() {                
+    javaTryPath=`normalizePath "$1"` 
+    verifyJavaHome "$javaTryPath"
+    if [ $VERIFY_OK -ne $verifyResult ] ; then
+	savedResult=$verifyResult
+
+    	if [ 0 -eq $isMacOSX ] ; then
+        	#check private jre
+		javaTryPath="$javaTryPath""/jre"
+		verifyJavaHome "$javaTryPath"	
+    	else
+		#check MacOSX Home dir
+		javaTryPath="$javaTryPath""/Home"
+		verifyJavaHome "$javaTryPath"			
+	fi	
+	
+	if [ $VERIFY_NOJAVA -eq $verifyResult ] ; then                                           
+		verifyResult=$savedResult
+	fi 
+    fi
+}
+
+removeEndSlashes() {
+ arg="$1"
+ tryRemove=`echo "$arg" | sed 's/\/\/*$//' 2>/dev/null`
+ if [ -n "$tryRemove" ] ; then
+      arg="$tryRemove"
+ fi
+ echo "$arg"
+}
+
+checkJavaHierarchy() {
+	# return 0 on no java
+	# return 1 on jre
+	# return 2 on jdk
+
+	tryJava="$1"
+	javaHierarchy=0
+	if [ -n "$tryJava" ] ; then
+		if [ -d "$tryJava" ] || [ $isSymlink "$tryJava" ] ; then # existing directory or a isSymlink        			
+			javaBin="$tryJava"/"bin"
+	        
+			if [ -d "$javaBin" ] || [ $isSymlink "$javaBin" ] ; then
+				javaBinJavac="$javaBin"/"javac"
+				if [ -f "$javaBinJavac" ] || [ $isSymlink "$javaBinJavac" ] ; then
+					#definitely JDK as the JRE doesn`t contain javac
+					javaHierarchy=2				
+				else
+					#check if we inside JRE
+					javaBinJava="$javaBin"/"java"
+					if [ -f "$javaBinJava" ] || [ $isSymlink "$javaBinJava" ] ; then
+						javaHierarchy=1
+					fi					
+				fi
+			fi
+		fi
+	fi
+	if [ 0 -eq $javaHierarchy ] ; then
+		debug "... no java there"
+	elif [ 1 -eq $javaHierarchy ] ; then
+		debug "... JRE there"
+	elif [ 2 -eq $javaHierarchy ] ; then
+		debug "... JDK there"
+	fi
+}
+
+verifyJavaHome() { 
+    verifyResult=$VERIFY_NOJAVA
+    java=`removeEndSlashes "$1"`
+    debug "... verify    : $java"    
+
+    java=`resolveSymlink "$java"`    
+    debug "... real path : $java"
+
+    checkJavaHierarchy "$java"
+	
+    if [ 0 -ne $javaHierarchy ] ; then 
+	testJVMclasspath=`escapeString "$TEST_JVM_CLASSPATH"`
+	testJVMclass=`escapeString "$TEST_JVM_CLASS"`
+
+        pointer="$POSSIBLE_JAVA_EXE_SUFFIX"
+        while [ -n "$pointer" ] && [ -z "$LAUNCHER_JAVA_EXE" ]; do
+            arg=`echo "$pointer" | sed "s/:.*//"`
+	    back=`echo "$arg" | sed "s/\\\//\\\\\\\\\//g"`
+	    end=`echo "$pointer"       | sed "s/${back}://"`
+	    arg=`echo "$back" | sed "s/\\\\\\\\\//\\\//g"`
+	    pointer="$end"
+            javaExe="$java/$arg"	    
+
+            if [ -x "$javaExe" ] ; then		
+                javaExeEscaped=`escapeString "$javaExe"`
+                command="$javaExeEscaped -classpath $testJVMclasspath $testJVMclass"
+
+                debug "Executing java verification command..."
+		debug "$command"
+                output=`eval "$command" 2>/dev/null`
+                javaVersion=`echo "$output"   | sed "2d;3d;4d;5d"`
+		javaVmVersion=`echo "$output" | sed "1d;3d;4d;5d"`
+		vendor=`echo "$output"        | sed "1d;2d;4d;5d"`
+		osname=`echo "$output"        | sed "1d;2d;3d;5d"`
+		osarch=`echo "$output"        | sed "1d;2d;3d;4d"`
+
+		debug "Java :"
+                debug "       executable = {$javaExe}"	
+		debug "      javaVersion = {$javaVersion}"
+		debug "    javaVmVersion = {$javaVmVersion}"
+		debug "           vendor = {$vendor}"
+		debug "           osname = {$osname}"
+		debug "           osarch = {$osarch}"
+		comp=0
+
+		if [ -n "$javaVersion" ] && [ -n "$javaVmVersion" ] && [ -n "$vendor" ] && [ -n "$osname" ] && [ -n "$osarch" ] ; then
+		    debug "... seems to be java indeed"
+		    javaVersionEsc=`escapeBackslash "$javaVersion"`
+                    javaVmVersionEsc=`escapeBackslash "$javaVmVersion"`
+                    javaVersion=`awk 'END { idx = index(b,a); if(idx!=0) { print substr(b,idx,length(b)) } else { print a } }' a="$javaVersionEsc" b="$javaVmVersionEsc" < /dev/null`
+
+		    #remove build number
+		    javaVersion=`echo "$javaVersion" | sed 's/-.*$//;s/\ .*//'`
+		    verifyResult=$VERIFY_UNCOMPATIBLE
+
+	            if [ -n "$javaVersion" ] ; then
+			debug " checking java version = {$javaVersion}"
+			javaCompCounter=0
+
+			while [ $javaCompCounter -lt $JAVA_COMPATIBLE_PROPERTIES_NUMBER ] && [ -z "$LAUNCHER_JAVA_EXE" ] ; do				
+				comp=1
+				setJavaCompatibilityProperties_$javaCompCounter
+				debug "Min Java Version : $JAVA_COMP_VERSION_MIN"
+				debug "Max Java Version : $JAVA_COMP_VERSION_MAX"
+				debug "Java Vendor      : $JAVA_COMP_VENDOR"
+				debug "Java OS Name     : $JAVA_COMP_OSNAME"
+				debug "Java OS Arch     : $JAVA_COMP_OSARCH"
+
+				if [ -n "$JAVA_COMP_VERSION_MIN" ] ; then
+                                    compMin=`ifVersionLess "$javaVersion" "$JAVA_COMP_VERSION_MIN"`
+                                    if [ 1 -eq $compMin ] ; then
+                                        comp=0
+                                    fi
+				fi
+
+		                if [ -n "$JAVA_COMP_VERSION_MAX" ] ; then
+                                    compMax=`ifVersionGreater "$javaVersion" "$JAVA_COMP_VERSION_MAX"`
+                                    if [ 1 -eq $compMax ] ; then
+                                        comp=0
+                                    fi
+		                fi				
+				if [ -n "$JAVA_COMP_VENDOR" ] ; then
+					debug " checking vendor = {$vendor}, {$JAVA_COMP_VENDOR}"
+					subs=`echo "$vendor" | sed "s/${JAVA_COMP_VENDOR}//"`
+					if [ `ifEquals "$subs" "$vendor"` -eq 1 ]  ; then
+						comp=0
+						debug "... vendor incompatible"
+					fi
+				fi
+	
+				if [ -n "$JAVA_COMP_OSNAME" ] ; then
+					debug " checking osname = {$osname}, {$JAVA_COMP_OSNAME}"
+					subs=`echo "$osname" | sed "s/${JAVA_COMP_OSNAME}//"`
+					
+					if [ `ifEquals "$subs" "$osname"` -eq 1 ]  ; then
+						comp=0
+						debug "... osname incompatible"
+					fi
+				fi
+				if [ -n "$JAVA_COMP_OSARCH" ] ; then
+					debug " checking osarch = {$osarch}, {$JAVA_COMP_OSARCH}"
+					subs=`echo "$osarch" | sed "s/${JAVA_COMP_OSARCH}//"`
+					
+					if [ `ifEquals "$subs" "$osarch"` -eq 1 ]  ; then
+						comp=0
+						debug "... osarch incompatible"
+					fi
+				fi
+				if [ $comp -eq 1 ] ; then
+				        LAUNCHER_JAVA_EXE="$javaExe"
+					LAUNCHER_JAVA="$java"
+					verifyResult=$VERIFY_OK
+		    		fi
+				debug "       compatible = [$comp]"
+				javaCompCounter=`expr "$javaCompCounter" + 1`
+			done
+		    fi		    
+		fi		
+            fi	    
+        done
+   fi
+}
+
+checkFreeSpace() {
+	size="$1"
+	path="$2"
+
+	if [ ! -d "$path" ] && [ ! $isSymlink "$path" ] ; then
+		# if checking path is not an existing directory - check its parent dir
+		path=`dirname "$path"`
+	fi
+
+	diskSpaceCheck=0
+
+	if [ 0 -eq $PERFORM_FREE_SPACE_CHECK ] ; then
+		diskSpaceCheck=1
+	else
+		# get size of the atomic entry (directory)
+		freeSpaceDirCheck="$path"/freeSpaceCheckDir
+		debug "Checking space in $path (size = $size)"
+		mkdir -p "$freeSpaceDirCheck"
+		# POSIX compatible du return size in 1024 blocks
+		du --block-size=$DEFAULT_DISK_BLOCK_SIZE "$freeSpaceDirCheck" 1>/dev/null 2>&1
+		
+		if [ $? -eq 0 ] ; then 
+			debug "    getting POSIX du with 512 bytes blocks"
+			atomicBlock=`du --block-size=$DEFAULT_DISK_BLOCK_SIZE "$freeSpaceDirCheck" | awk ' { print $A }' A=1 2>/dev/null` 
+		else
+			debug "    getting du with default-size blocks"
+			atomicBlock=`du "$freeSpaceDirCheck" | awk ' { print $A }' A=1 2>/dev/null` 
+		fi
+		rm -rf "$freeSpaceDirCheck"
+	        debug "    atomic block size : [$atomicBlock]"
+
+                isBlockNumber=`ifNumber "$atomicBlock"`
+		if [ 0 -eq $isBlockNumber ] ; then
+			out "Can\`t get disk block size"
+			exitProgram $ERROR_INPUTOUPUT
+		fi
+		requiredBlocks=`expr \( "$1" / $DEFAULT_DISK_BLOCK_SIZE \) + $atomicBlock` 1>/dev/null 2>&1
+		if [ `ifNumber $1` -eq 0 ] ; then 
+		        out "Can\`t calculate required blocks size"
+			exitProgram $ERROR_INPUTOUPUT
+		fi
+		# get free block size
+		column=4
+		df -P --block-size="$DEFAULT_DISK_BLOCK_SIZE" "$path" 1>/dev/null 2>&1
+		if [ $? -eq 0 ] ; then 
+			# gnu df, use POSIX output
+			 debug "    getting GNU POSIX df with specified block size $DEFAULT_DISK_BLOCK_SIZE"
+			 availableBlocks=`df -P --block-size="$DEFAULT_DISK_BLOCK_SIZE"  "$path" | sed "1d" | awk ' { print $A }' A=$column 2>/dev/null`
+		else 
+			# try POSIX output
+			df -P "$path" 1>/dev/null 2>&1
+			if [ $? -eq 0 ] ; then 
+				 debug "    getting POSIX df with 512 bytes blocks"
+				 availableBlocks=`df -P "$path" | sed "1d" | awk ' { print $A }' A=$column 2>/dev/null`
+			# try  Solaris df from xpg4
+			elif  [ -x /usr/xpg4/bin/df ] ; then 
+				 debug "    getting xpg4 df with default-size blocks"
+				 availableBlocks=`/usr/xpg4/bin/df -P "$path" | sed "1d" | awk ' { print $A }' A=$column 2>/dev/null`
+			# last chance to get free space
+			else		
+				 debug "    getting df with default-size blocks"
+				 availableBlocks=`df "$path" | sed "1d" | awk ' { print $A }' A=$column 2>/dev/null`
+			fi
+		fi
+		debug "    available blocks : [$availableBlocks]"
+		if [ `ifNumber "$availableBlocks"` -eq 0 ] ; then
+			out "Can\`t get the number of the available blocks on the system"
+			exitProgram $ERROR_INPUTOUTPUT
+		fi
+		
+		# compare
+                debug "    required  blocks : [$requiredBlocks]"
+
+		if [ $availableBlocks -gt $requiredBlocks ] ; then
+			debug "... disk space check OK"
+			diskSpaceCheck=1
+		else 
+		        debug "... disk space check FAILED"
+		fi
+	fi
+	if [ 0 -eq $diskSpaceCheck ] ; then
+		mbDownSize=`expr "$size" / 1024 / 1024`
+		mbUpSize=`expr "$size" / 1024 / 1024 + 1`
+		mbSize=`expr "$mbDownSize" \* 1024 \* 1024`
+		if [ $size -ne $mbSize ] ; then	
+			mbSize="$mbUpSize"
+		else
+			mbSize="$mbDownSize"
+		fi
+		
+		message "$MSG_ERROR_FREESPACE" "$mbSize" "$ARG_TEMPDIR"	
+		exitProgram $ERROR_FREESPACE
+	fi
+}
+
+prepareClasspath() {
+    debug "Processing external jars ..."
+    processJarsClasspath
+ 
+    LAUNCHER_CLASSPATH=""
+    if [ -n "$JARS_CLASSPATH" ] ; then
+		if [ -z "$LAUNCHER_CLASSPATH" ] ; then
+			LAUNCHER_CLASSPATH="$JARS_CLASSPATH"
+		else
+			LAUNCHER_CLASSPATH="$LAUNCHER_CLASSPATH":"$JARS_CLASSPATH"
+		fi
+    fi
+
+    if [ -n "$PREPEND_CP" ] ; then
+	debug "Appending classpath with [$PREPEND_CP]"
+	PREPEND_CP=`resolveString "$PREPEND_CP"`
+
+	if [ -z "$LAUNCHER_CLASSPATH" ] ; then
+		LAUNCHER_CLASSPATH="$PREPEND_CP"		
+	else
+		LAUNCHER_CLASSPATH="$PREPEND_CP":"$LAUNCHER_CLASSPATH"	
+	fi
+    fi
+    if [ -n "$APPEND_CP" ] ; then
+	debug "Appending classpath with [$APPEND_CP]"
+	APPEND_CP=`resolveString "$APPEND_CP"`
+	if [ -z "$LAUNCHER_CLASSPATH" ] ; then
+		LAUNCHER_CLASSPATH="$APPEND_CP"	
+	else
+		LAUNCHER_CLASSPATH="$LAUNCHER_CLASSPATH":"$APPEND_CP"	
+	fi
+    fi
+    debug "Launcher Classpath : $LAUNCHER_CLASSPATH"
+}
+
+resolvePropertyStrings() {
+	args="$1"
+	escapeReplacedString="$2"
+	propertyStart=`echo "$args" | sed "s/^.*\\$P{//"`
+	propertyValue=""
+	propertyName=""
+
+	#Resolve i18n strings and properties
+	if [ 0 -eq `ifEquals "$propertyStart" "$args"` ] ; then
+		propertyName=`echo "$propertyStart" |  sed "s/}.*//" 2>/dev/null`
+		if [ -n "$propertyName" ] ; then
+			propertyValue=`getMessage "$propertyName"`
+
+			if [ 0 -eq `ifEquals "$propertyValue" "$propertyName"` ] ; then				
+				propertyName="\$P{$propertyName}"
+				args=`replaceString "$args" "$propertyName" "$propertyValue" "$escapeReplacedString"`
+			fi
+		fi
+	fi
+			
+	echo "$args"
+}
+
+
+resolveLauncherSpecialProperties() {
+	args="$1"
+	escapeReplacedString="$2"
+	propertyValue=""
+	propertyName=""
+	propertyStart=`echo "$args" | sed "s/^.*\\$L{//"`
+
+	
+        if [ 0 -eq `ifEquals "$propertyStart" "$args"` ] ; then
+ 		propertyName=`echo "$propertyStart" |  sed "s/}.*//" 2>/dev/null`
+		
+
+		if [ -n "$propertyName" ] ; then
+			case "$propertyName" in
+		        	"nbi.launcher.tmp.dir")                        		
+					propertyValue="$LAUNCHER_EXTRACT_DIR"
+					;;
+				"nbi.launcher.java.home")	
+					propertyValue="$LAUNCHER_JAVA"
+					;;
+				"nbi.launcher.user.home")
+					propertyValue="$HOME"
+					;;
+				"nbi.launcher.parent.dir")
+					propertyValue="$LAUNCHER_DIR"
+					;;
+				*)
+					propertyValue="$propertyName"
+					;;
+			esac
+			if [ 0 -eq `ifEquals "$propertyValue" "$propertyName"` ] ; then				
+				propertyName="\$L{$propertyName}"
+				args=`replaceString "$args" "$propertyName" "$propertyValue" "$escapeReplacedString"`
+			fi      
+		fi
+	fi            
+	echo "$args"
+}
+
+resolveString() {
+ 	args="$1"
+	escapeReplacedString="$2"
+	last="$args"
+	repeat=1
+
+	while [ 1 -eq $repeat ] ; do
+		repeat=1
+		args=`resolvePropertyStrings "$args" "$escapeReplacedString"`
+		args=`resolveLauncherSpecialProperties "$args" "$escapeReplacedString"`		
+		if [ 1 -eq `ifEquals "$last" "$args"` ] ; then
+		    repeat=0
+		fi
+		last="$args"
+	done
+	echo "$args"
+}
+
+replaceString() {
+	initialString="$1"	
+	fromString="$2"
+	toString="$3"
+	if [ -n "$4" ] && [ 0 -eq `ifEquals "$4" "false"` ] ; then
+		toString=`escapeString "$toString"`
+	fi
+	fromString=`echo "$fromString" | sed "s/\\\//\\\\\\\\\//g" 2>/dev/null`
+	toString=`echo "$toString" | sed "s/\\\//\\\\\\\\\//g" 2>/dev/null`
+        replacedString=`echo "$initialString" | sed "s/${fromString}/${toString}/g" 2>/dev/null`        
+	echo "$replacedString"
+}
+
+prepareJVMArguments() {
+    debug "Prepare JVM arguments... "    
+
+    jvmArgCounter=0
+    debug "... resolving string : $LAUNCHER_JVM_ARGUMENTS"
+    LAUNCHER_JVM_ARGUMENTS=`resolveString "$LAUNCHER_JVM_ARGUMENTS" true`
+    debug "... resolved  string :  $LAUNCHER_JVM_ARGUMENTS"
+    while [ $jvmArgCounter -lt $JVM_ARGUMENTS_NUMBER ] ; do		
+	 argumentVar="$""JVM_ARGUMENT_$jvmArgCounter"
+         arg=`eval "echo \"$argumentVar\""`
+	 debug "... jvm argument [$jvmArgCounter] [initial]  : $arg"
+	 arg=`resolveString "$arg"`
+	 debug "... jvm argument [$jvmArgCounter] [resolved] : $arg"
+	 arg=`escapeString "$arg"`
+	 debug "... jvm argument [$jvmArgCounter] [escaped] : $arg"
+	 LAUNCHER_JVM_ARGUMENTS="$LAUNCHER_JVM_ARGUMENTS $arg"	
+ 	 jvmArgCounter=`expr "$jvmArgCounter" + 1`
+    done                
+    if [ ! -z "${DEFAULT_USERDIR_ROOT}" ] ; then
+            debug "DEFAULT_USERDIR_ROOT: $DEFAULT_USERDIR_ROOT"
+            LAUNCHER_JVM_ARGUMENTS="$LAUNCHER_JVM_ARGUMENTS -Dnetbeans.default_userdir_root=\"${DEFAULT_USERDIR_ROOT}\""	
+    fi
+    if [ ! -z "${DEFAULT_CACHEDIR_ROOT}" ] ; then
+            debug "DEFAULT_CACHEDIR_ROOT: $DEFAULT_CACHEDIR_ROOT"
+            LAUNCHER_JVM_ARGUMENTS="$LAUNCHER_JVM_ARGUMENTS -Dnetbeans.default_cachedir_root=\"${DEFAULT_CACHEDIR_ROOT}\""	
+    fi
+
+    debug "Final JVM arguments : $LAUNCHER_JVM_ARGUMENTS"            
+}
+
+prepareAppArguments() {
+    debug "Prepare Application arguments... "    
+
+    appArgCounter=0
+    debug "... resolving string : $LAUNCHER_APP_ARGUMENTS"
+    LAUNCHER_APP_ARGUMENTS=`resolveString "$LAUNCHER_APP_ARGUMENTS" true`
+    debug "... resolved  string :  $LAUNCHER_APP_ARGUMENTS"
+    while [ $appArgCounter -lt $APP_ARGUMENTS_NUMBER ] ; do		
+	 argumentVar="$""APP_ARGUMENT_$appArgCounter"
+         arg=`eval "echo \"$argumentVar\""`
+	 debug "... app argument [$appArgCounter] [initial]  : $arg"
+	 arg=`resolveString "$arg"`
+	 debug "... app argument [$appArgCounter] [resolved] : $arg"
+	 arg=`escapeString "$arg"`
+	 debug "... app argument [$appArgCounter] [escaped] : $arg"
+	 LAUNCHER_APP_ARGUMENTS="$LAUNCHER_APP_ARGUMENTS $arg"	
+ 	 appArgCounter=`expr "$appArgCounter" + 1`
+    done
+    debug "Final application arguments : $LAUNCHER_APP_ARGUMENTS"            
+}
+
+
+runCommand() {
+	cmd="$1"
+	debug "Running command : $cmd"
+	if [ -n "$OUTPUT_FILE" ] ; then
+		#redirect all stdout and stderr from the running application to the file
+		eval "$cmd" >> "$OUTPUT_FILE" 2>&1
+	elif [ 1 -eq $SILENT_MODE ] ; then
+		# on silent mode redirect all out/err to null
+		eval "$cmd" > /dev/null 2>&1	
+	elif [ 0 -eq $USE_DEBUG_OUTPUT ] ; then
+		# redirect all output to null
+		# do not redirect errors there but show them in the shell output
+		eval "$cmd" > /dev/null	
+	else
+		# using debug output to the shell
+		# not a silent mode but a verbose one
+		eval "$cmd"
+	fi
+	return $?
+}
+
+executeMainClass() {
+	prepareClasspath
+	prepareJVMArguments
+	prepareAppArguments
+	debug "Running main jar..."
+	message "$MSG_RUNNING"
+	classpathEscaped=`escapeString "$LAUNCHER_CLASSPATH"`
+	mainClassEscaped=`escapeString "$MAIN_CLASS"`
+	launcherJavaExeEscaped=`escapeString "$LAUNCHER_JAVA_EXE"`
+	tmpdirEscaped=`escapeString "$LAUNCHER_JVM_TEMP_DIR"`
+	
+	command="$launcherJavaExeEscaped $LAUNCHER_JVM_ARGUMENTS -Djava.io.tmpdir=$tmpdirEscaped -classpath $classpathEscaped $mainClassEscaped $LAUNCHER_APP_ARGUMENTS"
+
+	debug "Running command : $command"
+	runCommand "$command"
+	exitCode=$?
+	debug "... java process finished with code $exitCode"
+	exitProgram $exitCode
+}
+
+escapeString() {
+	echo "$1" | sed "s/\\\/\\\\\\\/g;s/\ /\\\\ /g;s/\"/\\\\\"/g;s/(/\\\\\(/g;s/)/\\\\\)/g;" # escape spaces, commas and parentheses
+}
+
+getMessage() {
+        getLocalizedMessage_$LAUNCHER_LOCALE $@
+}
+
+POSSIBLE_JAVA_ENV="JAVA:JAVA_HOME:JAVAHOME:JAVA_PATH:JAVAPATH:JDK:JDK_HOME:JDKHOME:ANT_JAVA:"
+POSSIBLE_JAVA_EXE_SUFFIX_SOLARIS="bin/java:bin/sparcv9/java:"
+POSSIBLE_JAVA_EXE_SUFFIX_COMMON="bin/java:"
diff --git a/src/main/cpp/launcher/windows/.dep.inc b/src/main/cpp/launcher/windows/.dep.inc
new file mode 100644
index 0000000..4560e55
--- /dev/null
+++ b/src/main/cpp/launcher/windows/.dep.inc
@@ -0,0 +1,5 @@
+# This code depends on make tool being used
+DEPFILES=$(wildcard $(addsuffix .d, ${OBJECTFILES}))
+ifneq (${DEPFILES},)
+include ${DEPFILES}
+endif
diff --git a/src/main/cpp/launcher/windows/Makefile b/src/main/cpp/launcher/windows/Makefile
new file mode 100644
index 0000000..1debec6
--- /dev/null
+++ b/src/main/cpp/launcher/windows/Makefile
@@ -0,0 +1,109 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# 
+
+#
+#  There exist several targets which are by default empty and which can be 
+#  used for execution of your targets. These targets are usually executed 
+#  before and after some main targets. They are: 
+#
+#     .build-pre:              called before 'build' target
+#     .build-post:             called after 'build' target
+#     .clean-pre:              called before 'clean' target
+#     .clean-post:             called after 'clean' target
+#     .clobber-pre:            called before 'clobber' target
+#     .clobber-post:           called after 'clobber' target
+#     .all-pre:                called before 'all' target
+#     .all-post:               called after 'all' target
+#     .help-pre:                called before 'help' target
+#     .help-post:               called after 'help' target
+#
+#  Targets beginning with '.' are not intended to be called on their own.
+#
+#  Main targets can be executed directly, and they are:
+#  
+#     build                    build a specific configuration
+#     clean                    remove built files from a configuration
+#     clobber                  remove all built files
+#     all                      build all configurations
+#     help                     print help mesage
+#  
+#  Targets .build-impl, .clean-impl, .clobber-impl, .all-impl, and
+#  .help-impl are implemented in nbproject/makefile-impl.mk.
+#
+
+# Environment 
+MKDIR=mkdir
+CP=cp
+CCADMIN=CCadmin
+RANLIB=ranlib
+RESCOMP=windres
+
+
+# build
+build: .build-pre .build-impl .build-post
+
+.build-pre:
+	mkdir -p build
+	windres -I resources -o  build/icon.o -i resources/res.rc
+
+.build-post:
+# Add your post 'build' code here...
+
+
+# clean
+clean: .clean-pre .clean-impl .clean-post
+
+.clean-pre:
+	rm -rf build/icon.o
+
+.clean-post:
+# Add your post 'clean' code here...
+
+
+# clobber
+clobber: .clobber-pre .clobber-impl .clobber-post
+
+.clobber-pre:
+# Add your pre 'clobber' code here...
+
+.clobber-post:
+# Add your post 'clobber' code here...
+
+
+# all
+all: .all-pre .all-impl .all-post
+
+.all-pre:
+# Add your pre 'all' code here...
+
+.all-post:
+# Add your post 'all' code here...
+
+
+# help
+help: .help-pre .help-impl .help-post
+
+.help-pre:
+# Add your pre 'help' code here...
+
+.help-post:
+# Add your post 'help' code here...
+
+# include project implementation makefile
+include nbproject/Makefile-impl.mk
diff --git a/src/main/cpp/launcher/windows/Makefile-vc b/src/main/cpp/launcher/windows/Makefile-vc
new file mode 100644
index 0000000..78bc631
--- /dev/null
+++ b/src/main/cpp/launcher/windows/Makefile-vc
@@ -0,0 +1,92 @@
+#
+#
+
+
+!include <$(PLATFORM_SDK)/include/win32.mak>
+
+# define the compiler and linker for all the platforms
+CC32="$(VC_2005)\Bin\cl.exe"
+L32="$(VC_2005)\Bin\link.exe"
+MT32="$(PLATFORM_SDK)\Bin\mt.exe"
+RC32="$(VC_2005)\Bin\rc.exe"
+
+BUILD_DIR32=.\build\32bit
+OUTPUT_FILE32=.\dist\nlw.exe
+MANIFEST_FILE32=.\resources\nlw.exe.manifest
+#Alternative manifest file - read more in resources\res.rc
+#MANIFEST_FILE32=.\resources\nlw-alt.exe.manifest
+
+SOURCE_FILES=\
+	.\src\ExtractUtils.c \
+	.\src\FileUtils.c \
+	.\src\JavaUtils.c \
+	.\src\Launcher.c \
+	.\src\Main.c \
+	.\src\ProcessUtils.c \
+	.\src\RegistryUtils.c \
+	.\src\StringUtils.c \
+	.\src\SystemUtils.c
+
+
+CC32_OPTS=/O1 /Os \
+	/I "$(VC_2005)\include" \
+	/D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_CRT_SECURE_NO_DEPRECATE" \
+	/FD /EHsc /MT \
+	/Fo"$(BUILD_DIR32)\\"  /Fd"$(BUILD_DIR32)\vc80.pdb" \
+	/W3 /nologo /c /Wp64 /TC /errorReport:prompt
+
+LINKING_LIBRARIES=\
+	user32.lib\
+	gdi32.lib \
+	comdlg32.lib \
+	comctl32.lib \
+	advapi32.lib\
+	shell32.lib \
+	ole32.lib \
+	oleaut32.lib \
+	userenv.lib \
+	libcmt.lib \
+	kernel32.lib
+
+L32_OPTS=\
+	/OUT:$(OUTPUT_FILE32) \
+	/INCREMENTAL:NO \
+	/LIBPATH:"$(PLATFORM_SDK)\Lib" \
+	/MANIFEST \
+	/MANIFESTFILE:"$(BUILD_DIR32)\nlw.exe.intermediate.manifest" \
+	/NODEFAULTLIB \
+	/SUBSYSTEM:WINDOWS \
+	/OPT:REF /OPT:ICF \
+	/MACHINE:X86 \
+	/ERRORREPORT:PROMPT \
+	$(LINKING_LIBRARIES)
+
+	
+RC32_OPTS=\
+	/I ".\resources" /fo $(BUILD_DIR32)\resources.obj
+	
+
+all: init build-32
+
+clean:
+  
+
+init:
+  - md $(BUILD_DIR32)
+  - md .\dist
+
+  del /Q /S $(BUILD_DIR32)
+  del /Q  $(OUTPUT_FILE32)  
+
+build-32: 
+  Set CPU=i386
+  Set Lib=%VC_2005%\Lib;%PLATFORM_SDK%\Lib;%Lib%
+  Set Include=%PLATFORM_SDK%\Include;%Include%
+  Set Path=%PLATFORM_SDK%\Bin;%PLATFORM_SDK%\Bin\WinNT;%VC_2005_PATH%;%path%
+  Set APPVER=5.01
+  Set TARGETOS=WINNT
+  
+  $(CC32) $(CC32_OPTS) $(SOURCE_FILES)
+  $(RC32) $(RC32_OPTS) resources/res.rc
+  $(L32) $(L32_OPTS) $(BUILD_DIR32)\ExtractUtils.obj $(BUILD_DIR32)\FileUtils.obj $(BUILD_DIR32)\JavaUtils.obj $(BUILD_DIR32)\Launcher.obj $(BUILD_DIR32)\Main.obj $(BUILD_DIR32)\ProcessUtils.obj $(BUILD_DIR32)\RegistryUtils.obj $(BUILD_DIR32)\StringUtils.obj $(BUILD_DIR32)\SystemUtils.obj $(BUILD_DIR32)\resources.obj
+  $(MT32)  /outputresource:"$(OUTPUT_FILE32);#1" -manifest $(MANIFEST_FILE32) $(BUILD_DIR32)\nlw.exe.intermediate.manifest
diff --git a/src/main/cpp/launcher/windows/Makefile-vc-wo-crt b/src/main/cpp/launcher/windows/Makefile-vc-wo-crt
new file mode 100644
index 0000000..6a693f5
--- /dev/null
+++ b/src/main/cpp/launcher/windows/Makefile-vc-wo-crt
@@ -0,0 +1,92 @@
+#
+#
+
+
+!include <$(PLATFORM_SDK)/include/win32.mak>
+
+# define the compiler and linker for all the platforms
+CC32="$(VC_2005)\Bin\cl.exe"
+L32="$(VC_2005)\Bin\link.exe"
+MT32="$(PLATFORM_SDK)\Bin\mt.exe"
+RC32="$(VC_2005)\Bin\rc.exe"
+
+BUILD_DIR32=.\build\32bit
+OUTPUT_FILE32=.\dist\nlw.exe
+MANIFEST_FILE32=.\resources\nlw.exe.manifest
+#Alternative manifest file - read more in resources\res.rc
+#MANIFEST_FILE32=.\resources\nlw-alt.exe.manifest
+
+SOURCE_FILES=\
+	.\src\ExtractUtils.c \
+	.\src\FileUtils.c \
+	.\src\JavaUtils.c \
+	.\src\Launcher.c \
+	.\src\Main.c \
+	.\src\ProcessUtils.c \
+	.\src\RegistryUtils.c \
+	.\src\StringUtils.c \
+	.\src\SystemUtils.c
+
+
+CC32_OPTS=/O1 /Os \
+	/I "$(VC_2005)\include" \
+	/D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_CRT_SECURE_NO_DEPRECATE" \
+	/FD /EHsc /GS- \
+	/Fo"$(BUILD_DIR32)\\"  /Fd"$(BUILD_DIR32)\vc80.pdb" \
+	/W3 /nologo /c /Wp64 /TC /errorReport:prompt
+
+LINKING_LIBRARIES=\
+	user32.lib\
+	gdi32.lib \
+	comdlg32.lib \
+	comctl32.lib \
+	advapi32.lib\
+	shell32.lib \
+	ole32.lib \
+	oleaut32.lib \
+	userenv.lib \
+	kernel32.lib \
+
+L32_OPTS=\
+	/OUT:$(OUTPUT_FILE32) \
+	/INCREMENTAL:NO \
+	/LIBPATH:"$(PLATFORM_SDK)\Lib" \
+	/MANIFEST \
+	/MANIFESTFILE:"$(BUILD_DIR32)\nlw.exe.intermediate.manifest" \
+	/NODEFAULTLIB \
+	/SUBSYSTEM:WINDOWS \
+	/OPT:REF /OPT:ICF \
+	/MACHINE:X86 \
+	/ERRORREPORT:PROMPT \
+        /ENTRY:MyMain \
+	$(LINKING_LIBRARIES)
+
+	
+RC32_OPTS=\
+	/I ".\resources" /fo $(BUILD_DIR32)\resources.obj
+	
+
+all: init build-32
+
+clean:
+  
+
+init:
+  - md $(BUILD_DIR32)
+  - md .\dist
+
+  del /Q /S $(BUILD_DIR32)
+  del /Q  $(OUTPUT_FILE32)  
+
+build-32: 
+  Set CPU=i386
+  Set Lib=%VC_2005%\Lib;%PLATFORM_SDK%\Lib;%Lib%
+  Set Include=%PLATFORM_SDK%\Include;%Include%
+  Set Path=%PLATFORM_SDK%\Bin;%PLATFORM_SDK%\Bin\WinNT;%VC_2005_PATH%;%path%
+  Set APPVER=5.01
+  Set TARGETOS=WINNT
+  
+  $(CC32) $(CC32_OPTS) $(SOURCE_FILES)
+  $(RC32) $(RC32_OPTS) resources/res.rc
+  $(L32) $(L32_OPTS) $(BUILD_DIR32)\ExtractUtils.obj $(BUILD_DIR32)\FileUtils.obj $(BUILD_DIR32)\JavaUtils.obj $(BUILD_DIR32)\Launcher.obj $(BUILD_DIR32)\Main.obj $(BUILD_DIR32)\ProcessUtils.obj $(BUILD_DIR32)\RegistryUtils.obj $(BUILD_DIR32)\StringUtils.obj $(BUILD_DIR32)\SystemUtils.obj $(BUILD_DIR32)\resources.obj
+  $(MT32)  /outputresource:"$(OUTPUT_FILE32);#1" -manifest $(MANIFEST_FILE32) $(BUILD_DIR32)\nlw.exe.intermediate.manifest
diff --git a/src/main/cpp/launcher/windows/i18n/launcher.properties b/src/main/cpp/launcher/windows/i18n/launcher.properties
new file mode 100644
index 0000000..70f24c5
--- /dev/null
+++ b/src/main/cpp/launcher/windows/i18n/launcher.properties
@@ -0,0 +1,54 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# 
+
+nlw.jvm.notfoundmessage=Java SE Development Kit (JDK) was not found on this computer\nJDK 8 or newer is required for installing the NetBeans IDE. Make sure that the JDK is properly installed and run installer again. You can specify valid JDK location using {0} installer argument.\n\nTo download the JDK, visit http://www.oracle.com/technetwork/java/javase/downloads
+nlw.jvm.usererror=Java Runtime Environment (JRE) was not found\nThere is no JRE at the specified location {0}
+nlw.jvm.unsupportedversion=Unsupported Java VM version\nThe Java VM at {0} has the unsupported version
+nlw.freespace=There is not enough free disk space to extract installation data\n{0} MB of free disk space is required in a temporary folder. Clean up the disk space and run installer again. You can specify a temporary folder with sufficient disk space using {1} installer argument
+nlw.tmpdir=Can't create temporary directory\nThe temporary directory for extracting data {0} was not created
+nlw.integrity=Installer file is corrupted\nInstaller file {0} seems to be corrupted
+nlw.output.error=Data extraction error\nCan't create file {0}!\nThe following error occured :\n{1}
+nlw.java.process.error=An error occured while running java process\n{0}
+nlw.missing.external.resource=Can`t run NetBeans Installer.\nAn external file with necessary data is required but missing:\n{0}
+nlw.bundled.jvm.extract.error=Cannot prepare bundled JVM to run the installer.\nMost probably the bundled JVM is not compatible with the current platform.
+nlw.bundled.jvm.verify.error=An error occured while verifying bundled JVM.\nMost probably the bundled JVM is not compatible with the current platform.
+
+nlw.arg.output={0} <output-file>\n\tRedirect output to file <output-file>
+nlw.arg.javahome={0} <javahomedir>\n\tRun jar file using JVM from <javahomedir>
+nlw.arg.verbose={0}\n\tUse verbose output
+nlw.arg.tempdir={0} <temp-dir>\n\tUse <temp-dir> for extracting data
+nlw.arg.extract={0} [directory]\n\tExtract all bundled data to the specific directory.\n\tIf directory is not specified then extract to the current directory
+nlw.arg.classpatha={0} <classpath>\n\tAppend classpath with <classpath>
+nlw.arg.classpathp={0} <classpath>\n\tPrepend classpath with <classpath>
+nlw.arg.disable.space.check={0}\n\tDisable free space check
+nlw.arg.locale={0} <locale>\n\tOverride system default locale with <locale>
+nlw.arg.silent={0} \n\tRun installer silently
+nlw.arg.help={0}\n\tShow help message
+
+
+nlw.msg.create.tmpdir=Creating temporary directory ...
+nlw.msg.extract=Extracting data ...
+nlw.msg.jvmsearch=Finding JVM on your system ...
+nlw.msg.setoptions=Setting command options ...
+nlw.msg.running=Running JVM ...
+nlw.msg.title=Please wait while the launcher prepares data to run the installer ...
+nlw.msg.messagebox.title=Apache NetBeans IDE Installer
+nlw.msg.progress.title=Configuring the installer ...
+nlw.msg.button.error=Exit Installer
+nlw.msg.main.title=Apache NetBeans IDE Installer
diff --git a/src/main/cpp/launcher/windows/nbproject/configurations.xml b/src/main/cpp/launcher/windows/nbproject/configurations.xml
new file mode 100644
index 0000000..095caed
--- /dev/null
+++ b/src/main/cpp/launcher/windows/nbproject/configurations.xml
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+<configurationDescriptor version="84">
+  <logicalFolder name="root" displayName="root" projectFiles="true" kind="ROOT">
+    <logicalFolder name="HeaderFiles"
+                   displayName="Header Files"
+                   projectFiles="true">
+      <itemPath>src/Errors.h</itemPath>
+      <itemPath>src/ExtractUtils.h</itemPath>
+      <itemPath>src/FileUtils.h</itemPath>
+      <itemPath>src/JavaUtils.h</itemPath>
+      <itemPath>src/Launcher.h</itemPath>
+      <itemPath>src/Main.h</itemPath>
+      <itemPath>src/ProcessUtils.h</itemPath>
+      <itemPath>src/RegistryUtils.h</itemPath>
+      <itemPath>src/StringUtils.h</itemPath>
+      <itemPath>src/SystemUtils.h</itemPath>
+      <itemPath>src/Types.h</itemPath>
+    </logicalFolder>
+    <logicalFolder name="ResourceFiles"
+                   displayName="Resource Files"
+                   projectFiles="true">
+      <itemPath>resources/res.rc</itemPath>
+    </logicalFolder>
+    <logicalFolder name="SourceFiles"
+                   displayName="Source Files"
+                   projectFiles="true">
+      <itemPath>src/ExtractUtils.c</itemPath>
+      <itemPath>src/FileUtils.c</itemPath>
+      <itemPath>src/JavaUtils.c</itemPath>
+      <itemPath>src/Launcher.c</itemPath>
+      <itemPath>src/Main.c</itemPath>
+      <itemPath>src/ProcessUtils.c</itemPath>
+      <itemPath>src/RegistryUtils.c</itemPath>
+      <itemPath>src/StringUtils.c</itemPath>
+      <itemPath>src/SystemUtils.c</itemPath>
+    </logicalFolder>
+    <logicalFolder name="ExternalFiles"
+                   displayName="Important Files"
+                   projectFiles="false">
+      <itemPath>Makefile</itemPath>
+    </logicalFolder>
+  </logicalFolder>
+  <projectmakefile>Makefile</projectmakefile>
+  <confs>
+    <conf name="Debug" type="1">
+      <toolsSet>
+        <remote-sources-mode>LOCAL_SOURCES</remote-sources-mode>
+        <compilerSet>Cygwin|Cygwin</compilerSet>
+      </toolsSet>
+      <compileType>
+        <cTool>
+          <stripSymbols>true</stripSymbols>
+          <commandLine>-mno-cygwin</commandLine>
+          <warningLevel>3</warningLevel>
+        </cTool>
+        <ccTool>
+          <stripSymbols>true</stripSymbols>
+        </ccTool>
+        <linkerTool>
+          <output>dist/nlw</output>
+          <stripSymbols>true</stripSymbols>
+          <linkerLibItems>
+            <linkerOptionItem>-lole32 -luuid -lkernel32 -lcomctl32 -luserenv</linkerOptionItem>
+          </linkerLibItems>
+          <commandLine>-mwindows -mno-cygwin build/icon.o</commandLine>
+        </linkerTool>
+      </compileType>
+    </conf>
+    <conf name="Release" type="1">
+      <toolsSet>
+        <remote-sources-mode>LOCAL_SOURCES</remote-sources-mode>
+        <compilerSet>Cygwin|Cygwin</compilerSet>
+      </toolsSet>
+      <compileType>
+        <cTool>
+          <developmentMode>5</developmentMode>
+        </cTool>
+        <ccTool>
+          <developmentMode>5</developmentMode>
+        </ccTool>
+        <fortranCompilerTool>
+          <developmentMode>5</developmentMode>
+        </fortranCompilerTool>
+      </compileType>
+    </conf>
+  </confs>
+</configurationDescriptor>
diff --git a/src/main/cpp/launcher/windows/nbproject/project.properties b/src/main/cpp/launcher/windows/nbproject/project.properties
new file mode 100644
index 0000000..3807b67
--- /dev/null
+++ b/src/main/cpp/launcher/windows/nbproject/project.properties
@@ -0,0 +1,20 @@
+
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# 
+
diff --git a/src/main/cpp/launcher/windows/nbproject/project.xml b/src/main/cpp/launcher/windows/nbproject/project.xml
new file mode 100644
index 0000000..017b77b
--- /dev/null
+++ b/src/main/cpp/launcher/windows/nbproject/project.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+<project xmlns="http://www.netbeans.org/ns/project/1">
+    <type>org.netbeans.modules.cnd.makeproject</type>
+    <configuration>
+        <data xmlns="http://www.netbeans.org/ns/make-project/1">
+            <name>NBI Native Launcher : Windows</name>
+            <make-project-type>0</make-project-type>
+            <c-extensions>c</c-extensions>
+            <cpp-extensions/>
+            <header-extensions>h</header-extensions>
+            <sourceEncoding>UTF-8</sourceEncoding>
+            <make-dep-projects/>
+            <sourceRootList/>
+            <confList>
+                <confElem>
+                    <name>Debug</name>
+                    <type>1</type>
+                </confElem>
+                <confElem>
+                    <name>Release</name>
+                    <type>1</type>
+                </confElem>
+            </confList>
+        </data>
+    </configuration>
+</project>
diff --git a/src/main/cpp/launcher/windows/resources/icon.ico b/src/main/cpp/launcher/windows/resources/icon.ico
new file mode 100644
index 0000000..ec123c0
--- /dev/null
+++ b/src/main/cpp/launcher/windows/resources/icon.ico
Binary files differ
diff --git a/src/main/cpp/launcher/windows/resources/nlw-alt.exe.manifest b/src/main/cpp/launcher/windows/resources/nlw-alt.exe.manifest
new file mode 100644
index 0000000..62fb856
--- /dev/null
+++ b/src/main/cpp/launcher/windows/resources/nlw-alt.exe.manifest
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> 
+   <assemblyIdentity version="1.0.0.0" processorArchitecture="X86" name="nlw" type="win32"/>
+      <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
+      <security>
+         <requestedPrivileges>
+            <requestedExecutionLevel level="asInvoker"/> 
+         </requestedPrivileges>
+      </security>
+   </trustInfo>
+</assembly>
\ No newline at end of file
diff --git a/src/main/cpp/launcher/windows/resources/nlw.exe.manifest b/src/main/cpp/launcher/windows/resources/nlw.exe.manifest
new file mode 100644
index 0000000..a22dcb9
--- /dev/null
+++ b/src/main/cpp/launcher/windows/resources/nlw.exe.manifest
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> 
+   <assemblyIdentity version="1.0.0.0" processorArchitecture="X86" name="nlw" type="win32"/>
+      <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
+      <security>
+         <requestedPrivileges>
+            <requestedExecutionLevel level="requireAdministrator"/> 
+         </requestedPrivileges>
+      </security>
+   </trustInfo>
+</assembly>
\ No newline at end of file
diff --git a/src/main/cpp/launcher/windows/resources/res.rc b/src/main/cpp/launcher/windows/resources/res.rc
new file mode 100644
index 0000000..012c85e
--- /dev/null
+++ b/src/main/cpp/launcher/windows/resources/res.rc
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+
+// Uncomment the following lines to add special "Vista" manifest under Cygwin using GCC and WINDRES
+// Seems that tools from MS Platform SDK/MS VS C++ 2005 EE (C compiler, resource compiler and manifest tool) ignore that
+// (so you can leave that uncommented for both tools at once) but I haven`t check that much.
+// PS. Currently uncommented - seems to be working with GCC compiler (checked by Martin Sladecek)
+#define RT_MANIFEST  24
+#define CREATEPROCESS_MANIFEST_RESOURCE_ID 1
+
+
+// Using of nlw.exe.manifest means that on Vista every installer/uninstaller (launcher, in general) invocation would require admin privileges which user would be asked for (evaluation dialog). 
+// In that case the executable icon would have "shield" mark.
+// Using of nlw-alt.exe.manifest means that on Vista evaluation dialog is not displayed. To run it with admin right user have to execute "Run as Administrator" explicitely.
+// Without the build-it manifest the following issue can occur (reported Martin Sladecek):
+// When launcher would have "instal" in its name (uninstall.exe for instance), then - due to UAC and it`s method of checking "installer-like" names and code stamps - it would be executed with Administrator`s environment - it is would be different from the user that performed the installation.
+// Only one of the following lines should be commented, the other one should be uncommented.
+CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "nlw.exe.manifest"
+//CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "nlw-alt.exe.manifest"
+
+100 ICON DISCARDABLE "icon.ico"
+
diff --git a/src/main/cpp/launcher/windows/src/Errors.h b/src/main/cpp/launcher/windows/src/Errors.h
new file mode 100644
index 0000000..7955823
--- /dev/null
+++ b/src/main/cpp/launcher/windows/src/Errors.h
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef _Errors_H
+#define	_Errors_H
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+    
+#define ERROR_OK                            0
+#define ERROR_INTEGRITY                     1000
+#define ERROR_FREESPACE                     1001
+#define ERROR_INPUTOUPUT                    1002
+#define ERROR_JVM_UNCOMPATIBLE              1003
+#define ERROR_JVM_NOT_FOUND                 1004
+#define ERROR_ON_EXECUTE_PROCESS            1005
+#define ERROR_PROCESS_TIMEOUT               1006
+#define ERROR_USER_TERMINATED               1007
+#define EXTERNAL_RESOURCE_MISSING           1008
+#define ERROR_BUNDLED_JVM_EXTRACTION        1009
+#define ERROR_BUNDLED_JVM_VERIFICATION      1010
+    
+#define EXIT_CODE_EVENTS_INITIALIZATION_ERROR 1022
+#define EXIT_CODE_GUI_INITIALIZATION_ERROR  1023
+#define EXIT_CODE_STUB                      1024
+#define EXIT_CODE_SYSTEM_ERROR              1025
+
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _Errors_H */
+
diff --git a/src/main/cpp/launcher/windows/src/ExtractUtils.c b/src/main/cpp/launcher/windows/src/ExtractUtils.c
new file mode 100644
index 0000000..edbfa55
--- /dev/null
+++ b/src/main/cpp/launcher/windows/src/ExtractUtils.c
@@ -0,0 +1,761 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include "FileUtils.h"
+#include "StringUtils.h"
+#include "SystemUtils.h"
+#include "JavaUtils.h"
+#include "RegistryUtils.h"
+#include "ExtractUtils.h"
+#include "Launcher.h"
+#include "Main.h"
+
+const DWORD   STUB_FILL_SIZE      = 450000;
+
+void skipLauncherStub(LauncherProperties * props,  DWORD stubSize) {
+    HANDLE hFileRead = props->handler;
+    
+    if(hFileRead!=INVALID_HANDLE_VALUE) {
+        // just read stub data.. no need to write it anywhere
+        DWORD read = 0;
+        char * offsetbuf = newpChar(stubSize);
+        DWORD sizeLeft = stubSize;
+        while(ReadFile(hFileRead, offsetbuf, sizeLeft, &read, 0) && sizeLeft && read) {
+            sizeLeft-=read;
+            addProgressPosition(props, read);
+            if(sizeLeft==0) break;
+            if(read==0) { // we need some more bytes to read but we can`t to read
+                props->status = ERROR_INTEGRITY;
+                break;
+            }
+        }
+        FREE(offsetbuf);
+    }
+}
+
+
+void skipStub(LauncherProperties * props) {
+    if(props->isOnlyStub) {
+        WCHAR * os;
+        props->status = EXIT_CODE_STUB;        
+        os = appendStringW(NULL, L"It`s only the launcher stub.\nOS: ");
+        if(is9x()) os = appendStringW(os, L"Windows 9x");
+        if(isNT()) os = appendStringW(os, L"Windows NT");
+        if(is2k()) os = appendStringW(os, L"Windows 2000");
+        if(isXP()) os = appendStringW(os, L"Windows XP");
+        if(is2003())  os = appendStringW(os, L"Windows 2003");
+        if(isVista()) os = appendStringW(os, L"Windows Vista");
+        if(is2008())  os = appendStringW(os, L"Windows 2008");
+        if(is7())     os = appendStringW(os, L"Windows 7");
+	if(IsWow64) os = appendStringW(os, L" x64");
+        showMessageW(props,  os , 0);
+	FREE(os);
+    } else {
+        skipLauncherStub(props, STUB_FILL_SIZE);
+        if(!isOK(props)) {
+            writeMessageA(props, OUTPUT_LEVEL_NORMAL, 1,
+                    "Error! Can`t process launcher stub", 1);
+            showErrorW(props, INTEGRITY_ERROR_PROP, 1, props->exeName);
+        }
+    }
+}
+
+void modifyRestBytes(SizedString* rest, DWORD start) {
+    
+    DWORD len = rest->length - start;
+    char * restBytesNew = NULL;
+    
+    if(len>0) {
+        DWORD i;
+        restBytesNew = newpChar(len);
+        for(i=start;i<rest->length;i++) {
+            restBytesNew[i-start] = (rest->bytes) [i];
+        }
+    }
+    FREE(rest->bytes);
+    rest->bytes = restBytesNew;
+    rest->length = len;
+}
+
+DWORD readStringFromBuf(SizedString *rest, SizedString * result, DWORD isUnicode) {
+    if((rest->length)!=0) {
+        // we have smth in the restBytes that we have read but haven`t yet proceeded
+        DWORD i=0;
+        for(i=0;i<rest->length;i++) {
+            DWORD check = ((rest->bytes)[i]==0);
+            if(isUnicode) {
+                if ( (i/2)*2==i) {// i is even
+                    check = check && (i < rest->length-1 && ((rest->bytes)[i+1]==0));
+                } else {
+                    check = 0;
+                }
+            }
+            if( check ) { // we have found null character in the rest bytes
+                result->bytes = appendStringN(NULL, 0, rest->bytes, i);
+                result->length = i;
+                modifyRestBytes(rest, i + 1 + isUnicode);
+                return ERROR_OK;
+            }
+        }
+        //here we have found no \0 character in the rest of bytes...
+    }
+    return ERROR_INPUTOUPUT;
+}
+
+void readString(LauncherProperties * props, SizedString * result, DWORD isUnicode) {
+    DWORD * status = & props->status;
+    HANDLE hFileRead = props->handler;
+    SizedString * rest = props->restOfBytes;
+    DWORD bufferSize = props->bufsize;
+    DWORD read=0;
+    char * buf = NULL;
+    
+    if(*status != ERROR_OK ) return;
+    
+    if(readStringFromBuf(rest, result, isUnicode)==ERROR_OK) {
+        return;
+    }
+    
+    //we need to read file for more data to find \0 character...
+    
+    buf = newpChar(bufferSize);
+    
+    while (ReadFile(hFileRead, buf, bufferSize, &read, 0) && read) {
+        addProgressPosition(props, read);
+        rest->bytes = appendStringN(rest->bytes, rest->length, buf, read);
+        rest->length = rest->length + read;
+        if(readStringFromBuf(rest, result, isUnicode)==ERROR_OK) {
+            //if(result->bytes!=NULL) {
+            //we have find \0 character
+            break;
+        }
+        ZERO(buf, sizeof(char) * bufferSize);
+        if(read==0) { // we have nothing to read.. smth wrong
+            *status = ERROR_INTEGRITY;
+            break;
+        }
+    }
+    FREE(buf);
+    return;
+}
+
+
+
+void readNumber(LauncherProperties * props, DWORD * result) {
+    if(isOK(props)) {
+        
+        SizedString * numberString = createSizedString();
+        DWORD i =0;
+        DWORD number = 0;
+        
+        readString(props, numberString, 0);
+        if(!isOK(props)) {
+            freeSizedString(&numberString);
+            writeMessageA(props, OUTPUT_LEVEL_DEBUG, 1,
+                    "Error!! Can`t read number string. Most probably integrity error.", 1);
+            return;
+        }
+        
+        if(numberString->bytes==NULL) {
+            freeSizedString(&numberString);
+            writeMessageA(props, OUTPUT_LEVEL_DEBUG, 1,
+                    "Error!! Can`t read number string (it can`t be NULL). Most probably integrity error.", 1);
+            props->status = ERROR_INTEGRITY;
+            return;
+        }
+        
+        
+        for(;i<numberString->length;i++) {
+            char c = numberString->bytes[i];
+            if(c>='0' && c<='9') {
+                number = number * 10 + (c - '0');
+            } else if(c==0) {
+                // we have reached the end of number section
+                writeMessageA(props, OUTPUT_LEVEL_DEBUG, 1,
+                        "Can`t read number from string (it contains zero character):", 1);
+                writeMessageA(props, OUTPUT_LEVEL_DEBUG, 1, numberString->bytes, 1);
+                props->status = ERROR_INTEGRITY;
+                break;
+            } else {
+                // unexpected...
+                writeMessageA(props, OUTPUT_LEVEL_DEBUG, 1,
+                        "Can`t read number from string (unexpected error):", 1);
+                writeMessageA(props, OUTPUT_LEVEL_DEBUG, 1, numberString->bytes, 1);
+                props->status = ERROR_INTEGRITY;
+                break;
+            }
+        }
+        freeSizedString(&numberString);
+        *result = number;
+    }
+}
+
+void readStringWithDebugW(LauncherProperties * props, WCHAR ** dest, char * paramName) {
+    SizedString *sizedStr = createSizedString();
+    if(paramName!=NULL) {
+        writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "Reading ", 0);
+        writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, paramName, 0);
+        writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, " : ", 0);
+    }
+    readString(props, sizedStr, 1);
+    if(!isOK(props)) {
+        freeSizedString(&sizedStr);
+        writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0,
+                "[ERROR] Can`t read string !! Seems to be integrity error", 1);
+        return;
+    }
+    *dest = createWCHAR(sizedStr);
+    freeSizedString(&sizedStr);
+    if(paramName!=NULL) {
+        if((*dest)!=NULL) {
+            writeMessageW(props, OUTPUT_LEVEL_DEBUG, 0,  *dest, 1);
+        } else {
+            writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "NULL", 1);
+        }
+    }
+    return;
+}
+
+void readStringWithDebugA(LauncherProperties * props, char ** dest, char * paramName) {
+    SizedString *sizedStr = createSizedString();
+    
+    if(paramName!=NULL) {
+        writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "Reading ", 0);
+        writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, paramName, 0);
+        writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, " : ", 0);
+    }
+    readString( props, sizedStr, 0);
+    if(!isOK(props)) {
+        freeSizedString(&sizedStr);
+        writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0,
+                "[ERROR] Can`t read string!!! Seems to be integritiy error", 1);
+        return;
+    }
+    *dest = appendString(NULL, sizedStr->bytes);
+    if(paramName!=NULL) {
+        if((*dest)==NULL) {
+            writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "NULL", 1);
+        } else {
+            writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, *dest, 1);
+        }
+    }
+    freeSizedString(&sizedStr);
+    return;
+}
+
+
+void readNumberWithDebug(LauncherProperties * props, DWORD * dest, char * paramName) {
+    writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "Reading ", 0);
+    writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, paramName, 0);
+    writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, " : ", 0);
+    readNumber(props, dest);
+    
+    if(!isOK(props)) {
+        writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0,
+                "[ERROR] Can`t read number !!! Seems to be integrity error", 1);
+        return;
+    }
+    writeDWORD(props, OUTPUT_LEVEL_DEBUG, 0, NULL, *dest, 1);
+    return;
+}
+void readBigNumberWithDebug(LauncherProperties * props, int64t * dest, char * paramName) {
+    DWORD low = 0;
+    DWORD high = 0;
+    writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "Reading ", 0);
+    writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0,  paramName, 0);
+    writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, " : ", 0);
+    
+    readNumber(props, &low);
+    if(isOK(props)) {
+        readNumber(props, &high);
+    }
+    if(!isOK(props)) {
+        writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0,
+                "[ERROR] Can`t read number !!! Seems to be integrity error", 1);
+        return;
+    }
+    dest->High = high;
+    dest->Low  = low;
+    writeint64t(props, OUTPUT_LEVEL_DEBUG, 0, "", dest, 1);
+}
+
+// returns: ERROR_OK, ERROR_INPUTOUPUT, ERROR_INTEGRITY
+void extractDataToFile(LauncherProperties * props, WCHAR *output, int64t * fileSize, DWORD expectedCRC ) {
+    if(isOK(props)) {
+        DWORD * status = & props->status;
+        HANDLE hFileRead = props->handler;
+        int64t * size = fileSize;
+        DWORD counter = 0;
+        DWORD crc32 = -1L;
+        HANDLE hFileWrite = CreateFileW(output, GENERIC_READ | GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, hFileRead);
+        
+        if (hFileWrite == INVALID_HANDLE_VALUE) {
+            WCHAR * err;
+            writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "[ERROR] Can`t create file ", 0);
+            writeMessageW(props, OUTPUT_LEVEL_DEBUG, 0, output, 1);
+            
+            err = getErrorDescription(GetLastError());
+            writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "Error description : ", 0);
+            writeMessageW(props, OUTPUT_LEVEL_DEBUG, 0, err, 1);
+            
+            showErrorW(props, OUTPUT_ERROR_PROP, 2, output, err);
+            FREE(err);
+            *status = ERROR_INPUTOUPUT;
+            return;
+        }
+        if(props->restOfBytes->length!=0 && props->restOfBytes->bytes!=NULL) {
+            //check if the data stored in restBytes is more than we neen
+            // rest bytes contains much less than int64t so we operate here only bith low bits of size
+            DWORD restBytesToWrite = (compare(size, props->restOfBytes->length)> 0 ) ? props->restOfBytes->length : size->Low;
+            DWORD usedBytes = restBytesToWrite;
+            
+            char *ptr = props->restOfBytes->bytes;
+            
+            DWORD write = 0;
+            while (restBytesToWrite >0) {
+                WriteFile(hFileWrite, ptr, restBytesToWrite, &write, 0);
+                update_crc32(&crc32, ptr, write);
+                restBytesToWrite -= write;
+                ptr +=write;
+            }
+            modifyRestBytes(props->restOfBytes, usedBytes);
+            minus(size, usedBytes);
+            
+        }
+        
+        
+        if(compare(size, 0) > 0 ) {
+            DWORD bufferSize = props->bufsize;
+            char * buf = newpChar(bufferSize);
+            DWORD bufsize = (compare(size, bufferSize) > 0) ? bufferSize : size->Low;
+            DWORD read = 0 ;
+            //  printf("Using buffer size: %u/%u\n", bufsize, bufferSize);
+            while (ReadFile(hFileRead, buf, bufsize, &read, 0) && read && compare(size, 0) > 0) {
+                addProgressPosition(props, read);
+                WriteFile(hFileWrite, buf, read, &read, 0);
+                update_crc32(&crc32, buf, read);
+                
+                minus(size, read);
+                
+                if((compare(size, bufsize)<0) && (compare(size, 0)>0) ) {
+                    bufsize = size->Low;
+                }
+                ZERO(buf, sizeof(char) * bufferSize);
+                if(compare(size, 0)==0) {
+                    break;
+                }
+                if((counter ++) % 20 == 0)  {
+                    if(isTerminated(props)) break;
+                }
+                
+            }
+            if((compare(size, 0)>0 || read==0) && !isTerminated(props)) {
+                // we could not read requested size
+                * status = ERROR_INTEGRITY;
+                writeMessageA(props, OUTPUT_LEVEL_DEBUG, 1,
+                        "Can`t read data from file : not enought data", 1);
+            }
+            FREE(buf);
+        }
+        CloseHandle(hFileWrite);
+        crc32=~crc32;
+        if(isOK(props) && crc32!=expectedCRC) {
+            writeDWORD(props, OUTPUT_LEVEL_DEBUG, 0, "expected CRC : ", expectedCRC, 1);
+            writeDWORD(props, OUTPUT_LEVEL_DEBUG, 0, "real     CRC : ", crc32, 1);
+            * status = ERROR_INTEGRITY;
+            
+        }
+    }
+}
+
+//returns : ERROR_OK, ERROR_INTEGRITY, ERROR_FREE_SPACE
+void extractFileToDir(LauncherProperties * props, WCHAR ** resultFile) {
+    WCHAR * fileName = NULL;
+    int64t * fileLength = NULL;
+    DWORD crc = 0;
+    writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "Extracting file ...", 1);
+    readStringWithDebugW( props, & fileName, "file name");
+    
+    fileLength = newint64_t(0, 0);
+    readBigNumberWithDebug( props, fileLength, "file length ");
+    
+    readNumberWithDebug( props, &crc, "CRC32");
+    
+    if(!isOK(props)) return;
+    
+    if(fileName!=NULL) {
+        DWORD i=0;
+        WCHAR * dir;
+        resolveString(props, &fileName);
+        
+        for(i=0;i<getLengthW(fileName);i++) {
+            if(fileName[i]==L'/') {
+                fileName[i]=L'\\';
+            }
+        }
+        
+        dir = getParentDirectory(fileName);
+        writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "   ... extract to directory = ", 0);
+        writeMessageW(props, OUTPUT_LEVEL_DEBUG, 0,  dir, 1);
+        
+        checkFreeSpace(props, dir, fileLength);
+        FREE(dir);
+        if(isOK(props)) {
+            writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "   ... starting data extraction", 1);
+            writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "   ... output file is ", 0);
+            writeMessageW(props, OUTPUT_LEVEL_DEBUG, 0, fileName, 1);
+            extractDataToFile(props, fileName, fileLength, crc);
+            writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "   ... extraction finished", 1);
+            *resultFile = fileName;
+        } else {
+            writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "   ... data extraction canceled", 1);
+        }
+    } else {
+        writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0,  "Error! File name can`t be null. Seems to be integrity error!", 1);
+        *resultFile = NULL;
+        props -> status = ERROR_INTEGRITY;
+    }
+    FREE(fileLength);
+    return;
+}
+
+
+void loadI18NStrings(LauncherProperties * props) {
+    DWORD i=0;
+    DWORD j=0;
+    //read number of locales
+    
+    DWORD numberOfLocales = 0;
+    DWORD numberOfProperties = 0;
+    
+    readNumberWithDebug(props, &numberOfLocales, "number of locales");
+    if(!isOK(props)) return;
+    if(numberOfLocales==0) {
+        props->status = ERROR_INTEGRITY;
+        return ;
+    }
+    
+    
+    readNumberWithDebug( props, &numberOfProperties, "i18n properties");
+    if(!isOK(props)) return;
+    if(numberOfProperties==0) {
+        props->status = ERROR_INTEGRITY;
+        return ;
+    }
+    
+    props->i18nMessages = (I18NStrings * ) LocalAlloc(LPTR, sizeof(I18NStrings) * numberOfProperties);
+    
+    props->I18N_PROPERTIES_NUMBER = numberOfProperties;
+    props->i18nMessages->properties = newppChar(props->I18N_PROPERTIES_NUMBER);
+    props->i18nMessages->strings = newppWCHAR(props->I18N_PROPERTIES_NUMBER);
+    
+    for(i=0; isOK(props) && i<numberOfProperties;i++) {
+        // read property name as ASCII
+        char * propName = NULL;
+        char * number = DWORDtoCHARN(i,2);
+        props->i18nMessages->properties[i] = NULL;
+        props->i18nMessages->strings[i] = NULL;
+        propName = appendString(NULL, "property name ");
+        
+        propName = appendString(propName, number);
+        FREE(number);
+        
+        readStringWithDebugA(props, & (props->i18nMessages->properties[i]), propName);
+        FREE(propName);
+    }
+    if(isOK(props)) {
+        
+        DWORD isLocaleMatches;
+        WCHAR * localeName;
+        WCHAR * currentLocale = getLocaleName();
+        
+        writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "Current System Locale : ", 0);
+        writeMessageW(props, OUTPUT_LEVEL_DEBUG, 0,  currentLocale, 1);
+        
+        if(props->userDefinedLocale!=NULL) { // using user-defined locale via command-line parameter
+            writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "[CMD Argument] Try to use locale ", 0);
+            writeMessageW(props, OUTPUT_LEVEL_NORMAL, 0, props->userDefinedLocale, 1);
+            FREE(currentLocale);
+            currentLocale = appendStringW(NULL, props->userDefinedLocale);
+        }
+        
+        for(j=0;j<numberOfLocales;j++) { //  for all locales in file...
+            // read locale name as UNICODE ..
+            // it should be like en_US or smth like that
+            localeName = NULL;
+            readStringWithDebugW(props, &localeName, "locale name");
+            if(!isOK(props)) break;
+            
+            isLocaleMatches = (localeName==NULL) ?  1 :
+                searchW(currentLocale, localeName) != NULL;
+                
+                //read properties names and value
+                for(i=0;i<numberOfProperties;i++) {
+                    // read property value as UNICODE
+                    
+                    WCHAR * value = NULL;
+                    char * s1 =  DWORDtoCHAR(i + 1);
+                    char * s2 =  DWORDtoCHAR(numberOfProperties);
+                    char * s3 = appendString(NULL , "value ");
+                    s3 = appendString(s3 , s1);
+                    s3 = appendString(s3, "/");
+                    s3 = appendString(s3, s2);
+                    FREE(s1);
+                    FREE(s2);
+                    readStringWithDebugW(props, &value, s3);
+                    
+                    FREE(s3);
+                    if(!isOK(props)) break;
+                    if(isLocaleMatches) {
+                        //it is a know property
+                        FREE(props->i18nMessages->strings[i]);
+                        props->i18nMessages->strings[i] = appendStringW(NULL, value);
+                    }
+                    FREE(value);
+                }
+                FREE(localeName);
+        }
+        FREE(currentLocale);
+    }
+}
+
+LauncherResource * newLauncherResource() {
+    LauncherResource * file = (LauncherResource *) LocalAlloc(LPTR, sizeof(LauncherResource));
+    file->path=NULL;
+    file->resolved=NULL;
+    file->type=0;
+    return file;
+}
+WCHARList * newWCHARList(DWORD number) {
+    WCHARList * list = (WCHARList*) LocalAlloc(LPTR, sizeof(WCHARList));
+    list->size  = number;
+    if(number>0) {
+        DWORD i=0;
+        list->items = newppWCHAR(number);
+        for(i=0;i<number;i++) {
+            list->items[i] = NULL;
+        }
+    } else {
+        list->items = NULL;
+    }
+    return list;
+}
+
+void freeWCHARList(WCHARList ** plist) {
+    WCHARList * list;
+    list = * plist;
+    if(list!=NULL) {
+        DWORD i=0;
+        if(list->items!=NULL) {
+            for(i=0;i<list->size;i++) {
+                FREE(list->items[i]);
+            }
+            FREE(list->items);
+        }
+        FREE(*plist);
+    }
+}
+
+LauncherResourceList * newLauncherResourceList(DWORD number) {
+    LauncherResourceList * list = (LauncherResourceList*) LocalAlloc(LPTR, sizeof(LauncherResourceList));
+    list->size  = number;
+    if(number > 0) {
+        DWORD i=0;
+        
+        list->items = (LauncherResource**) LocalAlloc(LPTR, sizeof(LauncherResource*) * number);
+        for(i=0;i<number;i++) {
+            list->items[i] = NULL;
+        }
+    } else {
+        list->items = NULL;
+    }
+    return list;
+}
+
+void freeLauncherResource(LauncherResource ** file) {
+    if(*file!=NULL) {
+        FREE((*file)->path);
+        FREE((*file)->resolved);
+        FREE(*file);
+        
+    }
+}
+
+
+void extractLauncherResource(LauncherProperties * props, LauncherResource ** file, char * name) {
+    char * typeStr = appendString(appendString(NULL, name), " type");
+    * file = newLauncherResource();
+    
+    readNumberWithDebug( props, & ((*file)->type) , typeStr);
+    
+    if(isOK(props)) {
+        FREE(typeStr);
+        
+        if((*file)->type==0) { //bundled
+            writeMessageA(props, OUTPUT_LEVEL_DEBUG, 1,  "... file is bundled", 1);
+            extractFileToDir(props, & ((*file)->path));
+            if(!isOK(props)) {
+                writeMessageA(props, OUTPUT_LEVEL_DEBUG, 1,  "Error extracting file!", 1);
+                return;
+            } else {
+                (*file)->resolved = appendStringW(NULL, (*file)->path);
+                writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "file was succesfully extracted to ", 0);
+                writeMessageW(props, OUTPUT_LEVEL_DEBUG, 0,  (*file)->path, 1);
+            }
+        } else {
+            writeMessageA(props, OUTPUT_LEVEL_DEBUG, 1,  "... file is external", 1);
+            readStringWithDebugW(props, & ((*file)->path), name);
+            if(!isOK(props)) {
+                writeMessageA(props, OUTPUT_LEVEL_DEBUG, 1, "Error reading ", 1);
+                writeMessageA(props, OUTPUT_LEVEL_DEBUG, 1, name, 1);
+            }
+        }
+    }  else {
+        writeMessageA(props, OUTPUT_LEVEL_DEBUG, 1, "Error reading ", 0);
+        writeMessageA(props, OUTPUT_LEVEL_DEBUG, 1, typeStr, 0);
+        FREE(typeStr);
+    }
+}
+
+void readWCHARList(LauncherProperties * props, WCHARList ** list, char * name) {
+    DWORD number = 0;
+    DWORD i =0;
+    char * numberStr = appendString(appendString(NULL, "number of "), name);
+    
+    * list = NULL;
+    readNumberWithDebug(props, &number, numberStr);
+    FREE(numberStr);
+    
+    if(!isOK(props)) return;
+    
+    * list = newWCHARList(number);
+    for(i=0;i < (*list)->size ;i++) {
+        char * nextStr = appendString(appendString(NULL, "next item in "), name);
+        readStringWithDebugW(props, &((*list)->items[i]), nextStr);
+        FREE(nextStr);
+        if(!isOK(props)) return;
+    }
+}
+void readLauncherResourceList(LauncherProperties * props,  LauncherResourceList ** list, char * name) {
+    DWORD num = 0;
+    DWORD i=0;
+    char * numberStr = appendString(appendString(NULL, "number of "), name);
+    readNumberWithDebug(props, &num, numberStr);
+    FREE(numberStr);
+    if(!isOK(props)) return;
+    
+    * list = newLauncherResourceList(num);
+    for(i=0;i<(*list)->size;i++) {
+        extractLauncherResource(props, & ((*list)->items[i]), "launcher resource");
+        if(!isOK(props)) {
+            char * str = appendString(appendString(NULL, "Error processing "), name);
+            writeMessageA(props, OUTPUT_LEVEL_DEBUG, 1, str, 1);
+            FREE(str);
+            break;
+        }
+    }
+}
+
+void readLauncherProperties(LauncherProperties * props) {
+    DWORD i=0;
+    char * str = NULL;
+    
+    readWCHARList(props, &(props->jvmArguments), "jvm arguments");
+    if(!isOK(props)) return;
+    
+    readWCHARList(props, &(props->appArguments), "app arguments");
+    if(!isOK(props)) return;
+    
+    readStringWithDebugW(props, &(props->mainClass), "Main Class");
+    if(!isOK(props)) return;
+    
+    readStringWithDebugW(props, &(props->testJVMClass), "TestJVM Class");
+    if(!isOK(props)) return;
+    
+    readNumberWithDebug( props, &(props->compatibleJavaNumber),
+            "compatible java");
+    if(!isOK(props)) return;
+    
+    
+    
+    if ( props->compatibleJavaNumber > 0 ) {
+        props->compatibleJava = (JavaCompatible **) LocalAlloc(LPTR, sizeof(JavaCompatible *) * props->compatibleJavaNumber);
+        for(i=0;i<props->compatibleJavaNumber;i++) {
+            
+            props->compatibleJava [i] = newJavaCompatible() ;
+            
+            readStringWithDebugA(props, &str, "min java version");
+            if(!isOK(props)) return;
+            props->compatibleJava[i]->minVersion = getJavaVersionFromString(str, &props->status);
+            FREE(str);
+            if(!isOK(props)) return;
+            
+            str = NULL;
+            readStringWithDebugA(props, &str, "max java version");
+            if(!isOK(props)) return;
+            props->compatibleJava[i]->maxVersion = getJavaVersionFromString(str, &props->status);
+            FREE(str);
+            if(!isOK(props)) return;
+            
+            readStringWithDebugA(props, &(props->compatibleJava[i]->vendor) ,
+                    "vendor");
+            if(!isOK(props)) return;
+            
+            readStringWithDebugA(props, &(props->compatibleJava[i]->osName) ,
+                    "os name");
+            if(!isOK(props)) return;
+            
+            readStringWithDebugA(props, &(props->compatibleJava[i]->osArch) ,
+                    "os arch");
+            if(!isOK(props)) return;
+            
+        }
+    }
+    readNumberWithDebug( props, &props->bundledNumber, "bundled files");
+    readBigNumberWithDebug(props, props->bundledSize, "bundled size");
+}
+
+void extractJVMData(LauncherProperties * props) {
+    if(isOK(props)) {
+        
+        writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "Extracting JVM data... ", 1);
+        extractLauncherResource(props,  &(props->testJVMFile), "testJVM file");
+        if(!isOK(props)) {
+            writeMessageA(props, OUTPUT_LEVEL_DEBUG, 1, "Error extracting testJVM file!", 1);
+            return ;
+        }
+        
+        readLauncherResourceList(props, &(props->jvms), "JVMs");
+    }
+}
+
+void extractData(LauncherProperties *props) {
+    if(isOK(props)) {
+        writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "Extracting Bundled data... ", 1);
+        readLauncherResourceList(props,  &(props->jars), "bundled and external files");
+        if(isOK(props)) {
+            readLauncherResourceList(props,  &(props->other), "other data");
+        }
+    }
+}
diff --git a/src/main/cpp/launcher/windows/src/ExtractUtils.h b/src/main/cpp/launcher/windows/src/ExtractUtils.h
new file mode 100644
index 0000000..f816df8
--- /dev/null
+++ b/src/main/cpp/launcher/windows/src/ExtractUtils.h
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef _ExtractUtils_H
+#define	_ExtractUtils_H
+
+#include <windows.h>
+#include "StringUtils.h"
+#include "JavaUtils.h"
+#include "Errors.h"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif    
+    
+    extern const DWORD STUB_FILL_SIZE;
+    
+    void skipStub(LauncherProperties * props);
+    
+    void loadI18NStrings(LauncherProperties * props);
+    
+    WCHARList * newWCHARList(DWORD number) ;
+    void readLauncherProperties(LauncherProperties * props);    
+    void freeWCHARList(WCHARList ** plist);
+    void freeLauncherResource(LauncherResource ** file);
+    
+    void extractJVMData(LauncherProperties * props);
+    void extractData(LauncherProperties *props);
+    
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _ExtractUtils_H */
diff --git a/src/main/cpp/launcher/windows/src/FileUtils.c b/src/main/cpp/launcher/windows/src/FileUtils.c
new file mode 100644
index 0000000..6c36fd6
--- /dev/null
+++ b/src/main/cpp/launcher/windows/src/FileUtils.c
@@ -0,0 +1,593 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <windows.h>
+#include <wchar.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <userenv.h>
+#include "FileUtils.h"
+#include "StringUtils.h"
+
+HANDLE stdoutHandle = INVALID_HANDLE_VALUE;
+HANDLE stderrHandle = INVALID_HANDLE_VALUE;
+
+DWORD newLine = 1;
+const WCHAR * FILE_SEP = L"\\";
+
+const long CRC32_TABLE[256] = {
+    0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535,
+    0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd,
+    0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d,
+    0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
+    0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
+    0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
+    0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac,
+    0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
+    0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab,
+    0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
+    0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb,
+    0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+    0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea,
+    0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce,
+    0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
+    0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
+    0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409,
+    0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
+    0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739,
+    0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+    0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268,
+    0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0,
+    0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8,
+    0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+    0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
+    0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703,
+    0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7,
+    0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
+    0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae,
+    0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+    0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6,
+    0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
+    0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d,
+    0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5,
+    0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
+    0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+    0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
+};
+
+void writeTimeStamp(HANDLE hd, DWORD need) {
+    DWORD written;
+    if(need==1) {
+        SYSTEMTIME t;	
+        char * yearStr;
+        char * monthStr;
+        char * dayStr;
+        char * hourStr;
+        char * minuteStr;
+        char * secondStr;
+        char * msStr;
+        char * result = NULL;
+        GetLocalTime(&t);
+        yearStr = word2charN(t.wYear,2);
+        monthStr = word2charN(t.wMonth,2);
+        dayStr = word2charN(t.wDay,2);
+        hourStr = word2charN(t.wHour,2);
+        minuteStr = word2charN(t.wMinute,2);
+        secondStr = word2charN(t.wSecond,2);
+        msStr = word2charN(t.wMilliseconds,3);
+        
+        result = appendString(NULL, "[");
+        result = appendString(result, yearStr);
+        result = appendString(result, "-");
+        result = appendString(result, monthStr);
+        result = appendString(result, "-");
+        result = appendString(result, dayStr);
+        result = appendString(result, " ");
+        result = appendString(result, hourStr);
+        result = appendString(result, ":");
+        result = appendString(result, minuteStr);
+        result = appendString(result, ":");
+        result = appendString(result, secondStr);
+        result = appendString(result, ".");
+        result = appendString(result, msStr);
+        result = appendString(result, "]> ");
+
+        WriteFile(hd, result, sizeof(char) * getLengthA(result), & written, NULL);
+        FREE(result);
+        FREE(yearStr);
+        FREE(monthStr);
+        FREE(dayStr);
+
+        FREE(hourStr);
+        FREE(minuteStr);
+        FREE(secondStr);
+        FREE(msStr);
+    }
+}
+
+void writeMessageA(LauncherProperties * props, DWORD level, DWORD isErr,  const char * message, DWORD needEndOfLine) {
+    if(level>=props->outputLevel) {
+        HANDLE hd = (isErr) ? props->stderrHandle : props->stdoutHandle;
+        DWORD written;
+        writeTimeStamp(hd, newLine);
+        WriteFile(hd, message, sizeof(char) * getLengthA(message), & written, NULL);
+        if(needEndOfLine>0) {
+            newLine = 0;
+            while((needEndOfLine--)>0) {
+                writeMessageA(props, level, isErr, "\r\n", 0);
+                newLine = 1;
+            }
+            flushHandle(hd);
+        } else {
+            newLine = 0;
+        }
+    }
+}
+
+void writeMessageW(LauncherProperties * props, DWORD level, DWORD isErr,  const WCHAR * message, DWORD needEndOfLine) {
+    if ( level >= props->outputLevel ) {
+        char * msg = toChar(message);
+        writeMessageA(props, level, isErr, msg, needEndOfLine);
+        FREE(msg);
+    }
+}
+void writeDWORD(LauncherProperties * props, DWORD level,  DWORD isErr,  const char * message, DWORD value, DWORD needEndOfLine) {
+    char * dwordStr = DWORDtoCHAR(value);
+    writeMessageA(props, level, isErr, message, 0);
+    writeMessageA(props, level, isErr, dwordStr, needEndOfLine);
+    FREE(dwordStr);
+}
+
+void writeint64t(LauncherProperties * props, DWORD level, DWORD isErr, const char * message, int64t * value, DWORD needEndOfLine) {
+    char * str = int64ttoCHAR(value);
+    writeMessageA(props, level, isErr, message, 0);
+    writeMessageA(props, level, isErr, str, needEndOfLine);
+    FREE(str);
+}
+void writeErrorA(LauncherProperties * props, DWORD level, DWORD isErr, const char * message, const WCHAR * param, DWORD errorCode) {
+    WCHAR * err = getErrorDescription(errorCode);
+    writeMessageA(props, level, isErr, message, 0);
+    writeMessageW(props, level, isErr, param, 1);
+    writeMessageW(props, level, isErr, err, 1);
+    FREE(err);
+}
+
+void flushHandle(HANDLE hd) {
+    FlushFileBuffers(hd);
+}
+
+int64t * getFreeSpace(WCHAR *path) {
+    int64t bytes;
+    int64t * result = newint64_t(0, 0);
+    WCHAR * dst = appendStringW(NULL, path);
+    
+    while(!fileExists(dst)) {
+        WCHAR * parent = getParentDirectory(dst);
+        FREE(dst);
+        dst = parent;
+        if(dst==NULL) break;
+    }
+    if(dst==NULL) return result; // no parent ? strange
+    if (GetDiskFreeSpaceExW(dst, (PULARGE_INTEGER) &bytes, NULL, NULL)) {
+        result->High = bytes.High;
+        result->Low  = bytes.Low;
+    }
+    FREE(dst);
+    return result;
+}
+
+void checkFreeSpace(LauncherProperties * props, WCHAR * tmpDir, int64t * size) {
+    if(props->checkForFreeSpace) {
+        int64t * space = getFreeSpace(tmpDir);
+        DWORD   result = 0;
+        result = ((space->High > size->High) ||
+                (space->High == size->High && space->Low >= size->Low));
+        
+        if(!result) {            
+            WCHAR * available = NULL;
+            WCHAR * str = NULL;
+            WCHAR * required = NULL;
+            available = int64ttoWCHAR(space);
+            required  = int64ttoWCHAR(size);
+            str = appendStringW(str, L"Not enough free space in ");
+            str = appendStringW(str, tmpDir);
+            str = appendStringW(str, L", available=");
+            str = appendStringW(str, available);
+            str = appendStringW(str, L", required=");
+            str = appendStringW(str, required);
+
+            writeMessageW(props, OUTPUT_LEVEL_DEBUG, 1, str, 1);
+            FREE(str);
+            FREE(available);
+            FREE(required);
+            props->status = ERROR_FREESPACE;
+        }
+        FREE(space);
+    } else {
+        writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "... free space checking is disabled", 1);
+    }
+}
+
+DWORD fileExists(WCHAR *path) {
+    WIN32_FILE_ATTRIBUTE_DATA attrs;
+    return GetFileAttributesExW(path, GetFileExInfoStandard, &attrs);
+}
+
+DWORD isDirectory(WCHAR *path) {
+    WIN32_FILE_ATTRIBUTE_DATA attrs;
+    if(GetFileAttributesExW(path, GetFileExInfoStandard, &attrs)) {
+        return (attrs.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
+    }
+    else {
+        return 0;
+    }
+}
+WCHAR * getParentDirectory(WCHAR * dir) {
+    WCHAR * ptr = dir;
+    WCHAR * res = NULL;
+    while(1) {
+        if(searchW(ptr, FILE_SEP)==NULL) {
+            break;
+        }
+        ptr = searchW(ptr, FILE_SEP) + 1;
+    }
+    res = appendStringNW(NULL, 0, dir, getLengthW(dir) - getLengthW(ptr) - 1);
+    return res;
+}
+WCHAR * normalizePath(WCHAR * dir) {
+    WCHAR * directory = NULL;
+    WCHAR * ptr1, *ptr2, *ptr3;
+    DWORD i=0;
+    DWORD len;
+    ptr1 = searchW(dir, L":\\");
+    ptr2 = searchW(dir, L":/");
+    ptr3 = searchW(dir, L"\\\\");
+    if(ptr1==NULL && ptr2==NULL && dir!=ptr3) { //relative path
+        directory = appendStringW(getCurrentDirectory(), FILE_SEP);
+        directory = appendStringW(directory, dir);
+    } else {
+        directory = appendStringW(NULL, dir);
+    }
+    len = getLengthW(directory);
+    
+    for(i=0;i<len;i++) {
+        if(directory[i]=='/') directory[i] = '\\';
+    }
+    return directory;
+}
+
+void createDirectory(LauncherProperties * props, WCHAR * directory) {
+    
+    WCHAR * parent;
+    // now directory is the absolute path with normalized slashes
+    writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "Getting parent directory of ", 0);
+    writeMessageW(props, OUTPUT_LEVEL_DEBUG, 0, directory, 1);
+    
+    parent = getParentDirectory(directory);
+    
+    if(parent!=NULL) {
+        writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "    parent = ", 0);
+        writeMessageW(props, OUTPUT_LEVEL_DEBUG, 0, parent, 1);
+        
+        if(!fileExists(parent)) {
+            writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "... doesn`t exist. Create it...", 1);
+            createDirectory(props, parent);
+        } else {
+            writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "    ... exist. ", 1);
+        }
+        if(isOK(props)) {
+            DWORD parentAttrs = GetFileAttributesW(parent);
+            if(parentAttrs == INVALID_FILE_ATTRIBUTES) {
+                props-> status = ERROR_INPUTOUPUT;
+            } else  {
+                SECURITY_ATTRIBUTES secattr;
+                int64t * minSize = newint64_t(0, 0);
+                
+                secattr.nLength = sizeof(SECURITY_ATTRIBUTES);
+                secattr.lpSecurityDescriptor = 0;
+                secattr.bInheritHandle = 1;
+                writeMessageA(props, OUTPUT_LEVEL_DEBUG, 1, "... creating directory itself... ", 0);
+                writeMessageW(props, OUTPUT_LEVEL_DEBUG, 1, directory, 1);
+                
+                checkFreeSpace(props, parent, minSize);
+                FREE(minSize);
+                
+                if(isOK(props)) {
+                    props->status = (CreateDirectoryExW(parent, directory, &secattr)) ? ERROR_OK : ERROR_INPUTOUPUT;
+                    if(!isOK(props)) {
+                        props->status = (CreateDirectoryW(directory, &secattr)) ? ERROR_OK : ERROR_INPUTOUPUT;
+                    }
+                    props->status = (fileExists(directory)) ? ERROR_OK : ERROR_INPUTOUPUT;
+                    
+                    if(isOK(props)) {
+                        SetFileAttributesW(directory, parentAttrs);
+                    } else {
+                        writeErrorA(props, OUTPUT_LEVEL_DEBUG, 1, "Error! Can`t create directory : ", directory, GetLastError());
+                    }
+                }
+            }
+        }
+        FREE(parent);
+    } else {
+        writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "    parent is NULL ", 1);
+        props-> status = ERROR_INPUTOUPUT;
+    }
+}
+
+#define a 16807         /* multiplier */
+#define m 2147483647L   /* 2**31 - 1 */
+#define q 127773L       /* m div a */
+#define r 2836          /* m mod a */
+
+long nextRandDigit(long seed)
+{
+      unsigned long lo, hi;
+
+      lo = a * (long)(seed & 0xFFFF);
+      hi = a * (long)((unsigned long)seed >> 16);
+      lo += (hi & 0x7FFF) << 16;
+      if (lo > m)
+      {
+            lo &= m;
+            ++lo;
+      }
+      lo += hi >> 15;
+      if (lo > m)
+      {
+            lo &= m;
+            ++lo;
+      }
+      return (long)lo;
+}
+
+void createTempDirectory(LauncherProperties * props, WCHAR * argTempDir, DWORD createRndSubDir) {
+    WCHAR * t = (argTempDir!=NULL) ? appendStringW(NULL, argTempDir) : getSystemTemporaryDirectory();
+    
+    WCHAR * nbiTmp = normalizePath(t);
+    FREE(t);
+    if(createRndSubDir) {
+        WCHAR * randString = newpWCHAR(6);
+        DWORD i=0;
+        DWORD initValue = GetTickCount() & 0x7FFFFFFF;
+        long value = (long) initValue;
+        nbiTmp = appendStringW(nbiTmp, L"\\NBI");        
+        
+        for(i=0;i<5;i++) {
+            value = nextRandDigit(value);
+            randString[i] = '0' + (WCHAR) (value% 10);
+        }
+        nbiTmp = appendStringW(appendStringW(nbiTmp, randString), L".tmp");
+        FREE(randString);
+    }
+    
+    writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "Using temp directory for extracting data : ", 0);
+    writeMessageW(props, OUTPUT_LEVEL_NORMAL, 0, nbiTmp, 1);
+    
+    if(fileExists(nbiTmp) ) {
+        if(!isDirectory(nbiTmp)) {
+            props->status = ERROR_INPUTOUPUT;
+            writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, ".. exists but not a directory", 1);
+        } else {
+            writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "Output directory already exist so don`t create it", 1);
+        }
+    }
+    else {
+        writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "creating directory...", 1);
+        createDirectory(props, nbiTmp);
+        if(isOK(props)) {
+            props->tmpDirCreated = 1;
+            writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "Directory created : ", 0);
+            writeMessageW(props, OUTPUT_LEVEL_DEBUG, 0, nbiTmp, 1);
+            // set hidden attribute
+            if(createRndSubDir) {
+                writeMessageA(props, OUTPUT_LEVEL_DEBUG, 1, "Setting hidden attributes to ", 0);
+                writeMessageW(props, OUTPUT_LEVEL_DEBUG, 1, nbiTmp, 1);
+                
+                SetFileAttributesW(nbiTmp, GetFileAttributesW(nbiTmp) | FILE_ATTRIBUTE_HIDDEN);
+            }
+        } else {
+            writeMessageA(props, OUTPUT_LEVEL_DEBUG, 1, "Error! Can`t create nbi temp directory : ", 0);
+            writeMessageW(props, OUTPUT_LEVEL_DEBUG, 1, nbiTmp, 1);
+        }
+    }
+    props->tmpDir = nbiTmp;
+    return;
+}
+
+
+void deleteDirectory(LauncherProperties * props, WCHAR * dir) {
+    DWORD attrs = GetFileAttributesW(dir);
+    DWORD dwError;
+    DWORD count = 0 ;
+    if(attrs==INVALID_FILE_ATTRIBUTES) {
+        writeErrorA(props, OUTPUT_LEVEL_DEBUG, 1, "Error! Can`t get attributes of the dir : ", dir, GetLastError());
+        return;
+    }
+    if(!SetFileAttributesW(dir, attrs & FILE_ATTRIBUTE_NORMAL)) {
+        writeErrorA(props, OUTPUT_LEVEL_DEBUG, 1, "Error! Can`t set attributes of the dir : ", dir, GetLastError());
+    }
+    
+    
+    if(attrs & FILE_ATTRIBUTE_DIRECTORY) {
+        WIN32_FIND_DATAW FindFileData;
+        HANDLE hFind = INVALID_HANDLE_VALUE;
+        
+        WCHAR * DirSpec = appendStringW(appendStringW(NULL, dir), L"\\*" );
+        
+        // Find the first file in the directory.
+        hFind = FindFirstFileW(DirSpec, &FindFileData);
+        
+        if (hFind == INVALID_HANDLE_VALUE) {
+            writeErrorA(props, OUTPUT_LEVEL_DEBUG, 1, "Error! Can`t file with pattern ", DirSpec, GetLastError());
+        }
+        else {
+            // List all the other files in the directory.
+            while (FindNextFileW(hFind, &FindFileData) != 0) {
+                if(lstrcmpW(FindFileData.cFileName, L".")!=0 &&
+                        lstrcmpW(FindFileData.cFileName, L"..")!=0 ) {
+                    WCHAR * child = appendStringW(appendStringW(appendStringW(NULL, dir), FILE_SEP), FindFileData.cFileName);
+                    deleteDirectory(props, child);
+                    FREE(child);
+                }
+            }
+            
+            dwError = GetLastError();
+            FindClose(hFind);
+            if (dwError != ERROR_NO_MORE_FILES) {
+                writeErrorA(props, OUTPUT_LEVEL_DEBUG, 1, "Error! Can`t find file with pattern : ", DirSpec, dwError);
+            }
+        }
+        
+        // 20 tries in 2 seconds to delete the directory
+        while(!RemoveDirectoryW(dir) && count++ < 20) Sleep(100);
+        FREE(DirSpec);
+    }
+    else {
+        // 20 tries in 2 seconds to delete the file
+        while(!DeleteFileW(dir) && count++ < 20) Sleep(100);
+    }
+}
+
+
+
+
+WCHAR * getSystemTemporaryDirectory() {
+    WCHAR * expanded = newpWCHAR(MAX_PATH);
+    DWORD result;
+    if(GetTempPathW(MAX_PATH, expanded)!=0) {
+        return expanded;
+    }
+    
+    result = GetEnvironmentVariableW(L"TEMP", expanded, MAX_PATH);
+    if(result<=0 || result>MAX_PATH) {
+        //writeOutputLn("Can`t find variable TEMP");
+        result = GetEnvironmentVariableW(L"TMP", expanded, MAX_PATH);
+        if(result<=0 || result>MAX_PATH) {
+            //writeOutputLn("Can`t find variable TMP");
+            result = GetEnvironmentVariableW(L"USERPROFILE", expanded, MAX_PATH);
+            if(result>0 && result<=MAX_PATH) {
+                expanded = appendStringW(expanded, L"\\Local Settings\\Temp");
+            } else{
+                WCHAR * curdir = getCurrentDirectory();
+                ZERO(expanded, sizeof(WCHAR) * MAX_PATH);
+                lstrcpynW(expanded, curdir, MAX_PATH);
+                FREE(curdir);
+            }
+        }
+    }
+    return expanded;
+}
+
+WCHAR * getExePath() {
+    WCHAR * szPath = newpWCHAR(MAX_PATH);
+    
+    if( !GetModuleFileNameW( NULL, szPath, MAX_PATH ) ) {
+        FREE(szPath);
+        return NULL;
+    } else {
+        return szPath;//appendStringNW(NULL, 0, szPath, getLengthW(szPath));
+    }
+}
+
+
+WCHAR * getExeName() {
+    WCHAR * szPath = newpWCHAR(MAX_PATH);
+    WCHAR * result = NULL;
+    if(GetModuleFileNameW( NULL, szPath, MAX_PATH )) {
+        WCHAR * lastSlash = szPath;
+        while(searchW(lastSlash, FILE_SEP)!=NULL) {
+            lastSlash = searchW(lastSlash, FILE_SEP) + 1;
+        }
+        result = appendStringW(NULL, lastSlash);
+    } 
+    FREE(szPath);
+    return result;
+}
+
+WCHAR * getExeDirectory() {
+    WCHAR * szPath = newpWCHAR(MAX_PATH);
+    WCHAR * result = NULL;
+    if(GetModuleFileNameW( NULL, szPath, MAX_PATH )) {
+        WCHAR * lastSlash = szPath;
+        while(searchW(lastSlash, FILE_SEP)!=NULL) {
+            lastSlash = searchW(lastSlash, FILE_SEP) + 1;
+        }        
+        result = appendStringNW(NULL, 0 , szPath,
+                getLengthW(szPath) - getLengthW(lastSlash) - 1);
+    }
+    FREE(szPath);
+    return result;
+}
+
+WCHAR * getCurrentDirectory() {
+    WCHAR * buf = newpWCHAR(MAX_PATH);
+    
+    if(GetCurrentDirectoryW(MAX_PATH, buf)!=0) {
+        return buf;
+    } else {
+        FREE(buf);
+        return NULL;
+    }
+}
+WCHAR * getCurrentUserHome() {
+    HANDLE hUser;
+    WCHAR * buf = NULL;
+    if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hUser)) {
+        DWORD size = MAX_PATH;
+        buf = newpWCHAR(MAX_PATH);
+        GetUserProfileDirectoryW(hUser, buf, &size);
+        if (size > MAX_PATH) {
+            FREE(buf);
+            buf = newpWCHAR(size + 1);
+            if(!GetUserProfileDirectoryW(hUser, buf, &size)) {
+                FREE(buf);
+            }
+        }
+        CloseHandle(hUser);
+    }
+    if(buf==NULL) {
+        DWORD size = MAX_PATH;
+        buf = newpWCHAR(size);
+        size = GetEnvironmentVariableW(L"USERPROFILE", buf, MAX_PATH);
+        if( size > MAX_PATH) {
+            FREE(buf);
+            buf = newpWCHAR(size + 1);
+            GetEnvironmentVariableW(L"USERPROFILE", buf, size);
+        } else if (size==0) {
+            FREE(buf);
+        }
+    }
+    return buf;
+}
+int64t * getFileSize(WCHAR * path) {
+    WIN32_FILE_ATTRIBUTE_DATA wfad;
+    int64t * res = newint64_t(0, 0);
+    if (GetFileAttributesExW(path,
+            GetFileExInfoStandard,
+            &wfad)) {
+        res->Low  = wfad.nFileSizeLow;
+        res->High = wfad.nFileSizeHigh ;
+    }
+    return res;
+}
+
+void update_crc32(DWORD * crc, char *ptr, DWORD size) {    
+    while( size-- )  *crc = CRC32_TABLE[(unsigned char) (*crc^*ptr++)] ^ (*crc>>8);
+}
diff --git a/src/main/cpp/launcher/windows/src/FileUtils.h b/src/main/cpp/launcher/windows/src/FileUtils.h
new file mode 100644
index 0000000..0b01ace
--- /dev/null
+++ b/src/main/cpp/launcher/windows/src/FileUtils.h
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef _FileUtils_H
+#define	_FileUtils_H
+
+#include <windows.h>
+#include "Errors.h"
+#include "Types.h"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+    
+#define OUTPUT_LEVEL_DEBUG 0
+#define OUTPUT_LEVEL_NORMAL 1
+    
+    
+    extern const WCHAR * FILE_SEP;
+    extern const long CRC32_TABLE[256];
+    void update_crc32(DWORD * crc32, char * buf, DWORD size);
+    int64t * getFreeSpace(WCHAR *path);
+    int64t * getFileSize(WCHAR * path);
+    void checkFreeSpace(LauncherProperties * props, WCHAR * tmpDir, int64t * size);
+    WCHAR * getParentDirectory(WCHAR * dir);
+    void createDirectory(LauncherProperties * props, WCHAR * directory);
+    void createTempDirectory(LauncherProperties * props, WCHAR * argTempDir, DWORD createRndSubDir);
+    void deleteDirectory(LauncherProperties * props,WCHAR * dir);
+    WCHAR * getExePath();
+    WCHAR * getExeName();
+    WCHAR * getExeDirectory();
+    
+    WCHAR * getSystemTemporaryDirectory();    
+    DWORD isDirectory(WCHAR *path);
+    WCHAR * getCurrentDirectory();
+    WCHAR * getCurrentUserHome();
+        
+    
+    void writeMessageW(LauncherProperties * props, DWORD level,DWORD isErr,  const WCHAR * message, DWORD needEndOfLine);
+    void writeMessageA(LauncherProperties * props,DWORD level, DWORD isErr,  const char  * message, DWORD needEndOfLine);
+    void writeErrorA(LauncherProperties * props,DWORD level,   DWORD isErr,  const char  * message, const WCHAR * param, DWORD errorCode);
+    void writeDWORD(LauncherProperties * props,DWORD level,    DWORD isErr,  const char  * message, DWORD value, DWORD needEndOfLine);
+    void writeint64t(LauncherProperties * props,DWORD level,   DWORD isErr,  const char  * message, int64t * value, DWORD needEndOfLine);
+    
+    void flushHandle(HANDLE hd);
+    DWORD fileExists(WCHAR * path);
+    
+    #ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _FileUtils_H */
diff --git a/src/main/cpp/launcher/windows/src/JavaUtils.c b/src/main/cpp/launcher/windows/src/JavaUtils.c
new file mode 100644
index 0000000..9e4245e
--- /dev/null
+++ b/src/main/cpp/launcher/windows/src/JavaUtils.c
@@ -0,0 +1,796 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <wchar.h>
+#include <stdio.h>
+#include "JavaUtils.h"
+#include "RegistryUtils.h"
+#include "StringUtils.h"
+#include "SystemUtils.h"
+#include "FileUtils.h"
+#include "ProcessUtils.h"
+#include "Launcher.h"
+#include "Main.h"
+
+const DWORD JAVA_VERIFICATION_PROCESS_TIMEOUT = 10000; // 10sec
+const DWORD UNPACK200_EXTRACTION_TIMEOUT = 60000; //60 seconds on each file
+const DWORD JAVA_VERIFICATION_PROCESS_PRIORITY = NORMAL_PRIORITY_CLASS;
+const WCHAR * JAVA_EXE_SUFFIX = L"\\bin\\java.exe";
+const WCHAR * UNPACK200_EXE_SUFFIX = L"\\bin\\unpack200.exe";
+const WCHAR * JAVA_LIB_SUFFIX = L"\\lib";
+const WCHAR * PACK_GZ_SUFFIX  = L".pack.gz";
+const WCHAR * JAR_PACK_GZ_SUFFIX = L".jar.pack.gz";
+
+const DWORD JVM_EXTRACTION_TIMEOUT = 180000;  //180sec
+
+WCHAR * JAVA_REGISTRY_KEYS [] = {
+    L"SOFTWARE\\JavaSoft\\Java Runtime Environment",
+    L"SOFTWARE\\JavaSoft\\Java Development Kit",
+    L"SOFTWARE\\JavaSoft\\JDK",
+    L"SOFTWARE\\JRockit\\Java Runtime Environment",
+    L"SOFTWARE\\JRockit\\Java Development Kit",
+    L"SOFTWARE\\IBM\\Java Runtime Environment",
+    L"SOFTWARE\\IBM\\Java2 Runtime Environment",
+    L"SOFTWARE\\IBM\\Java Development Kit",
+};
+WCHAR * JAVA_HOME = L"JavaHome";
+WCHAR * CURRENT_VERSION = L"CurrentVersion";
+
+WCHAR * getJavaHomeValue(WCHAR *parentkey, WCHAR *subkey, BOOL access64key) {
+    return getStringValuePC(HKEY_LOCAL_MACHINE, parentkey, subkey, JAVA_HOME, access64key);
+}
+
+
+WCHAR * getTestJVMFileName(WCHAR * testJVMFile) {
+    WCHAR * filePtr = testJVMFile;
+    WCHAR * testJavaClass = NULL;
+    
+    if(filePtr!=NULL) {
+        WCHAR * dotClass = NULL;
+        while(searchW(filePtr, L"\\")!=NULL) {
+            filePtr = searchW(filePtr, L"\\");
+            filePtr++;
+        }
+        dotClass = searchW(filePtr, L".class");
+        
+        if(dotClass!=NULL) {
+            testJavaClass = appendStringNW(NULL, 0, filePtr, getLengthW(filePtr) - getLengthW(dotClass));
+        }
+    }
+    return testJavaClass;
+}
+
+
+//returns 0 if equals, 1 if first > second, -1 if first < second
+char compareJavaVersion(JavaVersion * first, JavaVersion * second) {
+    if(first==NULL) return (second==NULL) ? 0 : -1;
+    if(second==NULL) return -1;
+    if(first->major == second->major) {
+        if(first->minor == second->minor) {
+            if(first->micro == second->micro) {
+                if(first->update == second->update) return 0;
+                return (first->update > second->update) ? 1 : -1;
+            }
+            return (first->micro > second->micro) ? 1 : -1;
+        }
+        return (first->minor > second->minor) ? 1 : -1;
+    } else {
+        return (first->major > second->major) ? 1 : -1;
+    }
+}
+DWORD isJavaCompatible(JavaProperties *currentJava, JavaCompatible ** compatibleJava, DWORD number) {
+    JavaVersion * current = currentJava->version;
+    DWORD i = 0 ;
+    
+    for(i=0;i<number;i++) {
+        DWORD check = 1;
+        
+        check = (compareJavaVersion(current, compatibleJava[i]->minVersion) >= 0 &&
+                compareJavaVersion(current, compatibleJava[i]->maxVersion) <= 0) ? check : 0;
+                
+                if (check) {
+                    if(compatibleJava[i]->vendor!=NULL) {
+                        check = (searchA(currentJava->vendor, compatibleJava[i]->vendor) != NULL) ? check : 0;
+                    }
+                    if (compatibleJava[i]->osName!=NULL) {
+                        check = (searchA(currentJava->osName, compatibleJava[i]->osName)!=NULL) ? check : 0;
+                    }
+                    
+                    if (compatibleJava[i]->osArch!=NULL) {
+                        check = (searchA(currentJava->osArch, compatibleJava[i]->osArch)!=NULL) ? check : 0;
+                    }
+                    if(check) {
+                        return 1;
+                    }
+                }
+    }
+    return 0;
+}
+
+JavaVersion * getJavaVersionFromString(char * string, DWORD * result) {
+    JavaVersion *vers = NULL;
+    if(getLengthA(string)<3) {
+        return vers;
+    }
+
+    const char *p = string;
+
+    // get major 
+    long major = 0;
+    while(*p!=0) {
+        char c = *p++;
+        if(c>='0' && c<='9') {
+            major = (major) * 10 + c - '0';
+            if (major > 999) return vers;
+            continue;
+        } else if(c=='.' || c=='+'){
+            break;
+        } else{
+            return vers;
+        }
+    }
+
+    // get minor 
+    long minor = 0;
+    while(*p!=0) {
+        char c = *p;
+        if(c>='0' && c<='9') {
+            minor = (minor) * 10 + c - '0';
+            p++;
+            continue;
+        }
+        break;
+    }
+
+    *result = ERROR_OK;
+    vers = (JavaVersion*) LocalAlloc(LPTR, sizeof(JavaVersion));
+    vers->major  = major;
+    vers->minor  = minor;
+    vers->micro  = 0;
+    vers->update = 0;
+    ZERO(vers->build, 128);
+
+    if(p[0]=='.') { // micro...
+        p++;
+        while(*p!=0) {
+            char c = *p;
+            if(c>='0' && c<='9') {
+                vers->micro = (vers->micro) * 10 + c - '0';
+                p++;
+                continue;
+            } else if(c=='_') {//update
+                p++;
+                while((c = *p) != 0) {
+                    p++;
+                    if(c>='0' && c<='9') {
+                        vers->update = (vers->update) * 10 + c - '0';
+                        continue;
+                    } else {
+                        break;
+                    }
+                }
+            } else {
+                if(*p!=0) p++;
+            }
+            if(c=='-' && *p!=0) { // build number
+                lstrcpyn(vers->build, p, min(127, getLengthA(p)+1));
+            }
+            break;
+        }
+    }
+    return vers;
+}
+
+DWORD getJavaPropertiesFromOutput(LauncherProperties * props, char *str, JavaProperties ** javaProps) {
+    DWORD separators = getLineSeparatorNumber(str);
+    DWORD result = ERROR_INPUTOUPUT;
+    * javaProps = NULL;
+    if(separators == TEST_JAVA_PARAMETERS) {
+        char * start;
+        char * end;
+        char * javaVersion;
+        char * javaVmVersion;
+        char * javaVendor;
+        char * osName;
+        char * osArch;
+        char * string;
+        JavaVersion * vers;
+        
+        start = str;
+        end = searchA(start, "\n");
+        
+        javaVersion = appendStringN(NULL, 0, start, getLengthA(start) - getLengthA(end)-1);
+        writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "    java.version =  ", 0);
+        writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, javaVersion, 1);
+        start = end + 1;
+        end = searchA(start, "\n");
+        
+        
+        javaVmVersion = appendStringN(NULL, 0, start, getLengthA(start) - getLengthA(end)-1);
+        writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "    java.vm.version = ", 0);
+        writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, javaVmVersion, 1);
+        start = end + 1;
+        end = searchA(start, "\n");
+        
+        javaVendor = appendStringN(NULL, 0, start, getLengthA(start) - getLengthA(end)-1);
+        writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "    java.vendor = ", 0);
+        writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, javaVendor, 1);
+        start = end + 1;
+        end = searchA(start, "\n");
+        
+        osName = appendStringN(NULL, 0, start, getLengthA(start) - getLengthA(end)-1);
+        writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "    os.name = ", 0);
+        writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, osName, 1);
+        start = end + 1;
+        end = searchA(start, "\n");
+        
+        osArch = appendStringN(NULL, 0, start, getLengthA(start) - getLengthA(end)-1);
+        writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "    os.arch = ", 0);
+        writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, osArch, 2);
+        
+        string = javaVersion;
+        
+        
+        if(javaVmVersion!=NULL) {
+            string = searchA(javaVmVersion, javaVersion);
+            if(string==NULL) {
+                string = javaVersion;
+            }
+        }
+        writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "... getting java version from string : ", 0);
+        writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, string, 1);
+        
+        vers = getJavaVersionFromString(string, & result);
+        if(javaProps != NULL) {
+            writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "... some java there", 1);
+            * javaProps = (JavaProperties *) LocalAlloc(LPTR, sizeof(JavaProperties));
+            (*javaProps)->version = vers;
+            (*javaProps)->vendor   = javaVendor;
+            (*javaProps)->osName   = osName;
+            (*javaProps)->osArch   = osArch;
+            (*javaProps)->javaHome = NULL;
+            (*javaProps)->javaExe  = NULL;
+        } else {
+            writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "... no java  there", 1);
+            FREE(javaVendor);
+            FREE(osName);
+            FREE(osArch);
+        }
+        FREE(javaVmVersion);
+        FREE(javaVersion);
+    }
+    return result;
+}
+
+
+void getJavaProperties(WCHAR * location, LauncherProperties * props, JavaProperties ** javaProps) {
+    WCHAR *testJavaClass  = props->testJVMClass;
+    WCHAR *javaExecutable = getJavaResource(location, JAVA_EXE_SUFFIX);
+    WCHAR *libDirectory   = getJavaResource(location, JAVA_LIB_SUFFIX);
+    
+    if(fileExists(javaExecutable) && testJavaClass!=NULL && isDirectory(libDirectory)) {
+        WCHAR * command = NULL;
+        HANDLE hRead;
+        HANDLE hWrite;
+        
+        writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "... java hierarchy there", 1);
+        // <location>\bin\java.exe exists
+
+        
+        appendCommandLineArgument(&command, javaExecutable);
+        appendCommandLineArgument(&command, L"-classpath");
+        appendCommandLineArgument(&command, props->testJVMFile->resolved);
+        appendCommandLineArgument(&command, testJavaClass);
+        
+        
+        CreatePipe(&hRead, &hWrite, NULL, 0);
+        // Start the child process.
+        executeCommand(props, command, NULL, JAVA_VERIFICATION_PROCESS_TIMEOUT, hWrite, INVALID_HANDLE_VALUE, JAVA_VERIFICATION_PROCESS_PRIORITY);
+        if(props->status!= ERROR_ON_EXECUTE_PROCESS && props->status!= ERROR_PROCESS_TIMEOUT) {
+            char * output = readHandle(hRead);
+            writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "           output :\n", 0);
+            writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, output, 1);
+            
+            props->status = getJavaPropertiesFromOutput(props, output, javaProps);
+            if(props->status == ERROR_OK) {
+                (*javaProps)->javaHome = appendStringW(NULL, location);
+                (*javaProps)->javaExe  = appendStringW(NULL, javaExecutable);
+            }
+            FREE(output);
+        } else if(props->status == ERROR_PROCESS_TIMEOUT) {
+            // java verification process finished by time out
+            props->status = ERROR_INPUTOUPUT;
+        }
+        FREE(command);
+        CloseHandle(hWrite);
+        CloseHandle(hRead);
+    } else {
+        writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "... not a java hierarchy", 1);
+        props->status = ERROR_INPUTOUPUT;
+    }
+    FREE(libDirectory);
+    FREE(javaExecutable);
+}
+
+
+
+char * getJavaVersionFormatted(const JavaProperties * javaProps) {
+    char *result = NULL;
+    if(javaProps!=NULL) {
+        JavaVersion * version = javaProps->version;
+        if(version!=NULL) {
+            char * majorStr = long2char(version->major);
+            char * minorStr = long2char(version->minor);
+            char * microStr = long2char(version->micro);
+            result = appendString(result, majorStr);
+            result = appendString(result, ".");
+            result = appendString(result, minorStr);
+            result = appendString(result, ".");
+            result = appendString(result, microStr);
+            FREE(majorStr);
+            FREE(minorStr);
+            FREE(microStr);
+            
+            if(version->update!=0) {
+                char * updateStr = long2charN(version->update, 2);
+                result = appendString(result, "_");
+                result = appendString(result, updateStr);
+                FREE(updateStr);
+            }
+            if(getLengthA(version->build) > 0) {
+                result = appendString(result, "-");
+                result = appendString(result, version->build);
+            }
+        }
+    }
+    return result;
+}
+
+
+JavaCompatible * newJavaCompatible() {
+    JavaCompatible * props = (JavaCompatible *) LocalAlloc(LPTR, sizeof(JavaCompatible));
+    props->minVersion = NULL;
+    props->maxVersion = NULL;
+    props->vendor = NULL;
+    props->osName = NULL;
+    return props;
+}
+
+void freeJavaProperties(JavaProperties ** props) {
+    if(*props!=NULL) {
+        FREE((*props)->version);
+        FREE((*props)->javaHome);
+        FREE((*props)->javaExe);
+        FREE((*props)->vendor);
+        FREE(*props);
+    }
+}
+
+WCHAR * getJavaResource(WCHAR * location, const WCHAR * suffix) {
+    return appendStringW(appendStringW(NULL, location), suffix);
+}
+
+
+void searchCurrentJavaRegistry(LauncherProperties * props, BOOL access64key) {
+    DWORD i=0;
+    WCHAR ** keys = JAVA_REGISTRY_KEYS;
+    DWORD k=0;
+    WCHAR * buffer = newpWCHAR(MAX_LEN_VALUE_NAME);
+    HKEY rootKeys [2] = {HKEY_LOCAL_MACHINE, HKEY_CURRENT_USER};
+    DWORD rootKeysNumber = sizeof(rootKeys)/sizeof(HKEY);
+    DWORD keysNumber = sizeof(JAVA_REGISTRY_KEYS)/sizeof(WCHAR*);
+    DWORD status = ERROR_OK;
+    
+    writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "Search java in CurrentVersion values...", 1);
+    
+    
+    for ( k = 0; k < rootKeysNumber; k++) {
+        for(i=0; i < keysNumber;i++) {
+            if(isTerminated(props)) {
+                return;
+            }
+            else {
+                
+                WCHAR * value = getStringValue(rootKeys[k], keys[i], CURRENT_VERSION, access64key);
+                if(value!=NULL) {
+                    WCHAR *javaHome = getStringValuePC(rootKeys[k], keys[i], value, JAVA_HOME, access64key);
+                    writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "... ", 0);
+                    writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, (rootKeys[k]==HKEY_LOCAL_MACHINE) ? "HKEY_LOCAL_MACHINE" : "HKEY_CURRENT_USER", 0);
+                    writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "\\", 0);
+                    writeMessageW(props, OUTPUT_LEVEL_NORMAL, 0, keys[i], 0);
+                    writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "\\", 0);
+                    writeMessageW(props, OUTPUT_LEVEL_NORMAL, 0, CURRENT_VERSION, 0);
+                    writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "->", 0);
+                    writeMessageW(props, OUTPUT_LEVEL_NORMAL, 0, value, 0);
+                    writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "[", 0);
+                    writeMessageW(props, OUTPUT_LEVEL_NORMAL, 0, JAVA_HOME, 0);
+                    writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "] = ", 0);
+                    writeMessageW(props, OUTPUT_LEVEL_NORMAL, 0, javaHome, 1);
+                    
+                    FREE(value);
+                    trySetCompatibleJava(javaHome, props);
+                    FREE(javaHome);
+                    if(props->java!=NULL) {
+                        FREE(buffer);
+                        return;
+                    }
+                }
+            }
+        }
+    }
+    
+    
+    // we found no CurrentVersion java... just search for other possible keys
+    writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "Search java in other values...", 1);
+    
+    
+    for(k=0;k<rootKeysNumber;k++) {
+        for(i=0;i<keysNumber;i++) {
+            HKEY  hkey = 0;
+            DWORD   index  = 0 ;
+            if (RegOpenKeyExW(rootKeys[k], keys[i], 0, KEY_READ | ((access64key && IsWow64) ? KEY_WOW64_64KEY : 0), &hkey) == ERROR_SUCCESS) {
+                DWORD number = 0;
+                if (RegQueryInfoKeyW(hkey, NULL, NULL, NULL, &number, NULL, NULL, NULL, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
+                    DWORD err = 0;
+                    do {
+                        
+                        DWORD size = MAX_LEN_VALUE_NAME;
+                        buffer[0]  = 0;
+                        err = RegEnumKeyExW(hkey, index, buffer, &size, NULL, NULL, NULL, NULL);
+                        if (err == ERROR_SUCCESS) {
+                            WCHAR  * javaHome = getJavaHomeValue(keys[i], buffer, access64key);
+                            status = ERROR_OK;
+                            
+                            writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, (rootKeys[k]==HKEY_LOCAL_MACHINE) ? "HKEY_LOCAL_MACHINE" : "HKEY_CURRENT_USER", 0);
+                            writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "\\", 0);
+                            writeMessageW(props, OUTPUT_LEVEL_NORMAL, 0, keys[i], 0);
+                            writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "\\", 0);
+                            writeMessageW(props, OUTPUT_LEVEL_NORMAL, 0, buffer, 0);
+                            writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "[", 0);
+                            writeMessageW(props, OUTPUT_LEVEL_NORMAL, 0, JAVA_HOME, 0);
+                            writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "] = ", 0);
+                            writeMessageW(props, OUTPUT_LEVEL_NORMAL, 0, javaHome, 1);
+                            
+                            trySetCompatibleJava(javaHome, props);
+                            FREE(javaHome);
+                            if(props->java!=NULL) {
+                                i = keysNumber; // to the end of cycles
+                                k = rootKeysNumber;
+                                break;
+                            }
+                            
+                        }
+                        index++;
+                    } while (err == ERROR_SUCCESS);
+                }
+            }
+            if (hkey != 0) {
+                RegCloseKey(hkey);
+            }
+        }
+    }
+    FREE(buffer);
+    return;
+}
+
+
+void searchJavaFromEnvVariables(LauncherProperties * props) {
+    static WCHAR * ENVS [] = {
+        L"JAVA_HOME",
+        L"JAVAHOME",
+        L"JAVA_PATH",
+        L"JDK_HOME",
+        L"JDKHOME",
+        L"ANT_JAVA",
+        L"JAVA",
+        L"JDK"
+    };
+    
+    WCHAR buffer [MAX_PATH];
+    
+    int size = sizeof(ENVS)/sizeof(WCHAR *);
+    int i=0;
+    int ret;
+    
+    for(i=0;i<size;i++) {
+        if(isTerminated(props)) return;
+        buffer[0]='\0';
+        ret = GetEnvironmentVariableW((WCHAR *) ENVS[i], (WCHAR *) buffer, MAX_PATH);
+        if (ret > 0 && ret <= MAX_PATH) {
+            writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "    <", 0);
+            writeMessageW(props, OUTPUT_LEVEL_NORMAL, 0, ENVS[i], 0);
+            writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "> = ", 0);
+            writeMessageW(props, OUTPUT_LEVEL_NORMAL, 0, buffer, 1);
+            trySetCompatibleJava(buffer, props);
+            if(props->java!=NULL) {
+                break;
+            }
+        }
+    }
+}
+
+
+
+
+void unpackJars(LauncherProperties * props, WCHAR * jvmDir, WCHAR * startDir, WCHAR * unpack200exe) {
+    DWORD attrs;
+    DWORD dwError;
+    DWORD count = 0 ;
+    
+    if(!isOK(props)) return;
+    attrs = GetFileAttributesW(startDir);
+    if(attrs==INVALID_FILE_ATTRIBUTES) {
+        writeErrorA(props, OUTPUT_LEVEL_DEBUG, 1, "Error! Can`t get attributes of the file : ", startDir, GetLastError());
+        return;
+    }
+    if(attrs & FILE_ATTRIBUTE_DIRECTORY) { // is directory
+        WIN32_FIND_DATAW FindFileData;
+        HANDLE hFind = INVALID_HANDLE_VALUE;
+        
+        WCHAR * DirSpec = appendStringW(appendStringW(NULL, startDir), L"\\*" );
+        
+        // Find the first file in the directory.
+        hFind = FindFirstFileW(DirSpec, &FindFileData);
+        
+        if (hFind == INVALID_HANDLE_VALUE) {
+            writeErrorA(props, OUTPUT_LEVEL_DEBUG, 1, "Error! Can`t file with pattern ", DirSpec, GetLastError());
+        }
+        else {
+            // List all the other files in the directory.
+            writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "... listing directory ", 0);
+            writeMessageW(props, OUTPUT_LEVEL_DEBUG, 0, startDir, 1);
+            
+            while (FindNextFileW(hFind, &FindFileData) != 0 && isOK(props)) {
+                if(lstrcmpW(FindFileData.cFileName, L".")!=0 &&
+                        lstrcmpW(FindFileData.cFileName, L"..")!=0) {
+                    WCHAR * child = NULL;
+                    
+                    child = appendStringW(appendStringW(appendStringW(NULL, startDir), FILE_SEP), FindFileData.cFileName);
+                    if(isDirectory(child)) {
+                        writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "... directory : ", 0);
+                        writeMessageW(props, OUTPUT_LEVEL_DEBUG, 0, child, 1);
+                        unpackJars(props, jvmDir, child, unpack200exe);
+                    } else  if(searchW(FindFileData.cFileName, JAR_PACK_GZ_SUFFIX)!=NULL) {
+                        WCHAR * jarName = appendStringW(appendStringW(
+                                appendStringW(NULL, startDir), FILE_SEP),
+                                appendStringNW(NULL, 0, FindFileData.cFileName,
+                                getLengthW(FindFileData.cFileName) - getLengthW(PACK_GZ_SUFFIX)));
+                        WCHAR * unpackCommand = NULL;
+                        writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "... packed jar : ", 0);
+                        writeMessageW(props, OUTPUT_LEVEL_DEBUG, 0, child, 1);
+                        writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "... jar name : ", 0);
+                        writeMessageW(props, OUTPUT_LEVEL_DEBUG, 0, jarName, 1);
+                        
+                        
+                        appendCommandLineArgument(&unpackCommand, unpack200exe);
+                        appendCommandLineArgument(&unpackCommand, L"-r"); // remove input file
+                        appendCommandLineArgument(&unpackCommand, child);
+                        appendCommandLineArgument(&unpackCommand, jarName);
+                        
+                        executeCommand(props, unpackCommand, NULL, UNPACK200_EXTRACTION_TIMEOUT, props->stdoutHandle, props->stderrHandle, NORMAL_PRIORITY_CLASS);
+                        FREE(unpackCommand);
+                        if(!isOK(props)) {
+                            if(props->status==ERROR_PROCESS_TIMEOUT) {
+                                writeMessageA(props, OUTPUT_LEVEL_DEBUG, 1, "... could not unpack file : timeout", 1);
+                            } else {
+                                writeMessageA(props, OUTPUT_LEVEL_DEBUG, 1, "... an error occured unpacking the file", 1);
+                            }
+                            props->exitCode = props->status;
+                        }
+                        FREE(jarName);
+                    }
+                    FREE(child);
+                }
+            }
+            
+            dwError = GetLastError();
+            FindClose(hFind);
+            if (dwError != ERROR_NO_MORE_FILES) {
+                writeErrorA(props, OUTPUT_LEVEL_DEBUG, 1, "Error! Can`t find file with pattern : ", DirSpec, dwError);
+            }
+        }
+        FREE(DirSpec);
+    }
+    
+}
+void installJVM(LauncherProperties * props, LauncherResource *jvm) {
+    WCHAR * command = NULL;
+    WCHAR * jvmDir = getParentDirectory(jvm->resolved);
+    
+    jvmDir = appendStringW(jvmDir, L"\\_jvm");
+    createDirectory(props, jvmDir);
+    if(!isOK(props)) {
+        writeMessageA(props, OUTPUT_LEVEL_DEBUG, 1, "... cannot create dir for JVM extraction :", 0);
+        writeMessageW(props, OUTPUT_LEVEL_DEBUG, 1, jvmDir, 1);
+        FREE(jvmDir);
+        return;
+    }
+    
+    appendCommandLineArgument(&command, jvm->resolved);
+    appendCommandLineArgument(&command, L"-d");
+    appendCommandLineArgument(&command, jvmDir);
+    
+    executeCommand(props, command, jvmDir, JVM_EXTRACTION_TIMEOUT, props->stdoutHandle, props->stderrHandle, NORMAL_PRIORITY_CLASS);
+    FREE(command);
+    if(!isOK(props)) {
+        if(props->status==ERROR_PROCESS_TIMEOUT) {
+            writeMessageA(props, OUTPUT_LEVEL_DEBUG, 1, "... could not extract JVM : timeout", 1);
+        } else {
+            writeMessageA(props, OUTPUT_LEVEL_DEBUG, 1, "... an error occured during running JVM extraction file", 1);
+        }
+        props->exitCode = props->status;
+    } else {
+        WCHAR * unpack200exe = appendStringW(appendStringW(NULL, jvmDir), UNPACK200_EXE_SUFFIX);
+        if(fileExists(unpack200exe)) {
+            unpackJars(props, jvmDir, jvmDir, unpack200exe);
+        } else {
+            writeMessageA(props, OUTPUT_LEVEL_DEBUG, 1, "... no unpack200 command", 1);
+            props->status = ERROR_BUNDLED_JVM_EXTRACTION;
+        }
+        if(!isOK(props)) {
+            writeMessageA(props, OUTPUT_LEVEL_DEBUG, 1, "Could not unpack200 the JVM jars", 1);
+        }
+        FREE(unpack200exe);
+    }
+    FREE(jvm->resolved);
+    jvm->resolved = jvmDir;
+}
+
+void installBundledJVMs(LauncherProperties * props) {
+    if ( props->jvms->size > 0 ) {
+        DWORD i=0;
+        writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "... search for bundled JVMs", 1);
+        for(i=0;i<props->jvms->size; i++) {
+            if(props->jvms->items[i]->type==0 && !isTerminated(props)) {
+                resolvePath(props, props->jvms->items[i]);
+                writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "... install bundled JVM ", 0);
+                writeMessageW(props, OUTPUT_LEVEL_NORMAL, 0, props->jvms->items[i]->resolved, 1);
+                installJVM(props, props->jvms->items[i]);
+                if(isTerminated(props)) return;                
+                if(isOK(props)) {
+                    trySetCompatibleJava(props->jvms->items[i]->resolved, props);
+                    if(props->java!=NULL) {
+                        break;
+                    } else  {
+                        props->status = ERROR_BUNDLED_JVM_VERIFICATION;
+                        return;
+                    }
+                }
+                else {
+                    writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "... error occured during JVM extraction", 1);
+                    props->status = ERROR_BUNDLED_JVM_EXTRACTION;
+                    return;
+                }
+            }
+        }
+    }
+}
+void searchJavaInstallationFolder(LauncherProperties * props) {   
+    char executablePath [MAX_PATH];
+    GetModuleFileName(0, executablePath, MAX_PATH);
+    char * pch = strrchr(executablePath, '\\');    
+    char installationFolder [MAX_PATH]= "";
+    int i = 0;
+    int end = (int) (pch - executablePath);
+    printf("%i", end);
+    for(i; i < end; i++) {
+        installationFolder[i] = executablePath[i];
+    }
+    strcat(installationFolder, "\\bin\\jre");
+    
+    // check if JRE is in installation folder
+    WCHAR * nestedJreFolder = toWCHAR(installationFolder); 
+    if (!fileExists(nestedJreFolder)) {
+        // if not exists - return
+        return;
+    }
+    
+    // if exists - copy to temp folder to run uninstaller on that jvm
+    // to be able to delete jvm in installation folder
+    WCHAR * tempJreFolder = NULL;
+    tempJreFolder = appendStringW(tempJreFolder, props->testJVMFile->resolved); 
+    tempJreFolder = appendStringW(tempJreFolder, L"\\_jvm\\");    
+    
+    WCHAR * command = NULL;
+    appendCommandLineArgument(&command, L"xcopy");
+    appendCommandLineArgument(&command, nestedJreFolder);
+    appendCommandLineArgument(&command, tempJreFolder);
+    appendCommandLineArgument(&command, L"/e");
+    appendCommandLineArgument(&command, L"/y");
+    
+    writeMessageA(props, OUTPUT_LEVEL_DEBUG, 1, "Copying nested JRE to temp folder", 0);
+    
+    executeCommand(props, command, NULL, JVM_EXTRACTION_TIMEOUT, props->stdoutHandle, props->stderrHandle, NORMAL_PRIORITY_CLASS);
+    
+    if (fileExists(tempJreFolder)) {    
+        trySetCompatibleJava(tempJreFolder, props);
+    }
+}
+void searchJavaSystemLocations(LauncherProperties * props) {
+    if ( props->jvms->size > 0 ) {
+        DWORD i=0;
+        writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "Search jvm using some predefined locations", 1);
+        for(i=0;i<props->jvms->size && !isTerminated(props);i++) {
+            resolvePath(props, props->jvms->items[i]);
+            if(props->jvms->items[i]->type!=0) { // bundled JVMs are already checked
+                trySetCompatibleJava(props->jvms->items[i]->resolved, props);
+                if(props->java!=NULL) {
+                    break;
+                }
+            }
+        }        
+    }
+}
+void findSystemJava(LauncherProperties *props) {
+    // install bundled JVMs if any
+    if(isTerminated(props)) return;
+    installBundledJVMs(props);
+    
+    if(!isOK(props) || isTerminated(props)) return;
+    // search in <installation folder>/bin/jre
+    if(props->java==NULL) {
+        writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "Search java in installation folder", 1);
+        searchJavaInstallationFolder(props);
+    }
+    // search JVM in the system paths    
+    if(props->java==NULL) {
+        writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "Search java in the system paths", 1);
+        searchJavaSystemLocations(props);
+    }
+    
+    if(isTerminated(props)) return;
+    if(props->java==NULL) {
+        writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "Search java in environment variables", 1);
+        searchJavaFromEnvVariables(props);
+    }
+    
+    // search JVM in the registry
+    if(isTerminated(props)) return;
+    if(props->java==NULL) {        
+	if(IsWow64) {
+	   writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "Search java in 64-bit registry", 1);
+           searchCurrentJavaRegistry(props, 1);
+        }
+        if(props->java==NULL) {
+	    writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "Search java in 32-bit registry", 1);
+            searchCurrentJavaRegistry(props, 0);
+        }
+    }
+}
+
+
+void printJavaProperties(LauncherProperties * props, JavaProperties * javaProps) {
+    if(javaProps!=NULL) {
+        char * jv = getJavaVersionFormatted(javaProps);
+        writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "Current Java:", 1);
+        writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "       javaHome: ", 0);
+        writeMessageW(props, OUTPUT_LEVEL_NORMAL, 0, javaProps->javaHome, 1);
+        writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "        javaExe: ", 0);
+        writeMessageW(props, OUTPUT_LEVEL_NORMAL, 0, javaProps->javaExe, 1);
+        writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "        version: ", 0);
+        writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, jv, 1);
+        writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "         vendor: ", 0);
+        writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, javaProps->vendor, 1);
+        writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "        os.name: ", 0);
+        writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, javaProps->osName, 1);
+        writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "        os.arch: ", 0);
+        writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, javaProps->osArch, 1);
+        FREE(jv);
+    }
+}
diff --git a/src/main/cpp/launcher/windows/src/JavaUtils.h b/src/main/cpp/launcher/windows/src/JavaUtils.h
new file mode 100644
index 0000000..fa9109d
--- /dev/null
+++ b/src/main/cpp/launcher/windows/src/JavaUtils.h
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef _JavaUtils_H
+#define	_JavaUtils_H
+
+#include <windows.h>
+#include "Launcher.h"
+#include "Types.h"
+#include "Errors.h"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+    
+// java.version
+// java.vm.version
+// java.vendor
+// os.name
+// os.arch
+#define TEST_JAVA_PARAMETERS 5    
+#define MAX_LEN_VALUE_NAME 16383
+
+WCHAR * getJavaResource(WCHAR * location, const WCHAR * suffix);
+
+void getJavaProperties(WCHAR * location, LauncherProperties * props, JavaProperties ** javaProps);
+
+void findSystemJava(LauncherProperties * props);
+
+JavaVersion * getJavaVersionFromString(char * string, DWORD * result);
+
+char compareJavaVersion(JavaVersion * first, JavaVersion * second);
+
+DWORD isJavaCompatible(JavaProperties *currentJava, JavaCompatible ** compatibleJava, DWORD number);
+
+void printJavaProperties(LauncherProperties * props, JavaProperties * javaProps);
+
+void freeJavaProperties(JavaProperties ** props);
+
+void installJVM(LauncherProperties * props, LauncherResource *jvm);
+
+JavaCompatible * newJavaCompatible();
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _JavaUtils_H */
diff --git a/src/main/cpp/launcher/windows/src/Launcher.c b/src/main/cpp/launcher/windows/src/Launcher.c
new file mode 100644
index 0000000..95bdcbd
--- /dev/null
+++ b/src/main/cpp/launcher/windows/src/Launcher.c
@@ -0,0 +1,1009 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <windows.h>
+#include <wchar.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <shellapi.h>
+#include "FileUtils.h"
+#include "StringUtils.h"
+#include "JavaUtils.h"
+#include "RegistryUtils.h"
+#include "Launcher.h"
+#include "ProcessUtils.h"
+#include "StringUtils.h"
+#include "ExtractUtils.h"
+#include "Main.h"
+#include "shlobj.h"
+
+const DWORD NUMBER_OF_HELP_ARGUMENTS = 11;
+const DWORD READ_WRITE_BUFSIZE = 65536;
+const WCHAR * outputFileArg       = L"--output";
+const WCHAR * javaArg             = L"--javahome";
+const WCHAR * debugArg            = L"--verbose";
+const WCHAR * tempdirArg          = L"--tempdir";
+const WCHAR * classPathPrepend    = L"--classpath-prepend";
+const WCHAR * classPathAppend     = L"--classpath-append";
+const WCHAR * extractArg          = L"--extract";
+const WCHAR * helpArg             = L"--help";
+const WCHAR * helpOtherArg        = L"/?";
+const WCHAR * silentArg           = L"--silent";
+const WCHAR * nospaceCheckArg     = L"--nospacecheck";
+const WCHAR * localeArg           = L"--locale";
+
+const WCHAR * javaParameterPrefix = L"-J";
+
+const WCHAR * NEW_LINE            = L"\n";
+
+const WCHAR * CLASSPATH_SEPARATOR = L";";
+const WCHAR * CLASS_SUFFIX = L".class";
+
+
+DWORD isLauncherArgument(LauncherProperties * props, WCHAR * value) {
+    DWORD i=0;
+    for(i=0;i<props->launcherCommandArguments->size;i++) {
+        if(lstrcmpW(props->launcherCommandArguments->items[i], value)==0) {
+            return 1;
+        }
+    }
+    return 0;
+}
+
+DWORD getArgumentIndex(LauncherProperties * props, const WCHAR *arg, DWORD removeArgument) {
+    WCHARList *cmd = props->commandLine;
+    DWORD i=0;
+    for(i=0;i<cmd->size;i++) {
+        if(cmd->items[i]!=NULL) { // argument has not been cleaned yet
+            if(lstrcmpW(arg, cmd->items[i])==0) { //argument is the same as the desired
+                if(removeArgument) FREE(cmd->items[i]); // free it .. we don`t need it anymore
+                return i;
+            }
+        }
+    }
+    return cmd->size;
+}
+
+DWORD argumentExists(LauncherProperties * props, const WCHAR *arg, DWORD removeArgument) {
+    DWORD index = getArgumentIndex(props, arg, removeArgument);
+    return (index < props->commandLine->size);
+    
+}
+WCHAR * getArgumentValue(LauncherProperties * props, const WCHAR *arg, DWORD removeArgument, DWORD mandatory) {
+    WCHARList *cmd = props->commandLine;
+    WCHAR * result = NULL;
+    DWORD i = getArgumentIndex(props, arg, removeArgument);
+    if((i+1) < cmd->size) {
+        //we have at least one more argument
+        if(mandatory || !isLauncherArgument(props, cmd->items[i+1])) {
+            result = appendStringW(NULL, cmd->items[i+1]);
+            if(removeArgument) FREE(cmd->items[i+1]);
+        }
+    }
+    return result;
+}
+
+
+void setOutputFile(LauncherProperties * props, WCHAR *path) {
+    HANDLE out = INVALID_HANDLE_VALUE ;
+    
+    out = CreateFileW(path, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, CREATE_ALWAYS, 0, 0);
+    if(out!=INVALID_HANDLE_VALUE) {
+        SetStdHandle(STD_OUTPUT_HANDLE, out);
+        SetStdHandle(STD_ERROR_HANDLE, out);
+        props->stdoutHandle = out;
+        props->stderrHandle = out;
+        writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "[CMD Argument] Redirect output to file : ", 0);
+        writeMessageW(props, OUTPUT_LEVEL_DEBUG, 0, path, 1);
+    } else  {
+        WCHAR * err = NULL;
+        DWORD code = GetLastError();
+        props->status = ERROR_INPUTOUPUT;
+        writeErrorA(props, OUTPUT_LEVEL_DEBUG, 1, "[CMD Argument] Can`t create file: ", path, code);
+        err = getErrorDescription(code);
+        showMessageW(props, L"Can`t redirect output to file!\n\nRequested file : %s\n%s", 2, path, err);
+        FREE(err);
+    }
+}
+
+void setOutput(LauncherProperties * props) {
+    WCHAR * file = props->userDefinedOutput;
+    if(file!=NULL) {
+        DWORD exists = fileExists(file);
+        if((exists && !isDirectory(file) )|| !exists) {
+            setOutputFile(props, file);
+        }
+    }
+    
+    writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0,
+            (props->outputLevel == OUTPUT_LEVEL_DEBUG) ?
+                "[CMD Argument] Using debug output." :
+                "Using normal output." , 1);
+                
+}
+
+
+void loadLocalizationStrings(LauncherProperties *props) {
+    
+    // load localized messages
+    writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "Loading I18N Strings.", 1);
+    loadI18NStrings(props);
+    
+    if(!isOK(props)) {
+        writeMessageA(props, OUTPUT_LEVEL_NORMAL, 1, "Error! Can`t load i18n strings!!", 1);
+        showErrorW(props, INTEGRITY_ERROR_PROP, 1, props->exeName);
+    }
+}
+
+void readDefaultRoots(LauncherProperties *props) {                       
+    TCHAR appDataValueTChar[MAX_PATH];
+    TCHAR localAppDataValueTChar[MAX_PATH];    
+    SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, appDataValueTChar);
+    SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, localAppDataValueTChar);    
+    WCHAR* appDataValue = toWCHAR(appDataValueTChar);
+    WCHAR* localAppDataValue = toWCHAR(localAppDataValueTChar);
+                        
+    writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "Reading Default Userdir and Cachedir roots...", 1);
+    
+    props->defaultUserDirRoot = appendStringW(appDataValue, toWCHAR("\\NetBeans"));
+    writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "defaultUserDirRoot: ", 0);
+    writeMessageW(props, OUTPUT_LEVEL_DEBUG, 0, props->defaultUserDirRoot, 1);
+    
+    props->defaultCacheDirRoot = appendStringW(localAppDataValue, toWCHAR("\\NetBeans\\Cache"));
+    writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "defaultCacheDirRoot: ", 0);
+    writeMessageW(props, OUTPUT_LEVEL_DEBUG, 0, props->defaultCacheDirRoot, 1);
+    
+    writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "End of Reading Default Roots.", 1);
+}
+
+void createTMPDir(LauncherProperties * props) {
+    WCHAR * argTempDir = NULL;
+    DWORD createRndSubDir = 1;
+    
+    if((argTempDir = props->userDefinedExtractDir) !=NULL) {
+        writeMessageA(props, OUTPUT_LEVEL_DEBUG, 1, "[CMD Argument] Extract data to directory: ", 0);
+        writeMessageW(props, OUTPUT_LEVEL_DEBUG, 1, argTempDir, 1);
+        createRndSubDir = 0;
+    } else if((argTempDir = props->userDefinedTempDir) !=NULL) {
+        writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "[CMD Argument] Using tmp directory: ", 0);
+        writeMessageW(props, OUTPUT_LEVEL_NORMAL, 0, argTempDir, 1);
+    }
+    
+    createTempDirectory(props, argTempDir, createRndSubDir);
+    if(!isOK(props)) {
+        showErrorW(props, CANT_CREATE_TEMP_DIR_PROP, 1, props->tmpDir);
+    }
+}
+
+void checkExtractionStatus(LauncherProperties *props) {
+    if(props->status == ERROR_FREESPACE) {
+        DWORD hiMB  = props->bundledSize->High;
+        DWORD lowMB  = props->bundledSize->Low;
+        DWORD hiMult = (hiMB!=0) ? ((MAXDWORD / 1024) + 1) / 1024 : 0;
+        DWORD dw = hiMult * hiMB + lowMB / (1024 * 1024) + 1;
+        WCHAR * size = DWORDtoWCHAR(dw);
+        
+        writeMessageA(props, OUTPUT_LEVEL_DEBUG, 1, "Error! Not enought free space !", 1);
+        showErrorW(props, NOT_ENOUGH_FREE_SPACE_PROP, 2, size, tempdirArg);
+        FREE(size);
+    }
+    else if(props->status == ERROR_INTEGRITY) {
+        writeMessageA(props, OUTPUT_LEVEL_DEBUG, 1, "Error! Can`t extract data from bundle. Seems to be integrirty error!", 1);
+        showErrorW(props, INTEGRITY_ERROR_PROP, 1, props->exeName);
+    }
+}
+
+
+void trySetCompatibleJava(WCHAR * location, LauncherProperties * props) {
+    if(isTerminated(props)) return;
+    if(location!=NULL) {
+        JavaProperties * javaProps = NULL;
+        
+        if(inList(props->alreadyCheckedJava, location)) {
+            writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "... already checked location ", 0);
+            writeMessageW(props, OUTPUT_LEVEL_NORMAL, 0, location, 1);
+            // return here and don`t proceed with private jre checking since it`s already checked as well
+            return;
+        } else {
+            props->alreadyCheckedJava = addStringToList(props->alreadyCheckedJava, location);
+        }
+        
+        getJavaProperties(location, props, &javaProps);
+        
+        if(isOK(props)) {
+            writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "... some java at ", 0);
+            writeMessageW(props, OUTPUT_LEVEL_NORMAL, 0, location, 1);
+            // some java there, check compatibility
+            writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "... checking compatibility of java : ", 0);
+            writeMessageW(props, OUTPUT_LEVEL_NORMAL, 0, javaProps->javaHome, 1);
+            if(isJavaCompatible(javaProps, props->compatibleJava, props->compatibleJavaNumber)) {
+                writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "... compatible", 1);
+                props->java = javaProps;
+            } else {
+                props->status = ERROR_JVM_UNCOMPATIBLE;
+                writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "... uncompatible", 1);
+                freeJavaProperties(&javaProps);
+            }
+        } else {
+            writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "... no java at ", 0);
+            writeMessageW(props, OUTPUT_LEVEL_NORMAL, 0, location, 1);
+            if (props->status==ERROR_INPUTOUPUT) {
+                props->status = ERROR_JVM_NOT_FOUND;
+            }
+        }
+        
+        if(props->status == ERROR_JVM_NOT_FOUND) { // check private JRE
+            //DWORD privateJreStatus = props->status;
+            WCHAR * privateJre = appendStringW(NULL, location);
+            privateJre = appendStringW(privateJre, L"\\jre");
+            writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "... check private jre at ", 0);
+            writeMessageW(props, OUTPUT_LEVEL_NORMAL, 0, privateJre, 1);
+            
+            if(inList(props->alreadyCheckedJava, privateJre)) {
+                writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "... already checked location ", 0);
+                writeMessageW(props, OUTPUT_LEVEL_NORMAL, 0, privateJre, 1);
+            } else {
+                props->alreadyCheckedJava = addStringToList(props->alreadyCheckedJava, privateJre);
+                
+                getJavaProperties(privateJre, props, &javaProps);
+                if(isOK(props)) {
+                    writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "... checking compatibility of private jre : ", 0);
+                    writeMessageW(props, OUTPUT_LEVEL_NORMAL, 0, javaProps->javaHome, 1);
+                    if(isJavaCompatible(javaProps, props->compatibleJava, props->compatibleJavaNumber)) {
+                        props->java = javaProps;
+                        props->status = ERROR_OK;
+                    } else {
+                        freeJavaProperties(&javaProps);
+                        props->status = ERROR_JVM_UNCOMPATIBLE;
+                    }
+                } else if (props->status==ERROR_INPUTOUPUT) {
+                    props->status = ERROR_JVM_NOT_FOUND;
+                }
+            }
+            FREE(privateJre);
+        }
+    } else {
+        props->status = ERROR_JVM_NOT_FOUND;
+    }
+}
+
+void resolveTestJVM(LauncherProperties * props) {
+    WCHAR * testJVMFile = NULL;
+    WCHAR * testJVMClassPath = NULL;
+    
+    writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "Resolving testJVM classpath...", 1);
+    writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "... first step : ", 0);
+    writeMessageW(props, OUTPUT_LEVEL_DEBUG, 0, props->testJVMFile->path, 1);
+    resolvePath(props, props->testJVMFile);
+    testJVMFile = props->testJVMFile->resolved;
+    
+    writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "... second     : ", 0);
+    writeMessageW(props, OUTPUT_LEVEL_DEBUG, 0, props->testJVMFile->resolved, 1);
+    
+    
+    if(isDirectory(testJVMFile)) { // the directory of the class file is set
+        writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "... testJVM is : directory ", 1);
+        testJVMClassPath = appendStringW(NULL, testJVMFile);
+    } else { // testJVMFile is either .class file or .jar/.zip file with the neccessary class file
+        WCHAR * dir = getParentDirectory(testJVMFile);
+        WCHAR * ptr = testJVMFile;
+        do {
+            ptr = searchW(ptr, CLASS_SUFFIX); // check if ptr contains .class
+            if(ptr==NULL) { // .jar or .zip file
+                writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "... testJVM is : ZIP/JAR file", 1);
+                testJVMClassPath = appendStringW(NULL, testJVMFile);
+                break;
+            }
+            ptr += getLengthW(CLASS_SUFFIX); // shift to the right after the ".class"
+            
+            if(ptr==NULL || getLengthW(ptr)==0) { // .class was at the end of the ptr
+                writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "... testJVM is : .class file ", 1);
+                testJVMClassPath = appendStringW(NULL, dir);
+                break;
+            }
+        } while(1);
+        FREE(dir);
+    }
+    
+    FREE(props->testJVMFile->resolved);
+    props->testJVMFile->resolved = testJVMClassPath;
+    writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "... resolved   : ", 0);
+    writeMessageW(props, OUTPUT_LEVEL_DEBUG, 0, props->testJVMFile->resolved, 1);
+}
+
+void findSuitableJava(LauncherProperties * props) {
+    if(!isOK(props)) return;
+    
+    //resolve testJVM file
+    resolveTestJVM(props);
+    
+    if(!fileExists(props->testJVMFile->resolved)) {
+        writeMessageA(props, OUTPUT_LEVEL_NORMAL, 1, "Can`t find TestJVM classpath : ", 0);
+        writeMessageW(props, OUTPUT_LEVEL_NORMAL, 1, props->testJVMFile->resolved, 1);
+        showErrorW(props, JVM_NOT_FOUND_PROP, 1, javaArg);
+        props->status = ERROR_JVM_NOT_FOUND;
+        return;
+    } else if(!isTerminated(props)) {
+        
+        // try to get java location from command line arguments
+        writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "", 1);
+        writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "Finding JAVA...", 1);
+        
+        //WCHAR * java = NULL;
+        
+        if(props->userDefinedJavaHome!=NULL) { // using user-defined JVM via command-line parameter
+            writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "[CMD Argument] Try to use java from ", 0);
+            writeMessageW(props, OUTPUT_LEVEL_NORMAL, 0, props->userDefinedJavaHome, 1);
+            
+            trySetCompatibleJava(props->userDefinedJavaHome, props);
+            if( props->status == ERROR_JVM_NOT_FOUND || props->status == ERROR_JVM_UNCOMPATIBLE) {
+                const char * prop = (props->status == ERROR_JVM_NOT_FOUND) ?
+                    JVM_USER_DEFINED_ERROR_PROP :
+                    JVM_UNSUPPORTED_VERSION_PROP;
+                    showErrorW(props, prop, 1, props->userDefinedJavaHome);
+            }
+        } else { // no user-specified java argument
+            findSystemJava(props);
+            if( props->java ==NULL) {
+                writeMessageA(props, OUTPUT_LEVEL_DEBUG, 1, "... no java was found", 1);
+                if(props->status == ERROR_BUNDLED_JVM_EXTRACTION) {
+                    showErrorW(props, BUNDLED_JVM_EXTRACT_ERROR_PROP, 1, javaArg);
+                } else if(props->status == ERROR_BUNDLED_JVM_VERIFICATION) {
+                    showErrorW(props, BUNDLED_JVM_VERIFY_ERROR_PROP, 1, javaArg);
+                } else {
+                    showErrorW(props, JVM_NOT_FOUND_PROP, 1, javaArg);
+                    props->status = ERROR_JVM_NOT_FOUND;
+                }                
+            }
+        }
+        
+        if(props->java!=NULL) {
+            writeMessageA(props, OUTPUT_LEVEL_NORMAL, 1, "Compatible jvm was found on the system", 1);
+            printJavaProperties(props, props->java);
+        } else {
+            writeMessageA(props, OUTPUT_LEVEL_NORMAL, 1, "No compatible jvm was found on the system", 1);
+        }
+    }
+    return;
+}
+
+
+
+void resolveLauncherStringProperty(LauncherProperties * props, WCHAR ** result) {
+    if(*result!=NULL) {
+        WCHAR * propStart = searchW(*result, L"$P{");
+        if(propStart!=NULL) {
+            WCHAR * propEnd = searchW(propStart + 3, L"}");
+            if(propEnd!=NULL) {
+                WCHAR * propName;
+                writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "... resolving string property", 1);
+                propName = appendStringNW(NULL, 0, propStart + 3 ,
+                        getLengthW(propStart + 3) - getLengthW(propEnd));
+                writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "... property name is : ", 0);
+                writeMessageW(props, OUTPUT_LEVEL_DEBUG, 0, propName, 1);
+                
+                if(propName!=NULL) {
+                    char * name = toChar(propName);
+                    const WCHAR * propValue = getI18nProperty(props, name);
+                    if(propValue!=NULL) {
+                        WCHAR * tmp = appendStringNW(NULL, 0, *result, getLengthW(*result) - getLengthW(propStart));
+                        tmp = appendStringW(tmp, propValue); 
+                        tmp = appendStringW(tmp, propEnd + 1);
+                        FREE(*result);
+                        *result = tmp;
+                    }
+                    FREE(name);
+                    FREE(propName);
+                }
+            }
+        }
+    }
+}
+
+void resolveLauncherProperties(LauncherProperties * props, WCHAR **result) {
+    if(*result != NULL) {
+        WCHAR * propStart = searchW(*result, L"$L{");
+        if(propStart!=NULL) {
+            WCHAR * propEnd = searchW(propStart + 3, L"}");
+            if(propEnd!=NULL) {
+                WCHAR * propName = appendStringNW(NULL, 0, propStart + 3 , getLengthW(propStart + 3) - getLengthW(propEnd));
+                if(propName!=NULL) {
+                    WCHAR * propValue = NULL;
+                    
+                    if(lstrcmpW(propName, L"nbi.launcher.tmp.dir")==0) {
+                        propValue = appendStringW(NULL, props->tmpDir); // launcher tmpdir
+                    } else if(lstrcmpW(propName, L"nbi.launcher.java.home")==0) {
+                        if(props->java!=NULL) {
+                            propValue  = appendStringW(NULL, props->java->javaHome); // relative to javahome
+                        }
+                    } else if(lstrcmpW(propName, L"nbi.launcher.user.home")==0) {
+                        propValue = getCurrentUserHome();
+                    } else if(lstrcmpW(propName, L"nbi.launcher.parent.dir")==0) {
+                        propValue = appendStringW(NULL, props->exeDir); // launcher parent
+                    }
+                    
+                    
+                    if(propValue!=NULL) {
+                        WCHAR * tmp = appendStringNW(NULL, 0, *result, getLengthW(*result) - getLengthW(propStart));
+                        tmp = appendStringW(tmp, propValue);
+                        tmp = appendStringW(tmp, propEnd + 1);                        
+                        FREE(*result);
+                        FREE(propValue);
+                        *result = tmp;
+                    }
+                }
+            }
+        }
+    }
+    
+}
+
+void resolveString(LauncherProperties * props, WCHAR ** result) {
+    WCHAR * tmp = NULL;
+    
+    writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "Resolving string : ", 0);
+    writeMessageW(props, OUTPUT_LEVEL_DEBUG, 0, *result, 1);
+    do {
+        FREE(tmp);
+        tmp = appendStringW(NULL, *result);
+        //writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "... step 1 : ", 0);
+        //writeMessageW(props, OUTPUT_LEVEL_DEBUG, 0, *result, 1);
+        resolveLauncherProperties(props, result);
+        //writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "... step 2 : ", 0);
+        //writeMessageW(props, OUTPUT_LEVEL_DEBUG, 0, *result, 1);
+        resolveLauncherStringProperty(props, result);
+        //writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "... step 3 : ", 0);
+        //writeMessageW(props, OUTPUT_LEVEL_DEBUG, 0, *result, 1);
+    } while(lstrcmpW(tmp, *result)!=0);
+    
+    FREE(tmp);
+    
+    writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, ".... resolved : ", 0);
+    writeMessageW(props, OUTPUT_LEVEL_DEBUG, 0, *result, 1);
+}
+
+void resolvePath(LauncherProperties * props, LauncherResource * file) {
+    WCHAR * result = NULL;
+    DWORD i=0;
+    
+    if(file==NULL) return;
+    if(file->resolved!=NULL) return;
+    
+    file->resolved = appendStringW(NULL, file->path);
+    resolveString(props, & (file->resolved));
+    
+    for(i=0;i<getLengthW(file->resolved);i++) {
+        if(file->resolved[i]==L'/') {
+            file->resolved[i]=L'\\';
+        }
+    }
+}
+
+void setClasspathElements(LauncherProperties * props) {
+    if(isOK(props)) {
+        WCHAR * preCP = NULL;
+        WCHAR * appCP = NULL;
+        WCHAR *tmp = NULL;
+        DWORD i = 0 ;
+        
+        writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "Modifying classpath ...", 1);
+        // add some libraries to the beginning of the classpath
+        while((preCP = getArgumentValue(props, classPathPrepend, 1, 1))!=NULL) {
+            writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "... adding entry to the beginning of classpath : ", 0);
+            writeMessageW(props, OUTPUT_LEVEL_DEBUG, 0, preCP, 1);
+            if (props->classpath != NULL) {
+                preCP = appendStringW(preCP, CLASSPATH_SEPARATOR);
+            }
+            //WCHAR *last = props->classpath;
+            resolveString(props, &preCP);
+            tmp = appendStringW(preCP, props->classpath);
+            FREE(props->classpath);
+            props->classpath = tmp;
+        }
+        
+        
+        for(i=0;i<props->jars->size;i++) {
+            WCHAR * resolvedCpEntry = NULL;
+            resolvePath(props, props->jars->items[i]);
+            resolvedCpEntry = props->jars->items[i]->resolved;
+            if(!fileExists(resolvedCpEntry)) {
+                props->status = EXTERNAL_RESOURCE_MISSING;
+                showErrorW(props, EXTERNAL_RESOURE_LACK_PROP, 1, resolvedCpEntry);
+                return;
+            }
+            if (props->classpath != NULL) {
+                props->classpath = appendStringW(props->classpath, CLASSPATH_SEPARATOR);
+            }
+            props->classpath = appendStringW(props->classpath, resolvedCpEntry);
+        }
+        
+        // add some libraries to the end of the classpath
+        while((appCP = getArgumentValue(props, classPathAppend, 1, 1))!=NULL) {
+            writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "... adding entry to the end of classpath : ", 0);
+            writeMessageW(props, OUTPUT_LEVEL_DEBUG, 0, appCP, 1);
+            if (props->classpath != NULL) {
+                props->classpath = appendStringW(props->classpath, CLASSPATH_SEPARATOR);
+            }
+            resolveString(props, &appCP);
+            props->classpath = appendStringW(props->classpath, appCP);
+            FREE(appCP);
+        }
+        
+        writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "... finished", 1);
+    }
+}
+
+void setAdditionalArguments(LauncherProperties * props) {
+    if(isOK(props)) {
+        WCHARList * cmd = props->commandLine;
+        WCHAR ** javaArgs;
+        WCHAR ** appArgs;
+        DWORD i=0;
+        DWORD jArg = 0; // java arguments number
+        DWORD aArg = 0; // app arguments number
+        
+        writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0,
+                "Parsing rest of command line arguments to add them to java or application parameters... ", 1);
+        
+        // get number for array creation
+        for(i=0;i<cmd->size;i++) {
+            if(cmd->items[i]!=NULL) {
+                if(searchW(cmd->items[i], javaParameterPrefix)!=NULL) {
+                    jArg++;
+                } else {
+                    aArg++;
+                }
+            }
+        }
+        
+        // handle DefaultUserDirRoot, DefaultCacheDirRoot - increasing array size
+        jArg = jArg + 2;
+        
+        //fill the array
+        if(jArg>0) {
+            int size = jArg + props->jvmArguments->size;
+            writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, DWORDtoCHAR(size), 1);
+            javaArgs = newppWCHAR(jArg + props->jvmArguments->size);
+            for (i=0;i<props->jvmArguments->size;i++) {
+                javaArgs[i] = props->jvmArguments->items[i];
+            }
+            FREE(props->jvmArguments->items);
+            
+            // cont. handle DefaultUserDirRoot, DefaultCacheDirRoot
+            // * add -Dnetbeans.default_userdir_root
+            // * add -Dnetbeans.default_cachedir_root
+            javaArgs[i-2] = appendStringW(toWCHAR("-Dnetbeans.default_userdir_root="), props->defaultUserDirRoot);
+            writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "Added an JVM argument: ", 0);
+            writeMessageW(props, OUTPUT_LEVEL_DEBUG, 0, javaArgs[i-2], 1);
+            
+            javaArgs[i-1] = appendStringW(toWCHAR("-Dnetbeans.default_cachedir_root="), props->defaultCacheDirRoot);
+            writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "Added an JVM argument: ", 0);
+            writeMessageW(props, OUTPUT_LEVEL_DEBUG, 0, javaArgs[i-1], 1);
+        } else {
+            javaArgs = NULL;
+        }
+        
+        if(aArg>0) {
+            appArgs = newppWCHAR(aArg + props->appArguments->size);
+            for (i=0; i < props->appArguments->size; i++) {
+                appArgs [i]= props->appArguments->items[i];
+            }
+            FREE(props->appArguments->items);
+        } else {
+            appArgs = NULL;
+        }
+        jArg = aArg = 0;
+        
+        for(i=0;i<cmd->size;i++) {
+            if(cmd->items[i]!=NULL) {
+                if(searchW(cmd->items[i], javaParameterPrefix)!=NULL) {
+                    javaArgs [ props->jvmArguments->size + jArg] = appendStringW(NULL, cmd->items[i] + getLengthW(javaParameterPrefix));
+                    writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "... adding JVM argument : ", 0);
+                    writeMessageW(props, OUTPUT_LEVEL_DEBUG, 0, javaArgs [ props->jvmArguments->size + jArg], 1);
+                    jArg ++ ;
+                } else {
+                    appArgs  [ props->appArguments->size + aArg] = appendStringW(NULL, cmd->items[i]);
+                    writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "... adding APP argument : ", 0);
+                    writeMessageW(props, OUTPUT_LEVEL_DEBUG, 0, appArgs  [ props->appArguments->size + aArg], 1);
+                    aArg++;
+                }
+                FREE(cmd->items[i]);
+            }
+        }
+        props->appArguments->size  = props->appArguments->size + aArg;
+        props->jvmArguments->size  = props->jvmArguments->size + jArg;
+        if(props->jvmArguments->items==NULL) props->jvmArguments->items = javaArgs;
+        if(props->appArguments->items==NULL) props->appArguments->items = appArgs;
+        writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "... resolving jvm arguments", 1);
+        for(i=0;i<props->jvmArguments->size;i++) {
+            resolveString(props, &props->jvmArguments->items[i]);
+        }
+        writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "... resolving app arguments", 1);
+        for(i=0;i<props->appArguments->size;i++) {
+            resolveString(props, &props->appArguments->items[i]);
+        }
+        writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "... finished parsing parameters", 1);
+    }
+}
+void appendCommandLineArgument( WCHAR ** command, const WCHAR * arg) {    
+    WCHAR * escapedString = escapeString(arg);
+    *command = appendStringW(*command, escapedString);
+    FREE(escapedString);
+    *command = appendStringW(*command, L" ");    
+}
+
+void setLauncherCommand(LauncherProperties *props) {
+    if(!isOK(props)) return;
+    
+    if(props->java==NULL) {
+        props->status = ERROR_JVM_NOT_FOUND;
+        return;
+    } else {
+        WCHAR * command = NULL;
+        WCHAR * javaIOTmpdir = NULL;
+        DWORD i = 0;
+        
+        appendCommandLineArgument(&command, props->java->javaExe);
+        command = appendStringW(command, L"-Djava.io.tmpdir=");
+        javaIOTmpdir = getParentDirectory(props->tmpDir);
+        appendCommandLineArgument(&command, javaIOTmpdir);
+        FREE(javaIOTmpdir);
+        
+        
+        for(i=0;i<props->jvmArguments->size;i++) {
+            appendCommandLineArgument(&command, props->jvmArguments->items[i]);
+        }
+        
+        appendCommandLineArgument(&command, L"-classpath");
+        appendCommandLineArgument(&command, props->classpath);
+        appendCommandLineArgument(&command, props->mainClass);
+        
+        for(i=0;i<props->appArguments->size; i++) {
+            appendCommandLineArgument(&command, props->appArguments->items[i]);
+        }
+        props->command = command;
+    }
+}
+
+void executeMainClass(LauncherProperties * props) {
+    if(isOK(props) && !isTerminated(props)) {
+        int64t * minSize = newint64_t(0, 0);
+        writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "Executing main class", 1);
+        checkFreeSpace(props, props->tmpDir, minSize);
+        if(isOK(props)) {
+            HANDLE hErrorRead;
+            HANDLE hErrorWrite;
+            char * error = NULL;
+            
+            CreatePipe(&hErrorRead, &hErrorWrite, NULL, 0);
+            hideLauncherWindows(props);
+            executeCommand(props, props->command, NULL, INFINITE, props->stdoutHandle, hErrorWrite, NORMAL_PRIORITY_CLASS);
+            if(!isOK(props)) {
+                writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "... an error occured during JVM running main class", 1);
+                props->exitCode = props->status;
+            } else {
+                char * s = DWORDtoCHAR(props->exitCode);
+                writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "... main class has finished its work. Exit code is ", 0);
+                writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, s, 1);
+                FREE(s);
+            }
+            
+            error = readHandle(hErrorRead);
+            if(getLengthA(error)>1) {
+                DWORD showMessage = 0;
+                char * ptr = error;
+                while(ptr!=NULL) {
+                    //Bug #105165 and #194242
+                    if((searchA(ptr, "Picked up ") == NULL && searchA(ptr, "fatal: Not a git repository") == NULL) && getLengthA(ptr) > 1) {
+                        showMessage = 1;
+                        break;
+                    }
+                    ptr = searchA(ptr, "\n");
+                    if(ptr!=NULL) ptr++;
+                }
+                
+                if(showMessage && props->exitCode != 0) {
+                    WCHAR * errorW = toWCHAR(error);
+                    showMessageW(props, getI18nProperty(props, JAVA_PROCESS_ERROR_PROP), 1, errorW);
+                    FREE(errorW);
+                } else {
+                    writeMessageA(props, OUTPUT_LEVEL_NORMAL, 1, error, 1);
+                }
+            }
+            CloseHandle(hErrorWrite);
+            CloseHandle(hErrorRead);
+            FREE(error);
+            Sleep(1);
+        } else {
+            props->status = ERROR_FREESPACE;
+            props->exitCode = props->status;
+            writeMessageA(props, OUTPUT_LEVEL_DEBUG, 1, "... there is not enough space in tmp dir to execute main jar", 1);
+        }
+        FREE(minSize);
+    }
+}
+
+DWORD isOnlyHelp(LauncherProperties * props) {
+    if(argumentExists(props, helpArg, 1) || argumentExists(props, helpOtherArg, 1)) {
+        
+        WCHARList * help = newWCHARList(NUMBER_OF_HELP_ARGUMENTS);
+        DWORD counter = 0;
+        WCHAR * helpString = NULL;
+        
+        help->items[counter++] = formatMessageW(getI18nProperty(props, ARG_JAVA_PROP), 1, javaArg);
+        help->items[counter++] = formatMessageW(getI18nProperty(props, ARG_TMP_PROP), 1, tempdirArg);
+        help->items[counter++] = formatMessageW(getI18nProperty(props, ARG_EXTRACT_PROP), 1, extractArg);
+        help->items[counter++] = formatMessageW(getI18nProperty(props, ARG_OUTPUT_PROPERTY), 1, outputFileArg);
+        help->items[counter++] = formatMessageW(getI18nProperty(props, ARG_DEBUG_PROP), 1, debugArg);
+        help->items[counter++] = formatMessageW(getI18nProperty(props, ARG_CPA_PROP), 1, classPathAppend);
+        help->items[counter++] = formatMessageW(getI18nProperty(props, ARG_CPP_PROP), 1, classPathPrepend);
+        help->items[counter++] = formatMessageW(getI18nProperty(props, ARG_DISABLE_SPACE_CHECK), 1, nospaceCheckArg);
+        help->items[counter++] = formatMessageW(getI18nProperty(props, ARG_LOCALE_PROP), 1, localeArg);
+        help->items[counter++] = formatMessageW(getI18nProperty(props, ARG_SILENT_PROP), 1, silentArg);
+        help->items[counter++] = formatMessageW(getI18nProperty(props, ARG_HELP_PROP), 1, helpArg);
+        
+        
+        for(counter=0;counter<NUMBER_OF_HELP_ARGUMENTS;counter++) {
+            helpString = appendStringW(appendStringW(helpString, help->items[counter]), NEW_LINE);
+        }
+        freeWCHARList(&help);
+        showMessageW(props, helpString, 0);
+        FREE(helpString);
+        return 1;
+    }
+    return 0;
+}
+
+DWORD isSilent(LauncherProperties * props) {
+    return props->silentMode;
+}
+
+WCHARList * getCommandlineArguments() {
+    int argumentsNumber = 0;
+    int i=0;
+    WCHAR ** commandLine = CommandLineToArgvW(GetCommandLineW(), &argumentsNumber);
+    // the first is always the running program..  we don`t need it
+    // it is that same as GetModuleFileNameW says
+    WCHARList * commandsList = newWCHARList((DWORD) (argumentsNumber - 1) );
+    for(i=0;i<argumentsNumber - 1;i++) {
+        commandsList->items[i] = appendStringW(NULL, commandLine[i + 1]);
+    }
+    
+    LocalFree(commandLine);
+    return commandsList;
+}
+
+
+LauncherProperties * createLauncherProperties() {
+    LauncherProperties *props = (LauncherProperties*)LocalAlloc(LPTR, sizeof(LauncherProperties));
+    DWORD c = 0;
+    props->launcherCommandArguments = newWCHARList(11);
+    props->launcherCommandArguments->items[c++] = appendStringW(NULL, outputFileArg);
+    props->launcherCommandArguments->items[c++] = appendStringW(NULL, javaArg);
+    props->launcherCommandArguments->items[c++] = appendStringW(NULL, debugArg);
+    props->launcherCommandArguments->items[c++] = appendStringW(NULL, tempdirArg);
+    props->launcherCommandArguments->items[c++] = appendStringW(NULL, classPathPrepend);
+    props->launcherCommandArguments->items[c++] = appendStringW(NULL, classPathAppend);
+    props->launcherCommandArguments->items[c++] = appendStringW(NULL, extractArg);
+    props->launcherCommandArguments->items[c++] = appendStringW(NULL, helpArg);
+    props->launcherCommandArguments->items[c++] = appendStringW(NULL, helpOtherArg);
+    props->launcherCommandArguments->items[c++] = appendStringW(NULL, silentArg);
+    props->launcherCommandArguments->items[c++] = appendStringW(NULL, nospaceCheckArg);
+    
+    props->jvmArguments = NULL;
+    props->appArguments = NULL;
+    props->extractOnly  = 0;
+    props->mainClass    = NULL;
+    props->testJVMClass = NULL;
+    props->classpath    = NULL;
+    props->jars         = NULL;
+    props->testJVMFile  = NULL;
+    props->tmpDir       = NULL;
+    props->tmpDirCreated = 0;
+    props->compatibleJava=NULL;
+    props->compatibleJavaNumber=0;
+    props->java    = NULL;
+    props->command = NULL;
+    props->jvms    = NULL;
+    props->other   = NULL;
+    props->alreadyCheckedJava = NULL;
+    props->exePath = getExePath();
+    props->exeName = getExeName();
+    props->exeDir  = getExeDirectory();
+    props->handler = CreateFileW(props->exePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+    props->bundledSize = newint64_t(0, 0);
+    props->bundledNumber = 0;
+    props->commandLine   = getCommandlineArguments();
+    props->status       = ERROR_OK;
+    props->exitCode     = 0;
+    props->outputLevel  = argumentExists(props, debugArg, 1) ? OUTPUT_LEVEL_DEBUG : OUTPUT_LEVEL_NORMAL;
+    props->stdoutHandle = GetStdHandle(STD_OUTPUT_HANDLE);
+    props->stderrHandle = GetStdHandle(STD_ERROR_HANDLE);
+    props->bufsize = READ_WRITE_BUFSIZE;
+    props->restOfBytes = createSizedString();
+    props->I18N_PROPERTIES_NUMBER = 0;
+    props->i18nMessages = NULL;
+    props->userDefinedJavaHome    = getArgumentValue(props, javaArg, 1, 1);
+    props->userDefinedTempDir     = getArgumentValue(props, tempdirArg, 1, 1);
+    props->userDefinedLocale = getArgumentValue(props, localeArg, 0, 1);
+    props->userDefinedExtractDir  = NULL;
+    props->extractOnly = 0;
+    
+    if(argumentExists(props, extractArg, 0)) {
+        props->userDefinedExtractDir = getArgumentValue(props, extractArg, 1, 0);
+        if(props->userDefinedExtractDir==NULL) {// next argument is null or another launcher argument
+            props->userDefinedExtractDir = getCurrentDirectory();
+        }
+        props->extractOnly = 1;
+    }
+    props->userDefinedOutput      = getArgumentValue(props, outputFileArg, 1, 1);
+    props->checkForFreeSpace      = !argumentExists(props, nospaceCheckArg, 0);
+    props->silentMode             = argumentExists(props, silentArg, 0);
+    props->launcherSize = getFileSize(props->exePath);
+    props->isOnlyStub = (compare(props->launcherSize, STUB_FILL_SIZE) < 0);
+    return props;
+}
+void freeLauncherResourceList(LauncherResourceList ** list) {
+    if(*list!=NULL) {
+        if((*list)->items!=NULL) {
+            DWORD i=0;
+            for(i=0;i<(*list)->size;i++) {
+                freeLauncherResource(&((*list)->items[i]));
+            }
+            FREE((*list)->items);
+        }
+        FREE((*list));
+    }
+}
+
+
+void freeLauncherProperties(LauncherProperties **props) {
+    if((*props)!=NULL) {
+        DWORD i=0;
+        writeMessageA(*props, OUTPUT_LEVEL_DEBUG, 0, "Closing launcher properties", 1);
+        freeWCHARList(& ( (*props)->appArguments));
+        freeWCHARList(& ( (*props)->jvmArguments));
+        
+        FREE((*props)->mainClass);
+        FREE((*props)->testJVMClass);
+        FREE((*props)->classpath);
+        freeLauncherResourceList(&((*props)->jars));
+        
+        freeLauncherResourceList(&((*props)->jvms));
+        
+        freeLauncherResourceList(&((*props)->other));
+        
+        freeLauncherResource(&((*props)->testJVMFile));
+        
+        FREE((*props)->tmpDir);
+        for(i=0;i<(*props)->compatibleJavaNumber;i++) {
+            JavaCompatible * jc = (*props)->compatibleJava[i];
+            if(jc!=NULL) {
+                FREE(jc->minVersion);
+                FREE(jc->maxVersion);
+                FREE(jc->vendor);
+                FREE(jc->osName);
+                FREE(jc->osArch);
+                FREE((*props)->compatibleJava[i]);
+            }
+        }
+        freeStringList(&((*props)->alreadyCheckedJava));
+        FREE((*props)->compatibleJava);
+        freeJavaProperties(&((*props)->java));
+        FREE((*props)->userDefinedJavaHome);
+        FREE((*props)->userDefinedTempDir);
+        FREE((*props)->userDefinedExtractDir);
+        FREE((*props)->userDefinedOutput);
+        FREE((*props)->userDefinedLocale);
+        FREE((*props)->command);
+        FREE((*props)->exePath);
+        FREE((*props)->exeDir);
+        FREE((*props)->exeName);
+        FREE((*props)->bundledSize);
+        FREE((*props)->launcherSize);
+        freeSizedString(&((*props)->restOfBytes));
+        
+        flushHandle((*props)->stdoutHandle);
+        flushHandle((*props)->stderrHandle);
+        CloseHandle((*props)->stdoutHandle);
+        CloseHandle((*props)->stderrHandle);
+        
+        freeI18NMessages((*props));
+        freeWCHARList(& ((*props)->launcherCommandArguments));
+        freeWCHARList(& ((*props)->commandLine));
+        CloseHandle((*props)->handler);
+        
+        FREE((*props));
+    }
+    return;
+}
+void printStatus(LauncherProperties * props) {
+    char * s = DWORDtoCHAR(props->status);
+    writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "... EXIT status : ", 0);
+    writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, s, 1);
+    FREE(s);
+    s = DWORDtoCHAR(props->exitCode);
+    writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "... EXIT code : ", 0);
+    writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, s, 1);
+    FREE(s);
+}
+
+void processLauncher(LauncherProperties * props) {
+    setOutput(props);
+    if(!isOK(props) || isTerminated(props)) return;
+    
+    setProgressRange(props, props->launcherSize);
+    if(!isOK(props) || isTerminated(props)) return;
+    
+    skipStub(props);
+    if(!isOK(props) || isTerminated(props)) return;
+    
+    readDefaultRoots(props);
+    if(!isOK(props) || isTerminated(props)) return;
+    
+    loadLocalizationStrings(props);
+    if(!isOK(props) || isTerminated(props)) return;
+    
+    if(isOnlyHelp(props)) return;
+    
+    setProgressTitleString(props, getI18nProperty(props, MSG_PROGRESS_TITLE));
+    setMainWindowTitle(props, getI18nProperty(props, MAIN_WINDOW_TITLE));
+    showLauncherWindows(props);
+    if(!isOK(props) || isTerminated(props)) return;
+    
+    readLauncherProperties(props);
+    checkExtractionStatus(props);
+    if(!isOK(props) || isTerminated(props)) return;
+    
+    if(props->bundledNumber > 0) {
+        createTMPDir(props);
+        if(isOK(props)) {
+            checkFreeSpace(props, props->tmpDir, props->bundledSize);
+            checkExtractionStatus(props);
+        }
+    }
+    
+    if (isOK(props) ){
+        extractJVMData(props);
+        checkExtractionStatus(props);
+        if (isOK(props) && !props->extractOnly && !isTerminated(props)) {
+            findSuitableJava(props);
+        }
+        
+        if (isOK(props) && !isTerminated(props)) {
+            extractData(props);
+            checkExtractionStatus(props);
+            if (isOK(props) && (props->java!=NULL)  && !isTerminated(props)) {
+                setClasspathElements(props);
+                if(isOK(props) && (props->java!=NULL)  && !isTerminated(props)) {
+                    setAdditionalArguments(props);
+                    setLauncherCommand(props);
+                    Sleep(500);
+                    executeMainClass(props);
+                }
+            }
+        }
+    }
+    
+    if(!props->extractOnly && props->tmpDirCreated) {
+        writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "... deleting temporary directory ", 1);
+        deleteDirectory(props, props->tmpDir);
+    }
+    
+}
diff --git a/src/main/cpp/launcher/windows/src/Launcher.h b/src/main/cpp/launcher/windows/src/Launcher.h
new file mode 100644
index 0000000..d062795
--- /dev/null
+++ b/src/main/cpp/launcher/windows/src/Launcher.h
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef _Launcher_H
+#define	_Launcher_H
+
+#include <windows.h>
+#include "Errors.h"
+#include "JavaUtils.h"
+#include "Types.h"
+
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+    
+    extern const WCHAR * NEW_LINE;
+    
+    LauncherProperties * createLauncherProperties();
+    void freeLauncherProperties(LauncherProperties ** props);
+    
+    void printStatus(LauncherProperties * props);
+    void trySetCompatibleJava(WCHAR * location, LauncherProperties * props);
+    DWORD isSilent(LauncherProperties * props);
+    DWORD isLauncherArgument(LauncherProperties * props, WCHAR * value);
+    void processLauncher(LauncherProperties * props);
+    
+    void resolvePath(LauncherProperties * props, LauncherResource * file);
+    void resolveString(LauncherProperties * props, WCHAR ** result);
+    void resolveLauncherProperties(LauncherProperties * props, WCHAR **result);    
+    void appendCommandLineArgument( WCHAR ** command, const WCHAR * arg);
+    
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _Launcher_H */
diff --git a/src/main/cpp/launcher/windows/src/Main.c b/src/main/cpp/launcher/windows/src/Main.c
new file mode 100644
index 0000000..5a819ee
--- /dev/null
+++ b/src/main/cpp/launcher/windows/src/Main.c
@@ -0,0 +1,672 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <commctrl.h>
+#include "Launcher.h"
+#include "FileUtils.h"
+#include "StringUtils.h"
+#include "SystemUtils.h"
+#include "ExtractUtils.h"
+#include "Main.h"
+
+#define HAVE_WCHAR_H 1
+
+char mainClassName[80] = "Main NBI Window Class";
+char mainTitle [80] = "NBI Launcher";
+char showMessageTitle [] = "\n<ShowMessage>\n";
+HWND hwndPB = NULL;
+HWND hwndMain = NULL;
+HWND hwndErrorDetail = NULL;
+HWND hwndErrorTitle = NULL;
+HWND hwndButton = NULL;
+HWND hwndProgressTitle = NULL;
+
+HINSTANCE globalInstance = NULL;
+int64t * totalProgressSize = NULL;
+int64t * currentProgressSize = NULL;
+long steps = 1000;
+long lastCheckedStep = 0;
+int iCmdShowGlobal = 0;
+
+HANDLE initializationSuccess = NULL;
+HANDLE initializationFailed = NULL;
+HANDLE closingWindowsRequired = NULL;
+HANDLE closingWindowsConfirmed = NULL;
+HANDLE buttonPressed = NULL;
+
+#define BTN_EXIT 254
+
+LRESULT CALLBACK WndProc(HWND hwnd, UINT umsg, WPARAM wParam, LPARAM lParam) {
+    switch (umsg) {
+        case WM_CLOSE:
+            SetEvent(closingWindowsRequired);
+            DestroyWindow(hwndPB);
+            DestroyWindow(hwndProgressTitle);
+            DestroyWindow(hwndErrorDetail);
+            DestroyWindow(hwndErrorTitle);
+            DestroyWindow(hwndButton);
+            DestroyWindow(hwnd);
+            return 0;
+            
+        case WM_DESTROY:
+            UnregisterClass(mainClassName, globalInstance);
+            PostQuitMessage(0);
+            return 0;
+        case WM_COMMAND:
+            if(LOWORD(wParam)==BTN_EXIT) {
+                SetEvent(buttonPressed);
+                return 0;
+            }
+    }
+    return DefWindowProc(hwnd, umsg, wParam, lParam);
+}
+
+void initMainWindow(LauncherProperties * props, HINSTANCE hInstance) {
+    if(!isSilent(props)) {
+        int systemWidth = GetSystemMetrics(SM_CXSCREEN);
+        int systemHeight = GetSystemMetrics(SM_CYSCREEN);
+        
+        int w = 460;
+        int h = 200;
+        int x = (systemWidth - w)/2;
+        int y = (systemHeight - h)/2;
+
+        InitCommonControls();
+
+        hwndMain = CreateWindow(mainClassName, mainTitle,
+                //WS_OVERLAPPED | WS_EX_TOOLWINDOW,
+                WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | WS_MINIMIZEBOX /* | WS_THICKFRAME | WS_MAXIMIZEBOX*/
+                ,
+                x, y, w, h, NULL, NULL, hInstance, NULL);        
+    }
+}
+
+void initErrorTitleWindow(LauncherProperties *props, HINSTANCE hInstance) {
+    if(!isSilent(props)) {
+        RECT rcClient;
+        int cyVScroll;
+        cyVScroll = GetSystemMetrics(SM_CYVSCROLL);
+        GetClientRect(hwndMain, &rcClient);
+        hwndErrorTitle = CreateWindowExW(0,  WC_STATICW,  WC_STATICW, WS_CHILD,
+                rcClient.left + 10,  15, rcClient.right - 20, 20, hwndMain, NULL, hInstance, NULL);
+        if (hwndErrorTitle)  {
+            HFONT hFont = (HFONT) GetStockObject(DEFAULT_GUI_FONT);
+            LOGFONT lfTitle;
+            HFONT titleFont;
+            
+            GetObject(hFont, sizeof(lfTitle), &lfTitle);
+            lfTitle.lfWeight = FW_ULTRABOLD;//OLD;
+            lfTitle.lfHeight = lfTitle.lfHeight  + 2 ;
+            lfTitle.lfWidth  = 0;
+            titleFont = CreateFontIndirect(&lfTitle);
+            SendMessage(hwndErrorTitle, WM_SETFONT, (WPARAM) titleFont , FALSE);
+            //DeleteObject(titleFont );
+            setErrorTitleString(props, NULL);
+        }
+    }
+}
+
+void initErrorDetailWindow(LauncherProperties *props, HINSTANCE hInstance) {
+    if(!isSilent(props)) {
+        RECT rcClient;
+        int cyVScroll;
+        cyVScroll = GetSystemMetrics(SM_CYVSCROLL);
+        GetClientRect(hwndMain, &rcClient);
+        hwndErrorDetail = CreateWindowExW(0,  WC_STATICW,  WC_STATICW, WS_CHILD  ,
+                rcClient.left + 10,  40, rcClient.right - 20, 80,
+                hwndMain, NULL, hInstance, NULL);
+        if (hwndErrorDetail)  {
+            LOGFONT lfDetail;
+            HFONT detailFont;
+            HFONT hFont = (HFONT) GetStockObject(DEFAULT_GUI_FONT);
+            GetObject(hFont, sizeof(lfDetail), &lfDetail);
+            lfDetail.lfHeight = lfDetail.lfHeight + 2;
+            lfDetail.lfWidth  = 0;
+            detailFont = CreateFontIndirect(&lfDetail);
+            SendMessage(hwndErrorDetail, WM_SETFONT, (WPARAM) detailFont, FALSE);
+            //DeleteObject(detailFont);
+            setErrorDetailString(props, NULL);
+        }
+    }
+}
+
+void initProgressTitleWindow(LauncherProperties *props, HINSTANCE hInstance) {
+    if(!isSilent(props)) {
+        RECT rcClient;
+        int cyVScroll;
+        int height = 20;
+        cyVScroll = GetSystemMetrics(SM_CYVSCROLL);
+        GetClientRect(hwndMain, &rcClient);
+        hwndProgressTitle = CreateWindowExW(0,  WC_STATICW,  WC_STATICW, WS_CHILD | WS_VISIBLE ,
+                rcClient.left + 10, (rcClient.bottom - cyVScroll)/2 - height, rcClient.right - 20, height,
+                hwndMain, NULL, hInstance, NULL);
+        if (hwndProgressTitle)  {
+            LOGFONT lfTitle;
+            HFONT progressTitleFont;
+            HFONT hFont = (HFONT) GetStockObject(DEFAULT_GUI_FONT);
+            GetObject(hFont, sizeof(lfTitle), &lfTitle);
+            lfTitle.lfHeight = lfTitle.lfHeight + 2;
+            lfTitle.lfWidth  = 0;
+            progressTitleFont = CreateFontIndirect(&lfTitle);
+            SendMessage(hwndProgressTitle, WM_SETFONT, (WPARAM) progressTitleFont, FALSE);
+            //DeleteObject(detailFont);
+            setProgressTitleString(props, NULL);
+        }
+    }
+}
+
+void initProgressWindow(LauncherProperties * props, HINSTANCE hInstance) {
+    if(!isSilent(props)) {
+        RECT rcClient;
+        int cyVScroll;
+        cyVScroll = GetSystemMetrics(SM_CYVSCROLL);
+        GetClientRect(hwndMain, &rcClient);
+        hwndPB = CreateWindowExW(0, PROGRESS_CLASSW, NULL, WS_CHILD | WS_VISIBLE | PBS_SMOOTH,
+                rcClient.left + 10,  (rcClient.bottom - cyVScroll)/2 , rcClient.right - 20, cyVScroll,
+                hwndMain, NULL, hInstance, NULL);
+        totalProgressSize->Low = 100;
+        totalProgressSize->High = 0;
+    }
+}
+
+void initExitButton(LauncherProperties * props, HINSTANCE hInstance) {
+    if(!isSilent(props)) {
+        RECT rcClient;
+        //int cyVScroll    = GetSystemMetrics(SM_CYVSCROLL);
+        int buttonWidth  = 180;
+        int buttonHeight = 25;
+        
+        GetClientRect(hwndMain, &rcClient);
+        hwndButton = CreateWindowExW(0, WC_BUTTONW, NULL,
+                WS_CHILD  | BS_DEFPUSHBUTTON | WS_TABSTOP | BS_PUSHBUTTON  ,
+                rcClient.right - 20 - buttonWidth, rcClient.bottom - 10 - buttonHeight, buttonWidth, buttonHeight,
+                hwndMain, (HMENU)BTN_EXIT, hInstance, 0);
+        if (hwndButton)  {
+            LOGFONT lfButton;
+            HFONT buttonFont;
+            HFONT hFont = (HFONT) GetStockObject(DEFAULT_GUI_FONT);
+            GetObject(hFont, sizeof(lfButton), &lfButton);
+            lfButton.lfHeight = lfButton.lfHeight + 2;
+            lfButton.lfWidth  = 0;
+            buttonFont = CreateFontIndirect(&lfButton);
+            SendMessage(hwndButton, WM_SETFONT, (WPARAM) buttonFont, FALSE);
+            SetFocus(hwndButton);
+            //DeleteObject(detailFont);
+            setButtonString(props, NULL);
+            UpdateWindow(hwndButton);
+        }
+    }
+}
+
+void showErrorW(LauncherProperties * props, const char * error, const DWORD varArgsNumber, ...) {
+    
+    WCHAR * errorTitle = NULL;
+    WCHAR * errorMessage = NULL;
+    DWORD  totalLength = 0;
+    DWORD counter=0;
+    WCHAR * result = NULL;
+    va_list ap;
+    
+    getI18nPropertyTitleDetail(props, error, & errorTitle, &errorMessage);
+    totalLength=getLengthW(errorMessage);
+    
+    va_start(ap, varArgsNumber);
+    
+    while((counter++)<varArgsNumber) {
+        WCHAR * arg = va_arg( ap, WCHAR * );
+        totalLength+=getLengthW(arg);
+    }
+    va_end(ap);
+    result = newpWCHAR(totalLength + 1);
+    va_start(ap, varArgsNumber);
+    if(errorMessage!=NULL) {
+        wvsprintfW(result, errorMessage, ap);
+    }
+    va_end(ap);
+    
+    if(!isSilent(props)) {
+        HANDLE * events = (HANDLE *) LocalAlloc(LPTR, sizeof(HANDLE)*2);
+        
+        hide(props, hwndProgressTitle);
+        hide(props, hwndPB);
+        setErrorDetailString(props, result);
+        setErrorTitleString(props, errorTitle);
+        setButtonString(props, getI18nProperty(props, EXIT_BUTTON_PROP));
+        show(props, hwndErrorDetail);
+        show(props, hwndErrorTitle);
+        show(props, hwndButton);
+        
+        events[0] = buttonPressed;
+        events[1] = closingWindowsRequired;
+        WaitForMultipleObjects(2, events, FALSE, INFINITE);
+        FREE(events);
+    }
+    FREE(result);
+    FREE(errorTitle);
+    FREE(errorMessage);
+}
+
+BOOL InitInstance(LauncherProperties * props, HINSTANCE hInstance, int iCmdShow, HWND * MainWindowHandle) {
+    if(isSilent(props)) return TRUE;
+    iCmdShowGlobal = iCmdShow;
+    
+    initMainWindow(props, hInstance);
+    if(!hwndMain) return FALSE;
+    
+    initErrorTitleWindow(props, hInstance);
+    if(!hwndErrorTitle) return FALSE;
+    
+    initErrorDetailWindow(props, hInstance);
+    if(!hwndErrorDetail) return FALSE;
+    
+    initProgressWindow(props, hInstance);
+    if (! hwndPB)  return FALSE;
+    
+    initProgressTitleWindow(props, hInstance);
+    if (! hwndPB)  return FALSE;
+    
+    initExitButton(props, hInstance);
+    if (! hwndButton)  return FALSE;
+    
+    UpdateWindow(hwndMain);
+    * MainWindowHandle = hwndMain;
+    return TRUE;
+}
+
+void messageLoop(LauncherProperties * props){
+    if(!isSilent(props)) {
+        MSG message;
+        while(GetMessage(&message, NULL, 0, 0) > 0) {
+            if(!IsDialogMessage(hwndMain, & message)) {
+                TranslateMessage(&message);
+                DispatchMessage(&message);
+            }
+        }
+    }
+}
+
+BOOL InitApplication(LauncherProperties * props, HINSTANCE hInstance) {
+    if(isSilent(props)) {
+        return TRUE;
+    }
+    else {
+        
+        WNDCLASSEX wndclass;
+        wndclass.style = CS_HREDRAW | CS_VREDRAW;
+        wndclass.lpfnWndProc = (WNDPROC)WndProc;
+        wndclass.cbSize     = sizeof(WNDCLASSEX);
+        wndclass.cbClsExtra = 0;
+        wndclass.cbWndExtra = 0;
+        wndclass.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(100));
+        wndclass.hIconSm = (HICON)LoadImage(GetModuleHandle(NULL),
+                MAKEINTRESOURCE(100),
+                IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
+        wndclass.hInstance = hInstance;
+        wndclass.hCursor = LoadCursor( 0, IDC_ARROW );
+        wndclass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
+        wndclass.lpszMenuName = NULL;
+        wndclass.lpszClassName = mainClassName;
+        return RegisterClassEx(&wndclass);
+    }
+}
+
+
+DWORD isTerminated(LauncherProperties * props) {
+    if(props->status == ERROR_USER_TERMINATED) {
+        writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "... already terminated", 1);
+        return 1;
+    }
+    if (WAIT_OBJECT_0 == WaitForSingleObject(closingWindowsRequired, 0)) {
+        writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "... terminate signal!", 1);
+        props->status = ERROR_USER_TERMINATED;
+        return 1;
+    }
+    return 0;
+}
+
+void addProgressPosition(LauncherProperties * props, DWORD add) {
+    if(isSilent(props)) return;
+    if ( add > 0 ) {
+        int64t *mult1 = NULL;
+        int64t *mult2 = NULL;
+        int64t *currMult = NULL;
+        int comp1 = 0;
+        int comp2 = 0;
+        int goout = 0;
+
+        plus(currentProgressSize, add);
+        do {
+            multiply(mult1 = newint64_t(totalProgressSize->Low, totalProgressSize->High), lastCheckedStep);
+            multiply(mult2 = newint64_t(totalProgressSize->Low, totalProgressSize->High), lastCheckedStep + 1);
+            multiply(currMult = newint64_t(currentProgressSize->Low, currentProgressSize->High), steps);
+            comp1 = compareInt64t(currMult, mult1);
+
+            if (comp1 == 0) {
+                goout = 1;
+            } else {
+                comp2 = compareInt64t(currMult, mult2);
+                if (comp2 == 0) {
+                    lastCheckedStep++;
+                    goout = 1;
+                } else if (comp1 > 0 && comp2 < 0) {
+                    goout = 1;
+                } else {
+                    lastCheckedStep++;
+                }
+            }
+            FREE(mult1);
+            FREE(mult2);
+            FREE(currMult);
+            if(lastCheckedStep >= steps) {
+                lastCheckedStep = steps;
+                goout = 1;
+            }
+        } while (!goout);
+        SendMessage(hwndPB, PBM_SETPOS, lastCheckedStep, 0);
+    }
+}
+
+void setProgressRange(LauncherProperties * props, int64t * range) {
+    if(isSilent(props)) return;
+    totalProgressSize->Low = range->Low;
+    totalProgressSize->High = range->High;
+    currentProgressSize->Low = 0;
+    currentProgressSize->High = 0;
+    lastCheckedStep = 0;
+    SendMessage(hwndPB, PBM_SETRANGE, 0, MAKELPARAM(0, steps));
+    SendMessage(hwndPB, PBM_SETSTEP, 1, 0);
+}
+
+void hide(LauncherProperties * props, HWND hwnd) {
+    if(!isSilent(props) && hwndMain != NULL && hwnd!=NULL ) {
+        ShowWindow(hwnd, SW_HIDE);
+        UpdateWindow(hwnd);
+    }
+}
+void show(LauncherProperties * props, HWND hwnd) {
+    if(!isSilent(props) && hwndMain != NULL && hwnd!=NULL ) {
+        ShowWindow(hwnd, iCmdShowGlobal);
+        UpdateWindow(hwnd);
+    }
+}
+
+void setProgressTitleString(LauncherProperties * props, const WCHAR * message) {
+    if(isSilent(props)) return;
+    SetWindowTextW(hwndProgressTitle, message);
+    UpdateWindow(hwndProgressTitle);
+    UpdateWindow(hwndMain);
+}
+
+void setErrorTitleString(LauncherProperties * props, const WCHAR * message) {
+    if(isSilent(props)) return;
+    SetWindowTextW(hwndErrorTitle, message);
+    UpdateWindow(hwndErrorTitle);
+    UpdateWindow(hwndMain);
+}
+
+void setErrorDetailString(LauncherProperties * props, const WCHAR * message) {
+    if(isSilent(props)) return;
+    SetWindowTextW(hwndErrorDetail, message);
+    UpdateWindow(hwndErrorDetail);
+    UpdateWindow(hwndMain);
+}
+
+void setButtonString(LauncherProperties * props, const WCHAR * message) {
+    if(isSilent(props)) return;
+    SetWindowTextW(hwndButton, message);
+    UpdateWindow(hwndButton);
+    UpdateWindow(hwndMain);
+}
+
+void setMainWindowTitle(LauncherProperties * props, const WCHAR * message) {
+    if(isSilent(props)) return;
+    SetWindowTextW(hwndMain, message);
+    UpdateWindow(hwndMain);
+}
+
+void closeLauncherWindows(LauncherProperties * props) {
+    if(isSilent(props)) return;
+    SendMessage(hwndMain, WM_CLOSE, 0, 0);
+}
+
+
+void hideLauncherWindows(LauncherProperties * props) {
+    if(isSilent(props)) return;
+    if(hwndMain != NULL) {
+        ShowWindow(hwndMain, HIDE_WINDOW);
+        UpdateWindow(hwndMain);
+    }
+}
+
+
+void showLauncherWindows(LauncherProperties * props) {
+    if(isSilent(props)) return;
+    ShowWindow(hwndMain, iCmdShowGlobal);
+    SetForegroundWindow(hwndMain);
+    UpdateWindow(hwndMain);
+}
+
+void showMessageW(LauncherProperties * props, const WCHAR* message, const DWORD varArgsNumber, ...) {
+    DWORD totalLength = getLengthW(message);
+    va_list ap;
+    DWORD counter=0;
+    WCHAR * result = NULL;
+    writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, showMessageTitle, 0);
+    
+    va_start(ap, varArgsNumber);
+    
+    while((counter++)<varArgsNumber) {
+        WCHAR * arg = va_arg( ap, WCHAR * );
+        totalLength+=getLengthW(arg);
+    }
+    va_end(ap);
+    
+    result = newpWCHAR(totalLength + 1);
+    va_start(ap, varArgsNumber);
+    wvsprintfW(result, message, ap);
+    va_end(ap);
+    writeMessageW(props, OUTPUT_LEVEL_DEBUG, 0, result, 1);
+    if(!isSilent(props)) {
+        hideLauncherWindows(props);
+        MessageBoxW(hwndMain, result, getI18nProperty(props, MSG_MESSAGEBOX_TITLE), MB_OK);
+    }
+}
+
+/*
+void showMessageA(LauncherProperties * props, const char* message, const DWORD varArgsNumber, ...) {
+    DWORD totalLength = getLengthA(message);
+    va_list ap;
+    DWORD counter=0;
+    char * result = NULL;
+    
+    writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, showMessageTitle, 0);
+    va_start(ap, varArgsNumber);
+    while((counter++)<varArgsNumber) {
+        char * arg = va_arg( ap, char * );
+        totalLength+=getLengthA(arg);
+    }
+    va_end(ap);
+    
+    result = newpChar(totalLength + 1);
+    va_start(ap, varArgsNumber);
+    vsprintf(result, message, ap);
+    va_end(ap);
+    writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, result, 1);
+    
+    if(!isSilent(props)) {
+        char * prop = toChar(getI18nProperty(props, MSG_MESSAGEBOX_TITLE));
+        MessageBoxA(hwndMain, result, prop, MB_OK);
+        FREE(prop);
+    }
+    
+}
+*/
+/*
+ * WCHAR* GetStringFromStringTable( UINT uStringID ) {
+ * WCHAR   *pwchMem, *pwchCur;
+ * UINT      idRsrcBlk = uStringID / 16 + 1;
+ * int       strIndex  = uStringID % 16;
+ * HINSTANCE hModule = NULL;
+ * HRSRC     hResource = NULL;
+ * int i=0;
+ * LANGID lang = LANGIDFROMLCID(GetUserDefaultLCID());
+ *
+ * hResource = FindResourceExW( GetModuleHandleW(NULL), (LPWSTR)RT_STRING,
+ * MAKEINTRESOURCEW(idRsrcBlk), lang);
+ *
+ * if( hResource != NULL ) {
+ * pwchMem = (WCHAR *)LoadResource( hModule, hResource );
+ *
+ * if( pwchMem != NULL ) {
+ * pwchCur = pwchMem;
+ * for(i = 0; i<16; i++ ) {
+ * if( *pwchCur ) {
+ * int cchString = *pwchCur;  // String size in characters.
+ * pwchCur++;
+ * if( i == strIndex ) {
+ * WCHAR * tmp = appendStringNW(NULL, 0, pwchCur, cchString);
+ * return tmp;
+ * }
+ * pwchCur += cchString;
+ * }
+ * else
+ * pwchCur++;
+ * }
+ * }
+ * }
+ * return NULL;
+ *
+ * }*/
+
+
+
+
+DWORD WINAPI launcherThread(void * ptr) {
+    HANDLE * events = (HANDLE *) LocalAlloc(LPTR, sizeof(HANDLE)*2);
+    DWORD result;
+    events[0] = initializationSuccess;
+    events[1] = initializationFailed;
+    result = WaitForMultipleObjects(2, events, FALSE, INFINITE);
+    
+    FREE(events);
+    
+    if (result == WAIT_OBJECT_0) {
+        LauncherProperties * props = (LauncherProperties*) ptr;
+        processLauncher(props);
+        SetEvent(closingWindowsConfirmed);
+        closeLauncherWindows(props);
+    }
+    return 0;
+}
+
+
+void createLauncherThread(LauncherProperties *props) {
+    DWORD threadId;
+    if(CreateThread( NULL, 0, &launcherThread, (LPVOID) props, 0, &threadId )==NULL) {
+        SetEvent(closingWindowsConfirmed);
+    }
+}
+
+DWORD createGui(LauncherProperties* props, HINSTANCE hInstance, HINSTANCE hi, int nCmdShow) {
+    if (!InitApplication(props, hInstance)) {
+        SetEvent(initializationFailed);
+        return 0;
+    } else if (!InitInstance(props, hInstance, nCmdShow, & hwndMain)) {
+        SetEvent(initializationFailed);
+        return 0;
+    } else {
+        SetEvent(initializationSuccess);
+    }
+    return 1;
+}
+
+
+DWORD createEvents() {
+    initializationSuccess = CreateEventW(NULL, TRUE, FALSE, NULL);
+    if(initializationSuccess==NULL) {
+        return 0;
+    }
+    initializationFailed = CreateEventW(NULL, TRUE, FALSE, NULL);
+    if(initializationFailed==NULL) {
+        return 0;
+    }
+    buttonPressed = CreateEventW(NULL, TRUE, FALSE, NULL);
+    if(buttonPressed ==NULL) {
+        return 0;
+    }
+    closingWindowsRequired = CreateEventW(NULL, TRUE, FALSE, NULL);
+    if(closingWindowsRequired ==NULL) {
+        return 0;
+    }
+    closingWindowsConfirmed = CreateEventW(NULL, TRUE, FALSE, NULL);
+    if(closingWindowsConfirmed ==NULL) {
+        return 0;
+    }
+    
+    return 1;
+}
+
+int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hi, LPSTR lpCmdLine, int nCmdShow) {
+    DWORD exitCode = 1;
+    DWORD status = ERROR_OK;
+    
+    totalProgressSize = newint64_t(0,0);
+    currentProgressSize = newint64_t(0,0);
+    globalInstance = hInstance;
+    UNREFERENCED_PARAMETER(lpCmdLine);
+    initWow64();
+    if(is9x()) {
+        MessageBoxA(0, "Windows 9X platform is not supported", "Message", MB_OK);
+        status = EXIT_CODE_SYSTEM_ERROR;
+    } else {
+        if(!createEvents()) {
+            status = EXIT_CODE_EVENTS_INITIALIZATION_ERROR;
+        } else {
+            LauncherProperties * props = createLauncherProperties();
+            createLauncherThread(props);
+            if(!createGui(props, hInstance, hi, nCmdShow)) {
+                status = EXIT_CODE_GUI_INITIALIZATION_ERROR;	        
+            } else {	        
+                messageLoop(props);
+                WaitForSingleObject(closingWindowsConfirmed, INFINITE);
+            }
+            
+            status = props->status;
+            exitCode = props->exitCode;
+            printStatus(props);
+            freeLauncherProperties(&props);
+        }
+    }
+    FREE(currentProgressSize);
+    FREE(totalProgressSize);
+    return (status==ERROR_OK) ? exitCode : status;
+}
+
+int WINAPI MyMain(void) {
+    int exitCode;
+    STARTUPINFO StartupInfo;
+    StartupInfo.dwFlags = 0;
+    GetStartupInfo( &StartupInfo );
+    exitCode = WinMain(GetModuleHandle(NULL), NULL, NULL,  StartupInfo.dwFlags & STARTF_USESHOWWINDOW  ? StartupInfo.wShowWindow : SW_SHOWDEFAULT);
+    ExitProcess(exitCode);
+    return exitCode;
+}
diff --git a/src/main/cpp/launcher/windows/src/Main.h b/src/main/cpp/launcher/windows/src/Main.h
new file mode 100644
index 0000000..57c81ef
--- /dev/null
+++ b/src/main/cpp/launcher/windows/src/Main.h
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef _Main_H
+#define	_Main_H
+
+#include <wchar.h>
+#include "Errors.h"
+
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+void addProgressPosition(LauncherProperties *props,DWORD add);
+void setProgressRange(LauncherProperties *props, int64t * size);
+void setErrorDetailString(LauncherProperties *props,const WCHAR * message);
+void setErrorTitleString(LauncherProperties *props,const WCHAR * message);
+void setButtonString(LauncherProperties *props,const WCHAR * message);
+void setProgressTitleString(LauncherProperties *props,const WCHAR * message);
+void setMainWindowTitle(LauncherProperties * props, const WCHAR * message);
+
+void showLauncherWindows(LauncherProperties *props);
+void closeLauncherWindows(LauncherProperties *props);
+void hideLauncherWindows(LauncherProperties *props);
+
+void hide(LauncherProperties *props,HWND hwnd);
+void show(LauncherProperties *props,HWND hwnd);
+
+DWORD isTerminated(LauncherProperties * props);
+
+void showErrorW(LauncherProperties *props, const char * error, const DWORD varArgsNumber, ...);
+
+void showMessageW(LauncherProperties *props,const WCHAR* message, const DWORD number, ...);
+//void showMessageA(LauncherProperties *props,const char * message, const DWORD varArgsNumber, ...);
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _Main_H */
+
diff --git a/src/main/cpp/launcher/windows/src/ProcessUtils.c b/src/main/cpp/launcher/windows/src/ProcessUtils.c
new file mode 100644
index 0000000..0fcd9dd
--- /dev/null
+++ b/src/main/cpp/launcher/windows/src/ProcessUtils.c
@@ -0,0 +1,221 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "ProcessUtils.h"
+#include "StringUtils.h"
+#include "FileUtils.h"
+
+
+const DWORD DEFAULT_PROCESS_TIMEOUT = 30000; //30 sec
+
+DWORD readBuf(HANDLE hRead, WCHAR * buf, DWORD * bytesRead, HANDLE hWrite) {
+    ReadFile(hRead, buf, STREAM_BUF_LENGTH - 1, bytesRead, NULL);
+    
+    if((*bytesRead)>0 && hWrite!=INVALID_HANDLE_VALUE) {
+        DWORD bytesWritten = 0;
+        WriteFile(hWrite, buf, (*bytesRead), &bytesWritten, 0);
+    }
+    ZERO(buf, sizeof(buf));
+    return 0;
+}
+
+DWORD readNextData(HANDLE hRead, WCHAR * buf, HANDLE hWrite) {
+    DWORD bytesRead;
+    DWORD bytesAvailable;
+    ZERO(buf, sizeof(buf));
+    
+    PeekNamedPipe(hRead, buf, STREAM_BUF_LENGTH - 1, &bytesRead, &bytesAvailable, NULL);
+    if (bytesRead != 0) {
+        ZERO(buf, sizeof(buf));
+        if (bytesAvailable >= STREAM_BUF_LENGTH) {
+            while (bytesRead >= STREAM_BUF_LENGTH-1) {
+                readBuf(hRead, buf, &bytesRead, hWrite);
+            }
+        }
+        else {
+            readBuf(hRead, buf, &bytesRead, hWrite);
+        }
+        return bytesRead;
+    }
+    return 0;
+}
+
+// get already running process stdout
+DWORD readProcessStream(PROCESS_INFORMATION pi, HANDLE currentProcessStdin, HANDLE currentProcessStdout, HANDLE currentProcessStderr, DWORD timeOut, HANDLE hWriteInput, HANDLE hWriteOutput, HANDLE hWriteError) {
+    DWORD started = GetTickCount();
+    WCHAR buf[STREAM_BUF_LENGTH];
+    DWORD exitCode=0;    
+    DWORD outRead =0;
+    DWORD errRead =0;
+    DWORD inRead =0;
+    while(1) {
+        outRead = readNextData(currentProcessStdout, buf, hWriteOutput);
+        errRead = readNextData(currentProcessStderr, buf, hWriteError);
+        inRead  = readNextData(hWriteInput, buf, currentProcessStdin);
+        GetExitCodeProcess(pi.hProcess, &exitCode);
+        if (exitCode != STILL_ACTIVE) break;
+        
+        if(outRead == 0 && errRead==0 && inRead==0 && timeOut!=INFINITE) {
+            if((GetTickCount() - started) > timeOut) break;
+        }
+        //avoid extra using of CPU resources
+        Sleep(1);
+    }
+    return exitCode;
+}
+char * readHandle(HANDLE hRead) {
+    char * output = NULL;
+    char * buf = newpChar(STREAM_BUF_LENGTH);
+    DWORD total = 0;
+    DWORD read;
+    DWORD bytesRead;
+    DWORD bytesAvailable;
+    
+    while(1) {
+        PeekNamedPipe(hRead, buf, STREAM_BUF_LENGTH - 1, &bytesRead, &bytesAvailable, NULL);
+        if(bytesAvailable==0) break;
+        ReadFile(hRead, buf, STREAM_BUF_LENGTH - 1, &read, NULL);
+        if(read==0) break;
+        output = appendStringN(output, total, buf, read);
+        total+=read;
+    }
+    FREE(buf);
+    return output;
+}
+
+
+
+
+// run process and get its standart output
+// command - executing command
+// timeLimitMillis - timeout of the process running without any output
+// dir - working directory
+// return ERROR_ON_EXECUTE_PROCESS for serios error
+// return ERROR_PROCESS_TIMEOUT for timeout
+
+void executeCommand(LauncherProperties * props, WCHAR * command, WCHAR * dir, DWORD timeLimitMillis, HANDLE hWriteOutput, HANDLE hWriteError, DWORD priority) {
+    STARTUPINFOW si;
+    SECURITY_ATTRIBUTES sa;
+    SECURITY_DESCRIPTOR sd;
+    PROCESS_INFORMATION pi;
+    
+    HANDLE newProcessInput;
+    HANDLE newProcessOutput;
+    HANDLE newProcessError;
+    
+    HANDLE currentProcessStdout;
+    HANDLE currentProcessStdin;
+    HANDLE currentProcessStderr;
+    
+    WCHAR * directory;
+    
+    InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
+    SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE);
+    sa.lpSecurityDescriptor = &sd;
+    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
+    sa.bInheritHandle = TRUE;
+    
+    
+    if (!CreatePipe(&newProcessInput, &currentProcessStdin, &sa, 0)) {
+        writeErrorA(props, OUTPUT_LEVEL_NORMAL, 1, "Can`t create pipe for input. ", NULL , GetLastError());
+        props->status = ERROR_ON_EXECUTE_PROCESS;
+        return;
+    }
+    
+    if (!CreatePipe(&currentProcessStdout, &newProcessOutput, &sa, 0)) {
+        writeErrorA(props, OUTPUT_LEVEL_NORMAL, 1, "Can`t create pipe for output. ", NULL , GetLastError());
+        CloseHandle(newProcessInput);
+        CloseHandle(currentProcessStdin);
+        props->status = ERROR_ON_EXECUTE_PROCESS;
+        return;
+    }
+    
+    if (!CreatePipe(&currentProcessStderr, &newProcessError, &sa, 0)) {
+        writeErrorA(props, OUTPUT_LEVEL_NORMAL, 1, "Can`t create pipe for error. ", NULL , GetLastError());
+        CloseHandle(newProcessInput);
+        CloseHandle(currentProcessStdin);
+        CloseHandle(newProcessOutput);
+        CloseHandle(currentProcessStdout);
+        props->status = ERROR_ON_EXECUTE_PROCESS;
+        return;
+    }
+    
+    
+    GetStartupInfoW(&si);
+    
+    si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
+    si.wShowWindow = SW_HIDE;
+    si.hStdOutput = newProcessOutput;
+    si.hStdError = newProcessError;
+    si.hStdInput = newProcessInput;
+    
+    directory = (dir!=NULL) ? dir : getCurrentDirectory();
+    writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "Create new process: ", 1);
+    writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "          command : ", 0);
+    writeMessageW(props, OUTPUT_LEVEL_NORMAL, 0, command, 1);
+    writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "        directory : ", 0);
+    writeMessageW(props, OUTPUT_LEVEL_NORMAL, 0, directory, 1);
+    
+    props->exitCode = ERROR_OK;
+    if (CreateProcessW(NULL, command, NULL, NULL, TRUE,
+    CREATE_NEW_CONSOLE | CREATE_NO_WINDOW | CREATE_DEFAULT_ERROR_MODE | priority,
+    NULL, directory, &si, &pi)) {        
+        // TODO
+        // Check whether volder virtualization can brake things and provide method to disable it if necessary 
+        // I am not sure whether we need it off or on.
+        // http://www.netbeans.org/issues/show_bug.cgi?id=122186
+        DWORD timeOut = ((timeLimitMillis<=0) ? DEFAULT_PROCESS_TIMEOUT: timeLimitMillis);
+        props->status = ERROR_OK;
+        writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "... process created", 1);
+        
+        props->exitCode = readProcessStream(pi, currentProcessStdin, currentProcessStdout, currentProcessStderr, timeOut, newProcessInput, hWriteOutput, hWriteError);
+        
+        if(props->exitCode==STILL_ACTIVE) {
+            //actually we have reached the timeout of the process and need to terminate it
+            writeMessageA(props, OUTPUT_LEVEL_DEBUG, 1, "... process is timeouted", 1);
+            GetExitCodeProcess(pi.hProcess, & (props->exitCode));
+            
+            if(props->exitCode==STILL_ACTIVE) {
+                TerminateProcess(pi.hProcess, 0);
+                writeMessageA(props, OUTPUT_LEVEL_DEBUG, 1, "... terminate process", 1);
+                //Terminating process...It worked too much without any stdout/stdin/stderr
+                props->status = ERROR_PROCESS_TIMEOUT;//terminated by timeout                
+            }
+        } else {
+            //application finished its work... succesfully or not - it doesn`t matter            
+            writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "... process finished his work", 1);
+        }
+        CloseHandle(pi.hThread);
+        CloseHandle(pi.hProcess);
+    }  else {
+        writeErrorA(props, OUTPUT_LEVEL_DEBUG, 1, "... can`t create process.", NULL, GetLastError());
+        props->status = ERROR_ON_EXECUTE_PROCESS;        
+    }
+    
+    
+    CloseHandle(newProcessInput);
+    CloseHandle(newProcessOutput);
+    CloseHandle(newProcessError);
+    CloseHandle(currentProcessStdin);
+    CloseHandle(currentProcessStdout);
+    CloseHandle(currentProcessStderr);    
+}
+
+
+
diff --git a/src/main/cpp/launcher/windows/src/ProcessUtils.h b/src/main/cpp/launcher/windows/src/ProcessUtils.h
new file mode 100644
index 0000000..f553b20
--- /dev/null
+++ b/src/main/cpp/launcher/windows/src/ProcessUtils.h
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef _ProcessUtils_H
+#define	_ProcessUtils_H
+
+#include <windows.h>
+#include <stdio.h>
+#include "Errors.h"
+#include "Types.h"
+#include "ExtractUtils.h"
+#include "FileUtils.h"
+
+
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+    
+    #define STREAM_BUF_LENGTH 1024
+    
+    extern const DWORD DEFAULT_PROCESS_TIMEOUT;
+    
+    char * readHandle(HANDLE hRead);
+    
+    void executeCommand(LauncherProperties * props, WCHAR * command, WCHAR * dir, DWORD timeLimitMillis, HANDLE hWriteOutput, HANDLE hWriteError, DWORD priority);
+    
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _ProcessUtils_H */
diff --git a/src/main/cpp/launcher/windows/src/RegistryUtils.c b/src/main/cpp/launcher/windows/src/RegistryUtils.c
new file mode 100644
index 0000000..e60bd60
--- /dev/null
+++ b/src/main/cpp/launcher/windows/src/RegistryUtils.c
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "RegistryUtils.h"
+#include "StringUtils.h"
+#include "SystemUtils.h"
+#include "FileUtils.h"
+
+WCHAR * getStringValue(HKEY root, WCHAR *key, WCHAR *valueName, BOOL access64key) {
+    
+    HKEY hkey = 0 ;
+    WCHAR *result = NULL;
+    DWORD  type  = 0;
+    DWORD  size  = 0;
+    byte*  value = NULL;
+    
+    if(RegOpenKeyExW(root, key, 0, KEY_READ | ((access64key && IsWow64) ? KEY_WOW64_64KEY : 0), &hkey) == ERROR_SUCCESS) {
+        
+        if (RegQueryValueExW(hkey, valueName, NULL, &type, NULL, &size) == ERROR_SUCCESS) {
+            
+            value = (byte*) LocalAlloc(LPTR,(size + 1) * sizeof(WCHAR));
+            ZERO(value, sizeof(WCHAR) * (size + 1));
+            if (RegQueryValueExW(hkey, valueName, NULL, &type, value, &size) == ERROR_SUCCESS) {
+                if(type == REG_SZ) {
+                    result = (WCHAR *)value;
+                }
+            }
+            if(result==NULL) {
+                FREE(value);
+            }            
+        }
+    }
+    
+    if(hkey!=0) {
+        RegCloseKey(hkey);
+    }
+    return result;
+}
+WCHAR * getStringValuePC(HKEY root, WCHAR *parentkey, WCHAR *childkey, WCHAR *valueName, BOOL access64key) {
+    WCHAR * key = appendStringW(appendStringW(appendStringW(NULL, parentkey), L"\\"), childkey);
+    WCHAR *value = getStringValue(root, key, valueName, access64key);
+    FREE(key);
+    return value;
+}
diff --git a/src/main/cpp/launcher/windows/src/RegistryUtils.h b/src/main/cpp/launcher/windows/src/RegistryUtils.h
new file mode 100644
index 0000000..c9851b0
--- /dev/null
+++ b/src/main/cpp/launcher/windows/src/RegistryUtils.h
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef _RegistryUtils_H
+#define	_RegistryUtils_H
+
+#include <windows.h>
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+
+WCHAR * getStringValue(HKEY root, WCHAR *key, WCHAR *valueName, BOOL access64key);
+WCHAR * getStringValuePC(HKEY root, WCHAR *parentkey, WCHAR *childkey, WCHAR *valueName, BOOL access64key);
+
+#ifndef KEY_WOW64_32KEY
+#define KEY_WOW64_32KEY 0x0200
+#endif
+#ifndef KEY_WOW64_64KEY
+#define KEY_WOW64_64KEY 0x0100
+#endif
+
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _RegistryUtils_H */
diff --git a/src/main/cpp/launcher/windows/src/StringUtils.c b/src/main/cpp/launcher/windows/src/StringUtils.c
new file mode 100644
index 0000000..cf0423b
--- /dev/null
+++ b/src/main/cpp/launcher/windows/src/StringUtils.c
@@ -0,0 +1,794 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <wchar.h>
+#include <windows.h>
+#include <winnls.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "StringUtils.h"
+
+
+
+const char *  JVM_NOT_FOUND_PROP           = "nlw.jvm.notfoundmessage";
+const char *  JVM_USER_DEFINED_ERROR_PROP  = "nlw.jvm.usererror";
+    
+const char * JVM_UNSUPPORTED_VERSION_PROP = "nlw.jvm.unsupportedversion";
+const char * NOT_ENOUGH_FREE_SPACE_PROP   = "nlw.freespace";
+const char * CANT_CREATE_TEMP_DIR_PROP    = "nlw.tmpdir";
+const char * INTEGRITY_ERROR_PROP         = "nlw.integrity";
+const char * OUTPUT_ERROR_PROP            = "nlw.output.error";
+const char * JAVA_PROCESS_ERROR_PROP      = "nlw.java.process.error";
+const char * EXTERNAL_RESOURE_LACK_PROP   = "nlw.missing.external.resource";
+const char * BUNDLED_JVM_EXTRACT_ERROR_PROP = "nlw.bundled.jvm.extract.error";
+const char * BUNDLED_JVM_VERIFY_ERROR_PROP  = "nlw.bundled.jvm.verify.error";
+
+const char * ARG_OUTPUT_PROPERTY          = "nlw.arg.output";
+const char * ARG_JAVA_PROP                = "nlw.arg.javahome";
+const char * ARG_DEBUG_PROP               = "nlw.arg.verbose";
+const char * ARG_TMP_PROP                 = "nlw.arg.tempdir";
+const char * ARG_CPA_PROP                 = "nlw.arg.classpatha";
+const char * ARG_CPP_PROP                 = "nlw.arg.classpathp";
+const char * ARG_EXTRACT_PROP             = "nlw.arg.extract";
+const char * ARG_DISABLE_SPACE_CHECK      = "nlw.arg.disable.space.check";
+const char * ARG_LOCALE_PROP              = "nlw.arg.locale";
+const char * ARG_SILENT_PROP              = "nlw.arg.silent";
+const char * ARG_HELP_PROP                = "nlw.arg.help";
+
+const char * MSG_CREATE_TMPDIR     = "nlw.msg.create.tmpdir";
+const char * MSG_EXTRACT_DATA      = "nlw.msg.extract";
+const char * MSG_JVM_SEARCH        = "nlw.msg.jvmsearch";
+const char * MSG_SET_OPTIONS       = "nlw.msg.setoptions";
+const char * MSG_RUNNING           = "nlw.msg.running";
+const char * MSG_TITLE             = "nlw.msg.title";
+const char * MSG_MESSAGEBOX_TITLE  = "nlw.msg.messagebox.title";
+const char * MSG_PROGRESS_TITLE    = "nlw.msg.progress.title";
+
+const char * EXIT_BUTTON_PROP     = "nlw.msg.button.error" ;   
+const char * MAIN_WINDOW_TITLE     = "nlw.msg.main.title" ;
+
+
+
+
+//adds string the the initial string and modifies totalWCHARs and capacity
+// initial - the beginning of the string
+// size - pointer to the value that contains the length of the initial string
+//        It is modified to store returning string length
+// addString - additional string
+//
+
+
+void freeI18NMessages(LauncherProperties * props) {
+    if(props->i18nMessages!=NULL) {
+        DWORD i=0;
+        
+        for(i=0;i<props->I18N_PROPERTIES_NUMBER;i++) {
+            FREE(props->i18nMessages->properties[i]);
+            FREE(props->i18nMessages->strings[i]);
+        }        
+        FREE(props->i18nMessages->properties);        
+        FREE(props->i18nMessages->strings);        
+        FREE(props->i18nMessages);
+    }
+}
+
+char * searchA(const char * wcs1, const char * wcs2) {
+    char *cp = (char *) wcs1;
+    char *s1, *s2;
+    
+    if ( !*wcs2) {
+        return (char *)wcs1;
+    }
+    
+    while (*cp) {
+        s1 = cp;
+        s2 = (char *) wcs2;
+        
+        while ( *s1 && *s2 && !(*s1-*s2) ) {
+            s1++, s2++;
+        }
+        if (!*s2) {
+            return(cp);
+        }
+        cp++;
+    }
+    return(NULL);
+}
+
+WCHAR * searchW(const WCHAR * wcs1, const WCHAR * wcs2) {
+    WCHAR *cp = (WCHAR *) wcs1;
+    WCHAR *s1, *s2;
+    
+    if ( !*wcs2) {
+        return (WCHAR *)wcs1;
+    }
+    
+    while (*cp) {
+        s1 = cp;
+        s2 = (WCHAR *) wcs2;
+        
+        while ( *s1 && *s2 && !(*s1-*s2) ) {
+            s1++, s2++;
+        }
+        if (!*s2) {
+            return(cp);
+        }
+        cp++;
+    }
+    return(NULL);
+}
+
+void getI18nPropertyTitleDetail(LauncherProperties * props, const char * name, WCHAR ** title, WCHAR ** detail) {
+    const WCHAR * prop = getI18nProperty(props,name);    
+    WCHAR * detailStringSep = searchW(prop, L"\n");
+    
+    if(detailStringSep == NULL) {
+        *title = appendStringW(NULL, prop);
+        *detail = NULL;
+    } else {
+        DWORD dif = getLengthW(prop) - getLengthW(detailStringSep);
+        *title = appendStringNW(NULL, 0, prop, dif);
+        *detail = appendStringW(NULL, prop + (dif + 1));
+    }    
+}
+const WCHAR * getI18nProperty(LauncherProperties * props, const char * name) {
+    if(name==NULL) return NULL;
+    if(name!=NULL && props->i18nMessages!=NULL) {
+        DWORD i;
+        for(i=0;i<props->I18N_PROPERTIES_NUMBER;i++) {
+            char * pr = props->i18nMessages->properties[i];
+            if(pr!=NULL) { // hope so it`s true
+                if(lstrcmpA(name, pr)==0) {
+                    return props->i18nMessages->strings[i];
+                }
+            }
+        }
+    }
+    return getDefaultString(name);
+}
+
+WCHAR * getDefaultString(const char *name) {
+    if(lstrcmpA(name, JVM_NOT_FOUND_PROP)==0) {
+        return L"Can`t find suitable JVM. Specify it with %s argument";
+    } else if(lstrcmpA(name, NOT_ENOUGH_FREE_SPACE_PROP)==0) {
+        return L"Not enought free space at %s";
+    } else if(lstrcmpA(name, CANT_CREATE_TEMP_DIR_PROP)==0) {
+        return L"Can`t create temp directory %s";
+    } else if(lstrcmpA(name, INTEGRITY_ERROR_PROP)==0) {
+        return L"Integrity error. File %s is corrupted";
+    } else if(lstrcmpA(name, JVM_USER_DEFINED_ERROR_PROP)==0) {
+        return L"Can`t find JVM at %s";
+    } else if(lstrcmpA(name, JVM_UNSUPPORTED_VERSION_PROP)==0) {
+        return L"Unsupported JVM at %s";
+    } else if(lstrcmpA(name, OUTPUT_ERROR_PROP)==0) {
+        return L"Can`t create file %s.\nError: %s";
+    } else if(lstrcmpA(name, JAVA_PROCESS_ERROR_PROP)==0) {
+        return L"Java error:\n%s";
+    } else if(lstrcmpA(name, ARG_JAVA_PROP)==0) {
+        return L"%s Using specified JVM";
+    }  else if(lstrcmpA(name, ARG_OUTPUT_PROPERTY)==0) {
+        return L"%s Output all stdout/stderr to the file";
+    } else if(lstrcmpA(name, ARG_DEBUG_PROP)==0) {
+        return L"%s Use verbose output";
+    } else if(lstrcmpA(name, ARG_TMP_PROP)==0) {
+        return L"%s Use specified temporary dir for extracting data";
+    } else if(lstrcmpA(name, ARG_CPA_PROP)==0) {
+        return L"%s Append classpath";
+    }  else if(lstrcmpA(name, ARG_CPP_PROP)==0) {
+        return L"%s Prepend classpath";
+    } else if(lstrcmpA(name, ARG_EXTRACT_PROP)==0) {
+        return L"%s Extract all data";
+    }  else if(lstrcmpA(name, ARG_HELP_PROP)==0) {
+        return L"%s Using this help";
+    } else if(lstrcmpA(name, ARG_DISABLE_SPACE_CHECK)==0) {
+        return L"%s Disable free space check";
+    } else if(lstrcmpA(name, ARG_LOCALE_PROP )==0) {
+        return L"%s Use specified locale for messagess";       
+    } else if(lstrcmpA(name, ARG_SILENT_PROP )==0) {
+        return L"%s Run silently";       
+    } else if(lstrcmpA(name, MSG_CREATE_TMPDIR)==0) {
+        return L"Creating tmp directory...";
+    } else if(lstrcmpA(name, MSG_EXTRACT_DATA)==0) {
+        return L"Extracting data...";
+    } else if(lstrcmpA(name, MSG_JVM_SEARCH)==0) {
+        return L"Finding JVM...";
+    } else if(lstrcmpA(name, MSG_RUNNING)==0) {
+        return L"Running JVM...";
+    } else if(lstrcmpA(name, MSG_SET_OPTIONS)==0) {
+        return L"Setting command options...";
+    } else if(lstrcmpA(name, MSG_MESSAGEBOX_TITLE)==0) {
+        return L"Message";
+    } else if(lstrcmpA(name, MSG_PROGRESS_TITLE)==0) {
+        return L"Running";
+    } else if(lstrcmpA(name, EXIT_BUTTON_PROP)==0) {
+        return L"Exit";
+    } else if(lstrcmpA(name, MAIN_WINDOW_TITLE)==0) {
+        return L"NBI Launcher";
+    } else if(lstrcmpA(name, EXTERNAL_RESOURE_LACK_PROP)==0) {
+        return L"Can`t run launcher\nThe following file is missing : %s";
+    } else if(lstrcmpA(name, BUNDLED_JVM_EXTRACT_ERROR_PROP)==0) {
+        return L"Can`t run prepare bundled JVM";
+    } else if(lstrcmpA(name, BUNDLED_JVM_VERIFY_ERROR_PROP)==0) {
+        return L"Can`t run verify bundled JVM";
+    }
+    return NULL;   
+}
+
+DWORD getLengthA(const char * message) {
+    return (message!=NULL) ? lstrlenA(message) : 0;
+}
+
+DWORD getLengthW(const WCHAR * message) {
+    return (message!=NULL) ? lstrlenW(message) : 0;
+}
+
+//adds string the the initial string
+char *  appendStringN(char *  initial, DWORD initialLength, const char * addString, DWORD addStringLength) {
+    DWORD length = initialLength + addStringLength + 1;
+    if (length > 1) {
+        char * tmp = newpChar(length+1);
+        DWORD i=0;
+        if(initialLength!=0) {
+            for(i=0;i<initialLength;i++) {
+                tmp[i]=initial[i];
+            }
+            FREE(initial);
+        }
+        for(i=0;i<addStringLength;i++) {
+            tmp[i+initialLength] = addString[i];
+        }
+        
+        return tmp;
+    } else {
+        return NULL;
+    }
+}
+
+char * appendString(char *  initial, const char * addString) {
+    return appendStringN(initial, getLengthA(initial), addString, getLengthA(addString));
+}
+
+
+//adds string the the initial string
+WCHAR *  appendStringNW(WCHAR *  initial, DWORD initialLength, const WCHAR * addString, DWORD addStringLength) {
+    
+    DWORD length = initialLength + addStringLength + 1;
+    if(length>1) {
+        
+        WCHAR * tmp = newpWCHAR(length+1);
+        DWORD i=0;
+        
+        if(initialLength!=0) {
+            for(i=0;i<initialLength;i++) {
+                tmp[i]=initial[i];
+            }
+            FREE(initial);
+        }
+        
+        for(i=0;i<addStringLength;i++) {
+            tmp[i+initialLength] = addString[i];
+        }
+        tmp[length] = 0;
+        
+        return tmp;
+    } else {
+        
+        return NULL;
+    }
+}
+
+WCHAR * appendStringW(WCHAR *  initial, const WCHAR * addString) {
+    return appendStringNW(initial, getLengthW(initial), addString, getLengthW(addString));
+}
+
+WCHAR * escapeString(const WCHAR * string) {
+    DWORD length = getLengthW(string);
+    WCHAR *result = newpWCHAR(length * 2 + 4);
+    DWORD i=0;
+    DWORD r=0;
+    DWORD bsCounter = 0;    
+    int quoting = searchW(string, L" ") || searchW(string, L"\t");
+    if(quoting) {
+        result[r++] = '\"';
+    }
+    for(i=0;i<length;i++) {
+        const WCHAR c = string[i];
+        switch(c) {
+            case '\\' :
+                bsCounter++;
+                break;
+            case '"':
+                bsCounter++;
+                do {
+                    result[r++] = '\\';
+                    bsCounter--;
+                } while(bsCounter>0);
+            default:
+                bsCounter = 0;                
+                break;
+        }
+        result[r++] = c;
+    }
+    if(quoting) {
+        while(bsCounter>0) {
+            result[r++] = '\\';
+            bsCounter--;
+        }
+        result[r++] = '\"';
+    }
+    result[r] = '\0';    
+    return result;     
+}
+
+char * DWORDtoCHARN(DWORD value, int fillZeros) {
+    int digits = 0;
+    DWORD tmpValue = value;
+    int i = 0;
+    char * str;
+
+    do {
+        digits++;
+        tmpValue = tmpValue / 10;
+    } while(tmpValue!=0);
+    tmpValue = value;
+    if(digits < fillZeros) {
+        digits = fillZeros;
+    }
+    str = (char*) LocalAlloc(LPTR, sizeof(char)*(digits +1));
+    str[digits] = '\0';
+    for(i=0;i<digits;i++) {
+        str [digits - i - 1] = '0' + (char) (tmpValue - ((tmpValue / 10) * 10));
+        tmpValue = tmpValue / 10;
+    }
+    return str;
+}
+
+WCHAR * DWORDtoWCHARN(DWORD value, int fillZeros) {
+    int digits = 0;
+    DWORD tmpValue = value;
+    int i = 0;
+    WCHAR * str;
+
+    do {
+        digits++;
+        tmpValue = tmpValue / 10;
+    } while(tmpValue!=0);
+    tmpValue = value;
+    if(digits < fillZeros) {
+        digits = fillZeros;
+    }
+    
+    str = (WCHAR*) LocalAlloc(LPTR, sizeof(WCHAR)*(digits +1));
+    str[digits] = L'\0';
+    for(i=0;i<digits;i++) {
+        str [digits - i - 1] = L'0' + (WCHAR) (tmpValue - ((tmpValue / 10) * 10));
+        tmpValue = tmpValue / 10;
+    }
+    return str;
+}
+WCHAR * DWORDtoWCHAR(DWORD value) {
+    return DWORDtoWCHARN(value, 0);
+}
+
+char * DWORDtoCHAR(DWORD value) {
+    return DWORDtoCHARN(value,0);
+}
+
+char * long2charN(long value, int fillZeros) {
+    int digits = 0;
+    long tmpValue = value;
+    int i = 0;
+    char * str;
+    
+    do {
+        digits++;
+        tmpValue = tmpValue / 10;
+    } while(tmpValue!=0);
+    tmpValue = value;
+    if(digits < fillZeros) {
+        digits = fillZeros;
+    }
+    str = (char*) LocalAlloc(LPTR, sizeof(char)*(digits +1));
+    str[digits] = '\0';
+    for(i=0;i<digits;i++) {
+        str [digits - i - 1] = '0' + (char) (tmpValue - ((tmpValue / 10) * 10));
+        tmpValue = tmpValue / 10;
+    }
+    return str;
+}
+
+char * long2char(long value) {
+    return long2charN(value,0);
+}
+
+char * word2charN(WORD value, int fillZeros) {
+    int digits = 0;
+    WORD tmpValue = value;
+    int i = 0;
+    char * str;
+
+    do {
+        digits++;
+        tmpValue = tmpValue / 10;
+    } while(tmpValue!=0);
+    tmpValue = value;
+    if(digits < fillZeros) {
+        digits = fillZeros;
+    }
+    str = (char*) LocalAlloc(LPTR, sizeof(char)*(digits +1));
+    str[digits] = '\0';
+    for(i=0;i<digits;i++) {
+        str [digits - i - 1] = '0' + (char) (tmpValue - ((tmpValue / 10) * 10));
+        tmpValue = tmpValue / 10;
+    }
+    return str;
+}
+
+char * word2char(WORD value) {
+    return word2charN(value,0);
+}
+
+char * int64ttoCHAR(int64t* value) {
+    if(value->High==0) {
+        return DWORDtoCHAR(value->Low);
+    } else {
+        char * high = DWORDtoCHAR(value->High);
+        char * low  = DWORDtoCHAR(value->Low);
+        DWORD highLength = getLengthA(high);
+        DWORD lowLength  = getLengthA(low);
+
+        char * str = newpChar(highLength + lowLength + 9);
+        DWORD i = 0;
+        str[0] = '[';
+        str[1] = 'H';
+        str[2] = ']';
+        str[3] = '[';
+        str[4] = 'L';
+        str[5] = ']';
+        str[6] = '=';
+
+        for(i = 0; i < highLength; i++) {
+            str [7 + i] = high[i];
+        }
+        str [7 + highLength] =L',';
+        for(i = 0; i < lowLength;i++) {
+            str [8 + highLength + i] = low[i];
+        }
+        str [8 + highLength + lowLength] = '\0';
+        FREE(high);
+        FREE(low);
+        return str;
+    }
+}
+WCHAR * int64ttoWCHAR(int64t*value) {
+    if(value->High==0) {
+        return DWORDtoWCHAR(value->Low);
+    } else {
+        WCHAR * high = DWORDtoWCHAR(value->High);
+        WCHAR * low  = DWORDtoWCHAR(value->Low);
+        DWORD highLength = getLengthW(high);
+        DWORD lowLength  = getLengthW(low);
+
+        WCHAR * str = newpWCHAR(highLength + lowLength + 9);
+        DWORD i = 0;
+        str[0] = L'[';
+        str[1] = L'H';
+        str[2] = L']';
+        str[3] = L'[';
+        str[4] = L'L';
+        str[5] = L']';
+        str[6] = L'=';
+
+        for(i = 0; i < highLength;i++) {
+            str [7 + i] = high[i];
+        }
+        str [7 + highLength] = L',';
+        for(i = 0; i < lowLength;i++) {
+            str [8 + highLength + i] = low[i];
+        }
+        str [8 + highLength + lowLength] = L'\0';
+        FREE(high);
+        FREE(low);
+        return str;
+    }
+}
+
+void freeStringList(StringListEntry **ss) {
+    while ( (*ss) !=NULL) {
+        StringListEntry * tmp = (*ss)->next;
+        FREE((*ss)->string);
+        FREE((*ss));
+        * ss = tmp;
+    }
+}
+
+DWORD inList(StringListEntry * top, WCHAR * str) {    
+    StringListEntry * tmp = top;
+    while(tmp!=NULL) {
+        if(lstrcmpW(tmp->string, str)==0) {
+            return 1;            
+        }
+        tmp = tmp->next;
+    }
+    return 0;
+}
+
+StringListEntry * addStringToList(StringListEntry * top, WCHAR * str) {
+    StringListEntry * ss = (StringListEntry*) LocalAlloc(LPTR,sizeof(StringListEntry));    
+    ss->string = appendStringW(NULL, str);
+    ss->next   = top;
+    return ss;
+}
+
+
+DWORD getLineSeparatorNumber(char *str) {
+    DWORD result = 0;
+    char *ptr = str;
+    if(ptr!=NULL) {
+        while((ptr = searchA(ptr, "\n"))!=NULL) {
+            ptr++;
+            result++;
+            if(ptr==NULL)  break;
+        }
+    }
+    return result;
+}
+
+char *toCharN(const WCHAR * string, DWORD n) {    
+    DWORD len = 0;
+    DWORD length = 0;
+    char * str = NULL;
+    if(string==NULL) return NULL;
+    //static DWORD excludeCodepages [] = { 50220, 50221, 50222, 50225, 50227, 50229, 52936, 54936, 57002,  57003, 57004, 57005, 57006, 57007, 57008, 57009, 57010, 57011, 65000, 42};
+    //int symbols = 0;
+    len = getLengthW(string);    
+    if(n<len) len = n;
+    length = WideCharToMultiByte(CP_ACP, 0, string, len, NULL, 0, 0, NULL);
+    str = newpChar(length+1);
+    WideCharToMultiByte(CP_ACP, 0, string, len, str, length, 0, NULL);
+    return str;
+}
+
+char * toChar(const WCHAR * string) {
+    return toCharN(string, getLengthW(string));
+}
+
+WCHAR *createWCHAR(SizedString * sz) {
+    char * str = sz->bytes;
+    DWORD len = sz->length;
+    int unicodeFlags;    
+    DWORD i;
+    char * string = NULL;
+    char * ptr = NULL;
+    WCHAR * wstr = NULL;
+    if(str==NULL) return NULL;
+    //static DWORD excludeCodepages [] = { 50220, 50221, 50222, 50225, 50227, 50229, 52936, 54936, 57002,  57003, 57004, 57005, 57006, 57007, 57008, 57009, 57010, 57011, 65000, 42};
+    
+    string = appendStringN(NULL, 0 , str, len);    
+    ptr = string;
+    unicodeFlags = -1 ;
+    if(len>=2) {
+        BOOL hasBOM        = (*ptr == '\xFF' && *(ptr+1) == '\xFE');
+        BOOL hasReverseBOM = (*ptr == '\xFE' && *(ptr+1) == '\xFF');
+        
+        if (IsTextUnicode(string, len, &unicodeFlags) || hasBOM || hasReverseBOM) {
+            //text is unicode
+            len-= 2;
+            ptr+= 2;
+            if (unicodeFlags & IS_TEXT_UNICODE_REVERSE_SIGNATURE || hasReverseBOM) {
+                //we need to change bytes order
+                char c;
+                for (i = 0 ; i < len/2 ; i++) {
+                    c = ptr [2 * i] ;
+                    ptr [2 * i] = ptr [2 * i + 1] ;
+                    ptr [2 * i + 1] = c;
+                }
+            }
+        }
+        
+    }
+    wstr = newpWCHAR(len/2+1);
+    
+    for(i=0;i<len/2;i++) {
+        ptr[2*i] = (ptr[2*i]) & 0xFF;
+        ptr[2*i+1] = (ptr[2*i+1])& 0xFF;
+        wstr[i] = ((unsigned char) ptr[2*i]) + (((unsigned char)ptr[2*i+1])  << 8);
+    }
+    
+    FREE(string);
+    return wstr;
+}
+WCHAR *toWCHARn(char * str, DWORD n) {
+    DWORD len = 0;
+    DWORD length = 0;
+    WCHAR * wstr = NULL;
+    if(str==NULL) return NULL;
+    //static DWORD excludeCodepages [] = { 50220, 50221, 50222, 50225, 50227, 50229, 52936, 54936, 57002,  57003, 57004, 57005, 57006, 57007, 57008, 57009, 57010, 57011, 65000, 42};
+    len = getLengthA(str);
+    if(n<len) len = n;
+    length = MultiByteToWideChar(CP_ACP, 0, str, len, NULL, 0);
+    wstr = newpWCHAR(length+1);
+    MultiByteToWideChar(CP_ACP, 0, str, len, wstr, length);
+    return wstr;
+}
+
+WCHAR * toWCHAR( char *string) {
+    return toWCHARn(string, getLengthA(string));
+}
+
+SizedString * createSizedString() {
+    SizedString * s = (SizedString*)LocalAlloc(LPTR,sizeof(SizedString));
+    s->bytes = NULL;
+    s->length = 0;
+    return s;
+}
+
+void freeSizedString(SizedString ** s) {
+    if(*s!=NULL) {
+        FREE((*s)->bytes);
+        FREE((*s));
+        *s = NULL;
+    }
+}
+
+
+WCHAR * getLocaleName() {
+    LANGID langID = LANGIDFROMLCID(GetUserDefaultLCID());
+    LCID localeID = MAKELCID(langID, SORT_DEFAULT);
+    const   DWORD MAX_LENGTH = 512;
+    WCHAR * lang = newpWCHAR(MAX_LENGTH);
+    WCHAR * country = newpWCHAR(MAX_LENGTH);
+    WCHAR * locale = NULL;
+    GetLocaleInfoW(localeID, LOCALE_SISO639LANGNAME, lang, MAX_LENGTH);
+    GetLocaleInfoW(localeID, LOCALE_SISO3166CTRYNAME, country, MAX_LENGTH);    
+    locale = appendStringW(appendStringW(appendStringW(NULL, lang), L"_"), country);
+    FREE(country);
+    FREE(lang);
+    return locale;
+}
+
+WCHAR * newpWCHAR(DWORD length) {
+    WCHAR * res = (WCHAR*) LocalAlloc(LPTR,sizeof(WCHAR) * length);
+    ZERO(res, length * sizeof(WCHAR));
+    return res;
+}
+WCHAR ** newppWCHAR(DWORD length) {
+    return (WCHAR**) LocalAlloc(LPTR,sizeof(WCHAR *) * length);
+}
+
+
+char * newpChar(DWORD length) {
+    char * res = (char*) LocalAlloc(LPTR,sizeof(char) * length);
+    ZERO(res, length * sizeof(char));
+    return res;
+}
+
+char ** newppChar(DWORD length) {
+    return (char**) LocalAlloc(LPTR,sizeof(char*) * length);
+}
+
+int compare(int64t * size, DWORD value) {
+    if (size->High > 0) return 1;
+    
+    if (size->Low > value)  
+        return 1;
+    else if(size->Low == value) 
+        return 0;
+    else //if(size->Low < value)  
+        return -1;    
+}
+int compareInt64t(int64t * a1, int64t * a2) {
+    if (a1->High > a2->High) {
+        return 1;
+    } else if(a1->High == a2->High) {
+        if (a1->Low > a2->Low)  {
+            return 1;
+        } else if(a1->Low == a2->Low)  {
+            return 0;
+        }
+    }
+    return -1;
+}
+
+void plus(int64t * size, DWORD value) {
+    if(value!=0) {
+        if((MAXDWORD - size->Low) >= (value - 1)) {
+            size->Low = size->Low + value;
+        } else {
+            size->High = size->High + 1;
+            size->Low  = value - (MAXDWORD - size->Low) - 1;
+        }
+    }
+}
+void multiply(int64t * size, DWORD value) {
+    if(value==0) {
+        size->Low = 0;
+        size->High = 0;
+    } else {
+        DWORD i = 0;
+        DWORD low = size->Low;
+        DWORD high = size->High;
+        size->High = 0;
+        for(; i < value - 1 ; i++) {
+            plus(size, low);
+        }
+        size->High += high * value;
+    }
+}
+
+void minus(int64t * size, DWORD value) {
+    if(value!=0) {
+        if(size->Low < value) {
+            size->High = size->High -1;
+            size->Low = size->Low + (MAXDWORD - value) + 1;
+        } else {
+            size->Low = size->Low - value;
+        }}
+}
+int64t * newint64_t(DWORD low, DWORD high) {
+    int64t * res = (int64t *) LocalAlloc(LPTR,sizeof(int64t));
+    res->Low = low;
+    res->High = high;
+    return res;
+}
+WCHAR * getErrorDescription(DWORD dw) {
+    WCHAR * lpMsgBuf;
+    WCHAR * lpDisplayBuf = NULL;
+    WCHAR * res = DWORDtoWCHAR(dw);
+    
+    FormatMessageW( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+    NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR) &lpMsgBuf, 0, NULL );
+    
+    lpDisplayBuf = appendStringW(lpDisplayBuf, L"Error code (");
+    lpDisplayBuf = appendStringW(lpDisplayBuf, res);
+    lpDisplayBuf = appendStringW(lpDisplayBuf, L"): ");
+    lpDisplayBuf = appendStringW(lpDisplayBuf, lpMsgBuf);
+
+    FREE(lpMsgBuf);
+    FREE(res);
+    
+    return lpDisplayBuf;
+    
+}
+
+WCHAR * formatMessageW(const WCHAR* message, const DWORD varArgsNumber, ...) {
+    DWORD totalLength=getLengthW(message);
+    DWORD counter=0;
+    WCHAR * result = NULL;
+    
+    va_list ap;
+    va_start(ap, varArgsNumber);
+    
+    while((counter++)<varArgsNumber) {
+        WCHAR * arg = va_arg( ap, WCHAR * );
+        totalLength+=getLengthW(arg);
+    }
+    va_end(ap);
+    
+    result = newpWCHAR(totalLength + 1);
+    va_start(ap, varArgsNumber);
+    wvsprintfW(result, message, ap);
+    va_end(ap);
+    return result;
+}
+
+DWORD isOK(LauncherProperties * props) {
+    return (props->status == ERROR_OK);
+}
diff --git a/src/main/cpp/launcher/windows/src/StringUtils.h b/src/main/cpp/launcher/windows/src/StringUtils.h
new file mode 100644
index 0000000..9cf775c
--- /dev/null
+++ b/src/main/cpp/launcher/windows/src/StringUtils.h
@@ -0,0 +1,149 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef _StringUtils_H
+#define	_StringUtils_H
+
+#include <windows.h>
+#include <stdarg.h>
+#include "Types.h"
+#include "Errors.h"
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+extern const char *  JVM_NOT_FOUND_PROP;
+extern const char *  JVM_USER_DEFINED_ERROR_PROP;
+extern const char *  JVM_UNSUPPORTED_VERSION_PROP;
+extern const char *  NOT_ENOUGH_FREE_SPACE_PROP;  
+extern const char *  CANT_CREATE_TEMP_DIR_PROP;   
+extern const char *  INTEGRITY_ERROR_PROP;   
+extern const char *  OUTPUT_ERROR_PROP;          
+extern const char *  JAVA_PROCESS_ERROR_PROP;    
+extern const char *  EXTERNAL_RESOURE_LACK_PROP;    
+extern const char *  BUNDLED_JVM_EXTRACT_ERROR_PROP;    
+extern const char *  BUNDLED_JVM_VERIFY_ERROR_PROP;    
+extern const char *  ARG_OUTPUT_PROPERTY;        
+extern const char *  ARG_JAVA_PROP;              
+extern const char *  ARG_DEBUG_PROP;             
+extern const char *  ARG_TMP_PROP;               
+extern const char *  ARG_CPA_PROP;               
+extern const char *  ARG_CPP_PROP;               
+extern const char *  ARG_EXTRACT_PROP;
+extern const char *  ARG_DISABLE_SPACE_CHECK;
+extern const char *  ARG_LOCALE_PROP;
+extern const char *  ARG_SILENT_PROP;
+extern const char *  ARG_HELP_PROP;
+extern const char * MSG_CREATE_TMPDIR;     
+extern const char * MSG_EXTRACT_DATA;     
+extern const char * MSG_JVM_SEARCH;       
+extern const char * MSG_SET_OPTIONS;      
+extern const char * MSG_RUNNING;          
+extern const char * MSG_TITLE;            
+extern const char * MSG_MESSAGEBOX_TITLE; 
+extern const char * MSG_PROGRESS_TITLE;   
+extern const char * EXIT_BUTTON_PROP;     
+extern const char * MAIN_WINDOW_TITLE;    
+    
+#define FREE(x) { \
+	if((x)!=NULL) {\
+	LocalFree(x); \
+	(x)=NULL;\
+	}\
+}
+
+
+#ifdef _MSC_VER
+#define ZERO(x,y) SecureZeroMemory((x),(y));
+#else
+#define ZERO(x,y) ZeroMemory((x),(y));
+#endif
+
+
+    
+
+    
+    void freeI18NMessages(LauncherProperties * props);
+    
+    void getI18nPropertyTitleDetail(LauncherProperties * props, const char * name, WCHAR ** title, WCHAR ** detail);
+    const WCHAR * getI18nProperty(LauncherProperties * props, const char * name);
+    WCHAR * getDefaultString(const char *name);
+    
+    WCHAR * addString(WCHAR *  initial, WCHAR *addString, long number, WCHAR * totalWCHARs, WCHAR * capacity);
+    char *  appendStringN(char *  initial, DWORD initialLength, const char * addString, DWORD addStringLength);
+    WCHAR *  appendStringNW(WCHAR *  initial, DWORD initialLength, const WCHAR * addString, DWORD addStringLength);
+    char * appendString(char *  initial, const char * addString);
+    WCHAR * appendStringW(WCHAR *  initial, const WCHAR * addString);
+    WCHAR * escapeString(const WCHAR * string);
+    
+    void freeStringList(StringListEntry **s);
+    StringListEntry * addStringToList(StringListEntry * top, WCHAR * str);
+    DWORD inList(StringListEntry * top, WCHAR * str);
+    
+    char *toChar(const WCHAR * string);
+    char *toCharN(const WCHAR * string, DWORD length);
+    WCHAR * toWCHAR(char * string);
+    WCHAR * toWCHARn(char * string, DWORD length);
+    
+    WCHAR *createWCHAR(SizedString * sz);
+    
+    SizedString * createSizedString();
+    char * int64ttoCHAR(int64t*);
+    WCHAR * int64ttoWCHAR(int64t*);
+    char * DWORDtoCHAR(DWORD);
+    char * DWORDtoCHARN(DWORD,int);
+    
+    WCHAR * DWORDtoWCHAR(DWORD);
+    WCHAR * DWORDtoWCHARN(DWORD,int);
+    
+    char * long2char(long value);
+    char * long2charN(long value,int fillZeros);
+
+    char * word2char(WORD value);
+    char * word2charN(WORD value,int fillZeros);
+
+    void freeSizedString(SizedString ** s);
+        
+    WCHAR * getLocaleName();
+    
+    WCHAR * newpWCHAR(DWORD length);
+    char * newpChar(DWORD length);
+    WCHAR * searchW( const WCHAR * wcs1, const WCHAR * wcs2);
+    char * searchA(const char* str1, const char * str2);
+
+    WCHAR ** newppWCHAR(DWORD length);
+    char ** newppChar(DWORD length);
+    int64t * newint64_t(DWORD low, DWORD high);
+    int compare(int64t * size, DWORD value);
+    int compareInt64t(int64t * a1, int64t * a2);
+    void plus(int64t * size, DWORD value);
+    void multiply(int64t * size, DWORD value);
+    void minus(int64t * size, DWORD value);
+    DWORD getLineSeparatorNumber(char *str);
+    DWORD getLengthA(const char * message);
+    DWORD getLengthW(const WCHAR * message);
+    
+    WCHAR * getErrorDescription(DWORD dw);
+    WCHAR * formatMessageW(const WCHAR* message, const DWORD varArgsNumber, ...);    
+    DWORD isOK(LauncherProperties * props);
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _StringUtils_H */
diff --git a/src/main/cpp/launcher/windows/src/SystemUtils.c b/src/main/cpp/launcher/windows/src/SystemUtils.c
new file mode 100644
index 0000000..c8b423e
--- /dev/null
+++ b/src/main/cpp/launcher/windows/src/SystemUtils.c
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "SystemUtils.h"
+
+BOOL IsWow64 = FALSE;
+
+void getOSVersion(DWORD *id, DWORD *major, DWORD *minor, DWORD *productType) {
+    OSVERSIONINFOEX ver;
+    ver.dwOSVersionInfoSize = sizeof(ver);
+    GetVersionEx((OSVERSIONINFO *) &ver);
+    *id = ver.dwPlatformId;
+    *major = ver.dwMajorVersion;
+    *minor =  ver.dwMinorVersion;
+    *productType = ver.wProductType;
+    return;
+}
+
+DWORD is9x() {
+    DWORD id, major, minor, type;
+    getOSVersion(& id, & major, & minor, & type);
+    return (id == VER_PLATFORM_WIN32_WINDOWS) ? 1 : 0;
+}
+DWORD isNT() {    
+    DWORD id, major, minor, type;
+    getOSVersion(& id, & major, & minor, & type);
+    return (id == VER_PLATFORM_WIN32_NT && major == 4 && minor == 0) ? 1 : 0;
+}