aboutsummaryrefslogtreecommitdiffstats
path: root/sdkmanager
diff options
context:
space:
mode:
authorRaphael <raphael@google.com>2011-11-22 10:40:13 -0800
committerRaphael <raphael@google.com>2011-11-29 20:39:34 -0800
commit628920b73c59cbbb976c0c352baffb533b33c142 (patch)
tree73fba1da0c524357435adab89371b552d1b44183 /sdkmanager
parent27b2ac34506d7142e8b9fc5abe7aebcf1790e882 (diff)
downloadsdk-628920b73c59cbbb976c0c352baffb533b33c142.zip
sdk-628920b73c59cbbb976c0c352baffb533b33c142.tar.gz
sdk-628920b73c59cbbb976c0c352baffb533b33c142.tar.bz2
SDK: Extract find_java static library.
Change-Id: Ic8b2130a327d73c044c0931509385aed19f78a9e
Diffstat (limited to 'sdkmanager')
-rw-r--r--sdkmanager/win_android/Android.mk26
-rwxr-xr-xsdkmanager/win_android/find_java.cpp63
-rwxr-xr-xsdkmanager/win_android/find_java.h29
-rwxr-xr-xsdkmanager/win_android/utils.cpp192
-rwxr-xr-xsdkmanager/win_android/utils.h321
-rw-r--r--sdkmanager/win_android/win_android.cpp476
6 files changed, 628 insertions, 479 deletions
diff --git a/sdkmanager/win_android/Android.mk b/sdkmanager/win_android/Android.mk
index a50b3c7..2f111a0 100644
--- a/sdkmanager/win_android/Android.mk
+++ b/sdkmanager/win_android/Android.mk
@@ -1,13 +1,27 @@
# Copyright 2011 The Android Open Source Project
#
# Android.mk for sdkmanager/win_android
-#
-# This provides "win_android.exe", a replacement for "android.bat" for Windows only.
-
-#----- The current C++ sdklauncher -----
LOCAL_PATH := $(call my-dir)
+
+# find_java static library for host
+# ========================================================
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libfindjava
+LOCAL_SRC_FILES := find_java.cpp utils.cpp
+
+LOCAL_CFLAGS += -Wall -Wno-unused-parameter
+LOCAL_CFLAGS += -D_XOPEN_SOURCE -D_GNU_SOURCE -DSH_HISTORY -DUSE_MINGW
+
+include $(BUILD_HOST_STATIC_LIBRARY)
+
+
+# "win_android.exe", a host replacement for "android.bat". For the Windows SDK only.
+# ========================================================
+
include $(CLEAR_VARS)
ifeq ($(HOST_OS),windows)
@@ -15,9 +29,11 @@ ifeq ($(HOST_OS),windows)
LOCAL_SRC_FILES := \
win_android.cpp
+LOCAL_MODULE := win_android
+LOCAL_STATIC_LIBRARIES := libfindjava
+
LOCAL_CFLAGS += -Wall -Wno-unused-parameter
LOCAL_CFLAGS += -D_XOPEN_SOURCE -D_GNU_SOURCE -DSH_HISTORY -DUSE_MINGW
-LOCAL_MODULE := win_android
LOCAL_MODULE_TAGS := optional
diff --git a/sdkmanager/win_android/find_java.cpp b/sdkmanager/win_android/find_java.cpp
new file mode 100755
index 0000000..a3b7af8
--- /dev/null
+++ b/sdkmanager/win_android/find_java.cpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#ifdef _WIN32
+
+#include "find_java.h"
+
+#define _CRT_SECURE_NO_WARNINGS 1
+
+extern bool gDebug;
+
+// Search java.exe in the path
+bool findJavaInEnvPath(CPath *outJavaPath) {
+ SetLastError(0);
+ const char* envPath = getenv("PATH");
+ if (!envPath) return false;
+
+ CArray<CString> *paths = CString(envPath).split(';');
+ for(int i = 0; i < paths->size(); i++) {
+ CPath p((*paths)[i].cstr());
+ p.addPath("java.exe");
+ if (p.fileExists()) {
+ // Make sure we can actually run "java -version".
+ CString cmd;
+ cmd.setf("\"%s\" -version", p.cstr());
+ int code = execWait(cmd.cstr());
+ if (code == 0) {
+ if (gDebug) msgBox("Java found via env path: %s", p.cstr());
+ outJavaPath->set(p.cstr());
+ delete paths;
+ return true;
+ }
+ }
+ }
+
+ delete paths;
+ return false;
+}
+
+bool findJavaInRegistry(CPath *outJavaPath) {
+ // TODO
+ return false;
+}
+
+bool findJavaInProgramFiles(CPath *outJavaPath) {
+ // TODO
+ return false;
+}
+
+#endif /* _WIN32 */
diff --git a/sdkmanager/win_android/find_java.h b/sdkmanager/win_android/find_java.h
new file mode 100755
index 0000000..41e5720
--- /dev/null
+++ b/sdkmanager/win_android/find_java.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#ifndef _H_FIND_JAVA
+#define _H_FIND_JAVA
+
+#ifdef _WIN32
+
+#include "utils.h"
+
+bool findJavaInEnvPath(CPath *outJavaPath);
+bool findJavaInRegistry(CPath *outJavaPath);
+bool findJavaInProgramFiles(CPath *outJavaPath);
+
+#endif /* _WIN32 */
+#endif /* _H_FIND_JAVA */
diff --git a/sdkmanager/win_android/utils.cpp b/sdkmanager/win_android/utils.cpp
new file mode 100755
index 0000000..6da1893
--- /dev/null
+++ b/sdkmanager/win_android/utils.cpp
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#ifdef _WIN32
+
+#include "utils.h"
+
+#define _CRT_SECURE_NO_WARNINGS 1
+
+bool gDebug = false;
+
+// Displays a message in an ok+info dialog box.
+void msgBox(const char* text, ...) {
+ CString formatted;
+ va_list ap;
+ va_start(ap, text);
+ formatted.setv(text, ap);
+ va_end(ap);
+
+ MessageBoxA(NULL, formatted.cstr(), "Android SDK Manager", MB_OK | MB_ICONINFORMATION);
+}
+
+// Displays GetLastError prefixed with a description in an error dialog box
+void displayLastError(const char *description, ...) {
+ CString formatted;
+ va_list ap;
+ va_start(ap, description);
+ formatted.setv(description, ap);
+ va_end(ap);
+
+ CString error;
+ error.setLastWin32Error();
+ formatted.add("\r\n");
+ formatted.add(error.cstr());
+ MessageBox(NULL, formatted.cstr(), "Android SDK Manager - Error", 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 char *app, const char *params, const char *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_HIDE|SW_MINIMIZE;
+
+ int ret = CreateProcessA(
+ (LPSTR) app, /* program path */
+ (LPSTR) params, /* 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 */
+ 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 char *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 = CreateProcessA(
+ NULL, /* program path */
+ (LPSTR) 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) {
+ CHAR programDir[MAX_PATH];
+ int ret = GetModuleFileName(NULL, programDir, sizeof(programDir));
+ if (ret != 0) {
+ // Remove the last segment to keep only the directory.
+ int pos = ret - 1;
+ while (pos > 0 && programDir[pos] != '\\') {
+ --pos;
+ }
+ outDir->set(programDir, pos);
+ 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.
+PVOID disableWow64FsRedirection() {
+
+ // The call we want to make is the following:
+ // PVOID oldWow64Value;
+ // Wow64DisableWow64FsRedirection(&oldWow64Value);
+ // However that method may not exist (e.g. on non-64 systems) so
+ // we must not call it directly.
+
+ PVOID oldWow64Value = 0;
+
+ HMODULE hmod = LoadLibrary("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 non-64 systems) so
+ // we must not call it directly.
+
+ HMODULE hmod = LoadLibrary("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);
+ }
+}
+
+#endif /* _WIN32 */
diff --git a/sdkmanager/win_android/utils.h b/sdkmanager/win_android/utils.h
new file mode 100755
index 0000000..60d4da8
--- /dev/null
+++ b/sdkmanager/win_android/utils.h
@@ -0,0 +1,321 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#ifndef _H_UTILS
+#define _H_UTILS
+
+#ifdef _WIN32
+
+#include <direct.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <windows.h>
+
+// VS vs MINGW specific includes
+#ifdef USE_VS_CRT
+ #include <crtdbg.h> // for _ASSERT
+#else
+ #define _ASSERT(x) // undef
+#endif
+
+extern bool gDebug;
+
+// An array that knows its own size. Not dynamically resizable.
+template <class T> class CArray {
+ T* mPtr;
+ int mSize;
+public:
+ explicit CArray(int size) {
+ mSize = size;
+ mPtr = new T[size];
+ }
+
+ ~CArray() {
+ if (mPtr != NULL) {
+ delete[] mPtr;
+ mPtr = NULL;
+ }
+ mSize = 0;
+ }
+
+ T& operator[](int i) {
+ _ASSERT(i >= 0 && i < mSize);
+ return mPtr[i];
+ }
+
+ int size() const {
+ return mSize;
+ }
+};
+
+// A simple string class wrapper.
+class CString {
+protected:
+ char *mStr;
+public:
+ CString() { mStr = NULL; }
+ CString(const CString &str) { mStr = str.mStr == NULL ? NULL : _strdup(str.mStr); }
+ explicit CString(const char *str) { mStr = NULL; set(str); }
+ CString(const char *start, int length) { mStr = NULL; set(start, length); }
+
+ CString& set(const char *str) {
+ _free();
+ if (str != NULL) {
+ mStr = _strdup(str);
+ }
+ return *this;
+ }
+
+ CString& set(const char *start, int length) {
+ _free();
+ if (start != NULL) {
+ mStr = (char *)malloc(length + 1);
+ strncpy(mStr, start, length);
+ mStr[length] = 0;
+ }
+ return *this;
+ }
+
+ CString& setv(const char *str, va_list ap) {
+ _free();
+ // _vscprintf(str, ap) is only available with the MSVCRT, not MinGW.
+ // Instead we'll iterate till we have enough space to generate the string.
+ int len = strlen(str) + 1024;
+ mStr = (char *)malloc(len);
+ strcpy(mStr, str); // provide a default in case vsnprintf totally fails
+ for (int guard = 0; guard < 10; guard++) {
+ int ret = vsnprintf(mStr, len, str, ap);
+ if (ret == -1) {
+ // Some implementations don't give the proper size needed
+ // so double the space and try again.
+ len *= 2;
+ } else if (ret >= len) {
+ len = ret + 1;
+ } else {
+ // There was enough space to write.
+ break;
+ }
+ mStr = (char *)realloc((void *)mStr, len);
+ strcpy(mStr, str); // provide a default in case vsnprintf totally fails
+ }
+ return *this;
+ }
+
+ CString& setf(const char *str, ...) {
+ _free();
+ va_list ap;
+ va_start(ap, str);
+ setv(str, ap);
+ va_end(ap);
+ return *this;
+ }
+
+ virtual ~CString() { _free(); }
+
+ // Returns the C string owned by this CString. It will be
+ // invalid as soon as this CString is deleted or out of scope.
+ const char * cstr() const {
+ return mStr;
+ }
+
+ bool isEmpty() const {
+ return mStr == NULL || *mStr == 0;
+ }
+
+ int length() const {
+ return mStr == NULL ? 0 : strlen(mStr);
+ }
+
+ CString& add(const char *s) {
+ if (mStr == NULL) {
+ set(s);
+ } else {
+ mStr = (char *)realloc((void *)mStr, strlen(mStr) + strlen(s) + 1);
+ strcat(mStr, s);
+ }
+ return *this;
+ }
+
+ CArray<CString> * split(char sep) const {
+ if (mStr == NULL) {
+ return new CArray<CString>(0);
+ }
+ const char *last = NULL;
+ int n = 0;
+ for (const char *s = mStr; *s; s++) {
+ if (*s == sep && s != mStr && (last == NULL || s > last+1)) {
+ n++;
+ last = s;
+ }
+ }
+
+ CArray<CString> *result = new CArray<CString>(n);
+ last = NULL;
+ n = 0;
+ for (const char *s = mStr; *s; s++) {
+ if (*s == sep) {
+ if (s != mStr && (last == NULL || s > last+1)) {
+ const char *start = last ? last : mStr;
+ (*result)[n++].set(start, s-start);
+ }
+ last = s+1;
+ }
+ }
+
+ return result;
+ }
+
+ CString& setLastWin32Error() {
+ DWORD err = GetLastError();
+ LPSTR errStr;
+ if (FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | /* dwFlags */
+ FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL, /* lpSource */
+ err, /* dwMessageId */
+ 0, /* dwLanguageId */
+ (LPSTR)&errStr, /* lpBuffer */
+ 0, /* nSize */
+ NULL) != 0) { /* va_list args */
+ set(errStr);
+ LocalFree(errStr);
+ }
+ return *this;
+ }
+
+private:
+ void _free() {
+ if (mStr != NULL) {
+ free((void *)mStr);
+ mStr = NULL;
+ }
+ }
+
+};
+
+// A simple path class wrapper.
+class CPath : public CString {
+public:
+ CPath() : CString() { }
+ CPath(const CPath &str) : CString(str) { }
+ explicit CPath(const char *str) : CString(str) { }
+ CPath(const char *start, int length) : CString(start, length) { }
+
+ // Appends a path segment, adding a \ as necessary.
+ CPath& addPath(const CString &s) {
+ return addPath(s.cstr());
+ }
+
+ // Appends a path segment, adding a \ as necessary.
+ CPath& addPath(const char *s) {
+ _ASSERT(s != NULL);
+ if (s != NULL && s[0] != 0) {
+ int n = length();
+ if (n > 0 && s[0] != '\\' && mStr[n-1] != '\\') add("\\");
+ add(s);
+ }
+ return *this;
+ }
+
+ // Returns true if file exist and is not a directory.
+ // There's no garantee we have rights to access it.
+ bool fileExists() const {
+ if (mStr == NULL) return false;
+ DWORD attribs = GetFileAttributesA(mStr);
+ return attribs != INVALID_FILE_ATTRIBUTES &&
+ !(attribs & FILE_ATTRIBUTE_DIRECTORY);
+ }
+
+ // Returns true if file exist and is a directory.
+ // There's no garantee we have rights to access it.
+ bool dirExists() const {
+ if (mStr == NULL) return false;
+ DWORD attribs = GetFileAttributesA(mStr);
+ return attribs != INVALID_FILE_ATTRIBUTES &&
+ (attribs & FILE_ATTRIBUTE_DIRECTORY) != 0;
+ }
+
+ // Returns a copy of the directory portion of the path, if any
+ CPath dirName() const {
+ CPath result;
+ if (mStr != NULL) {
+ char *pos = strrchr(mStr, '\\');
+ if (pos != NULL) {
+ result.set(mStr, pos - mStr);
+ }
+ }
+ return result;
+ }
+
+ // Returns a pointer to the baseName part of the path.
+ // It becomes invalid if the path changes.
+ const char * baseName() const {
+ if (mStr != NULL) {
+ char *pos = strrchr(mStr, '\\');
+ if (pos != NULL) {
+ return pos + 1;
+ }
+ }
+ return NULL;
+ }
+
+ // If the path ends with the given searchName, replace in-place by the new name
+ void replaceName(const char *searchName, const char* newName) {
+ if (mStr == NULL) return;
+ int n = length();
+ int sn = strlen(searchName);
+ if (n < sn) return;
+ // if mStr ends with searchName
+ if (strcmp(mStr + n - sn, searchName) == 0) {
+ int sn2 = strlen(newName);
+ if (sn2 > sn) {
+ mStr = (char *)realloc((void *)mStr, n + sn2 - sn + 1);
+ }
+ strcpy(mStr + n - sn, newName);
+ mStr[n + sn2 - sn] = 0;
+ }
+ }
+};
+
+// Displays a message in an ok+info dialog box.
+void msgBox(const char* text, ...);
+
+// Displays GetLastError prefixed with a description in an error dialog box
+void displayLastError(const char *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 char *app, const char *params, const char *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 char *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);
+
+#endif /* _WIN32 */
+#endif /* _H_UTILS */
diff --git a/sdkmanager/win_android/win_android.cpp b/sdkmanager/win_android/win_android.cpp
index 2c957e0..6417051 100644
--- a/sdkmanager/win_android/win_android.cpp
+++ b/sdkmanager/win_android/win_android.cpp
@@ -27,20 +27,9 @@
#ifdef _WIN32
-#define _CRT_SECURE_NO_WARNINGS 1
+#include "utils.h"
+#include "find_java.h"
-#include <direct.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <string.h>
-#include <windows.h>
-
-// VS vs MINGW specific includes
-#ifdef USE_MINGW
- #define _ASSERT(x) // undef
-#else
- #include <crtdbg.h> // for _ASSERT
-#endif
// A NULL-terminated list of directory to create in the temp folder.
static const char * sMkDirList[] = {
@@ -69,467 +58,6 @@ static const char * sFilesToCopy[] = {
NULL,
};
-static bool gDebug = false;
-
-
-// An array that knows its own size. Not dynamically resizable.
-template <class T> class CArray {
- T* mPtr;
- int mSize;
-public:
- explicit CArray(int size) {
- mSize = size;
- mPtr = new T[size];
- }
-
- ~CArray() {
- if (mPtr != NULL) {
- delete[] mPtr;
- mPtr = NULL;
- }
- mSize = 0;
- }
-
- T& operator[](int i) {
- _ASSERT(i >= 0 && i < mSize);
- return mPtr[i];
- }
-
- int size() const {
- return mSize;
- }
-};
-
-// A simple string class wrapper.
-class CString {
-protected:
- char *mStr;
-public:
- CString() { mStr = NULL; }
- CString(const CString &str) { mStr = str.mStr == NULL ? NULL : _strdup(str.mStr); }
- explicit CString(const char *str) { mStr = NULL; set(str); }
- CString(const char *start, int length) { mStr = NULL; set(start, length); }
-
- CString& set(const char *str) {
- _free();
- if (str != NULL) {
- mStr = _strdup(str);
- }
- return *this;
- }
-
- CString& set(const char *start, int length) {
- _free();
- if (start != NULL) {
- mStr = (char *)malloc(length + 1);
- strncpy(mStr, start, length);
- mStr[length] = 0;
- }
- return *this;
- }
-
- CString& setv(const char *str, va_list ap) {
- _free();
- // _vscprintf(str, ap) is only available with the MSVCRT, not MinGW.
- // Instead we'll iterate till we have enough space to generate the string.
- int len = strlen(str) + 1024;
- mStr = (char *)malloc(len);
- strcpy(mStr, str); // provide a default in case vsnprintf totally fails
- for (int guard = 0; guard < 10; guard++) {
- int ret = vsnprintf(mStr, len, str, ap);
- if (ret == -1) {
- // Some implementations don't give the proper size needed
- // so double the space and try again.
- len *= 2;
- } else if (ret >= len) {
- len = ret + 1;
- } else {
- // There was enough space to write.
- break;
- }
- mStr = (char *)realloc((void *)mStr, len);
- strcpy(mStr, str); // provide a default in case vsnprintf totally fails
- }
- return *this;
- }
-
- CString& setf(const char *str, ...) {
- _free();
- va_list ap;
- va_start(ap, str);
- setv(str, ap);
- va_end(ap);
- return *this;
- }
-
- virtual ~CString() { _free(); }
-
- // Returns the C string owned by this CString. It will be
- // invalid as soon as this CString is deleted or out of scope.
- const char * cstr() const {
- return mStr;
- }
-
- bool isEmpty() const {
- return mStr == NULL || *mStr == 0;
- }
-
- int length() const {
- return mStr == NULL ? 0 : strlen(mStr);
- }
-
- CString& add(const char *s) {
- if (mStr == NULL) {
- set(s);
- } else {
- mStr = (char *)realloc((void *)mStr, strlen(mStr) + strlen(s) + 1);
- strcat(mStr, s);
- }
- return *this;
- }
-
- CArray<CString> * split(char sep) const {
- if (mStr == NULL) {
- return new CArray<CString>(0);
- }
- const char *last = NULL;
- int n = 0;
- for (const char *s = mStr; *s; s++) {
- if (*s == sep && s != mStr && (last == NULL || s > last+1)) {
- n++;
- last = s;
- }
- }
-
- CArray<CString> *result = new CArray<CString>(n);
- last = NULL;
- n = 0;
- for (const char *s = mStr; *s; s++) {
- if (*s == sep) {
- if (s != mStr && (last == NULL || s > last+1)) {
- const char *start = last ? last : mStr;
- (*result)[n++].set(start, s-start);
- }
- last = s+1;
- }
- }
-
- return result;
- }
-
-private:
- void _free() {
- if (mStr != NULL) {
- free((void *)mStr);
- mStr = NULL;
- }
- }
-
-};
-
-// A simple path class wrapper.
-class CPath : public CString {
-public:
- CPath() : CString() { }
- CPath(const CPath &str) : CString(str) { }
- explicit CPath(const char *str) : CString(str) { }
- CPath(const char *start, int length) : CString(start, length) { }
-
- // Appends a path segment, adding a \ as necessary.
- CPath& addPath(const CString &s) {
- return addPath(s.cstr());
- }
-
- // Appends a path segment, adding a \ as necessary.
- CPath& addPath(const char *s) {
- _ASSERT(s != NULL);
- if (s != NULL && s[0] != 0) {
- int n = length();
- if (n > 0 && s[0] != '\\' && mStr[n-1] != '\\') add("\\");
- add(s);
- }
- return *this;
- }
-
- // Returns true if file exist and is not a directory.
- // There's no garantee we have rights to access it.
- bool fileExists() const {
- if (mStr == NULL) return false;
- DWORD attribs = GetFileAttributesA(mStr);
- return attribs != INVALID_FILE_ATTRIBUTES &&
- !(attribs & FILE_ATTRIBUTE_DIRECTORY);
- }
-
- // Returns true if file exist and is a directory.
- // There's no garantee we have rights to access it.
- bool dirExists() const {
- if (mStr == NULL) return false;
- DWORD attribs = GetFileAttributesA(mStr);
- return attribs != INVALID_FILE_ATTRIBUTES &&
- (attribs & FILE_ATTRIBUTE_DIRECTORY) != 0;
- }
-
- // Returns a copy of the directory portion of the path, if any
- CPath dirName() const {
- CPath result;
- if (mStr != NULL) {
- char *pos = strrchr(mStr, '\\');
- if (pos != NULL) {
- result.set(mStr, pos - mStr);
- }
- }
- return result;
- }
-
- // Returns a pointer to the baseName part of the path.
- // It becomes invalid if the path changes.
- const char * baseName() const {
- if (mStr != NULL) {
- char *pos = strrchr(mStr, '\\');
- if (pos != NULL) {
- return pos + 1;
- }
- }
- return NULL;
- }
-
- // If the path ends with the given searchName, replace in-place by the new name
- void replaceName(const char *searchName, const char* newName) {
- if (mStr == NULL) return;
- int n = length();
- int sn = strlen(searchName);
- if (n < sn) return;
- // if mStr ends with searchName
- if (strcmp(mStr + n - sn, searchName) == 0) {
- int sn2 = strlen(newName);
- if (sn2 > sn) {
- mStr = (char *)realloc((void *)mStr, n + sn2 - sn + 1);
- }
- strcpy(mStr + n - sn, newName);
- mStr[n + sn2 - sn] = 0;
- }
- }
-};
-
-// ========= UTILITIES ==============
-
-// Displays a message in an ok+info dialog box.
-static void msgBox(const char* text, ...) {
- CString formatted;
- va_list ap;
- va_start(ap, text);
- formatted.setv(text, ap);
- va_end(ap);
-
- MessageBoxA(NULL, formatted.cstr(), "Android SDK Manager", MB_OK | MB_ICONINFORMATION);
-}
-
-static void displayLastError(const char *description, ...) {
- CString formatted;
- va_list ap;
- va_start(ap, description);
- formatted.setv(description, ap);
- va_end(ap);
-
- DWORD err = GetLastError();
- LPSTR errStr;
- if (FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | /* dwFlags */
- FORMAT_MESSAGE_FROM_SYSTEM,
- NULL, /* lpSource */
- err, /* dwMessageId */
- 0, /* dwLanguageId */
- (LPSTR)&errStr, /* lpBuffer */
- 0, /* nSize */
- NULL) != 0) { /* va_list args */
- formatted.add("\r\n");
- formatted.add(errStr);
- MessageBox(NULL, formatted.cstr(), "Android SDK Manager - Error", MB_OK | MB_ICONERROR);
- LocalFree(errStr);
- }
-}
-
-// 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.
-static int execNoWait(const char *app, const char *params, const char *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_HIDE|SW_MINIMIZE;
-
- int ret = CreateProcessA(
- (LPSTR) app, /* program path */
- (LPSTR) params, /* 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 */
- 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";
-static int execWait(const char *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 = CreateProcessA(
- NULL, /* program path */
- (LPSTR) 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;
-}
-
-static bool getModuleDir(CPath *outDir) {
- CHAR programDir[MAX_PATH];
- int ret = GetModuleFileName(NULL, programDir, sizeof(programDir));
- if (ret != 0) {
- // Remove the last segment to keep only the directory.
- int pos = ret - 1;
- while (pos > 0 && programDir[pos] != '\\') {
- --pos;
- }
- outDir->set(programDir, pos);
- return true;
- }
- return false;
-}
-
-// Disable 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.
-static PVOID disableWow64FsRedirection() {
-
- // The call we want to make is the following:
- // PVOID oldWow64Value;
- // Wow64DisableWow64FsRedirection(&oldWow64Value);
- // However that method may not exist (e.g. on non-64 systems) so
- // we must not call it directly.
-
- PVOID oldWow64Value = 0;
-
- HMODULE hmod = LoadLibrary("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.
-static void revertWow64FsRedirection(PVOID oldWow64Value) {
-
- // The call we want to make is the following:
- // Wow64RevertWow64FsRedirection(oldWow64Value);
- // However that method may not exist (e.g. on non-64 systems) so
- // we must not call it directly.
-
- HMODULE hmod = LoadLibrary("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);
- }
-}
-
-
-// =============================
-
-// Search java.exe in the path
-static bool findJavaInEnvPath(CPath *outJavaPath) {
- SetLastError(0);
- const char* envPath = getenv("PATH");
- if (!envPath) return false;
-
- CArray<CString> *paths = CString(envPath).split(';');
- for(int i = 0; i < paths->size(); i++) {
- CPath p((*paths)[i].cstr());
- p.addPath("java.exe");
- if (p.fileExists()) {
- // Make sure we can actually run "java -version".
- CString cmd;
- cmd.setf("\"%s\" -version", p.cstr());
- int code = execWait(cmd.cstr());
- if (code == 0) {
- if (gDebug) msgBox("Java found via env path: %s", p.cstr());
- outJavaPath->set(p.cstr());
- delete paths;
- return true;
- }
- }
- }
-
- delete paths;
- return false;
-}
-
-static bool findJavaInRegistry(CPath *outJavaPath) {
- // TODO
- return false;
-}
-
-static bool findJavaInProgramFiles(CPath *outJavaPath) {
- // TODO
- return false;
-}
// Creates a directory named dirLeafName in the TEMP directory.
// Returns the path in outDir on success.