sdklauncher.c revision ea66c92f80d9745721cfa28e22f2726b76579158
16508be1224ddec08910c464d2a905c4c2e1f7d80Raphael/*
26508be1224ddec08910c464d2a905c4c2e1f7d80Raphael * Copyright (C) 2009 The Android Open Source Project
36508be1224ddec08910c464d2a905c4c2e1f7d80Raphael *
46508be1224ddec08910c464d2a905c4c2e1f7d80Raphael * Licensed under the Apache License, Version 2.0 (the "License");
56508be1224ddec08910c464d2a905c4c2e1f7d80Raphael * you may not use this file except in compliance with the License.
66508be1224ddec08910c464d2a905c4c2e1f7d80Raphael * You may obtain a copy of the License at
76508be1224ddec08910c464d2a905c4c2e1f7d80Raphael *
86508be1224ddec08910c464d2a905c4c2e1f7d80Raphael *      http://www.apache.org/licenses/LICENSE-2.0
96508be1224ddec08910c464d2a905c4c2e1f7d80Raphael *
106508be1224ddec08910c464d2a905c4c2e1f7d80Raphael * Unless required by applicable law or agreed to in writing, software
116508be1224ddec08910c464d2a905c4c2e1f7d80Raphael * distributed under the License is distributed on an "AS IS" BASIS,
126508be1224ddec08910c464d2a905c4c2e1f7d80Raphael * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136508be1224ddec08910c464d2a905c4c2e1f7d80Raphael * See the License for the specific language governing permissions and
146508be1224ddec08910c464d2a905c4c2e1f7d80Raphael * limitations under the License.
156508be1224ddec08910c464d2a905c4c2e1f7d80Raphael */
166508be1224ddec08910c464d2a905c4c2e1f7d80Raphael
176508be1224ddec08910c464d2a905c4c2e1f7d80Raphael/*
186508be1224ddec08910c464d2a905c4c2e1f7d80Raphael * The "SDK Launcher" is for Windows only.
196508be1224ddec08910c464d2a905c4c2e1f7d80Raphael * This simple .exe will sit at the root of the Windows SDK
206508be1224ddec08910c464d2a905c4c2e1f7d80Raphael * and currently simply executes tools\android.bat.
216508be1224ddec08910c464d2a905c4c2e1f7d80Raphael * Eventually it should simply replace the batch file.
226508be1224ddec08910c464d2a905c4c2e1f7d80Raphael *
236508be1224ddec08910c464d2a905c4c2e1f7d80Raphael * TODO:
246508be1224ddec08910c464d2a905c4c2e1f7d80Raphael * - create temp dir, always copy *.jar there, exec android.jar
256508be1224ddec08910c464d2a905c4c2e1f7d80Raphael * - get jars to copy from some file
266508be1224ddec08910c464d2a905c4c2e1f7d80Raphael * - use a version number to copy jars only if needed (tools.revision?)
276508be1224ddec08910c464d2a905c4c2e1f7d80Raphael */
286508be1224ddec08910c464d2a905c4c2e1f7d80Raphael
296508be1224ddec08910c464d2a905c4c2e1f7d80Raphael#ifdef _WIN32
306508be1224ddec08910c464d2a905c4c2e1f7d80Raphael
316508be1224ddec08910c464d2a905c4c2e1f7d80Raphael#include <stdio.h>
326508be1224ddec08910c464d2a905c4c2e1f7d80Raphael#include <windows.h>
336508be1224ddec08910c464d2a905c4c2e1f7d80Raphael
34ea66c92f80d9745721cfa28e22f2726b76579158Raphael
35ea66c92f80d9745721cfa28e22f2726b76579158Raphaelvoid display_error(LPSTR description) {
36ea66c92f80d9745721cfa28e22f2726b76579158Raphael    DWORD err = GetLastError();
37ea66c92f80d9745721cfa28e22f2726b76579158Raphael    LPSTR s, s2;
38ea66c92f80d9745721cfa28e22f2726b76579158Raphael
39ea66c92f80d9745721cfa28e22f2726b76579158Raphael    fprintf(stderr, "%s, error %ld\n", description, err);
40ea66c92f80d9745721cfa28e22f2726b76579158Raphael
41ea66c92f80d9745721cfa28e22f2726b76579158Raphael    if (FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | /* dwFlags */
42ea66c92f80d9745721cfa28e22f2726b76579158Raphael                      FORMAT_MESSAGE_FROM_SYSTEM,
43ea66c92f80d9745721cfa28e22f2726b76579158Raphael                      NULL,                             /* lpSource */
44ea66c92f80d9745721cfa28e22f2726b76579158Raphael                      err,                              /* dwMessageId */
45ea66c92f80d9745721cfa28e22f2726b76579158Raphael                      0,                                /* dwLanguageId */
46ea66c92f80d9745721cfa28e22f2726b76579158Raphael                      (LPSTR)&s,                        /* lpBuffer */
47ea66c92f80d9745721cfa28e22f2726b76579158Raphael                      0,                                /* nSize */
48ea66c92f80d9745721cfa28e22f2726b76579158Raphael                      NULL) != 0) {                     /* va_list args */
49ea66c92f80d9745721cfa28e22f2726b76579158Raphael        fprintf(stderr, "%s", s);
50ea66c92f80d9745721cfa28e22f2726b76579158Raphael
51ea66c92f80d9745721cfa28e22f2726b76579158Raphael        s2 = (LPSTR) malloc(strlen(description) + strlen(s) + 5);
52ea66c92f80d9745721cfa28e22f2726b76579158Raphael        sprintf(s2, "%s\r\n%s", description, s);
53ea66c92f80d9745721cfa28e22f2726b76579158Raphael        MessageBox(NULL, s2, "Android SDK Setup - Error", MB_OK);
54ea66c92f80d9745721cfa28e22f2726b76579158Raphael        free(s2);
55ea66c92f80d9745721cfa28e22f2726b76579158Raphael        LocalFree(s);
56ea66c92f80d9745721cfa28e22f2726b76579158Raphael    }
57ea66c92f80d9745721cfa28e22f2726b76579158Raphael}
58ea66c92f80d9745721cfa28e22f2726b76579158Raphael
59ea66c92f80d9745721cfa28e22f2726b76579158Raphael
60ea66c92f80d9745721cfa28e22f2726b76579158RaphaelHANDLE create_temp_file(LPSTR temp_filename) {
61ea66c92f80d9745721cfa28e22f2726b76579158Raphael
62ea66c92f80d9745721cfa28e22f2726b76579158Raphael    HANDLE file_handle = INVALID_HANDLE_VALUE;
63ea66c92f80d9745721cfa28e22f2726b76579158Raphael    LPSTR temp_path = (LPSTR) malloc(MAX_PATH);
64ea66c92f80d9745721cfa28e22f2726b76579158Raphael
65ea66c92f80d9745721cfa28e22f2726b76579158Raphael    /* Get the temp directory path using GetTempPath.
66ea66c92f80d9745721cfa28e22f2726b76579158Raphael       GetTempFilename indicates that the temp path dir should not be larger than MAX_PATH-14.
67ea66c92f80d9745721cfa28e22f2726b76579158Raphael    */
68ea66c92f80d9745721cfa28e22f2726b76579158Raphael    int ret = GetTempPath(MAX_PATH - 14, temp_path);
69ea66c92f80d9745721cfa28e22f2726b76579158Raphael    if (ret > MAX_PATH || ret == 0) {
70ea66c92f80d9745721cfa28e22f2726b76579158Raphael        display_error("GetTempPath failed");
71ea66c92f80d9745721cfa28e22f2726b76579158Raphael        free(temp_path);
72ea66c92f80d9745721cfa28e22f2726b76579158Raphael        return INVALID_HANDLE_VALUE;
73ea66c92f80d9745721cfa28e22f2726b76579158Raphael    }
74ea66c92f80d9745721cfa28e22f2726b76579158Raphael
75ea66c92f80d9745721cfa28e22f2726b76579158Raphael    /* Now get a temp filename in the temp directory. */
76ea66c92f80d9745721cfa28e22f2726b76579158Raphael    if (!GetTempFileName(temp_path, "txt", 0, temp_filename)) {
77ea66c92f80d9745721cfa28e22f2726b76579158Raphael        display_error("GetTempFileName failed");
78ea66c92f80d9745721cfa28e22f2726b76579158Raphael
79ea66c92f80d9745721cfa28e22f2726b76579158Raphael    } else {
80ea66c92f80d9745721cfa28e22f2726b76579158Raphael        SECURITY_ATTRIBUTES sattr;
81ea66c92f80d9745721cfa28e22f2726b76579158Raphael        ZeroMemory(&sattr, sizeof(sattr));
82ea66c92f80d9745721cfa28e22f2726b76579158Raphael        sattr.nLength = sizeof(SECURITY_ATTRIBUTES);
83ea66c92f80d9745721cfa28e22f2726b76579158Raphael        sattr.bInheritHandle = TRUE;
84ea66c92f80d9745721cfa28e22f2726b76579158Raphael
85ea66c92f80d9745721cfa28e22f2726b76579158Raphael        file_handle = CreateFile(temp_filename,             // filename
86ea66c92f80d9745721cfa28e22f2726b76579158Raphael                                 GENERIC_WRITE,             // access: write
87ea66c92f80d9745721cfa28e22f2726b76579158Raphael                                 FILE_SHARE_READ,           // share mode: read OK
88ea66c92f80d9745721cfa28e22f2726b76579158Raphael                                 &sattr,                    // security attributes
89ea66c92f80d9745721cfa28e22f2726b76579158Raphael                                 CREATE_ALWAYS,             // create even if exists
90ea66c92f80d9745721cfa28e22f2726b76579158Raphael                                 FILE_ATTRIBUTE_NORMAL,     // flags and attributes
91ea66c92f80d9745721cfa28e22f2726b76579158Raphael                                 NULL);                     // template
92ea66c92f80d9745721cfa28e22f2726b76579158Raphael        if (file_handle == INVALID_HANDLE_VALUE) {
93ea66c92f80d9745721cfa28e22f2726b76579158Raphael            display_error("Create temp file failed");
94ea66c92f80d9745721cfa28e22f2726b76579158Raphael        }
95ea66c92f80d9745721cfa28e22f2726b76579158Raphael    }
96ea66c92f80d9745721cfa28e22f2726b76579158Raphael
97ea66c92f80d9745721cfa28e22f2726b76579158Raphael    free(temp_path);
98ea66c92f80d9745721cfa28e22f2726b76579158Raphael    return file_handle;
99ea66c92f80d9745721cfa28e22f2726b76579158Raphael}
100ea66c92f80d9745721cfa28e22f2726b76579158Raphael
101ea66c92f80d9745721cfa28e22f2726b76579158Raphael
102ea66c92f80d9745721cfa28e22f2726b76579158Raphaelvoid read_temp_file(LPSTR temp_filename) {
103ea66c92f80d9745721cfa28e22f2726b76579158Raphael    HANDLE handle;
104ea66c92f80d9745721cfa28e22f2726b76579158Raphael
105ea66c92f80d9745721cfa28e22f2726b76579158Raphael    handle = CreateFile(temp_filename,             // filename
106ea66c92f80d9745721cfa28e22f2726b76579158Raphael                        GENERIC_READ,              // access: read
107ea66c92f80d9745721cfa28e22f2726b76579158Raphael                        FILE_SHARE_READ,           // share mode: read OK
108ea66c92f80d9745721cfa28e22f2726b76579158Raphael                        NULL,                      // security attributes
109ea66c92f80d9745721cfa28e22f2726b76579158Raphael                        OPEN_EXISTING,             // only open existing file
110ea66c92f80d9745721cfa28e22f2726b76579158Raphael                        FILE_ATTRIBUTE_NORMAL,     // flags and attributes
111ea66c92f80d9745721cfa28e22f2726b76579158Raphael                        NULL);                     // template
112ea66c92f80d9745721cfa28e22f2726b76579158Raphael
113ea66c92f80d9745721cfa28e22f2726b76579158Raphael    if (handle == INVALID_HANDLE_VALUE) {
114ea66c92f80d9745721cfa28e22f2726b76579158Raphael        display_error("Open temp file failed");
115ea66c92f80d9745721cfa28e22f2726b76579158Raphael        return;
116ea66c92f80d9745721cfa28e22f2726b76579158Raphael    }
117ea66c92f80d9745721cfa28e22f2726b76579158Raphael
118ea66c92f80d9745721cfa28e22f2726b76579158Raphael    /* Cap the size we're reading.
119ea66c92f80d9745721cfa28e22f2726b76579158Raphael       4K is good enough to display in a message box.
120ea66c92f80d9745721cfa28e22f2726b76579158Raphael    */
121ea66c92f80d9745721cfa28e22f2726b76579158Raphael    DWORD size = 4096;
122ea66c92f80d9745721cfa28e22f2726b76579158Raphael
123ea66c92f80d9745721cfa28e22f2726b76579158Raphael    LPSTR buffer = (LPSTR) malloc(size + 1);
124ea66c92f80d9745721cfa28e22f2726b76579158Raphael
125ea66c92f80d9745721cfa28e22f2726b76579158Raphael    LPSTR p = buffer;
126ea66c92f80d9745721cfa28e22f2726b76579158Raphael    DWORD num_left = size;
127ea66c92f80d9745721cfa28e22f2726b76579158Raphael    DWORD num_read;
128ea66c92f80d9745721cfa28e22f2726b76579158Raphael    do {
129ea66c92f80d9745721cfa28e22f2726b76579158Raphael        if (!ReadFile(handle, p, num_left, &num_read, NULL)) {
130ea66c92f80d9745721cfa28e22f2726b76579158Raphael            display_error("Read Output failed");
131ea66c92f80d9745721cfa28e22f2726b76579158Raphael            break;
132ea66c92f80d9745721cfa28e22f2726b76579158Raphael        }
133ea66c92f80d9745721cfa28e22f2726b76579158Raphael
134ea66c92f80d9745721cfa28e22f2726b76579158Raphael        num_left -= num_read;
135ea66c92f80d9745721cfa28e22f2726b76579158Raphael        p += num_read;
136ea66c92f80d9745721cfa28e22f2726b76579158Raphael    } while (num_read > 0);
137ea66c92f80d9745721cfa28e22f2726b76579158Raphael
138ea66c92f80d9745721cfa28e22f2726b76579158Raphael    if (p != buffer) {
139ea66c92f80d9745721cfa28e22f2726b76579158Raphael        *p = 0;
140ea66c92f80d9745721cfa28e22f2726b76579158Raphael
141ea66c92f80d9745721cfa28e22f2726b76579158Raphael        /* Only output the buffer if it contains special keywords WARNING or ERROR. */
142ea66c92f80d9745721cfa28e22f2726b76579158Raphael        char* s1 = strstr(buffer, "WARNING");
143ea66c92f80d9745721cfa28e22f2726b76579158Raphael        char* s2 = strstr(buffer, "ERROR");
144ea66c92f80d9745721cfa28e22f2726b76579158Raphael
145ea66c92f80d9745721cfa28e22f2726b76579158Raphael        if (s2 != NULL && s2 < s1) {
146ea66c92f80d9745721cfa28e22f2726b76579158Raphael            s1 = s2;
147ea66c92f80d9745721cfa28e22f2726b76579158Raphael        }
148ea66c92f80d9745721cfa28e22f2726b76579158Raphael
149ea66c92f80d9745721cfa28e22f2726b76579158Raphael        if (s1 != NULL) {
150ea66c92f80d9745721cfa28e22f2726b76579158Raphael            /* We end the message at the first occurence of [INFO]. */
151ea66c92f80d9745721cfa28e22f2726b76579158Raphael            s2 = strstr(s1, "[INFO]");
152ea66c92f80d9745721cfa28e22f2726b76579158Raphael            if (s2 != NULL) {
153ea66c92f80d9745721cfa28e22f2726b76579158Raphael                *s2 = 0;
154ea66c92f80d9745721cfa28e22f2726b76579158Raphael            }
155ea66c92f80d9745721cfa28e22f2726b76579158Raphael
156ea66c92f80d9745721cfa28e22f2726b76579158Raphael            MessageBox(NULL, s1, "Android SDK Setup - Output", MB_OK);
157ea66c92f80d9745721cfa28e22f2726b76579158Raphael        }
158ea66c92f80d9745721cfa28e22f2726b76579158Raphael
159ea66c92f80d9745721cfa28e22f2726b76579158Raphael    }
160ea66c92f80d9745721cfa28e22f2726b76579158Raphael
161ea66c92f80d9745721cfa28e22f2726b76579158Raphael    free(buffer);
162ea66c92f80d9745721cfa28e22f2726b76579158Raphael
163ea66c92f80d9745721cfa28e22f2726b76579158Raphael    if (!CloseHandle(handle)) {
164ea66c92f80d9745721cfa28e22f2726b76579158Raphael        display_error("CloseHandle read temp file failed");
165ea66c92f80d9745721cfa28e22f2726b76579158Raphael    }
166ea66c92f80d9745721cfa28e22f2726b76579158Raphael}
167ea66c92f80d9745721cfa28e22f2726b76579158Raphael
168ea66c92f80d9745721cfa28e22f2726b76579158Raphael
1696508be1224ddec08910c464d2a905c4c2e1f7d80Raphaelint sdk_launcher() {
170ea66c92f80d9745721cfa28e22f2726b76579158Raphael    int                   result = 0;
1716508be1224ddec08910c464d2a905c4c2e1f7d80Raphael    STARTUPINFO           startup;
1726508be1224ddec08910c464d2a905c4c2e1f7d80Raphael    PROCESS_INFORMATION   pinfo;
173ea66c92f80d9745721cfa28e22f2726b76579158Raphael    CHAR                  program_path[MAX_PATH];
1746508be1224ddec08910c464d2a905c4c2e1f7d80Raphael    int                   ret;
175ea66c92f80d9745721cfa28e22f2726b76579158Raphael    CHAR                  temp_filename[MAX_PATH];
176ea66c92f80d9745721cfa28e22f2726b76579158Raphael    HANDLE                temp_handle;
177ea66c92f80d9745721cfa28e22f2726b76579158Raphael
178ea66c92f80d9745721cfa28e22f2726b76579158Raphael    ZeroMemory(&pinfo, sizeof(pinfo));
179ea66c92f80d9745721cfa28e22f2726b76579158Raphael
180ea66c92f80d9745721cfa28e22f2726b76579158Raphael    temp_handle = create_temp_file(temp_filename);
181ea66c92f80d9745721cfa28e22f2726b76579158Raphael    if (temp_handle == INVALID_HANDLE_VALUE) {
182ea66c92f80d9745721cfa28e22f2726b76579158Raphael        return 1;
183ea66c92f80d9745721cfa28e22f2726b76579158Raphael    }
1846508be1224ddec08910c464d2a905c4c2e1f7d80Raphael
1856508be1224ddec08910c464d2a905c4c2e1f7d80Raphael    ZeroMemory(&startup, sizeof(startup));
1866508be1224ddec08910c464d2a905c4c2e1f7d80Raphael    startup.cb = sizeof(startup);
187ea66c92f80d9745721cfa28e22f2726b76579158Raphael    startup.dwFlags    = STARTF_USESTDHANDLES;
188ea66c92f80d9745721cfa28e22f2726b76579158Raphael    startup.hStdInput  = GetStdHandle(STD_INPUT_HANDLE);
189ea66c92f80d9745721cfa28e22f2726b76579158Raphael    startup.hStdOutput = temp_handle;
190ea66c92f80d9745721cfa28e22f2726b76579158Raphael    startup.hStdError  = temp_handle;
1916508be1224ddec08910c464d2a905c4c2e1f7d80Raphael
1926508be1224ddec08910c464d2a905c4c2e1f7d80Raphael    /* get path of current program */
1936508be1224ddec08910c464d2a905c4c2e1f7d80Raphael    GetModuleFileName(NULL, program_path, sizeof(program_path));
1946508be1224ddec08910c464d2a905c4c2e1f7d80Raphael
1956508be1224ddec08910c464d2a905c4c2e1f7d80Raphael    ret = CreateProcess(
196ea66c92f80d9745721cfa28e22f2726b76579158Raphael            NULL,                                       /* program path */
197ea66c92f80d9745721cfa28e22f2726b76579158Raphael            "tools\\android.bat update sdk",            /* command-line */
1986508be1224ddec08910c464d2a905c4c2e1f7d80Raphael            NULL,                  /* process handle is not inheritable */
1996508be1224ddec08910c464d2a905c4c2e1f7d80Raphael            NULL,                   /* thread handle is not inheritable */
2006508be1224ddec08910c464d2a905c4c2e1f7d80Raphael            TRUE,                          /* yes, inherit some handles */
2016508be1224ddec08910c464d2a905c4c2e1f7d80Raphael            CREATE_NO_WINDOW,                /* we don't want a console */
2026508be1224ddec08910c464d2a905c4c2e1f7d80Raphael            NULL,                     /* use parent's environment block */
2036508be1224ddec08910c464d2a905c4c2e1f7d80Raphael            NULL,                    /* use parent's starting directory */
2046508be1224ddec08910c464d2a905c4c2e1f7d80Raphael            &startup,                 /* startup info, i.e. std handles */
2056508be1224ddec08910c464d2a905c4c2e1f7d80Raphael            &pinfo);
2066508be1224ddec08910c464d2a905c4c2e1f7d80Raphael
2076508be1224ddec08910c464d2a905c4c2e1f7d80Raphael    if (!ret) {
208ea66c92f80d9745721cfa28e22f2726b76579158Raphael        display_error("Failed to execute tools\\android.bat:");
209ea66c92f80d9745721cfa28e22f2726b76579158Raphael        result = 1;
210ea66c92f80d9745721cfa28e22f2726b76579158Raphael    } else {
211ea66c92f80d9745721cfa28e22f2726b76579158Raphael        WaitForSingleObject(pinfo.hProcess, INFINITE);
212ea66c92f80d9745721cfa28e22f2726b76579158Raphael        CloseHandle(pinfo.hProcess);
213ea66c92f80d9745721cfa28e22f2726b76579158Raphael        CloseHandle(pinfo.hThread);
214ea66c92f80d9745721cfa28e22f2726b76579158Raphael    }
215ea66c92f80d9745721cfa28e22f2726b76579158Raphael
216ea66c92f80d9745721cfa28e22f2726b76579158Raphael    if (!CloseHandle(temp_handle)) {
217ea66c92f80d9745721cfa28e22f2726b76579158Raphael        display_error("CloseHandle temp file failed");
218ea66c92f80d9745721cfa28e22f2726b76579158Raphael    }
219ea66c92f80d9745721cfa28e22f2726b76579158Raphael
220ea66c92f80d9745721cfa28e22f2726b76579158Raphael    if (!result) {
221ea66c92f80d9745721cfa28e22f2726b76579158Raphael        read_temp_file(temp_filename);
222ea66c92f80d9745721cfa28e22f2726b76579158Raphael    }
2236508be1224ddec08910c464d2a905c4c2e1f7d80Raphael
224ea66c92f80d9745721cfa28e22f2726b76579158Raphael    if (!DeleteFile(temp_filename)) {
225ea66c92f80d9745721cfa28e22f2726b76579158Raphael        display_error("Delete temp file failed");
2266508be1224ddec08910c464d2a905c4c2e1f7d80Raphael    }
2276508be1224ddec08910c464d2a905c4c2e1f7d80Raphael
228ea66c92f80d9745721cfa28e22f2726b76579158Raphael    return result;
2296508be1224ddec08910c464d2a905c4c2e1f7d80Raphael}
2306508be1224ddec08910c464d2a905c4c2e1f7d80Raphael
2316508be1224ddec08910c464d2a905c4c2e1f7d80Raphaelint main(int argc, char **argv) {
2326508be1224ddec08910c464d2a905c4c2e1f7d80Raphael    return sdk_launcher();
2336508be1224ddec08910c464d2a905c4c2e1f7d80Raphael}
2346508be1224ddec08910c464d2a905c4c2e1f7d80Raphael
2356508be1224ddec08910c464d2a905c4c2e1f7d80Raphael#endif /* _WIN32 */
236