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)) {