SDK android.exe: fix "access denied" error.
Issue was a typo and the script was setting the
files as read-only (instead of clearing the r-o
attribute, it was setting it) before trying to
copy them.
Also reverted the code that hides the launched
app window so that the sdkmanager actually be
visible.
SDK Bug: 5683762
Change-Id: Id23302981f84b227361c6208fe6ef512e0ac2de3
diff --git a/sdkmanager/win_android/utils.cpp b/sdkmanager/win_android/utils.cpp
index 6da1893..bef1aa7 100755
--- a/sdkmanager/win_android/utils.cpp
+++ b/sdkmanager/win_android/utils.cpp
@@ -59,7 +59,7 @@
ZeroMemory(&startup, sizeof(startup));
startup.cb = sizeof(startup);
startup.dwFlags = STARTF_USESHOWWINDOW;
- startup.wShowWindow = SW_HIDE|SW_MINIMIZE;
+ startup.wShowWindow = SW_SHOWDEFAULT;
int ret = CreateProcessA(
(LPSTR) app, /* program path */
@@ -67,7 +67,7 @@
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 */
+ 0, /* create flags */
NULL, /* use parent's environment block */
workDir, /* use parent's starting directory */
&startup, /* startup info, i.e. std handles */
@@ -142,13 +142,14 @@
// 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.
+// 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 non-64 systems) so
+ // However that method may not exist (e.g. on XP non-64 systems) so
// we must not call it directly.
PVOID oldWow64Value = 0;
@@ -173,7 +174,7 @@
// The call we want to make is the following:
// Wow64RevertWow64FsRedirection(oldWow64Value);
- // However that method may not exist (e.g. on non-64 systems) so
+ // However that method may not exist (e.g. on XP non-64 systems) so
// we must not call it directly.
HMODULE hmod = LoadLibrary("kernel32.dll");
diff --git a/sdkmanager/win_android/utils.h b/sdkmanager/win_android/utils.h
index 60d4da8..8c5cdb7 100755
--- a/sdkmanager/win_android/utils.h
+++ b/sdkmanager/win_android/utils.h
@@ -179,6 +179,7 @@
return result;
}
+ // Sets the string to the message matching Win32 GetLastError.
CString& setLastWin32Error() {
DWORD err = GetLastError();
LPSTR errStr;
@@ -190,7 +191,7 @@
(LPSTR)&errStr, /* lpBuffer */
0, /* nSize */
NULL) != 0) { /* va_list args */
- set(errStr);
+ setf("[%d] %s", err, errStr);
LocalFree(errStr);
}
return *this;
diff --git a/sdkmanager/win_android/win_android.cpp b/sdkmanager/win_android/win_android.cpp
index 6417051..32d090c 100644
--- a/sdkmanager/win_android/win_android.cpp
+++ b/sdkmanager/win_android/win_android.cpp
@@ -151,7 +151,7 @@
// CopyFile copies some attributes. It's common for tools to be unzipped
// as read-only so we need to remove any r-o attribute on existing
// files if we want a recopy to succeed.
- if ((destFindData.dwFileAttributes && FILE_ATTRIBUTE_READONLY) != 0) {
+ if ((destFindData.dwFileAttributes & FILE_ATTRIBUTE_READONLY) != 0) {
SetFileAttributes(destPath.cstr(),
destFindData.dwFileAttributes ^ FILE_ATTRIBUTE_READONLY);
}
@@ -174,14 +174,34 @@
const char *lpCmdLine) {
SetLastError(0);
- CPath javawPath(javaPath);
- javawPath.replaceName("java.exe", "javaw.exe");
- // Only accept it if we can actually find the exec
- PVOID oldWow64Value = disableWow64FsRedirection();
- if (!javawPath.fileExists()) {
- javawPath.set(javaPath);
+ // Which java binary to call.
+ // The default is to use java.exe to automatically dump stdout in
+ // the parent console.
+ CPath javaExecPath(javaPath);
+
+ // Attach to the parent console, if there's one.
+ if (AttachConsole(-1) == 0) {
+ // This can fail with ERROR_ACCESS_DENIED if the process is already
+ // attached to the parent console. That means there's a console so
+ // we want to keep invoking java.exe to get stdout into it.
+ //
+ // This also fails if there is no parent console, in which
+ // it means this was invoked not from a shell. It's a good
+ // signal we don't want a new console to show up so we'll
+ // switch to javaw.exe instead, if available.
+
+ if (GetLastError() != ERROR_ACCESS_DENIED) {
+ SetLastError(0);
+
+ javaExecPath.replaceName("java.exe", "javaw.exe");
+ // Only accept it if we can actually find the exec
+ PVOID oldWow64Value = disableWow64FsRedirection();
+ if (!javaExecPath.fileExists()) {
+ javaExecPath.set(javaPath);
+ }
+ revertWow64FsRedirection(&oldWow64Value);
+ }
}
- revertWow64FsRedirection(&oldWow64Value);
// Check whether the underlying system is x86 or x86_64.
// We use GetSystemInfo which will see the one masqueraded by Wow64.
@@ -194,20 +214,17 @@
arch.set("x86_64");
} else if (sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL) {
// Skip this. We'll just assume x86 and let it fail later.
+ // Keep this line for debugging purposes:
// displayLastError("Unknown Processor Architecture: %d", sysInfo.wProcessorArchitecture);
- // return false;
}
// Now build the command line.
- // Note that we pass the absolute javawPath to execNoWait
- // and the first parameter is just for the show.
+ // Note that we pass the absolute javaExecPath both to CreateProcess (via execNoWait)
+ // and we set it as argv[0] in the command line just for the show.
// Important: for the classpath to be able to contain "lib\\sdkmanager.jar", etc.,
// we need to set the toolsDir as the *temp* directory in execNoWait.
// It's important to not use toolsDir otherwise it would lock that diretory.
- // Tip: to connect the Java debugging to a running process, add this to the Java command line:
- // "-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000"
-
CString cmdLine;
cmdLine.setf("\"%s\" " // javaPath
"-Dcom.android.sdkmanager.toolsdir=\"%s\" " // toolsDir
@@ -215,11 +232,14 @@
"-classpath \"lib\\sdkmanager.jar;lib\\swtmenubar.jar;lib\\%s\\swt.jar\" " // arch
"com.android.sdkmanager.Main "
"%s", // extra parameters
- javawPath.baseName(), toolsDir, tmpDir, arch.cstr(), lpCmdLine);
+ javaExecPath.baseName(), toolsDir, tmpDir, arch.cstr(), lpCmdLine);
+
+ // Tip: to connect the Java debugging to a running process, add this to the Java command line:
+ // "-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000"
if (gDebug) msgBox("Executing: %s", cmdLine.cstr());
- if (!execNoWait(javawPath.cstr(), cmdLine.cstr(), tmpDir)) {
+ if (!execNoWait(javaExecPath.cstr(), cmdLine.cstr(), tmpDir)) {
displayLastError("Failed to run %s", cmdLine.cstr());
return false;
}
@@ -247,7 +267,7 @@
revertWow64FsRedirection(oldWow64Value);
- // For debugging it's more convenient to be able to override the tools directory location
+ // For debugging it's convenient to override the tools directory location
CPath toolsDir(getenv("ANDROID_SDKMAN_TOOLS_DIR"));
if (toolsDir.isEmpty()) {
if (!getModuleDir(&toolsDir)) {