1 /* 2 * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 #include <stdio.h> 27 #include <stdlib.h> 28 #include <string> 29 #include <windows.h> 30 31 //#define _DEBUG 32 33 #ifdef _DEBUG 34 #include <iostream> 35 #include <sstream> 36 #endif 37 38 using namespace std; 39 40 #define MAX_KEY_LENGTH 255 41 #define MAX_VALUE_NAME 16383 42 43 bool from_string (int &result, string &str) { 44 const char *p = str.c_str(); 45 int res = 0; 46 for (int index = 0; ; index ++) { 47 char c = str[index]; 48 if (c == 0 && index > 0) { 49 result = res; 50 return true; 51 } 52 if (c < '0' || c > '9') 53 return false; 54 res = res * 10 + (c - '0'); 55 } 56 } 57 /* 58 template <class T> 59 bool from_string(T& t, 60 const std::string& s, 61 std::ios_base& (*f)(std::ios_base&)) { 62 std::istringstream iss(s); 63 return !(iss >> f >> t).fail(); 64 }; 65 */ 66 void PrintCSBackupAPIErrorMessage(DWORD dwErr) { 67 68 char wszMsgBuff[512]; // Buffer for text. 69 70 DWORD dwChars; // Number of chars returned. 71 72 // Try to get the message from the system errors. 73 dwChars = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | 74 FORMAT_MESSAGE_IGNORE_INSERTS, 75 NULL, 76 dwErr, 77 0, 78 wszMsgBuff, 79 512, 80 NULL); 81 82 if (0 == dwChars) { 83 // The error code did not exist in the system errors. 84 // Try ntdsbmsg.dll for the error code. 85 86 HINSTANCE hInst; 87 88 // Load the library. 89 hInst = LoadLibraryA("ntdsbmsg.dll"); 90 if (NULL == hInst) { 91 #ifdef _DEBUG 92 cerr << "cannot load ntdsbmsg.dll\n"; 93 #endif 94 return; 95 96 } 97 98 // Try getting message text from ntdsbmsg. 99 dwChars = FormatMessageA(FORMAT_MESSAGE_FROM_HMODULE | 100 FORMAT_MESSAGE_IGNORE_INSERTS, 101 hInst, 102 dwErr, 103 0, 104 wszMsgBuff, 105 512, 106 NULL); 107 108 // Free the library. 109 FreeLibrary(hInst); 110 111 } 112 113 // Display the error message, or generic text if not found. 114 #ifdef _DEBUG 115 cerr << "Error value: " << dwErr << " Message: " << ((dwChars > 0) ? wszMsgBuff : "Error message not found.") << endl; 116 #endif 117 118 } 119 120 class JavaVersion { 121 public: 122 int v1; 123 int v2; 124 int v3; 125 string home; 126 string path; 127 128 JavaVersion(int pv1, int pv2, int pv3) { 129 v1 = pv1; 130 v2 = pv2; 131 v3 = pv3; 132 } 133 134 bool operator>(const JavaVersion &other) const { 135 if (v1 > other.v1) 136 return true; 137 if (v1 == other.v1) { 138 if (v2 > other.v2) 139 return true; 140 if (v2 == other.v2) 141 return v3 > other.v3; 142 } 143 return false; 144 } 145 146 bool operator>=(const JavaVersion &other) const { 147 if (v1 > other.v1) 148 return true; 149 if (v1 == other.v1) { 150 if (v2 > other.v2) 151 return true; 152 if (v2 == other.v2) 153 return v3 >= other.v3; 154 } 155 return false; 156 } 157 158 bool operator<(const JavaVersion &other) const { 159 if (v1 < other.v1) 160 return true; 161 if (v1 == other.v1) { 162 if (v2 < other.v2) 163 return true; 164 if (v2 == other.v2) 165 return v3 < other.v3; 166 } 167 return false; 168 } 169 }; 170 171 bool checkJavaHome(HKEY key, const char * sKey, const char * jv, JavaVersion *version) { 172 char p[MAX_KEY_LENGTH]; 173 HKEY hKey; 174 bool result = false; 175 int res; 176 177 strcpy_s(p, MAX_KEY_LENGTH, sKey); 178 strcat_s(p, MAX_KEY_LENGTH - strlen(p), "\\"); 179 strcat_s(p, MAX_KEY_LENGTH - strlen(p), jv); 180 181 if (RegOpenKeyExA(key, 182 p, 183 0, 184 KEY_READ, 185 &hKey) == ERROR_SUCCESS 186 ) { 187 DWORD ot = REG_SZ; 188 DWORD size = 255; 189 char data[MAX_PATH] = {0}; 190 if ((res = RegQueryValueExA(hKey, "JavaHome", NULL, &ot, (BYTE *) data, &size)) == ERROR_SUCCESS) { 191 version->home = data; 192 strcat_s(data, sizeof(data) - strlen(data), "\\bin\\java.exe"); 193 version->path = data; 194 result = GetFileAttributesA(data) != 0xFFFFFFFF; 195 } else { 196 PrintCSBackupAPIErrorMessage(res); 197 result = false; 198 } 199 RegCloseKey(hKey); 200 } else { 201 #ifdef _DEBUG 202 cerr << "Can not open registry key" << endl; 203 #endif 204 result = false; 205 } 206 207 return result; 208 } 209 210 JavaVersion * parseName(const char * jName) { 211 string s(jName); 212 213 if (s.length() == 0) { 214 return NULL; 215 } 216 217 string n; 218 string::size_type pos; 219 220 221 pos = s.find_first_of("."); 222 if (pos != string::npos) { 223 n = s.substr(0, pos); 224 s = s.substr(pos + 1); 225 } else { 226 n = s; 227 s = ""; 228 } 229 230 int v1 = 0; 231 232 if (n.length() > 0) { 233 if (!from_string(v1, n)) 234 // if (!from_string<int>(v1, n, std::dec)) 235 return NULL; 236 } 237 238 239 pos = s.find_first_of("."); 240 if (pos != string::npos) { 241 n = s.substr(0, pos); 242 s = s.substr(pos + 1); 243 } else { 244 n = s; 245 s = ""; 246 } 247 248 int v2 = 0; 249 250 if (n.length() > 0) { 251 if (!from_string(v2, n)) 252 // if (!from_string<int>(v2, n, std::dec)) 253 return NULL; 254 } 255 256 257 int nn = s.length(); 258 for (int i = 0; i < s.length(); i++) { 259 string c = s.substr(i, 1); 260 int tmp; 261 if (!from_string(tmp, c)) { 262 // if (!from_string<int>(tmp, c, std::dec)) { 263 nn = i; 264 break; 265 } 266 } 267 268 n = s.substr(0, nn); 269 if (nn < s.length()) { 270 s = s.substr(nn + 1); 271 } else s = ""; 272 273 int v3 = 0; 274 275 if (n.length() > 0) { 276 if (!from_string(v3, n)) 277 // if (!from_string<int>(v3, n, std::dec)) 278 v3 = 0; 279 } 280 281 int v4 = 0; 282 283 //update version 284 if (s.length() > 0) { 285 nn = s.length(); 286 for (int i = 0; i < s.length(); i++) { 287 string c = s.substr(i, 1); 288 int tmp; 289 if (!from_string(tmp, c)) { 290 // if (!from_string<int>(tmp, c, std::dec)) { 291 nn = i; 292 break; 293 } 294 } 295 296 n = s.substr(0, nn); 297 298 if (n.length() > 0) { 299 if (!from_string(v4, n)) 300 // if (!from_string<int>(v4, n, std::dec)) 301 v4 = 0; 302 } 303 } 304 305 return new JavaVersion(v2, v3, v4); 306 } 307 308 JavaVersion * GetMaxVersion(HKEY key, const char * sKey) { 309 HKEY hKey; 310 JavaVersion * result = NULL; 311 312 if (RegOpenKeyExA(key, 313 sKey, 314 0, 315 KEY_READ, 316 &hKey) == ERROR_SUCCESS 317 ) { 318 DWORD retCode; 319 char achClass[MAX_PATH]; // buffer for class name 320 DWORD cchClassName = MAX_PATH; // size of class string 321 322 323 DWORD cchValue = MAX_VALUE_NAME; 324 DWORD cSubKeys = 0; // number of subkeys 325 DWORD cbMaxSubKey; // longest subkey size 326 DWORD cchMaxClass; // longest class string 327 DWORD cValues; // number of values for key 328 DWORD cchMaxValue; // longest value name 329 DWORD cbMaxValueData; // longest value data 330 DWORD cbSecurityDescriptor; // size of security descriptor 331 FILETIME ftLastWriteTime; // last write time 332 333 retCode = RegQueryInfoKeyA( 334 hKey, // key handle 335 achClass, // buffer for class name 336 &cchClassName, // size of class string 337 NULL, // reserved 338 &cSubKeys, // number of subkeys 339 &cbMaxSubKey, // longest subkey size 340 &cchMaxClass, // longest class string 341 &cValues, // number of values for this key 342 &cchMaxValue, // longest value name 343 &cbMaxValueData, // longest value data 344 &cbSecurityDescriptor, // security descriptor 345 &ftLastWriteTime); // last write time 346 347 if (cSubKeys) { 348 for (unsigned int i = 0; i < cSubKeys; i++) { 349 char achKey[MAX_KEY_LENGTH]; // buffer for subkey name 350 DWORD cbName = MAX_KEY_LENGTH; 351 retCode = RegEnumKeyExA(hKey, i, 352 achKey, 353 &cbName, 354 NULL, 355 NULL, 356 NULL, 357 &ftLastWriteTime); 358 359 if (retCode == ERROR_SUCCESS) { 360 #ifdef _DEBUG 361 cout << achKey << endl; 362 #endif 363 JavaVersion * nv = parseName(achKey); 364 365 bool isHome = checkJavaHome(key, sKey, achKey, nv); 366 #ifdef _DEBUG 367 cout << nv->home << " " << isHome << endl; 368 #endif 369 370 if (isHome) 371 if (result == NULL) { 372 result = nv; 373 #ifdef _DEBUG 374 cout << "NEW" << endl; 375 #endif 376 } else { 377 if (nv != NULL) { 378 if (*nv > *result) { 379 #ifdef _DEBUG 380 cout << "REPLACE" << endl; 381 #endif 382 delete result; 383 result = nv; 384 } else { 385 #ifdef _DEBUG 386 cout << "NO" << endl; 387 #endif 388 delete nv; 389 } 390 } 391 } 392 393 } 394 395 } 396 } 397 398 RegCloseKey(hKey); 399 400 } 401 402 return result; 403 } 404 // ***************************************************************************** 405 406 int fileExists (const std::string& path) { 407 WIN32_FIND_DATA ffd; 408 HANDLE hFind; 409 410 hFind = FindFirstFile (path.c_str(), &ffd); 411 if (hFind == INVALID_HANDLE_VALUE) 412 return FALSE; 413 414 FindClose (hFind); 415 return (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0; 416 } 417 418 int main(int argc, char** argv) { 419 char buf[MAX_PATH]; 420 GetModuleFileName (NULL, buf, MAX_PATH); 421 std::string javafxhome = buf; 422 javafxhome.erase (javafxhome.rfind ("\\")); 423 424 std::string fxlib = javafxhome + "\\..\\lib\\"; 425 426 const char *s = getenv ("JAVA_HOME"); 427 std::string javacmd; 428 std::string javahome; 429 if (s != NULL) { 430 javahome = s; 431 javacmd = javahome + "\\bin\\java.exe"; 432 std::string javaccmd = javahome + "\\bin\\javac.exe"; 433 if (! fileExists (javacmd.c_str ()) || ! fileExists (javaccmd.c_str ())) { 434 javacmd = ""; 435 javahome = ""; 436 } 437 } else 438 javacmd = ""; 439 440 if (javacmd.length() <= 0) { 441 //JavaVersion * jv = NULL;//GetMaxVersion(HKEY_LOCAL_MACHINE, "SOFTWARE\\JavaSoft\\Java Runtime Environment"); 442 JavaVersion * jv2 = GetMaxVersion(HKEY_LOCAL_MACHINE, "SOFTWARE\\JavaSoft\\Java Development Kit"); 443 if (jv2 != NULL) { 444 javacmd = jv2->path; 445 javahome = jv2->home; 446 } else 447 javacmd = "java.exe"; 448 } 449 450 std::string cmd = "\"" + javacmd + "\""; 451 if (javahome.length() > 0) { 452 // cmd += " \"-Djava.home=" + javahome + "\""; 453 SetEnvironmentVariable ("JAVA_HOME", javahome.c_str ()); 454 } 455 cmd += " -Xmx256M \"-Djavafx.home=" + javafxhome 456 + "\" -classpath \"" + fxlib + "ant-javafx.jar;" 457 + "\" com.sun.javafx.tools.packager.Main"; 458 459 for (int i = 1; i < argc; i ++) { 460 cmd = cmd + " \"" + argv[i] + "\""; 461 } 462 463 #ifdef _DEBUG 464 printf ("%s", cmd.c_str()); 465 #endif 466 467 STARTUPINFO start; 468 PROCESS_INFORMATION pi; 469 memset (&start, 0, sizeof (start)); 470 start.cb = sizeof (start); 471 472 if (! CreateProcess (NULL, (char *) cmd.c_str (), 473 NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS, NULL, NULL, &start, &pi)) { 474 #ifdef _DEBUG 475 fprintf (stderr, "CAnnot start java.exe"); 476 #endif 477 return EXIT_FAILURE; 478 } 479 480 WaitForSingleObject (pi.hProcess, INFINITE); 481 unsigned long exitCode; 482 GetExitCodeProcess (pi.hProcess, &exitCode); 483 484 CloseHandle (pi.hProcess); 485 CloseHandle (pi.hThread); 486 487 return exitCode; 488 }