Example #1
0
int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow) {

    gDebug = (getenv("ANDROID_SDKMAN_DEBUG") != NULL);

    PVOID oldWow64Value = disableWow64FsRedirection();

    CPath javaPath;
    if (!findJavaInEnvPath(&javaPath) &&
        !findJavaInRegistry(&javaPath) &&
        !findJavaInProgramFiles(&javaPath)) {
        msgBox("Failed to find Java on your system. Please reinstall it.");
        return 2;
    }
    _ASSERT(!javaPath.isEmpty());

    revertWow64FsRedirection(oldWow64Value);

    // For debugging it's convenient to override the tools directory location
    CPath toolsDir(getenv("ANDROID_SDKMAN_TOOLS_DIR"));
    if (toolsDir.isEmpty()) {
        if (!getModuleDir(&toolsDir)) {
            displayLastError("Failed to get program's filename: ");
            return 1;
        }
    }
    _ASSERT(!toolsDir.isEmpty());

    CPath tmpDir;
    if (!mkTempDir("temp-android-tool", &tmpDir)) {
        return 1;
    }
    _ASSERT(!tmpDir.isEmpty());

    if (!mkDirs(tmpDir.cstr(), sMkDirList)) {
        return 1;
    }

    if (!copyFiles(toolsDir.cstr(), tmpDir.cstr(), sFilesToCopy)) {
        return 1;
    }

    if (!execSdkManager(javaPath.cstr(), toolsDir.cstr(), tmpDir.cstr(), lpCmdLine)) {
        displayLastError("Failed to start SDK Manager: ");
        return 1;
    }

    return 0;
}
void createTestFile(const string& testFilePath, const char* testFileText, int size /*0*/)
// write a test file to the test directory
// the size option is for 16 and 32 bit UTF files with NULs in the text
{
	// verify test directory
	string testDir = getTestDirectory();
	if (testFilePath.compare(0, testDir.length(), testDir) != 0
	        || !(testFilePath[testDir.length()] == '/'
	             || testFilePath[testDir.length()] == '\\'))
		ASTYLE_ABORT("File not written to test directory: " + testFilePath);
	// write the output file
	ofstream fout(testFilePath.c_str(), ios::binary | ios::trunc);
	if (!fout)
	{
#ifdef _WIN32
		displayLastError();
#endif
		ASTYLE_ABORT("Cannot open output file: " + testFilePath);
	}
	if (size == 0)
		fout << testFileText;
	else
		fout.write(testFileText, size);
	fout.close();
}
Example #3
0
void cleanTestDirectory(const wstring& directory)
// Windows remove files and sub directories from the test directory
{
	WIN32_FIND_DATAW FindFileData;
	// Find the first file in the directory
	// Find will get at least "." and "..".
	wstring firstFile = directory + L"\\*";
	HANDLE hFind = ::FindFirstFileW(firstFile.c_str(), &FindFileData);
	if (hFind == INVALID_HANDLE_VALUE)
	{
		displayLastError();
		systemAbort(L"Cannot open directory for clean: " + directory);
	}
	// remove files and sub directories
	do
	{
		// skip these
		if (wcscmp(FindFileData.cFileName, L".") == 0
				||  wcscmp(FindFileData.cFileName, L"..") == 0)
			continue;
		// clean and remove sub directories
		if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
		{
			wstring subDirectoryPath = directory + L"\\" + FindFileData.cFileName;
			cleanTestDirectory(subDirectoryPath);
			BOOL isRemoved = ::RemoveDirectoryW(subDirectoryPath.c_str());
			if (!isRemoved)
				retryRemoveDirectory(subDirectoryPath);
			continue;
		}
		// remove the file
		wstring filePathName = directory + L"\\" + FindFileData.cFileName;
		BOOL isRemoved = ::DeleteFileW(filePathName.c_str());
		if (!isRemoved)
		{
			displayLastError();
			systemAbort(L"Cannot remove file for clean: " + filePathName);
		}
	}
	while (::FindNextFileW(hFind, &FindFileData) != 0);
	// check for processing error
	FindClose(hFind);
	DWORD dwError = GetLastError();
	if (dwError != ERROR_NO_MORE_FILES)
		systemAbort(L"Error processing directory for clean: " + directory);
}
Example #4
0
// Creates a directory named dirLeafName in the TEMP directory.
// Returns the path in outDir on success.
static bool mkTempDir(const char *dirLeafName, CPath *outDir) {
    SetLastError(0);
    char tempPath[MAX_PATH + 1] = "";
    DWORD len = GetTempPathA(MAX_PATH, tempPath);
    if (len > 0 && len <= MAX_PATH) {
        _ASSERT(tempPath[len-1] == '\\');
        _ASSERT(len + strlen(dirLeafName) < MAX_PATH);
        if (len + strlen(dirLeafName) >= MAX_PATH) {
            displayLastError("TEMP path too long to create a temporary directory: %s", tempPath);
            return false;
        }
        strcat(tempPath, dirLeafName);
        outDir->set(tempPath);

        if (outDir->dirExists() ||
            CreateDirectoryA(tempPath, NULL /*lpSecurityAttributes*/) != 0) {
            return true;
        }
    }
    displayLastError("Failed to create a temporary directory: %s", tempPath);
    return false;
}
Example #5
0
// Creates all the directories from sMkDirList in the specified base tmpDir.
static bool mkDirs(const char *tmpDir, const char * dirList[]) {
    SetLastError(0);
    for (const char **dir = dirList; *dir != NULL; dir++) {
        CPath path(tmpDir);
        path.addPath(*dir);
        if (!path.dirExists()) {
            if (!CreateDirectoryA(path.cstr(), NULL /*lpSecurityAttributes*/)) {
                displayLastError("Failed to create directory: %s", path.cstr());
                return false;
            }
        }
    }
    return true;
}
Example #6
0
void retryRemoveDirectory(const wstring& directory)
// WINDOWS wait for files and sub-directories to be removed
{
	// sleep a max of 20 seconds for the remove
	for (size_t seconds = 1; seconds <= 20; seconds++)
	{
		sleep(1);
		BOOL isRemoved = ::RemoveDirectoryW(directory.c_str());
		if (isRemoved)
		{
//			cout << "remove retry: " << seconds << " seconds" << endl;
			return;
		}
	}
	displayLastError();
	systemAbort(L"Cannot remove file for clean: " + directory);
}
Example #7
0
void retryCreateDirectory(const string& directory)
// WINDOWS wait for directories to be removed
{
	// sleep a max of 20 seconds for the remove
	for (size_t seconds = 1; seconds <= 20; seconds++)
	{
		sleep(1);
		BOOL ok = ::CreateDirectory(directory.c_str(), NULL);
		if (ok || GetLastError() == ERROR_ALREADY_EXISTS)
		{
//			cout << "create retry: " << seconds << " seconds" << endl;
			return;
		}
	}
	displayLastError();
	systemAbort("Cannot create directory: " + directory);
}
Example #8
0
static bool execSdkManager(const char *javaPath,
                           const char *toolsDir,
                           const char *tmpDir,
                           const char *lpCmdLine) {
    SetLastError(0);

    // 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);
        }
    }

    // Check whether the underlying system is x86 or x86_64.
    // We use GetSystemInfo which will see the one masqueraded by Wow64.
    // (to get the real info, we would use GetNativeSystemInfo instead.)
    SYSTEM_INFO sysInfo;
    GetSystemInfo(&sysInfo);

    CString arch("x86");
    if (sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) {
        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);
    }

    // Now build the command line.
    // 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.

    CString cmdLine;
    cmdLine.setf("\"%s\" "                                   // javaPath
                 "-Dcom.android.sdkmanager.toolsdir=\"%s\" " // toolsDir
                 "-Dcom.android.sdkmanager.workdir=\"%s\" "  // workDir==toolsdir
                 "-classpath \"lib\\sdkmanager.jar;lib\\swtmenubar.jar;lib\\%s\\swt.jar\" " // arch
                 "com.android.sdkmanager.Main "
                 "%s",                                       // extra parameters
        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(javaExecPath.cstr(), cmdLine.cstr(), tmpDir)) {
        displayLastError("Failed to run %s", cmdLine.cstr());
        return false;
    }

    return true;
}
Example #9
0
static bool copyFiles(const char *toolsDir, const char *tmpDir, const char *globList[]) {
    SetLastError(0);
    WIN32_FIND_DATAA srcFindData;
    WIN32_FIND_DATAA destFindData;
    for (const char **glob = globList; *glob != NULL; glob++) {
        CPath globDir = CPath(*glob).dirName();

        CPath fullGlob(toolsDir);
        fullGlob.addPath(*glob);

        HANDLE srcH = FindFirstFileA(fullGlob.cstr(), &srcFindData);
        if (srcH == INVALID_HANDLE_VALUE) {
            displayLastError("Failed to list files: %s", *glob);
            return false;
        }
        do {
            // Skip directories
            if ((srcFindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
                continue;
            }
            CPath srcPath(toolsDir);
            srcPath.addPath(globDir).addPath(srcFindData.cFileName);

            CPath destPath(tmpDir);
            destPath.addPath(globDir).addPath(srcFindData.cFileName);

            // Skip copy if files are likely to not have changed.
            HANDLE destH = FindFirstFileA(destPath.cstr(), &destFindData);
            if (destH != INVALID_HANDLE_VALUE) {
                // Size must be same for us to skip it.
                if (srcFindData.nFileSizeHigh == destFindData.nFileSizeHigh &&
                    srcFindData.nFileSizeLow  == destFindData.nFileSizeLow) {
                    // Creation & access times can differ. However if the dest write time
                    // is >= than the source write time, it should be the same file.
                    LARGE_INTEGER srcWriteTime;
                    LARGE_INTEGER dstWriteTime;
                    srcWriteTime.HighPart = srcFindData.ftLastWriteTime.dwHighDateTime;
                    srcWriteTime.LowPart  = srcFindData.ftLastWriteTime.dwLowDateTime;
                    dstWriteTime.HighPart = destFindData.ftLastWriteTime.dwHighDateTime;
                    dstWriteTime.LowPart  = destFindData.ftLastWriteTime.dwLowDateTime;
                    if (dstWriteTime.QuadPart >= srcWriteTime.QuadPart) {
                        FindClose(destH);
                        continue;
                    }
                }

                FindClose(destH);

                // 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) {
                    SetFileAttributes(destPath.cstr(),
                        destFindData.dwFileAttributes ^ FILE_ATTRIBUTE_READONLY);
                }
            }

            if (!CopyFileA(srcPath.cstr(), destPath.cstr(), false /*bFailIfExists*/)) {
                FindClose(srcH);
                displayLastError("Failed to copy file: %s", destPath.cstr());
                return false;
            }
        } while (FindNextFileA(srcH, &srcFindData) != 0);
        FindClose(srcH);
    }
    return true;
}
Example #10
0
// Tries to invoke the java.exe at the given path and extract it's
// version number.
// - outVersionStr: if not null, will capture version as a string (e.g. "1.6")
// - outVersionInt: if not null, will capture version as an int (major * 1000 + minor, e.g. 1006).
bool getJavaVersion(CPath &javaPath, CString *outVersionStr, int *outVersionInt) {
    bool result = false;

    // Run "java -version", which outputs something like to *STDERR*:
    //
    // 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.setf("\"%s\" -version", javaPath.cstr());

    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)
        if (gIsConsole || gIsDebug) displayLastError("CreatePipe failed: ");
        return false;
    }
    if (!SetHandleInformation(stdoutPipeRd, HANDLE_FLAG_INHERIT, 0)) {
        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 = CreateProcessA(
            NULL,                   // program path
            (LPSTR) cmd.cstr(),     // 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);

    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.
    char 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
            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 captures roughtly the first line in lower case.
        char *j = strstr(first32, "java");
        char *v = strstr(first32, "version");
        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;
}