aboutsummaryrefslogtreecommitdiff
path: root/find_java2
diff options
context:
space:
mode:
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 000000000..311796097
--- /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 000000000..459e3a75b
--- /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 000000000..1435e1b0d
--- /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 000000000..a144bfc75
--- /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 000000000..ff767c6d8
--- /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 000000000..3c9ac4ed2
--- /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 000000000..1d5f98f0a
--- /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 000000000..3baa67f27
--- /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 000000000..7230def9a
--- /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 000000000..fc6d20b78
--- /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 000000000..c3b2e0f7b
--- /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 000000000..bee2edfab
--- /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 000000000..9dfdca755
--- /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 000000000..d56fbcdfd
--- /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 000000000..00a69d268
--- /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 000000000..86caf00be
--- /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 000000000..fc6d20b78
--- /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 000000000..354bd5dd2
--- /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 000000000..fbdd899e0
--- /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 000000000..7e0943c30
--- /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 000000000..60a2e230e
--- /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 000000000..c22b0086d
--- /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 000000000..ebe30c576
--- /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 000000000..b7f40a5f7
--- /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 000000000..392ad9e62
--- /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 000000000..11aca9706
--- /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 000000000..7c8c66b67
--- /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(programDir[0]));
+ 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 000000000..3557f5806
--- /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);