aboutsummaryrefslogtreecommitdiffstats
path: root/find_java2
diff options
context:
space:
mode:
authorRaphael Moll <ralf@android.com>2014-09-05 15:54:04 -0700
committerRaphael Moll <ralf@android.com>2014-09-16 12:42:44 -0700
commit6b94c869cda8de4481f923d3fd722a72665ba55c (patch)
tree3ea0b0483a78d8b0ddfac145c499c614275f316b /find_java2
parent9b200998ffe3485b6b3b2063b4e876f41cc430ea (diff)
downloadsdk-6b94c869cda8de4481f923d3fd722a72665ba55c.zip
sdk-6b94c869cda8de4481f923d3fd722a72665ba55c.tar.gz
sdk-6b94c869cda8de4481f923d3fd722a72665ba55c.tar.bz2
FindJava2+WinLauncher2 MFC app for Windows.
In the code base we have a "find_java" directory that compiles using mingw32 + an Android.mk; it is used to create the find_java.dll used by the NSIS installer, the find_java.exe that is used by android.bat to locate java before executing the SDK/AVD Manager and finally also used by the Android Studio WinLauncher. This reworks find_java to create 2 new MFC apps: - FindJava2 is a straight replacement for the previous find_java.exe. - WinLauncher2 will be a replacement for the Studio launcher. The main change is that the new app has a UI so it lists all the Java.exe paths and let the user add his/her own. Then it remembers the selected path using a registry key and reuses the next time if it's available. The app is built using VS2013 and MFC and there's no Android.mk for it. The goal is to just make prebuilts (that's how find_java.exe/dll and WinLauncher are actually used right now.) The FindJava2 part is final. What's left to do: - Merge the code of WinLauncher into WinLauncher2 to actually run Studio (they will be a need for both a 32-bit version and 64-bit version support.) - Create a new FindJava2.dll for NSIS once we decide how we want to use this in the new installer (e.g. do we just want to make sure there is "some" version of Java or do we want to include the select-and-register functionality too so that the user doesn't have to be asked again later?) Change-Id: I814ed46711ac17a66cd63b9e7c7d485632169ff1
Diffstat (limited to 'find_java2')
-rw-r--r--find_java2/.gitignore10
-rwxr-xr-xfind_java2/FindJava2.sln28
-rwxr-xr-xfind_java2/FindJava2/FindJava2.cpp199
-rwxr-xr-xfind_java2/FindJava2/FindJava2.h19
-rwxr-xr-xfind_java2/FindJava2/FindJava2.rc142
-rwxr-xr-xfind_java2/FindJava2/FindJava2.vcxproj112
-rwxr-xr-xfind_java2/FindJava2/resource.h19
-rwxr-xr-xfind_java2/FindJava2/stdafx.cpp24
-rwxr-xr-xfind_java2/FindJava2/stdafx.h55
-rwxr-xr-xfind_java2/FindJava2/targetver.h24
-rwxr-xr-xfind_java2/WinLauncher2/Resource.h19
-rwxr-xr-xfind_java2/WinLauncher2/WinLauncher2.rc174
-rwxr-xr-xfind_java2/WinLauncher2/WinLauncher2.vcxproj132
-rwxr-xr-xfind_java2/WinLauncher2/res/WinLauncher2.icobin0 -> 67777 bytes
-rwxr-xr-xfind_java2/WinLauncher2/stdafx.cpp24
-rwxr-xr-xfind_java2/WinLauncher2/stdafx.h66
-rwxr-xr-xfind_java2/WinLauncher2/targetver.h24
-rwxr-xr-xfind_java2/android_icon.icobin0 -> 300318 bytes
-rwxr-xr-xfind_java2/src/FindJava2Dlg.cpp268
-rwxr-xr-xfind_java2/src/FindJava2Dlg.h64
-rwxr-xr-xfind_java2/src/JavaFinder.cpp594
-rwxr-xr-xfind_java2/src/JavaFinder.h52
-rwxr-xr-xfind_java2/src/JavaPath.cpp97
-rwxr-xr-xfind_java2/src/JavaPath.h57
-rwxr-xr-xfind_java2/src/WinLauncher2App.cpp154
-rwxr-xr-xfind_java2/src/WinLauncher2App.h43
-rwxr-xr-xfind_java2/src/utils.cpp282
-rwxr-xr-xfind_java2/src/utils.h59
28 files changed, 2741 insertions, 0 deletions
diff --git a/find_java2/.gitignore b/find_java2/.gitignore
new file mode 100644
index 0000000..3117960
--- /dev/null
+++ b/find_java2/.gitignore
@@ -0,0 +1,10 @@
+ipch
+*.aps
+*.sdf
+*.opensdf
+*.suo
+*.filters
+*.user
+Debug
+Release
+
diff --git a/find_java2/FindJava2.sln b/find_java2/FindJava2.sln
new file mode 100755
index 0000000..459e3a7
--- /dev/null
+++ b/find_java2/FindJava2.sln
@@ -0,0 +1,28 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.30723.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WinLauncher2", "WinLauncher2\WinLauncher2.vcxproj", "{64980924-B76E-4E00-90A4-647E67CEB050}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FindJava2", "FindJava2\FindJava2.vcxproj", "{E696008D-A1B8-4434-B6B4-24ED251B1676}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {64980924-B76E-4E00-90A4-647E67CEB050}.Debug|Win32.ActiveCfg = Debug|Win32
+ {64980924-B76E-4E00-90A4-647E67CEB050}.Debug|Win32.Build.0 = Debug|Win32
+ {64980924-B76E-4E00-90A4-647E67CEB050}.Release|Win32.ActiveCfg = Release|Win32
+ {64980924-B76E-4E00-90A4-647E67CEB050}.Release|Win32.Build.0 = Release|Win32
+ {E696008D-A1B8-4434-B6B4-24ED251B1676}.Debug|Win32.ActiveCfg = Debug|Win32
+ {E696008D-A1B8-4434-B6B4-24ED251B1676}.Debug|Win32.Build.0 = Debug|Win32
+ {E696008D-A1B8-4434-B6B4-24ED251B1676}.Release|Win32.ActiveCfg = Release|Win32
+ {E696008D-A1B8-4434-B6B4-24ED251B1676}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/find_java2/FindJava2/FindJava2.cpp b/find_java2/FindJava2/FindJava2.cpp
new file mode 100755
index 0000000..1435e1b
--- /dev/null
+++ b/find_java2/FindJava2/FindJava2.cpp
@@ -0,0 +1,199 @@
+/*
+* Copyright (C) 2014 The Android Open Source Project
+*
+* Licensed 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 "stdafx.h"
+#include "FindJava2.h"
+#include "utils.h"
+#include "JavaFinder.h"
+#include "FindJava2Dlg.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#endif
+
+// The one and only MFC application object
+class CFindJava2App : public CWinApp {
+public:
+ CFindJava2App() {
+ }
+
+ // Set CWinApp default registry key. Must be consistent with all apps using findjava2.
+ void initRegistryKey() {
+ SetRegistryKey(_T("Android-FindJava2"));
+ }
+};
+
+CFindJava2App theApp;
+
+using namespace std;
+
+int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) {
+
+ // Init utils; use default app name based on VERSIONINFO.FileDescription
+ initUtils(NULL);
+
+ // initialize MFC and print and error on failure
+ HMODULE hModule = ::GetModuleHandle(NULL);
+ if (hModule == NULL) {
+ displayLastError(_T("Fatal Error: "));
+ return -2;
+ }
+ if (!AfxWinInit(hModule, NULL, ::GetCommandLine(), 0)) {
+ displayLastError(_T("Fatal Error: "));
+ return -3;
+ }
+
+ theApp.initRegistryKey();
+
+ gIsConsole = true; // tell utils to to print errors to stderr
+ gIsDebug = (getenv("ANDROID_SDKMAN_DEBUG") != NULL);
+
+ // Parse command line
+ bool doTests = false;
+ bool doShortPath = false;
+ bool doVersion = false;
+ bool doJavaW = false;
+ bool doForceUi = false;
+ bool doJava1_7 = false;
+
+ for (int i = 1; i < argc; i++) {
+ if (_tcsnccmp(argv[i], _T("-t"), 2) == 0) {
+ doTests = true;
+
+ } else if (_tcsnccmp(argv[i], _T("-d"), 2) == 0) {
+ gIsDebug = true;
+
+ } else if (_tcsnccmp(argv[i], _T("-s"), 2) == 0) {
+ doShortPath = true;
+
+ } else if (_tcsnccmp(argv[i], _T("-v"), 2) == 0) {
+ doVersion = true;
+
+ } else if (_tcsnccmp(argv[i], _T("-f"), 2) == 0) {
+ doForceUi = true;
+
+ } else if (_tcsnccmp(argv[i], _T("-7"), 2) == 0) {
+ doJava1_7 = true;
+
+ } else if (_tcscmp(argv[i], _T("-w")) == 0 || _tcscmp(argv[i], _T("-javaw")) == 0) {
+ doJavaW = true;
+
+ } else {
+ printf(
+ "Outputs the path of the first Java.exe found on the local system.\n"
+ "Returns code 0 when found, 1 when not found.\n"
+ "Options:\n"
+ "-h / -help : This help.\n"
+ "-t / -test : Internal test.\n"
+ "-f / -force : Force UI selection.\n"
+ "-7 : Java 1.7 minimum instead of 1.6.\n"
+ "-s / -short : Print path in short DOS form.\n"
+ "-w / -javaw : Search a matching javaw.exe; defaults to java.exe if not found.\n"
+ "-v / -version: Only prints the Java version found.\n"
+ );
+ return 2;
+ }
+ }
+
+
+ CJavaFinder javaFinder(JAVA_VERS_TO_INT(1, doJava1_7 ? 7 : 6));
+ CJavaPath javaPath = javaFinder.getRegistryPath();
+
+ if (doTests) {
+ std::set<CJavaPath> paths;
+ javaFinder.findJavaPaths(&paths);
+ bool regPrinted = false;
+ for (const CJavaPath &p : paths) {
+ bool isReg = (p == javaPath);
+ if (isReg) {
+ regPrinted = true;
+ }
+ _tprintf(_T("%c [%s] %s\n"), isReg ? '*' : ' ', p.getVersion(), p.mPath);
+ }
+
+ if (!regPrinted && !javaPath.isEmpty()) {
+ const CJavaPath &p = javaPath;
+ _tprintf(_T("* [%s] %s\n"), p.getVersion(), p.mPath);
+ }
+ return 0;
+ }
+
+ if (doForceUi || javaPath.isEmpty()) {
+ CFindJava2Dlg dlg;
+ dlg.setJavaFinder(&javaFinder);
+ INT_PTR nResponse = dlg.DoModal();
+
+ if (nResponse == IDOK) {
+ // Get java path selected by user and save into registry for later re-use
+ javaPath = dlg.getSelectedPath();
+ javaFinder.setRegistryPath(javaPath);
+ } else if (nResponse == -1) { // MFC boilerplate
+ TRACE(traceAppMsg, 0, "Warning: dialog creation failed, so application is terminating unexpectedly.\n");
+ return 1;
+ }
+ }
+
+ if (javaPath.isEmpty()) {
+ fprintf(stderr, "No java.exe path found");
+ return 1;
+ }
+
+ if (doShortPath) {
+ PVOID oldWow64Value = disableWow64FsRedirection();
+ if (!javaPath.toShortPath()) {
+ revertWow64FsRedirection(&oldWow64Value);
+ _ftprintf(stderr,
+ _T("Failed to convert path to a short DOS path: %s\n"),
+ javaPath.mPath);
+ return 1;
+ }
+ revertWow64FsRedirection(&oldWow64Value);
+ }
+
+ if (doVersion) {
+ // Print version found. We already have the version as an integer
+ // so we don't need to run java -version a second time.
+ _tprintf(_T("%s"), javaPath.getVersion());
+ return 0;
+ }
+
+ if (doJavaW) {
+ // Try to find a javaw.exe instead of java.exe at the same location.
+ CPath javawPath = javaPath.mPath;
+ javawPath.RemoveFileSpec();
+ javawPath.Append(_T("javaw.exe"));
+ javawPath.Canonicalize();
+
+ // Only accept it if we can actually find the exec
+ PVOID oldWow64Value = disableWow64FsRedirection();
+ bool exists = javawPath.FileExists() == TRUE; // skip BOOL-to-bool warning
+ revertWow64FsRedirection(&oldWow64Value);
+
+ if (!exists) {
+ _ftprintf(stderr,
+ _T("Failed to find javaw at: %s\n"),
+ javawPath);
+ return 1;
+ }
+
+ javaPath.mPath = javawPath;
+ }
+
+ // Print java.exe path found
+ _tprintf(_T("%s"), javaPath.mPath);
+ return 0;
+
+}
diff --git a/find_java2/FindJava2/FindJava2.h b/find_java2/FindJava2/FindJava2.h
new file mode 100755
index 0000000..a144bfc
--- /dev/null
+++ b/find_java2/FindJava2/FindJava2.h
@@ -0,0 +1,19 @@
+/*
+* Copyright (C) 2014 The Android Open Source Project
+*
+* Licensed 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.
+*/
+
+#pragma once
+
+#include "resource.h"
diff --git a/find_java2/FindJava2/FindJava2.rc b/find_java2/FindJava2/FindJava2.rc
new file mode 100755
index 0000000..ff767c6
--- /dev/null
+++ b/find_java2/FindJava2/FindJava2.rc
@@ -0,0 +1,142 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (United States) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 1,0,0,1
+ PRODUCTVERSION 1,0,0,1
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x40004L
+ FILETYPE 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "CompanyName", "Android"
+ VALUE "FileDescription", "Find Java for Android SDK"
+ VALUE "FileVersion", "2.0.0.1"
+ VALUE "InternalName", "FindJava2.exe"
+ VALUE "LegalCopyright", "(c) Android. All rights reserved."
+ VALUE "OriginalFilename", "FindJava2.exe"
+ VALUE "ProductName", "Android SDK"
+ VALUE "ProductVersion", "2.0.0.1"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_FINDJAVA2_DIALOG DIALOGEX 0, 0, 317, 196
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
+EXSTYLE WS_EX_APPWINDOW
+CAPTION "Find Java 2 for Android"
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ DEFPUSHBUTTON "Start",IDOK,205,174,50,14
+ PUSHBUTTON "Quit",IDCANCEL,260,174,50,14
+ PUSHBUTTON "Add...",IDC_BUTTON_ADD,7,174,50,14
+ LTEXT "Select which version of Java to use:",IDC_STATIC,7,7,116,8
+ CONTROL "",IDC_PATH_LIST,"SysListView32",LVS_REPORT | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,7,18,300,150
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ IDD_FINDJAVA2_DIALOG, DIALOG
+ BEGIN
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_ANDROID_ICON ICON "..\\android_icon.ico"
+#endif // English (United States) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/find_java2/FindJava2/FindJava2.vcxproj b/find_java2/FindJava2/FindJava2.vcxproj
new file mode 100755
index 0000000..3c9ac4e
--- /dev/null
+++ b/find_java2/FindJava2/FindJava2.vcxproj
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{E696008D-A1B8-4434-B6B4-24ED251B1676}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>FindJava2</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v120</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ <UseOfMfc>Dynamic</UseOfMfc>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v120</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ <UseOfMfc>Dynamic</UseOfMfc>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(ProjectDir);$(SolutionDir)\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalDependencies>version.lib</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(ProjectDir);$(SolutionDir)\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalDependencies>version.lib</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClInclude Include="..\src\FindJava2Dlg.h" />
+ <ClInclude Include="..\src\JavaFinder.h" />
+ <ClInclude Include="..\src\JavaPath.h" />
+ <ClInclude Include="..\src\utils.h" />
+ <ClInclude Include="FindJava2.h" />
+ <ClInclude Include="Resource.h" />
+ <ClInclude Include="stdafx.h" />
+ <ClInclude Include="targetver.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\src\FindJava2Dlg.cpp" />
+ <ClCompile Include="..\src\JavaFinder.cpp" />
+ <ClCompile Include="..\src\JavaPath.cpp" />
+ <ClCompile Include="..\src\utils.cpp" />
+ <ClCompile Include="FindJava2.cpp" />
+ <ClCompile Include="stdafx.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="FindJava2.rc" />
+ </ItemGroup>
+ <ItemGroup>
+ <Image Include="..\android_icon.ico" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/find_java2/FindJava2/resource.h b/find_java2/FindJava2/resource.h
new file mode 100755
index 0000000..1d5f98f
--- /dev/null
+++ b/find_java2/FindJava2/resource.h
@@ -0,0 +1,19 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by FindJava2.rc
+//
+#define IDI_ANDROID_ICON 5
+#define IDD_FINDJAVA2_DIALOG 102
+#define IDC_BUTTON_ADD 1000
+#define IDC_PATH_LIST 1001
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 101
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1000
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/find_java2/FindJava2/stdafx.cpp b/find_java2/FindJava2/stdafx.cpp
new file mode 100755
index 0000000..3baa67f
--- /dev/null
+++ b/find_java2/FindJava2/stdafx.cpp
@@ -0,0 +1,24 @@
+/*
+* Copyright (C) 2014 The Android Open Source Project
+*
+* Licensed 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.
+*/
+
+// stdafx.cpp : source file that includes just the standard includes
+// FindJava2.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+// TODO: reference any additional headers you need in STDAFX.H
+// and not in this file
diff --git a/find_java2/FindJava2/stdafx.h b/find_java2/FindJava2/stdafx.h
new file mode 100755
index 0000000..7230def
--- /dev/null
+++ b/find_java2/FindJava2/stdafx.h
@@ -0,0 +1,55 @@
+/*
+* Copyright (C) 2014 The Android Open Source Project
+*
+* Licensed 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.
+*/
+
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently,
+// but are changed infrequently.
+
+#pragma once
+
+#include "targetver.h"
+
+
+#define _CRT_SECURE_NO_WARNINGS
+
+#include <stdio.h>
+#include <tchar.h>
+#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit
+#define _AFX_NO_MFC_CONTROLS_IN_DIALOGS // remove support for MFC controls in dialogs
+
+#ifndef VC_EXTRALEAN
+#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers
+#endif
+
+#include <afx.h>
+#include <afxwin.h> // MFC core and standard components
+#include <afxext.h> // MFC extensions
+#ifndef _AFX_NO_OLE_SUPPORT
+#include <afxdtctl.h> // MFC support for Internet Explorer 4 Common Controls
+#endif
+#ifndef _AFX_NO_AFXCMN_SUPPORT
+#include <afxcmn.h> // MFC support for Windows Common Controls
+#endif // _AFX_NO_AFXCMN_SUPPORT
+
+#include <iostream>
+
+
+#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit
+
+#include <atlbase.h>
+#include <atlstr.h>
+
+// TODO: reference additional headers your program requires here
diff --git a/find_java2/FindJava2/targetver.h b/find_java2/FindJava2/targetver.h
new file mode 100755
index 0000000..fc6d20b
--- /dev/null
+++ b/find_java2/FindJava2/targetver.h
@@ -0,0 +1,24 @@
+/*
+* Copyright (C) 2014 The Android Open Source Project
+*
+* Licensed 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.
+*/
+
+#pragma once
+
+// Including SDKDDKVer.h defines the highest available Windows platform.
+
+// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
+// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
+
+#include <SDKDDKVer.h>
diff --git a/find_java2/WinLauncher2/Resource.h b/find_java2/WinLauncher2/Resource.h
new file mode 100755
index 0000000..c3b2e0f
--- /dev/null
+++ b/find_java2/WinLauncher2/Resource.h
@@ -0,0 +1,19 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by WinLauncher2.rc
+//
+#define IDI_ANDROID_ICON 5
+#define IDD_FINDJAVA2_DIALOG 102
+#define IDC_BUTTON_ADD 1000
+#define IDC_PATH_LIST 1001
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 130
+#define _APS_NEXT_COMMAND_VALUE 32771
+#define _APS_NEXT_CONTROL_VALUE 1000
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/find_java2/WinLauncher2/WinLauncher2.rc b/find_java2/WinLauncher2/WinLauncher2.rc
new file mode 100755
index 0000000..bee2edf
--- /dev/null
+++ b/find_java2/WinLauncher2/WinLauncher2.rc
@@ -0,0 +1,174 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#ifndef APSTUDIO_INVOKED
+#include "targetver.h"
+#endif
+#include "afxres.h"
+#include "verrsrc.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (United States) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#ifndef APSTUDIO_INVOKED\r\n"
+ "#include ""targetver.h""\r\n"
+ "#endif\r\n"
+ "#include ""afxres.h""\r\n"
+ "#include ""verrsrc.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "#define _AFX_NO_SPLITTER_RESOURCES\r\n"
+ "#define _AFX_NO_OLE_RESOURCES\r\n"
+ "#define _AFX_NO_TRACKER_RESOURCES\r\n"
+ "#define _AFX_NO_PROPERTY_RESOURCES\r\n"
+ "\r\n"
+ "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n"
+ "LANGUAGE 9, 1\r\n"
+ "#include ""res\\WinLauncher2.rc2"" // non-Microsoft Visual C++ edited resources\r\n"
+ "#include ""afxres.rc"" // Standard components\r\n"
+ "#if !defined(_AFXDLL)\r\n"
+ "#include ""afxribbon.rc"" // MFC ribbon and control bar resources\r\n"
+ "#endif\r\n"
+ "#endif\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 2,0,0,1
+ PRODUCTVERSION 2,0,0,1
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x40004L
+ FILETYPE 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "CompanyName", "Android"
+ VALUE "FileDescription", "Android Studio Windows Launcher"
+ VALUE "FileVersion", "2.0.0.1"
+ VALUE "InternalName", "WinLauncher2.exe"
+ VALUE "LegalCopyright", "(c) Android. All rights reserved."
+ VALUE "OriginalFilename", "WinLauncher2.exe"
+ VALUE "ProductName", "Android SDK"
+ VALUE "ProductVersion", "2.0.0.1"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_FINDJAVA2_DIALOG DIALOGEX 0, 0, 317, 197
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_APPWINDOW
+CAPTION "Find Java 2 for Android"
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ DEFPUSHBUTTON "Start",IDOK,205,174,50,14
+ PUSHBUTTON "Quit",IDCANCEL,260,174,50,14
+ PUSHBUTTON "Add...",IDC_BUTTON_ADD,7,174,50,14
+ LTEXT "Select which version of Java to use:",IDC_STATIC,7,7,116,8
+ CONTROL "",IDC_PATH_LIST,"SysListView32",LVS_REPORT | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,7,18,300,150
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_ANDROID_ICON ICON "..\\android_icon.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ IDD_FINDJAVA2_DIALOG, DIALOG
+ BEGIN
+ BOTTOMMARGIN, 196
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+#endif // English (United States) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+#define _AFX_NO_SPLITTER_RESOURCES
+#define _AFX_NO_OLE_RESOURCES
+#define _AFX_NO_TRACKER_RESOURCES
+#define _AFX_NO_PROPERTY_RESOURCES
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+LANGUAGE 9, 1
+#include "afxres.rc" // Standard components
+#if !defined(_AFXDLL)
+#include "afxribbon.rc" // MFC ribbon and control bar resources
+#endif
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/find_java2/WinLauncher2/WinLauncher2.vcxproj b/find_java2/WinLauncher2/WinLauncher2.vcxproj
new file mode 100755
index 0000000..9dfdca7
--- /dev/null
+++ b/find_java2/WinLauncher2/WinLauncher2.vcxproj
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{64980924-B76E-4E00-90A4-647E67CEB050}</ProjectGuid>
+ <RootNamespace>WinLauncher2</RootNamespace>
+ <Keyword>MFCProj</Keyword>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v120</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ <UseOfMfc>Dynamic</UseOfMfc>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v120</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ <UseOfMfc>Dynamic</UseOfMfc>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_WINDOWS;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(ProjectDir);$(SolutionDir)\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalDependencies>version.lib</AdditionalDependencies>
+ </Link>
+ <Midl>
+ <MkTypLibCompatible>false</MkTypLibCompatible>
+ <ValidateAllParameters>true</ValidateAllParameters>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </Midl>
+ <ResourceCompile>
+ <Culture>0x0409</Culture>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(ProjectDir);$(SolutionDir)\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalDependencies>version.lib</AdditionalDependencies>
+ </Link>
+ <Midl>
+ <MkTypLibCompatible>false</MkTypLibCompatible>
+ <ValidateAllParameters>true</ValidateAllParameters>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </Midl>
+ <ResourceCompile>
+ <Culture>0x0409</Culture>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClInclude Include="..\src\FindJava2Dlg.h" />
+ <ClInclude Include="..\src\JavaFinder.h" />
+ <ClInclude Include="..\src\JavaPath.h" />
+ <ClInclude Include="..\src\utils.h" />
+ <ClInclude Include="..\src\WinLauncher2App.h" />
+ <ClInclude Include="Resource.h" />
+ <ClInclude Include="stdafx.h" />
+ <ClInclude Include="targetver.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\src\FindJava2Dlg.cpp" />
+ <ClCompile Include="..\src\JavaFinder.cpp" />
+ <ClCompile Include="..\src\JavaPath.cpp" />
+ <ClCompile Include="..\src\utils.cpp" />
+ <ClCompile Include="..\src\WinLauncher2App.cpp" />
+ <ClCompile Include="stdafx.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="WinLauncher2.rc" />
+ </ItemGroup>
+ <ItemGroup>
+ <Image Include="..\android_icon.ico" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/find_java2/WinLauncher2/res/WinLauncher2.ico b/find_java2/WinLauncher2/res/WinLauncher2.ico
new file mode 100755
index 0000000..d56fbcd
--- /dev/null
+++ b/find_java2/WinLauncher2/res/WinLauncher2.ico
Binary files differ
diff --git a/find_java2/WinLauncher2/stdafx.cpp b/find_java2/WinLauncher2/stdafx.cpp
new file mode 100755
index 0000000..00a69d2
--- /dev/null
+++ b/find_java2/WinLauncher2/stdafx.cpp
@@ -0,0 +1,24 @@
+/*
+* Copyright (C) 2014 The Android Open Source Project
+*
+* Licensed 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.
+*/
+
+
+// stdafx.cpp : source file that includes just the standard includes
+// WinLauncher2.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+
diff --git a/find_java2/WinLauncher2/stdafx.h b/find_java2/WinLauncher2/stdafx.h
new file mode 100755
index 0000000..86caf00
--- /dev/null
+++ b/find_java2/WinLauncher2/stdafx.h
@@ -0,0 +1,66 @@
+/*
+* Copyright (C) 2014 The Android Open Source Project
+*
+* Licensed 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.
+*/
+
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently,
+// but are changed infrequently
+
+#pragma once
+
+#ifndef VC_EXTRALEAN
+#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers
+#endif
+
+#include "targetver.h"
+
+#define _CRT_SECURE_NO_WARNINGS
+
+#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit
+
+// turns off MFC's hiding of some common and often safely ignored warning messages
+#define _AFX_ALL_WARNINGS
+
+#include <afxwin.h> // MFC core and standard components
+#include <afxext.h> // MFC extensions
+
+
+#include <afxdisp.h> // MFC Automation classes
+
+
+
+#ifndef _AFX_NO_OLE_SUPPORT
+#include <afxdtctl.h> // MFC support for Internet Explorer 4 Common Controls
+#endif
+#ifndef _AFX_NO_AFXCMN_SUPPORT
+#include <afxcmn.h> // MFC support for Windows Common Controls
+#endif // _AFX_NO_AFXCMN_SUPPORT
+
+#include <afxcontrolbars.h> // MFC support for ribbons and control bars
+
+
+
+
+#ifdef _UNICODE
+#if defined _M_IX86
+#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#elif defined _M_X64
+#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#else
+#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#endif
+#endif
+
+
diff --git a/find_java2/WinLauncher2/targetver.h b/find_java2/WinLauncher2/targetver.h
new file mode 100755
index 0000000..fc6d20b
--- /dev/null
+++ b/find_java2/WinLauncher2/targetver.h
@@ -0,0 +1,24 @@
+/*
+* Copyright (C) 2014 The Android Open Source Project
+*
+* Licensed 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.
+*/
+
+#pragma once
+
+// Including SDKDDKVer.h defines the highest available Windows platform.
+
+// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
+// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
+
+#include <SDKDDKVer.h>
diff --git a/find_java2/android_icon.ico b/find_java2/android_icon.ico
new file mode 100755
index 0000000..354bd5d
--- /dev/null
+++ b/find_java2/android_icon.ico
Binary files differ
diff --git a/find_java2/src/FindJava2Dlg.cpp b/find_java2/src/FindJava2Dlg.cpp
new file mode 100755
index 0000000..fbdd899
--- /dev/null
+++ b/find_java2/src/FindJava2Dlg.cpp
@@ -0,0 +1,268 @@
+/*
+* Copyright (C) 2014 The Android Open Source Project
+*
+* Licensed 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 "stdafx.h"
+#include "utils.h"
+#include "FindJava2Dlg.h"
+#include "afxdialogex.h"
+#include <atlpath.h> // ATL CPath
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#endif
+
+#define COL_PATH 1
+
+
+CFindJava2Dlg::CFindJava2Dlg(CWnd* pParent /*=NULL*/)
+ : CDialog(CFindJava2Dlg::IDD, pParent), mSelectedIndex(-1) {
+ m_hIcon = AfxGetApp()->LoadIcon(IDI_ANDROID_ICON);
+}
+
+void CFindJava2Dlg::DoDataExchange(CDataExchange* pDX) {
+ CDialog::DoDataExchange(pDX);
+ DDX_Control(pDX, IDC_PATH_LIST, mPathsListCtrl);
+ DDX_Control(pDX, IDOK, mOkButton);
+}
+
+BEGIN_MESSAGE_MAP(CFindJava2Dlg, CDialog)
+ ON_WM_PAINT()
+ ON_WM_QUERYDRAGICON()
+ ON_BN_CLICKED(IDC_BUTTON_ADD, &CFindJava2Dlg::OnBnClickedButtonAdd)
+ ON_NOTIFY(NM_CLICK, IDC_PATH_LIST, &CFindJava2Dlg::OnNMClickPathList)
+ ON_NOTIFY(LVN_ITEMCHANGED, IDC_PATH_LIST, &CFindJava2Dlg::OnLvnItemchangedPathList)
+END_MESSAGE_MAP()
+
+
+// -----
+// CFindJava2Dlg message handlers
+
+BOOL CFindJava2Dlg::OnInitDialog() {
+ CDialog::OnInitDialog();
+
+ SetWindowText(getAppName());
+
+ // Set the icon for this dialog. The framework does this automatically
+ // when the application's main window is not a dialog
+ SetIcon(m_hIcon, TRUE); // Set big icon
+ SetIcon(m_hIcon, FALSE); // Set small icon
+
+ // Initialize list controls
+ mPathsListCtrl.SetExtendedStyle(
+ mPathsListCtrl.GetExtendedStyle() |
+ LVS_EX_CHECKBOXES |
+ LVS_EX_FULLROWSELECT |
+ LVS_EX_GRIDLINES);
+
+ // We want 2 columns: Java version and path
+ mPathsListCtrl.InsertColumn(0, _T("Version"), LVCFMT_RIGHT, 60, 0);
+ mPathsListCtrl.InsertColumn(1, _T("Path"), LVCFMT_LEFT, 386, 0);
+
+ mJavaFinder->findJavaPaths(&mPaths);
+ fillPathsList();
+ adjustButtons();
+
+ return TRUE; // return TRUE unless you set the focus to a control
+}
+
+// If you add a minimize button to your dialog, you will need the code below
+// to draw the icon. For MFC applications using the document/view model,
+// this is automatically done for you by the framework.
+// [Note: MFC boilerplate, keep as-is]
+void CFindJava2Dlg::OnPaint() {
+ if (IsIconic()) {
+ CPaintDC dc(this); // device context for painting
+
+ SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
+
+ // Center icon in client rectangle
+ int cxIcon = GetSystemMetrics(SM_CXICON);
+ int cyIcon = GetSystemMetrics(SM_CYICON);
+ CRect rect;
+ GetClientRect(&rect);
+ int x = (rect.Width() - cxIcon + 1) / 2;
+ int y = (rect.Height() - cyIcon + 1) / 2;
+
+ // Draw the icon
+ dc.DrawIcon(x, y, m_hIcon);
+ } else {
+ CDialog::OnPaint();
+ }
+}
+
+// The system calls this function to obtain the cursor to display while the user drags
+// the minimized window. [Note: MFC boilerplate, keep as-is]
+HCURSOR CFindJava2Dlg::OnQueryDragIcon() {
+ return static_cast<HCURSOR>(m_hIcon);
+}
+
+// Button add has been pressed; use file dialog and add path if it's a valid java.exe
+void CFindJava2Dlg::OnBnClickedButtonAdd() {
+ CFileDialog fileDlg(
+ TRUE, // true=open dialog, false=save-as dialog
+ _T("exe"), // lpszDefExt
+ _T("java.exe"), // lpszFileName
+ OFN_FILEMUSTEXIST || OFN_PATHMUSTEXIST,
+ NULL, // lpszFilter
+ this); // pParentWnd
+
+ if (fileDlg.DoModal() == IDOK) {
+ CString path = fileDlg.GetPathName();
+
+ CJavaPath javaPath;
+ if (!mJavaFinder->checkJavaPath(path, &javaPath)) {
+ CString msg;
+ if (javaPath.mVersion > 0) {
+ msg.Format(_T("Insufficient Java Version found: expected %s, got %s"),
+ CJavaPath(mJavaFinder->getMinVersion(), CPath()).getVersion(),
+ javaPath.getVersion());
+ } else {
+ msg.Format(_T("No valid Java Version found for %s"), path);
+ }
+ AfxMessageBox(msg, MB_OK);
+
+ } else {
+ if (mPaths.find(javaPath) == mPaths.end()) {
+ // Path isn't known yet so add it and refresh the list.
+ mPaths.insert(javaPath);
+ fillPathsList();
+ }
+
+ // Select item in list and set mSelectedIndex
+ selectPath(-1 /*index*/, &javaPath);
+ }
+ }
+}
+
+// An item in the list has been selected, select checkmark and set mSelectedIndex.
+void CFindJava2Dlg::OnNMClickPathList(NMHDR *pNMHDR, LRESULT *pResult) {
+ LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
+ int index = pNMItemActivate->iItem;
+ selectPath(index, nullptr);
+ *pResult = TRUE;
+}
+
+// An item in the list has changed, toggle checkmark as needed.
+void CFindJava2Dlg::OnLvnItemchangedPathList(NMHDR *pNMHDR, LRESULT *pResult) {
+ *pResult = FALSE;
+ LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
+
+ if ((pNMLV->uChanged & LVIF_STATE) != 0) {
+ // Item's state has changed. Check the selection to see if it needs to be adjusted.
+ int index = pNMLV->iItem;
+
+ UINT oldState = pNMLV->uOldState;
+ UINT newState = pNMLV->uNewState;
+
+ if ((oldState & LVIS_STATEIMAGEMASK) != 0 || (newState & LVIS_STATEIMAGEMASK) != 0) {
+ // Checkbox uses the STATEIMAGE: 1 for unchecked, 2 for checked.
+ // Checkbox is checked when (old/new-state & state-image-mask) == INDEXTOSTATEIMAGEMASK(2).
+
+ bool oldChecked = (oldState & LVIS_STATEIMAGEMASK) == INDEXTOSTATEIMAGEMASK(2);
+ bool newChecked = (newState & LVIS_STATEIMAGEMASK) == INDEXTOSTATEIMAGEMASK(2);
+
+ if (oldChecked && !newChecked && index == mSelectedIndex) {
+ mSelectedIndex = -1;
+ adjustButtons();
+ } else if (!oldChecked && newChecked && index != mSelectedIndex) {
+ // Uncheck any checked rows if any
+ for (int n = mPathsListCtrl.GetItemCount() - 1; n >= 0; --n) {
+ if (n != index && mPathsListCtrl.GetCheck(n)) {
+ mPathsListCtrl.SetCheck(n, FALSE);
+ }
+ }
+
+ mSelectedIndex = index;
+ adjustButtons();
+ }
+ // We handled this case, don't dispatch it further
+ *pResult = TRUE;
+ }
+ }
+}
+
+// -----
+
+const CJavaPath& CFindJava2Dlg::getSelectedPath() {
+ int i = 0;
+ for (const CJavaPath &p : mPaths) {
+ if (i == mSelectedIndex) {
+ return p;
+ }
+ ++i;
+ }
+
+ return CJavaPath::sEmpty;
+}
+
+
+void CFindJava2Dlg::fillPathsList() {
+ mPathsListCtrl.DeleteAllItems();
+ int index = 0;
+
+ for (const CJavaPath& pv : mPaths) {
+ mPathsListCtrl.InsertItem(index, pv.getVersion()); // column 0 = version
+ mPathsListCtrl.SetItemText(index, COL_PATH, pv.mPath); // column 1 = path
+ mPathsListCtrl.SetCheck(index, mSelectedIndex == index);
+ ++index;
+ }
+}
+
+// Checks the given index if valid. Unchecks all other items.
+//
+// If index >= 0, it is used to select that item from the ListControl.
+// Otherwise if path != nullptr, it is used to find the item and select it.
+//
+// Side effect: in both cases, mSelectedIndex is set to the matching index or -1.
+//
+// If index is invalid and path isn't in the mPaths list, all items are unselected
+// so calling this with (0, nullptr) will clear the current selection.
+void CFindJava2Dlg::selectPath(int index, const CJavaPath *path) {
+
+ const CJavaPath *foundPath;
+ // If index is not defined, find the given path in the internal list.
+ // If path is not defined, find its index in the internal list.
+ int i = 0;
+ int n = mPathsListCtrl.GetItemCount();
+ for (const CJavaPath &p : mPaths) {
+ if (index < 0 && path != nullptr && p == *path) {
+ index = i;
+ foundPath = path;
+ } else if (index == i) {
+ foundPath = &p;
+ }
+
+ // uncheck any marked path
+ if (i != index && i < n && mPathsListCtrl.GetCheck(i)) {
+ mPathsListCtrl.SetCheck(i, FALSE);
+ }
+
+ ++i;
+ }
+
+ mSelectedIndex = index;
+ if (index >= 0 && index <= n) {
+ mPathsListCtrl.SetCheck(index, TRUE);
+ }
+
+ adjustButtons();
+}
+
+void CFindJava2Dlg::adjustButtons() {
+ int n = mPathsListCtrl.GetItemCount();
+ mOkButton.EnableWindow(mSelectedIndex >= 0 && mSelectedIndex < n);
+}
diff --git a/find_java2/src/FindJava2Dlg.h b/find_java2/src/FindJava2Dlg.h
new file mode 100755
index 0000000..7e0943c
--- /dev/null
+++ b/find_java2/src/FindJava2Dlg.h
@@ -0,0 +1,64 @@
+/*
+* Copyright (C) 2014 The Android Open Source Project
+*
+* Licensed 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.
+*/
+
+#pragma once
+#include "afxwin.h"
+#include "JavaFinder.h"
+
+#include "resource.h" // main symbols
+
+
+// CFindJava2Dlg dialog
+class CFindJava2Dlg : public CDialog {
+ // Construction
+public:
+ CFindJava2Dlg(CWnd* pParent = NULL); // standard constructor
+
+ void setJavaFinder(CJavaFinder *javaFinder) { mJavaFinder = javaFinder; }
+ const CJavaPath& getSelectedPath();
+
+ // Dialog Data
+ enum { IDD = IDD_FINDJAVA2_DIALOG };
+
+protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+
+
+ // Implementation
+protected:
+ HICON m_hIcon;
+
+ // Generated message map functions
+ virtual BOOL OnInitDialog();
+ afx_msg void OnPaint();
+ afx_msg HCURSOR OnQueryDragIcon();
+ DECLARE_MESSAGE_MAP()
+
+ afx_msg void OnBnClickedButtonAdd();
+ afx_msg void OnNMClickPathList(NMHDR *pNMHDR, LRESULT *pResult);
+ afx_msg void OnLvnItemchangedPathList(NMHDR *pNMHDR, LRESULT *pResult);
+
+private:
+ std::set<CJavaPath> mPaths;
+ int mSelectedIndex;
+ CJavaFinder *mJavaFinder;
+ CListCtrl mPathsListCtrl;
+ CButton mOkButton;
+
+ void fillPathsList();
+ void adjustButtons();
+ void selectPath(int index = -1, const CJavaPath *path = nullptr);
+};
diff --git a/find_java2/src/JavaFinder.cpp b/find_java2/src/JavaFinder.cpp
new file mode 100755
index 0000000..60a2e23
--- /dev/null
+++ b/find_java2/src/JavaFinder.cpp
@@ -0,0 +1,594 @@
+/*
+* Copyright (C) 2014 The Android Open Source Project
+*
+* Licensed 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 "stdafx.h"
+#include "JavaFinder.h"
+#include "utils.h"
+
+#include <algorithm> // std::sort and std::unique
+
+#define _CRT_SECURE_NO_WARNINGS
+
+// --------------
+
+#define JF_REGISTRY_KEY _T("Software\\Android\\FindJava2")
+#define JF_REGISTRY_VALUE_PATH _T("JavaPath")
+#define JF_REGISTRY_VALUE_VERS _T("JavaVers")
+
+// --------------
+
+
+// Extract the first thing that looks like (digit.digit+).
+// Note: this will break when java reports a version with major > 9.
+// However it will reasonably cope with "1.10", if that ever happens.
+static bool extractJavaVersion(const TCHAR *start,
+ int length,
+ CString *outVersionStr,
+ int *outVersionInt) {
+ const TCHAR *end = start + length;
+ for (const TCHAR *c = start; c < end - 2; c++) {
+ if (isdigit(c[0]) &&
+ c[1] == '.' &&
+ isdigit(c[2])) {
+ const TCHAR *e = c + 2;
+ while (isdigit(e[1])) {
+ e++;
+ }
+ outVersionStr->SetString(c, e - c + 1);
+
+ // major is currently only 1 digit
+ int major = (*c - '0');
+ // add minor
+ int minor = 0;
+ for (int m = 1; *e != '.'; e--, m *= 10) {
+ minor += (*e - '0') * m;
+ }
+ *outVersionInt = JAVA_VERS_TO_INT(major, minor);
+ return true;
+ }
+ }
+ return false;
+}
+
+// Tries to invoke the java.exe at the given path and extract it's
+// version number.
+// - outVersionStr: not null, will capture version as a string (e.g. "1.6")
+// - outVersionInt: not null, will capture version as an int (see JavaPath.h).
+bool getJavaVersion(CPath &javaPath, CString *outVersionStr, int *outVersionInt) {
+ bool result = false;
+
+ // Run "java -version", which outputs something to *STDERR* like this:
+ //
+ // java version "1.6.0_29"
+ // Java(TM) SE Runtime Environment (build 1.6.0_29-b11)
+ // Java HotSpot(TM) Client VM (build 20.4-b02, mixed mode, sharing)
+ //
+ // We want to capture the first line, and more exactly the "1.6" part.
+
+
+ CString cmd;
+ cmd.Format(_T("\"%s\" -version"), (LPCTSTR) javaPath);
+
+ SECURITY_ATTRIBUTES saAttr;
+ STARTUPINFO startup;
+ PROCESS_INFORMATION pinfo;
+
+ // Want to inherit pipe handle
+ ZeroMemory(&saAttr, sizeof(saAttr));
+ saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
+ saAttr.bInheritHandle = TRUE;
+ saAttr.lpSecurityDescriptor = NULL;
+
+ // Create pipe for stdout
+ HANDLE stdoutPipeRd, stdoutPipeWt;
+ if (!CreatePipe(
+ &stdoutPipeRd, // hReadPipe,
+ &stdoutPipeWt, // hWritePipe,
+ &saAttr, // lpPipeAttributes,
+ 0)) { // nSize (0=default buffer size)
+ // In FindJava2, we do not report these errors. Leave commented for reference.
+ // // if (gIsConsole || gIsDebug) displayLastError("CreatePipe failed: ");
+ return false;
+ }
+ if (!SetHandleInformation(stdoutPipeRd, HANDLE_FLAG_INHERIT, 0)) {
+ // In FindJava2, we do not report these errors. Leave commented for reference.
+ // // if (gIsConsole || gIsDebug) displayLastError("SetHandleInformation failed: ");
+ return false;
+ }
+
+ ZeroMemory(&pinfo, sizeof(pinfo));
+
+ ZeroMemory(&startup, sizeof(startup));
+ startup.cb = sizeof(startup);
+ startup.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
+ startup.wShowWindow = SW_HIDE | SW_MINIMIZE;
+ // Capture both stderr and stdout
+ startup.hStdError = stdoutPipeWt;
+ startup.hStdOutput = stdoutPipeWt;
+ startup.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
+
+ BOOL ok = CreateProcess(
+ NULL, // program path
+ (LPTSTR)((LPCTSTR) cmd),// command-line
+ NULL, // process handle is not inheritable
+ NULL, // thread handle is not inheritable
+ TRUE, // yes, inherit some handles
+ 0, // process creation flags
+ NULL, // use parent's environment block
+ NULL, // use parent's starting directory
+ &startup, // startup info, i.e. std handles
+ &pinfo);
+
+ // In FindJava2, we do not report these errors. Leave commented for reference.
+ // // if ((gIsConsole || gIsDebug) && !ok) displayLastError("CreateProcess failed: ");
+
+ // Close the write-end of the output pipe (we're only reading from it)
+ CloseHandle(stdoutPipeWt);
+
+ // Read from the output pipe. We don't need to read everything,
+ // the first line should be 'Java version "1.2.3_45"\r\n'
+ // so reading about 32 chars is all we need.
+ TCHAR first32[32 + 1];
+ int index = 0;
+ first32[0] = 0;
+
+ if (ok) {
+ #define SIZE 1024
+ char buffer[SIZE];
+ DWORD sizeRead = 0;
+
+ while (ok) {
+ // Keep reading in the same buffer location
+ // Note: ReadFile uses a char buffer, not a TCHAR one.
+ ok = ReadFile(stdoutPipeRd, // hFile
+ buffer, // lpBuffer
+ SIZE, // DWORD buffer size to read
+ &sizeRead, // DWORD buffer size read
+ NULL); // overlapped
+ if (!ok || sizeRead == 0 || sizeRead > SIZE) break;
+
+ // Copy up to the first 32 characters
+ if (index < 32) {
+ DWORD n = 32 - index;
+ if (n > sizeRead) n = sizeRead;
+ // copy as lowercase to simplify checks later
+ for (char *b = buffer; n > 0; n--, b++, index++) {
+ char c = *b;
+ if (c >= 'A' && c <= 'Z') c += 'a' - 'A';
+ first32[index] = c;
+ }
+ first32[index] = 0;
+ }
+ }
+
+ WaitForSingleObject(pinfo.hProcess, INFINITE);
+
+ DWORD exitCode;
+ if (GetExitCodeProcess(pinfo.hProcess, &exitCode)) {
+ // this should not return STILL_ACTIVE (259)
+ result = exitCode == 0;
+ }
+
+ CloseHandle(pinfo.hProcess);
+ CloseHandle(pinfo.hThread);
+ }
+ CloseHandle(stdoutPipeRd);
+
+ if (result && index > 0) {
+ // Look for a few keywords in the output however we don't
+ // care about specific ordering or case-senstiviness.
+ // We only capture roughtly the first line in lower case.
+ TCHAR *j = _tcsstr(first32, _T("java"));
+ TCHAR *v = _tcsstr(first32, _T("version"));
+ // In FindJava2, we do not report these errors. Leave commented for reference.
+ // // if ((gIsConsole || gIsDebug) && (!j || !v)) {
+ // // fprintf(stderr, "Error: keywords 'java version' not found in '%s'\n", first32);
+ // // }
+ if (j != NULL && v != NULL) {
+ result = extractJavaVersion(first32, index, outVersionStr, outVersionInt);
+ }
+ }
+
+ return result;
+}
+
+// --------------
+
+// Checks whether we can find $PATH/java.exe.
+// inOutPath should be the directory where we're looking at.
+// In output, it will be the java path we tested.
+// Returns the java version integer found (e.g. 1006 for 1.6).
+// Return 0 in case of error.
+static int checkPath(CPath *inOutPath) {
+
+ // Append java.exe to path if not already present
+ CString &p = (CString&)*inOutPath;
+ int n = p.GetLength();
+ if (n < 9 || p.Right(9).CompareNoCase(_T("\\java.exe")) != 0) {
+ inOutPath->Append(_T("java.exe"));
+ }
+
+ int result = 0;
+ PVOID oldWow64Value = disableWow64FsRedirection();
+ if (inOutPath->FileExists()) {
+ // Run java -version
+ // Reject the version if it's not at least our current minimum.
+ CString versionStr;
+ if (!getJavaVersion(*inOutPath, &versionStr, &result)) {
+ result = 0;
+ }
+ }
+
+ revertWow64FsRedirection(oldWow64Value);
+ return result;
+}
+
+// Check whether we can find $PATH/bin/java.exe
+// Returns the Java version found (e.g. 1006 for 1.6) or 0 in case of error.
+static int checkBinPath(CPath *inOutPath) {
+
+ // Append bin to path if not already present
+ CString &p = (CString&)*inOutPath;
+ int n = p.GetLength();
+ if (n < 4 || p.Right(4).CompareNoCase(_T("\\bin")) != 0) {
+ inOutPath->Append(_T("bin"));
+ }
+
+ return checkPath(inOutPath);
+}
+
+// Search java.exe in the environment
+static void findJavaInEnvPath(std::set<CJavaPath> *outPaths) {
+ ::SetLastError(0);
+
+ const TCHAR* envPath = _tgetenv(_T("JAVA_HOME"));
+ if (envPath != NULL) {
+ CPath p(envPath);
+ int v = checkBinPath(&p);
+ if (v > 0) {
+ outPaths->insert(CJavaPath(v, p));
+ }
+ }
+
+ envPath = _tgetenv(_T("PATH"));
+ if (envPath != NULL) {
+ // Otherwise look at the entries in the current path.
+ // If we find more than one, keep the one with the highest version.
+ CString pathTokens(envPath);
+ int curPos = 0;
+ CString tok;
+ do {
+ tok = pathTokens.Tokenize(_T(";"), curPos);
+ if (!tok.IsEmpty()) {
+ CPath p(tok);
+ int v = checkPath(&p);
+ if (v > 0) {
+ outPaths->insert(CJavaPath(v, p));
+ }
+ }
+ } while (!tok.IsEmpty());
+ }
+}
+
+
+// --------------
+
+static bool getRegValue(const TCHAR *keyPath,
+ const TCHAR *keyName,
+ REGSAM access,
+ CString *outValue) {
+ HKEY key;
+ LSTATUS status = RegOpenKeyEx(
+ HKEY_LOCAL_MACHINE, // hKey
+ keyPath, // lpSubKey
+ 0, // ulOptions
+ KEY_READ | access, // samDesired,
+ &key); // phkResult
+ if (status == ERROR_SUCCESS) {
+ LSTATUS ret = ERROR_MORE_DATA;
+ DWORD size = 4096; // MAX_PATH is 260, so 4 KB should be good enough
+ TCHAR* buffer = (TCHAR*)malloc(size);
+
+ while (ret == ERROR_MORE_DATA && size < (1 << 16) /*64 KB*/) {
+ ret = RegQueryValueEx(
+ key, // hKey
+ keyName, // lpValueName
+ NULL, // lpReserved
+ NULL, // lpType
+ (LPBYTE)buffer, // lpData
+ &size); // lpcbData
+
+ if (ret == ERROR_MORE_DATA) {
+ size *= 2;
+ buffer = (TCHAR*)realloc(buffer, size);
+ } else {
+ buffer[size] = 0;
+ }
+ }
+
+ if (ret != ERROR_MORE_DATA) {
+ outValue->SetString(buffer);
+ }
+
+ free(buffer);
+ RegCloseKey(key);
+
+ return (ret != ERROR_MORE_DATA);
+ }
+
+ return false;
+}
+
+// Explore the registry to find a suitable version of Java.
+// Returns an int which is the version of Java found (e.g. 1006 for 1.6) and the
+// matching path in outJavaPath.
+// Returns 0 if nothing suitable was found.
+static int exploreJavaRegistry(const TCHAR *entry, REGSAM access, std::set<CJavaPath> *outPaths) {
+
+ // Let's visit HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment [CurrentVersion]
+ CPath rootKey(_T("SOFTWARE\\JavaSoft\\"));
+ rootKey.Append(entry);
+
+ CString currentVersion;
+ CPath subKey(rootKey);
+ if (getRegValue(subKey, _T("CurrentVersion"), access, &currentVersion)) {
+ // CurrentVersion should be something like "1.7".
+ // We want to read HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment\1.7 [JavaHome]
+ subKey.Append(currentVersion);
+ CString value;
+ if (getRegValue(subKey, _T("JavaHome"), access, &value)) {
+ CPath javaHome(value);
+ int v = checkBinPath(&javaHome);
+ if (v > 0) {
+ outPaths->insert(CJavaPath(v, javaHome));
+ }
+ }
+ }
+
+ // Try again, but this time look at all the versions available
+ HKEY javaHomeKey;
+ LSTATUS status = RegOpenKeyEx(
+ HKEY_LOCAL_MACHINE, // hKey
+ _T("SOFTWARE\\JavaSoft"), // lpSubKey
+ 0, // ulOptions
+ KEY_READ | access, // samDesired
+ &javaHomeKey); // phkResult
+ if (status == ERROR_SUCCESS) {
+ TCHAR name[MAX_PATH + 1];
+ DWORD index = 0;
+ CPath javaHome;
+ for (LONG result = ERROR_SUCCESS; result == ERROR_SUCCESS; index++) {
+ DWORD nameLen = MAX_PATH;
+ name[nameLen] = 0;
+ result = RegEnumKeyEx(
+ javaHomeKey, // hKey
+ index, // dwIndex
+ name, // lpName
+ &nameLen, // lpcName
+ NULL, // lpReserved
+ NULL, // lpClass
+ NULL, // lpcClass,
+ NULL); // lpftLastWriteTime
+ if (result == ERROR_SUCCESS && nameLen < MAX_PATH) {
+ name[nameLen] = 0;
+ CPath subKey(rootKey);
+ subKey.Append(name);
+
+ CString value;
+ if (getRegValue(subKey, _T("JavaHome"), access, &value)) {
+ CPath javaHome(value);
+ int v = checkBinPath(&javaHome);
+ if (v > 0) {
+ outPaths->insert(CJavaPath(v, javaHome));
+ }
+ }
+ }
+ }
+
+ RegCloseKey(javaHomeKey);
+ }
+
+ return 0;
+}
+
+static void findJavaInRegistry(std::set<CJavaPath> *outPaths) {
+ // We'll do the registry test 3 times: first using the default mode,
+ // then forcing the use of the 32-bit registry then forcing the use of
+ // 64-bit registry. On Windows 2k, the 2 latter will fail since the
+ // flags are not supported. On a 32-bit OS the 64-bit is obviously
+ // useless and the 2 first tests should be equivalent so we just
+ // need the first case.
+
+ // Check the JRE first, then the JDK.
+ exploreJavaRegistry(_T("Java Runtime Environment"), 0, outPaths);
+ exploreJavaRegistry(_T("Java Development Kit"), 0, outPaths);
+
+ // Get the app sysinfo state (the one hidden by WOW64)
+ SYSTEM_INFO sysInfo;
+ GetSystemInfo(&sysInfo);
+ WORD programArch = sysInfo.wProcessorArchitecture;
+ // Check the real sysinfo state (not the one hidden by WOW64) for x86
+ GetNativeSystemInfo(&sysInfo);
+ WORD actualArch = sysInfo.wProcessorArchitecture;
+
+ // Only try to access the WOW64-32 redirected keys on a 64-bit system.
+ // There's no point in doing this on a 32-bit system.
+ if (actualArch == PROCESSOR_ARCHITECTURE_AMD64) {
+ if (programArch != PROCESSOR_ARCHITECTURE_INTEL) {
+ // If we did the 32-bit case earlier, don't do it twice.
+ exploreJavaRegistry(_T("Java Runtime Environment"), KEY_WOW64_32KEY, outPaths);
+ exploreJavaRegistry(_T("Java Development Kit"), KEY_WOW64_32KEY, outPaths);
+
+ } else if (programArch != PROCESSOR_ARCHITECTURE_AMD64) {
+ // If we did the 64-bit case earlier, don't do it twice.
+ exploreJavaRegistry(_T("Java Runtime Environment"), KEY_WOW64_64KEY, outPaths);
+ exploreJavaRegistry(_T("Java Development Kit"), KEY_WOW64_64KEY, outPaths);
+ }
+ }
+}
+
+// --------------
+
+static void checkProgramFiles(std::set<CJavaPath> *outPaths) {
+
+ TCHAR programFilesPath[MAX_PATH + 1];
+ HRESULT result = SHGetFolderPath(
+ NULL, // hwndOwner
+ CSIDL_PROGRAM_FILES, // nFolder
+ NULL, // hToken
+ SHGFP_TYPE_CURRENT, // dwFlags
+ programFilesPath); // pszPath
+
+ CPath path(programFilesPath);
+ path.Append(_T("Java"));
+
+ // Do we have a C:\\Program Files\\Java directory?
+ if (!path.IsDirectory()) {
+ return;
+ }
+
+ CPath glob(path);
+ glob.Append(_T("j*"));
+
+ WIN32_FIND_DATA findData;
+ HANDLE findH = FindFirstFile(glob, &findData);
+ if (findH == INVALID_HANDLE_VALUE) {
+ return;
+ }
+ do {
+ if ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
+ CPath temp(path);
+ temp.Append(findData.cFileName);
+ // Check C:\\Program Files[x86]\\Java\\j*\\bin\\java.exe
+ int v = checkBinPath(&temp);
+ if (v > 0) {
+ outPaths->insert(CJavaPath(v, temp));
+ }
+ }
+ } while (FindNextFile(findH, &findData) != 0);
+ FindClose(findH);
+}
+
+static void findJavaInProgramFiles(std::set<CJavaPath> *outPaths) {
+ // Check the C:\\Program Files (x86) directory
+ // With WOW64 fs redirection in place by default, we should get the x86
+ // version on a 64-bit OS since this app is a 32-bit itself.
+ checkProgramFiles(outPaths);
+
+ // Check the real sysinfo state (not the one hidden by WOW64) for x86
+ SYSTEM_INFO sysInfo;
+ GetNativeSystemInfo(&sysInfo);
+
+ if (sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) {
+ // On a 64-bit OS, try again by disabling the fs redirection so
+ // that we can try the real C:\\Program Files directory.
+ PVOID oldWow64Value = disableWow64FsRedirection();
+ checkProgramFiles(outPaths);
+ revertWow64FsRedirection(oldWow64Value);
+ }
+}
+
+//------
+
+
+CJavaFinder::CJavaFinder(int minVersion) : mMinVersion(minVersion) {
+}
+
+
+CJavaFinder::~CJavaFinder() {
+}
+
+/*
+ * Checks whether there's a recorded path in the registry and whether
+ * this path still points to a valid Java executable.
+ * Returns false if any of these do not match,
+ * Returns true if both condition match,
+ * outPath contains the result path when returning true.
+*/
+CJavaPath CJavaFinder::getRegistryPath() {
+ CString existing;
+ CRegKey rk;
+
+ if (rk.Open(HKEY_CURRENT_USER, JF_REGISTRY_KEY, KEY_READ) == ERROR_SUCCESS) {
+ ULONG sLen = MAX_PATH;
+ TCHAR s[MAX_PATH + 1];
+ if (rk.QueryStringValue(JF_REGISTRY_VALUE_PATH, s, &sLen) == ERROR_SUCCESS) {
+ existing.SetString(s);
+ }
+ rk.Close();
+ }
+
+ if (!existing.IsEmpty()) {
+ CJavaPath javaPath;
+ if (checkJavaPath(existing, &javaPath)) {
+ return javaPath;
+ }
+ }
+
+ return CJavaPath::sEmpty;
+}
+
+bool CJavaFinder::setRegistryPath(const CJavaPath &javaPath) {
+ CRegKey rk;
+
+ if (rk.Create(HKEY_CURRENT_USER, JF_REGISTRY_KEY) == ERROR_SUCCESS) {
+ bool ok = rk.SetStringValue(JF_REGISTRY_VALUE_PATH, javaPath.mPath, REG_SZ) == ERROR_SUCCESS &&
+ rk.SetStringValue(JF_REGISTRY_VALUE_VERS, javaPath.getVersion(), REG_SZ) == ERROR_SUCCESS;
+ rk.Close();
+ return ok;
+ }
+
+ return false;
+}
+
+void CJavaFinder::findJavaPaths(std::set<CJavaPath> *paths) {
+ findJavaInEnvPath(paths);
+ findJavaInProgramFiles(paths);
+ findJavaInRegistry(paths);
+
+ // Exclude any entries that do not match the minimum version.
+ // The set is going to be fairly small so it's easier to do it here
+ // than add the filter logic in all the static methods above.
+ if (mMinVersion > 0) {
+ for (auto it = paths->begin(); it != paths->end(); ) {
+ if (it->mVersion < mMinVersion) {
+ it = paths->erase(it); // C++11 set.erase returns an iterator to the *next* element
+ } else {
+ ++it;
+ }
+ }
+ }
+}
+
+bool CJavaFinder::checkJavaPath(const CString &path, CJavaPath *outPath) {
+ CPath p(path);
+
+ // try this path (if it ends with java.exe) or path\\java.exe
+ int v = checkPath(&p);
+ if (v == 0) {
+ // reset path and try path\\bin\\java.exe
+ p = CPath(path);
+ v = checkBinPath(&p);
+ }
+
+ if (v > 0) {
+ outPath->set(v, p);
+ return v >= mMinVersion;
+ }
+
+ return false;
+}
+
diff --git a/find_java2/src/JavaFinder.h b/find_java2/src/JavaFinder.h
new file mode 100755
index 0000000..c22b008
--- /dev/null
+++ b/find_java2/src/JavaFinder.h
@@ -0,0 +1,52 @@
+/*
+* Copyright (C) 2014 The Android Open Source Project
+*
+* Licensed 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.
+*/
+
+#pragma once
+
+
+#include <set> // STL std::set
+#include "JavaPath.h"
+
+class CJavaFinder {
+public:
+ // Creates a new JavaFinder.
+ // minVersion to accept, using JAVA_VERS_TO_INT macro. 0 to accept everything.
+ CJavaFinder(int minVersion = 0);
+ ~CJavaFinder();
+
+ int getMinVersion() const { return mMinVersion; }
+
+ // Returns the path recorded in the registry.
+ // If there is no path or it is no longer valid, returns an empty string.
+ CJavaPath getRegistryPath();
+
+ // Sets the given path as the default to use in the registry.
+ // Returns true on success.
+ bool setRegistryPath(const CJavaPath &javaPath);
+
+ // Scans the registry, the environment and program files for potential Java.exe locations.
+ // Fills the given set with the tuples (version, path) found, guaranteed sorted and unique.
+ void findJavaPaths(std::set<CJavaPath> *paths);
+
+ // Checks the given path for a given java.exe.
+ // Input path variation tried are: path as-is, path/java.exe or path/bin/java.exe.
+ // Places the java path and version in outPath;
+ // Returns true if a java path was found *and* its version is at least mMinVersion.
+ bool checkJavaPath(const CString &path, CJavaPath *outPath);
+
+private:
+ int mMinVersion;
+};
diff --git a/find_java2/src/JavaPath.cpp b/find_java2/src/JavaPath.cpp
new file mode 100755
index 0000000..ebe30c5
--- /dev/null
+++ b/find_java2/src/JavaPath.cpp
@@ -0,0 +1,97 @@
+/*
+* Copyright (C) 2014 The Android Open Source Project
+*
+* Licensed 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 "stdafx.h"
+#include "JavaPath.h"
+#include "utils.h"
+
+#define _CRT_SECURE_NO_WARNINGS
+
+// --------------
+
+const CJavaPath CJavaPath::sEmpty = CJavaPath();
+
+CJavaPath::CJavaPath(int version, CPath path) : mVersion(version), mPath(path) {
+ mPath.Canonicalize();
+}
+
+bool CJavaPath::isEmpty() const {
+ return mVersion <= 0;
+}
+
+void CJavaPath::clear() {
+ mVersion = 0;
+ mPath = CPath();
+}
+
+void CJavaPath::set(int version, CPath path) {
+ mVersion = version;
+ mPath = path;
+ mPath.Canonicalize();
+}
+
+CString CJavaPath::getVersion() const {
+ CString s;
+ s.Format(_T("%d.%d"), JAVA_MAJOR(mVersion), JAVA_MINOR(mVersion));
+ return s;
+}
+
+
+bool CJavaPath::toShortPath() {
+ const TCHAR *longPath = mPath;
+ if (longPath == nullptr) {
+ return false;
+ }
+
+ DWORD lenShort = _tcslen(longPath) + 1;
+ TCHAR *shortPath = (TCHAR *)malloc(lenShort * sizeof(TCHAR));
+
+ DWORD length = GetShortPathName(longPath, shortPath, lenShort);
+ if (length > lenShort) {
+ // The buffer wasn't big enough, this is the size to use.
+ free(shortPath);
+ lenShort = length;
+ shortPath = (TCHAR *)malloc(length);
+ length = GetShortPathName(longPath, shortPath, lenShort);
+ }
+
+ if (length != 0) {
+ mPath = CPath(shortPath);
+ }
+
+ free(shortPath);
+ return length != 0;
+}
+
+bool CJavaPath::operator< (const CJavaPath& rhs) const {
+ if (mVersion != rhs.mVersion) {
+ // sort in reverse order on the version
+ return rhs.mVersion > mVersion;
+ }
+ // sort in normal order on the path
+ const CString &pl = mPath;
+ const CString &pr = rhs.mPath;
+ return pl.Compare(pr) < 0;
+}
+
+bool CJavaPath::operator== (const CJavaPath& rhs) const {
+ if (mVersion == rhs.mVersion) {
+ const CString &pl = mPath;
+ const CString &pr = rhs.mPath;
+ return pl.Compare(pr) == 0;
+ }
+ return false;
+}
diff --git a/find_java2/src/JavaPath.h b/find_java2/src/JavaPath.h
new file mode 100755
index 0000000..b7f40a5
--- /dev/null
+++ b/find_java2/src/JavaPath.h
@@ -0,0 +1,57 @@
+/*
+* Copyright (C) 2014 The Android Open Source Project
+*
+* Licensed 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.
+*/
+
+#pragma once
+
+#include <atlpath.h> // ATL CPath
+
+
+// Transforms a Java major.minor number (e.g. "1.7") to internal int value (1007)
+#define JAVA_VERS_TO_INT(major, minor) ((major) * 1000 + (minor))
+// Extracts the major part from the internal int major.minor number
+#define JAVA_MAJOR(majorMinor) ((majorMinor) / 1000)
+// Extracts the minor part from the internal int major.minor number
+#define JAVA_MINOR(majorMinor) ((majorMinor) % 1000)
+
+
+struct CJavaPath {
+ int mVersion;
+ CPath mPath;
+
+ // Static empty path that can be returned as a reference.
+ static const CJavaPath sEmpty;
+
+ CJavaPath() : mVersion(0) {}
+ CJavaPath(int version, CPath path);
+ void set(int version, CPath path);
+
+ // Returns true if path/version is empty/0
+ bool isEmpty() const;
+
+ // Clears path and version to 0
+ void clear();
+
+ // Converts the internal path into a short DOS path.
+ // Returns true if this was possible and false if the conversion failed.
+ bool toShortPath();
+
+ // Returns the version formatted as a string (e.g. "1.7" instead of 1007.)
+ CString getVersion() const;
+
+ // Operators < and == for this to be suitable in an ordered std::set
+ bool operator< (const CJavaPath& rhs) const;
+ bool operator== (const CJavaPath& rhs) const;
+};
diff --git a/find_java2/src/WinLauncher2App.cpp b/find_java2/src/WinLauncher2App.cpp
new file mode 100755
index 0000000..392ad9e
--- /dev/null
+++ b/find_java2/src/WinLauncher2App.cpp
@@ -0,0 +1,154 @@
+/*
+* Copyright (C) 2014 The Android Open Source Project
+*
+* Licensed 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 "stdafx.h"
+#include "WinLauncher2App.h"
+
+#include "utils.h"
+#include "JavaFinder.h"
+#include "FindJava2Dlg.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#endif
+
+
+// CWinLauncher2App
+
+BEGIN_MESSAGE_MAP(CWinLauncher2App, CWinApp)
+ ON_COMMAND(ID_HELP, &CWinApp::OnHelp)
+END_MESSAGE_MAP()
+
+
+// The one and only CWinLauncher2App object
+CWinLauncher2App theApp;
+
+class CLauncherCmdLineInfo : public CCommandLineInfo {
+public:
+ bool mDoHelp;
+ bool mDoForceUi;
+ bool mDoJava1_7;
+ CString mFilename;
+
+ CLauncherCmdLineInfo() : mDoHelp(false), mDoForceUi(false), mDoJava1_7(false) {}
+
+ virtual void ParseParam(const TCHAR* pszParam, BOOL bFlag, BOOL bLast) {
+ // Expected command line:
+ // /h | help : msg box with command line arguments
+ // /f | force : force UI selection
+ // /7 : require java 1.7
+ // path-to-launch
+
+ if (!bFlag) {
+ mFilename = pszParam;
+ } else if (_tcsnccmp(pszParam, _T("h"), 2) == 0) {
+ mDoHelp = true;
+ } else if (_tcsnccmp(pszParam, _T("f"), 2) == 0) {
+ mDoForceUi = true;
+ } else if (_tcsnccmp(pszParam, _T("7"), 2) == 0) {
+ mDoJava1_7 = true;
+ }
+ }
+};
+
+
+CWinLauncher2App::CWinLauncher2App() {
+ // support Restart Manager
+ m_dwRestartManagerSupportFlags = AFX_RESTART_MANAGER_SUPPORT_RESTART;
+
+ // TODO: add construction code here,
+ // Place all significant initialization in InitInstance
+}
+
+BOOL CWinLauncher2App::InitInstance() {
+ // InitCommonControlsEx() is required on Windows XP if an application
+ // manifest specifies use of ComCtl32.dll version 6 or later to enable
+ // visual styles. Otherwise, any window creation will fail.
+ INITCOMMONCONTROLSEX InitCtrls;
+ InitCtrls.dwSize = sizeof(InitCtrls);
+ // Set this to include all the common control classes you want to use
+ // in your application.
+ InitCtrls.dwICC = ICC_WIN95_CLASSES;
+ InitCommonControlsEx(&InitCtrls);
+
+ CWinApp::InitInstance();
+ AfxEnableControlContainer();
+
+ // Create the shell manager, in case the dialog contains
+ // any shell tree view or shell list view controls.
+ CShellManager *pShellManager = new CShellManager;
+
+ // Activate "Windows Native" visual manager for enabling themes in MFC controls
+ CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows));
+
+ // Set CWinApp default registry key. Must be consistent with all apps using findjava2.
+ SetRegistryKey(_T("Android-FindJava2"));
+
+ // Use VERSIONINFO.FileDescription as the canonical app name
+ initUtils(NULL);
+
+ CLauncherCmdLineInfo cmdLine;
+ ParseCommandLine(cmdLine);
+
+ if (cmdLine.mDoHelp) {
+ const TCHAR *msg =
+ _T("WinLauncher2 [/7|/f|/h]\r\n")
+ _T("/7 : Requires Java 1.7 instead of 1.6\r\n")
+ _T("/f : Force UI\r\n")
+ _T("/h : Help\r\n");
+ AfxMessageBox(msg);
+ return FALSE; // quit without starting MFC app msg loop
+ }
+
+ CJavaFinder javaFinder(JAVA_VERS_TO_INT(1, cmdLine.mDoJava1_7 ? 7 : 6));
+ CJavaPath javaPath = javaFinder.getRegistryPath();
+ if (cmdLine.mDoForceUi || javaPath.isEmpty()) {
+ javaPath.clear();
+
+ CFindJava2Dlg dlg;
+ dlg.setJavaFinder(&javaFinder);
+ m_pMainWnd = &dlg;
+ INT_PTR nResponse = dlg.DoModal();
+
+ if (nResponse == IDOK) {
+ // Use choice selected by user and save in registry.
+ javaPath = dlg.getSelectedPath();
+ javaFinder.setRegistryPath(javaPath);
+ } else if (nResponse == IDCANCEL) {
+ // Canceled by user, exit silently.
+ } else if (nResponse == -1) {
+ TRACE(traceAppMsg, 0, "Warning: dialog creation failed, so application is terminating unexpectedly.\n");
+ }
+ }
+
+ if (!javaPath.isEmpty()) {
+ // TODO actually launch configured app instead of just printing path.
+ CString msg(_T("PLACEHOLDER TODO run app using "));
+ msg.Append(javaPath.mPath);
+ AfxMessageBox(msg);
+ }
+
+ // Delete the shell manager created above.
+ if (pShellManager != NULL) {
+ delete pShellManager;
+ }
+
+ // Since the dialog has been closed, return FALSE so that we exit the
+ // application, rather than start the application's message pump.
+ return FALSE;
+}
+
diff --git a/find_java2/src/WinLauncher2App.h b/find_java2/src/WinLauncher2App.h
new file mode 100755
index 0000000..11aca97
--- /dev/null
+++ b/find_java2/src/WinLauncher2App.h
@@ -0,0 +1,43 @@
+/*
+* Copyright (C) 2014 The Android Open Source Project
+*
+* Licensed 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.
+*/
+
+#pragma once
+
+#ifndef __AFXWIN_H__
+ #error "include 'stdafx.h' before including this file for PCH"
+#endif
+
+#include "resource.h" // main symbols
+
+
+// CWinLauncher2App:
+// See WinLauncher2.cpp for the implementation of this class
+//
+
+class CWinLauncher2App : public CWinApp {
+public:
+ CWinLauncher2App();
+
+// Overrides
+public:
+ virtual BOOL InitInstance();
+
+// Implementation
+
+ DECLARE_MESSAGE_MAP()
+};
+
+extern CWinLauncher2App theApp; \ No newline at end of file
diff --git a/find_java2/src/utils.cpp b/find_java2/src/utils.cpp
new file mode 100755
index 0000000..9a9e3d2
--- /dev/null
+++ b/find_java2/src/utils.cpp
@@ -0,0 +1,282 @@
+/*
+* Copyright (C) 2014 The Android Open Source Project
+*
+* Licensed 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 "stdafx.h"
+#include "utils.h"
+
+// Set to true to get some extra debug information
+bool gIsDebug = false;
+// Set to true to output errors to stderr (for a Console app)
+// or to false to output using msg box (for a Windows UI app)
+bool gIsConsole = false;
+
+// Application name used in error dialog. Defined using initUtils()
+static CString gAppName("Find Java 2");
+
+// Called by the application to initialize the app name used in error dialog boxes.
+void initUtils(const TCHAR *appName) {
+ if (appName != NULL) {
+ gAppName = CString(appName);
+ return;
+ }
+
+ // Try to get the VERSIONINFO.FileDescription and use as app name
+ // Errors are ignored, in which case the default app name is used.
+
+ // First get the module (aka app instance) filename.
+ TCHAR moduleName[MAX_PATH + 1];
+ DWORD sz = ::GetModuleFileName(NULL /*AfxGetInstanceHandle()*/, moduleName, MAX_PATH);
+ if (sz == 0) {
+ // GetModuleFileName failed. Do nothing.
+ return;
+ }
+ moduleName[sz] = '\0'; // make sure string is properly terminated.
+
+ // Get the size of the FileVersionInfo buffer
+ DWORD obsoleteHandle; // see http://blogs.msdn.com/b/oldnewthing/archive/2007/07/31/4138786.aspx
+ DWORD fviSize = ::GetFileVersionInfoSize(moduleName, &obsoleteHandle);
+ if (fviSize == 0) {
+ return; // do nothing on error
+ }
+
+ char *fviBuffer = new char[fviSize];
+ if (::GetFileVersionInfo(moduleName, 0, fviSize, fviBuffer) != 0) {
+ VOID *vBuffer;
+ UINT vLen;
+
+ struct LANGUAGE_CODEPAGE {
+ WORD mLanguage;
+ WORD mCodePage;
+ } *lgcpBuffer;
+
+ UINT lgcpSize;
+
+ // Read the list of languages and code pages (c.f. MSDN for VerQueryValue)
+ if (::VerQueryValue(fviBuffer, _T("\\VarFileInfo\\Translation"), (LPVOID*)&lgcpBuffer, &lgcpSize) != 0 &&
+ lgcpSize >= sizeof(LANGUAGE_CODEPAGE)) {
+ // Use the first available language and code page
+ CString subBlock;
+ subBlock.Format(_T("\\StringFileInfo\\%04x%04x\\FileDescription"),
+ lgcpBuffer[0].mLanguage,
+ lgcpBuffer[0].mCodePage);
+ if (::VerQueryValue(fviBuffer, subBlock, &vBuffer, &vLen) != 0) {
+ gAppName.SetString((LPCTSTR)vBuffer, vLen);
+ }
+ }
+ }
+ delete fviBuffer;
+}
+
+CString getAppName() {
+ return gAppName;
+}
+
+
+// Displays a message in an ok+info dialog box.
+void msgBox(const TCHAR* text, ...) {
+ CString formatted;
+ va_list ap;
+ va_start(ap, text);
+ formatted.FormatV(text, ap);
+ va_end(ap);
+
+ // TODO global CString to get app name
+ MessageBox(NULL, formatted, gAppName, MB_OK | MB_ICONINFORMATION);
+}
+
+// Sets the string to the message matching Win32 GetLastError.
+// If message is non-null, it is prepended to the last error string.
+CString getLastWin32Error(const TCHAR* message) {
+ DWORD err = GetLastError();
+ CString result;
+ LPTSTR errStr;
+ if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | /* dwFlags */
+ FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL, /* lpSource */
+ err, /* dwMessageId */
+ 0, /* dwLanguageId */
+ (LPTSTR) &errStr, /* out lpBuffer */
+ 0, /* nSize */
+ NULL) != 0) { /* va_list args */
+ if (message == NULL) {
+ result.Format(_T("[%d] %s"), err, errStr);
+ } else {
+ result.Format(_T("%s[%d] %s"), message, err, errStr);
+ }
+ LocalFree(errStr);
+ }
+ return result;
+}
+
+// Displays GetLastError prefixed with a description in an error dialog box
+void displayLastError(const TCHAR *description, ...) {
+ CString formatted;
+ va_list ap;
+ va_start(ap, description);
+ formatted.FormatV(description, ap);
+ va_end(ap);
+
+ CString error = getLastWin32Error(NULL);
+ formatted.Append(_T("\r\n"));
+ formatted.Append(error);
+
+ if (gIsConsole) {
+ _ftprintf(stderr, _T("%s\n"), (LPCTSTR) formatted);
+ } else {
+ CString name(gAppName);
+ name.Append(_T(" - Error"));
+ MessageBox(NULL, formatted, name, MB_OK | MB_ICONERROR);
+ }
+}
+
+// Executes the command line. Does not wait for the program to finish.
+// The return code is from CreateProcess (0 means failure), not the running app.
+int execNoWait(const TCHAR *app, const TCHAR *params, const TCHAR *workDir) {
+ STARTUPINFO startup;
+ PROCESS_INFORMATION pinfo;
+
+ ZeroMemory(&pinfo, sizeof(pinfo));
+
+ ZeroMemory(&startup, sizeof(startup));
+ startup.cb = sizeof(startup);
+ startup.dwFlags = STARTF_USESHOWWINDOW;
+ startup.wShowWindow = SW_SHOWDEFAULT;
+
+ int ret = CreateProcess(
+ app, /* program path */
+ (TCHAR *)params, /* command-line */
+ NULL, /* process handle is not inheritable */
+ NULL, /* thread handle is not inheritable */
+ TRUE, /* yes, inherit some handles */
+ 0, /* create flags */
+ NULL, /* use parent's environment block */
+ workDir, /* use parent's starting directory */
+ &startup, /* startup info, i.e. std handles */
+ &pinfo);
+
+ if (ret) {
+ CloseHandle(pinfo.hProcess);
+ CloseHandle(pinfo.hThread);
+ }
+
+ return ret;
+}
+
+// Executes command, waits for completion and returns exit code.
+// As indicated in MSDN for CreateProcess, callers should double-quote the program name
+// e.g. cmd="\"c:\program files\myapp.exe\" arg1 arg2";
+int execWait(const TCHAR *cmd) {
+ STARTUPINFO startup;
+ PROCESS_INFORMATION pinfo;
+
+ ZeroMemory(&pinfo, sizeof(pinfo));
+
+ ZeroMemory(&startup, sizeof(startup));
+ startup.cb = sizeof(startup);
+ startup.dwFlags = STARTF_USESHOWWINDOW;
+ startup.wShowWindow = SW_HIDE | SW_MINIMIZE;
+
+ int ret = CreateProcess(
+ NULL, /* program path */
+ (LPTSTR)cmd, /* command-line */
+ NULL, /* process handle is not inheritable */
+ NULL, /* thread handle is not inheritable */
+ TRUE, /* yes, inherit some handles */
+ CREATE_NO_WINDOW, /* we don't want a console */
+ NULL, /* use parent's environment block */
+ NULL, /* use parent's starting directory */
+ &startup, /* startup info, i.e. std handles */
+ &pinfo);
+
+ int result = -1;
+ if (ret) {
+ WaitForSingleObject(pinfo.hProcess, INFINITE);
+
+ DWORD exitCode;
+ if (GetExitCodeProcess(pinfo.hProcess, &exitCode)) {
+ // this should not return STILL_ACTIVE (259)
+ result = exitCode;
+ }
+ CloseHandle(pinfo.hProcess);
+ CloseHandle(pinfo.hThread);
+ }
+
+ return result;
+}
+
+bool getModuleDir(CPath *outDir) {
+ TCHAR programDir[MAX_PATH];
+ int ret = GetModuleFileName(NULL, programDir, sizeof(programDir) * sizeof(TCHAR));
+ if (ret != 0) {
+ CPath dir(programDir);
+ dir.RemoveFileSpec();
+ *outDir = dir;
+ return true;
+ }
+ return false;
+}
+
+// Disables the FS redirection done by WOW64.
+// Because this runs as a 32-bit app, Windows automagically remaps some
+// folder under the hood (e.g. "Programs Files(x86)" is mapped as "Program Files").
+// This prevents the app from correctly searching for java.exe in these folders.
+// The registry is also remapped. This method disables this redirection.
+// Caller should restore the redirection later by using revertWow64FsRedirection().
+PVOID disableWow64FsRedirection() {
+
+ // The call we want to make is the following:
+ // PVOID oldWow64Value;
+ // Wow64DisableWow64FsRedirection(&oldWow64Value);
+ // However that method may not exist (e.g. on XP non-64 systems) so
+ // we must not call it directly.
+
+ PVOID oldWow64Value = 0;
+
+ HMODULE hmod = LoadLibrary(_T("kernel32.dll"));
+ if (hmod != NULL) {
+ FARPROC proc = GetProcAddress(hmod, "Wow64DisableWow64FsRedirection");
+ if (proc != NULL) {
+ typedef BOOL(WINAPI *disableWow64FuncType)(PVOID *);
+ disableWow64FuncType funcPtr = (disableWow64FuncType)proc;
+ funcPtr(&oldWow64Value);
+ }
+
+ FreeLibrary(hmod);
+ }
+
+ return oldWow64Value;
+}
+
+// Reverts the redirection disabled in disableWow64FsRedirection.
+void revertWow64FsRedirection(PVOID oldWow64Value) {
+
+ // The call we want to make is the following:
+ // Wow64RevertWow64FsRedirection(oldWow64Value);
+ // However that method may not exist (e.g. on XP non-64 systems) so
+ // we must not call it directly.
+
+ HMODULE hmod = LoadLibrary(_T("kernel32.dll"));
+ if (hmod != NULL) {
+ FARPROC proc = GetProcAddress(hmod, "Wow64RevertWow64FsRedirection");
+ if (proc != NULL) {
+ typedef BOOL(WINAPI *revertWow64FuncType)(PVOID);
+ revertWow64FuncType funcPtr = (revertWow64FuncType)proc;
+ funcPtr(oldWow64Value);
+ }
+
+ FreeLibrary(hmod);
+ }
+}
diff --git a/find_java2/src/utils.h b/find_java2/src/utils.h
new file mode 100755
index 0000000..3557f58
--- /dev/null
+++ b/find_java2/src/utils.h
@@ -0,0 +1,59 @@
+/*
+* Copyright (C) 2014 The Android Open Source Project
+*
+* Licensed 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.
+*/
+
+#pragma once
+
+#include <atlpath.h> // ATL CPath
+
+// Global flag indicating whether this is running in debug mode (more printfs)
+extern bool gIsDebug;
+// Global flag indicating whether this is running in console mode or GUI.
+// In console mode, errors are written on the console; in GUI they use a MsgBox.
+extern bool gIsConsole;
+
+// Must be called by the application to initialize the app name used in error dialog boxes.
+// If NULL is used, fetches VERSIONINFO.FileDescription from resources if available.
+void initUtils(const TCHAR *appName);
+
+// Returns the app name set in initUtils
+CString getAppName();
+
+// Displays a message in an ok+info dialog box. Useful in console mode.
+void msgBox(const TCHAR* text, ...);
+
+// Displays GetLastError prefixed with a description in an error dialog box. Useful in console mode.
+void displayLastError(const TCHAR *description, ...);
+
+// Executes the command line. Does not wait for the program to finish.
+// The return code is from CreateProcess (0 means failure), not the running app.
+int execNoWait(const TCHAR *app, const TCHAR *params, const TCHAR *workDir);
+
+// Executes command, waits for completion and returns exit code.
+// As indicated in MSDN for CreateProcess, callers should double-quote the program name
+// e.g. cmd="\"c:\program files\myapp.exe\" arg1 arg2";
+int execWait(const TCHAR *cmd);
+
+bool getModuleDir(CPath *outDir);
+
+// Disables the FS redirection done by WOW64.
+// Because this runs as a 32-bit app, Windows automagically remaps some
+// folder under the hood (e.g. "Programs Files(x86)" is mapped as "Program Files").
+// This prevents the app from correctly searching for java.exe in these folders.
+// The registry is also remapped.
+PVOID disableWow64FsRedirection();
+
+// Reverts the redirection disabled in disableWow64FsRedirection.
+void revertWow64FsRedirection(PVOID oldWow64Value);