blob: edbfa5543ace0be09d82a9b018d025d7f8b0d85f [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "FileUtils.h"
#include "StringUtils.h"
#include "SystemUtils.h"
#include "JavaUtils.h"
#include "RegistryUtils.h"
#include "ExtractUtils.h"
#include "Launcher.h"
#include "Main.h"
const DWORD STUB_FILL_SIZE = 450000;
void skipLauncherStub(LauncherProperties * props, DWORD stubSize) {
HANDLE hFileRead = props->handler;
if(hFileRead!=INVALID_HANDLE_VALUE) {
// just read stub data.. no need to write it anywhere
DWORD read = 0;
char * offsetbuf = newpChar(stubSize);
DWORD sizeLeft = stubSize;
while(ReadFile(hFileRead, offsetbuf, sizeLeft, &read, 0) && sizeLeft && read) {
sizeLeft-=read;
addProgressPosition(props, read);
if(sizeLeft==0) break;
if(read==0) { // we need some more bytes to read but we can`t to read
props->status = ERROR_INTEGRITY;
break;
}
}
FREE(offsetbuf);
}
}
void skipStub(LauncherProperties * props) {
if(props->isOnlyStub) {
WCHAR * os;
props->status = EXIT_CODE_STUB;
os = appendStringW(NULL, L"It`s only the launcher stub.\nOS: ");
if(is9x()) os = appendStringW(os, L"Windows 9x");
if(isNT()) os = appendStringW(os, L"Windows NT");
if(is2k()) os = appendStringW(os, L"Windows 2000");
if(isXP()) os = appendStringW(os, L"Windows XP");
if(is2003()) os = appendStringW(os, L"Windows 2003");
if(isVista()) os = appendStringW(os, L"Windows Vista");
if(is2008()) os = appendStringW(os, L"Windows 2008");
if(is7()) os = appendStringW(os, L"Windows 7");
if(IsWow64) os = appendStringW(os, L" x64");
showMessageW(props, os , 0);
FREE(os);
} else {
skipLauncherStub(props, STUB_FILL_SIZE);
if(!isOK(props)) {
writeMessageA(props, OUTPUT_LEVEL_NORMAL, 1,
"Error! Can`t process launcher stub", 1);
showErrorW(props, INTEGRITY_ERROR_PROP, 1, props->exeName);
}
}
}
void modifyRestBytes(SizedString* rest, DWORD start) {
DWORD len = rest->length - start;
char * restBytesNew = NULL;
if(len>0) {
DWORD i;
restBytesNew = newpChar(len);
for(i=start;i<rest->length;i++) {
restBytesNew[i-start] = (rest->bytes) [i];
}
}
FREE(rest->bytes);
rest->bytes = restBytesNew;
rest->length = len;
}
DWORD readStringFromBuf(SizedString *rest, SizedString * result, DWORD isUnicode) {
if((rest->length)!=0) {
// we have smth in the restBytes that we have read but haven`t yet proceeded
DWORD i=0;
for(i=0;i<rest->length;i++) {
DWORD check = ((rest->bytes)[i]==0);
if(isUnicode) {
if ( (i/2)*2==i) {// i is even
check = check && (i < rest->length-1 && ((rest->bytes)[i+1]==0));
} else {
check = 0;
}
}
if( check ) { // we have found null character in the rest bytes
result->bytes = appendStringN(NULL, 0, rest->bytes, i);
result->length = i;
modifyRestBytes(rest, i + 1 + isUnicode);
return ERROR_OK;
}
}
//here we have found no \0 character in the rest of bytes...
}
return ERROR_INPUTOUPUT;
}
void readString(LauncherProperties * props, SizedString * result, DWORD isUnicode) {
DWORD * status = & props->status;
HANDLE hFileRead = props->handler;
SizedString * rest = props->restOfBytes;
DWORD bufferSize = props->bufsize;
DWORD read=0;
char * buf = NULL;
if(*status != ERROR_OK ) return;
if(readStringFromBuf(rest, result, isUnicode)==ERROR_OK) {
return;
}
//we need to read file for more data to find \0 character...
buf = newpChar(bufferSize);
while (ReadFile(hFileRead, buf, bufferSize, &read, 0) && read) {
addProgressPosition(props, read);
rest->bytes = appendStringN(rest->bytes, rest->length, buf, read);
rest->length = rest->length + read;
if(readStringFromBuf(rest, result, isUnicode)==ERROR_OK) {
//if(result->bytes!=NULL) {
//we have find \0 character
break;
}
ZERO(buf, sizeof(char) * bufferSize);
if(read==0) { // we have nothing to read.. smth wrong
*status = ERROR_INTEGRITY;
break;
}
}
FREE(buf);
return;
}
void readNumber(LauncherProperties * props, DWORD * result) {
if(isOK(props)) {
SizedString * numberString = createSizedString();
DWORD i =0;
DWORD number = 0;
readString(props, numberString, 0);
if(!isOK(props)) {
freeSizedString(&numberString);
writeMessageA(props, OUTPUT_LEVEL_DEBUG, 1,
"Error!! Can`t read number string. Most probably integrity error.", 1);
return;
}
if(numberString->bytes==NULL) {
freeSizedString(&numberString);
writeMessageA(props, OUTPUT_LEVEL_DEBUG, 1,
"Error!! Can`t read number string (it can`t be NULL). Most probably integrity error.", 1);
props->status = ERROR_INTEGRITY;
return;
}
for(;i<numberString->length;i++) {
char c = numberString->bytes[i];
if(c>='0' && c<='9') {
number = number * 10 + (c - '0');
} else if(c==0) {
// we have reached the end of number section
writeMessageA(props, OUTPUT_LEVEL_DEBUG, 1,
"Can`t read number from string (it contains zero character):", 1);
writeMessageA(props, OUTPUT_LEVEL_DEBUG, 1, numberString->bytes, 1);
props->status = ERROR_INTEGRITY;
break;
} else {
// unexpected...
writeMessageA(props, OUTPUT_LEVEL_DEBUG, 1,
"Can`t read number from string (unexpected error):", 1);
writeMessageA(props, OUTPUT_LEVEL_DEBUG, 1, numberString->bytes, 1);
props->status = ERROR_INTEGRITY;
break;
}
}
freeSizedString(&numberString);
*result = number;
}
}
void readStringWithDebugW(LauncherProperties * props, WCHAR ** dest, char * paramName) {
SizedString *sizedStr = createSizedString();
if(paramName!=NULL) {
writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "Reading ", 0);
writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, paramName, 0);
writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, " : ", 0);
}
readString(props, sizedStr, 1);
if(!isOK(props)) {
freeSizedString(&sizedStr);
writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0,
"[ERROR] Can`t read string !! Seems to be integrity error", 1);
return;
}
*dest = createWCHAR(sizedStr);
freeSizedString(&sizedStr);
if(paramName!=NULL) {
if((*dest)!=NULL) {
writeMessageW(props, OUTPUT_LEVEL_DEBUG, 0, *dest, 1);
} else {
writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "NULL", 1);
}
}
return;
}
void readStringWithDebugA(LauncherProperties * props, char ** dest, char * paramName) {
SizedString *sizedStr = createSizedString();
if(paramName!=NULL) {
writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "Reading ", 0);
writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, paramName, 0);
writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, " : ", 0);
}
readString( props, sizedStr, 0);
if(!isOK(props)) {
freeSizedString(&sizedStr);
writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0,
"[ERROR] Can`t read string!!! Seems to be integritiy error", 1);
return;
}
*dest = appendString(NULL, sizedStr->bytes);
if(paramName!=NULL) {
if((*dest)==NULL) {
writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "NULL", 1);
} else {
writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, *dest, 1);
}
}
freeSizedString(&sizedStr);
return;
}
void readNumberWithDebug(LauncherProperties * props, DWORD * dest, char * paramName) {
writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "Reading ", 0);
writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, paramName, 0);
writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, " : ", 0);
readNumber(props, dest);
if(!isOK(props)) {
writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0,
"[ERROR] Can`t read number !!! Seems to be integrity error", 1);
return;
}
writeDWORD(props, OUTPUT_LEVEL_DEBUG, 0, NULL, *dest, 1);
return;
}
void readBigNumberWithDebug(LauncherProperties * props, int64t * dest, char * paramName) {
DWORD low = 0;
DWORD high = 0;
writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "Reading ", 0);
writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, paramName, 0);
writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, " : ", 0);
readNumber(props, &low);
if(isOK(props)) {
readNumber(props, &high);
}
if(!isOK(props)) {
writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0,
"[ERROR] Can`t read number !!! Seems to be integrity error", 1);
return;
}
dest->High = high;
dest->Low = low;
writeint64t(props, OUTPUT_LEVEL_DEBUG, 0, "", dest, 1);
}
// returns: ERROR_OK, ERROR_INPUTOUPUT, ERROR_INTEGRITY
void extractDataToFile(LauncherProperties * props, WCHAR *output, int64t * fileSize, DWORD expectedCRC ) {
if(isOK(props)) {
DWORD * status = & props->status;
HANDLE hFileRead = props->handler;
int64t * size = fileSize;
DWORD counter = 0;
DWORD crc32 = -1L;
HANDLE hFileWrite = CreateFileW(output, GENERIC_READ | GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, hFileRead);
if (hFileWrite == INVALID_HANDLE_VALUE) {
WCHAR * err;
writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "[ERROR] Can`t create file ", 0);
writeMessageW(props, OUTPUT_LEVEL_DEBUG, 0, output, 1);
err = getErrorDescription(GetLastError());
writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "Error description : ", 0);
writeMessageW(props, OUTPUT_LEVEL_DEBUG, 0, err, 1);
showErrorW(props, OUTPUT_ERROR_PROP, 2, output, err);
FREE(err);
*status = ERROR_INPUTOUPUT;
return;
}
if(props->restOfBytes->length!=0 && props->restOfBytes->bytes!=NULL) {
//check if the data stored in restBytes is more than we neen
// rest bytes contains much less than int64t so we operate here only bith low bits of size
DWORD restBytesToWrite = (compare(size, props->restOfBytes->length)> 0 ) ? props->restOfBytes->length : size->Low;
DWORD usedBytes = restBytesToWrite;
char *ptr = props->restOfBytes->bytes;
DWORD write = 0;
while (restBytesToWrite >0) {
WriteFile(hFileWrite, ptr, restBytesToWrite, &write, 0);
update_crc32(&crc32, ptr, write);
restBytesToWrite -= write;
ptr +=write;
}
modifyRestBytes(props->restOfBytes, usedBytes);
minus(size, usedBytes);
}
if(compare(size, 0) > 0 ) {
DWORD bufferSize = props->bufsize;
char * buf = newpChar(bufferSize);
DWORD bufsize = (compare(size, bufferSize) > 0) ? bufferSize : size->Low;
DWORD read = 0 ;
// printf("Using buffer size: %u/%u\n", bufsize, bufferSize);
while (ReadFile(hFileRead, buf, bufsize, &read, 0) && read && compare(size, 0) > 0) {
addProgressPosition(props, read);
WriteFile(hFileWrite, buf, read, &read, 0);
update_crc32(&crc32, buf, read);
minus(size, read);
if((compare(size, bufsize)<0) && (compare(size, 0)>0) ) {
bufsize = size->Low;
}
ZERO(buf, sizeof(char) * bufferSize);
if(compare(size, 0)==0) {
break;
}
if((counter ++) % 20 == 0) {
if(isTerminated(props)) break;
}
}
if((compare(size, 0)>0 || read==0) && !isTerminated(props)) {
// we could not read requested size
* status = ERROR_INTEGRITY;
writeMessageA(props, OUTPUT_LEVEL_DEBUG, 1,
"Can`t read data from file : not enought data", 1);
}
FREE(buf);
}
CloseHandle(hFileWrite);
crc32=~crc32;
if(isOK(props) && crc32!=expectedCRC) {
writeDWORD(props, OUTPUT_LEVEL_DEBUG, 0, "expected CRC : ", expectedCRC, 1);
writeDWORD(props, OUTPUT_LEVEL_DEBUG, 0, "real CRC : ", crc32, 1);
* status = ERROR_INTEGRITY;
}
}
}
//returns : ERROR_OK, ERROR_INTEGRITY, ERROR_FREE_SPACE
void extractFileToDir(LauncherProperties * props, WCHAR ** resultFile) {
WCHAR * fileName = NULL;
int64t * fileLength = NULL;
DWORD crc = 0;
writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "Extracting file ...", 1);
readStringWithDebugW( props, & fileName, "file name");
fileLength = newint64_t(0, 0);
readBigNumberWithDebug( props, fileLength, "file length ");
readNumberWithDebug( props, &crc, "CRC32");
if(!isOK(props)) return;
if(fileName!=NULL) {
DWORD i=0;
WCHAR * dir;
resolveString(props, &fileName);
for(i=0;i<getLengthW(fileName);i++) {
if(fileName[i]==L'/') {
fileName[i]=L'\\';
}
}
dir = getParentDirectory(fileName);
writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, " ... extract to directory = ", 0);
writeMessageW(props, OUTPUT_LEVEL_DEBUG, 0, dir, 1);
checkFreeSpace(props, dir, fileLength);
FREE(dir);
if(isOK(props)) {
writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, " ... starting data extraction", 1);
writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, " ... output file is ", 0);
writeMessageW(props, OUTPUT_LEVEL_DEBUG, 0, fileName, 1);
extractDataToFile(props, fileName, fileLength, crc);
writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, " ... extraction finished", 1);
*resultFile = fileName;
} else {
writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, " ... data extraction canceled", 1);
}
} else {
writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "Error! File name can`t be null. Seems to be integrity error!", 1);
*resultFile = NULL;
props -> status = ERROR_INTEGRITY;
}
FREE(fileLength);
return;
}
void loadI18NStrings(LauncherProperties * props) {
DWORD i=0;
DWORD j=0;
//read number of locales
DWORD numberOfLocales = 0;
DWORD numberOfProperties = 0;
readNumberWithDebug(props, &numberOfLocales, "number of locales");
if(!isOK(props)) return;
if(numberOfLocales==0) {
props->status = ERROR_INTEGRITY;
return ;
}
readNumberWithDebug( props, &numberOfProperties, "i18n properties");
if(!isOK(props)) return;
if(numberOfProperties==0) {
props->status = ERROR_INTEGRITY;
return ;
}
props->i18nMessages = (I18NStrings * ) LocalAlloc(LPTR, sizeof(I18NStrings) * numberOfProperties);
props->I18N_PROPERTIES_NUMBER = numberOfProperties;
props->i18nMessages->properties = newppChar(props->I18N_PROPERTIES_NUMBER);
props->i18nMessages->strings = newppWCHAR(props->I18N_PROPERTIES_NUMBER);
for(i=0; isOK(props) && i<numberOfProperties;i++) {
// read property name as ASCII
char * propName = NULL;
char * number = DWORDtoCHARN(i,2);
props->i18nMessages->properties[i] = NULL;
props->i18nMessages->strings[i] = NULL;
propName = appendString(NULL, "property name ");
propName = appendString(propName, number);
FREE(number);
readStringWithDebugA(props, & (props->i18nMessages->properties[i]), propName);
FREE(propName);
}
if(isOK(props)) {
DWORD isLocaleMatches;
WCHAR * localeName;
WCHAR * currentLocale = getLocaleName();
writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "Current System Locale : ", 0);
writeMessageW(props, OUTPUT_LEVEL_DEBUG, 0, currentLocale, 1);
if(props->userDefinedLocale!=NULL) { // using user-defined locale via command-line parameter
writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "[CMD Argument] Try to use locale ", 0);
writeMessageW(props, OUTPUT_LEVEL_NORMAL, 0, props->userDefinedLocale, 1);
FREE(currentLocale);
currentLocale = appendStringW(NULL, props->userDefinedLocale);
}
for(j=0;j<numberOfLocales;j++) { // for all locales in file...
// read locale name as UNICODE ..
// it should be like en_US or smth like that
localeName = NULL;
readStringWithDebugW(props, &localeName, "locale name");
if(!isOK(props)) break;
isLocaleMatches = (localeName==NULL) ? 1 :
searchW(currentLocale, localeName) != NULL;
//read properties names and value
for(i=0;i<numberOfProperties;i++) {
// read property value as UNICODE
WCHAR * value = NULL;
char * s1 = DWORDtoCHAR(i + 1);
char * s2 = DWORDtoCHAR(numberOfProperties);
char * s3 = appendString(NULL , "value ");
s3 = appendString(s3 , s1);
s3 = appendString(s3, "/");
s3 = appendString(s3, s2);
FREE(s1);
FREE(s2);
readStringWithDebugW(props, &value, s3);
FREE(s3);
if(!isOK(props)) break;
if(isLocaleMatches) {
//it is a know property
FREE(props->i18nMessages->strings[i]);
props->i18nMessages->strings[i] = appendStringW(NULL, value);
}
FREE(value);
}
FREE(localeName);
}
FREE(currentLocale);
}
}
LauncherResource * newLauncherResource() {
LauncherResource * file = (LauncherResource *) LocalAlloc(LPTR, sizeof(LauncherResource));
file->path=NULL;
file->resolved=NULL;
file->type=0;
return file;
}
WCHARList * newWCHARList(DWORD number) {
WCHARList * list = (WCHARList*) LocalAlloc(LPTR, sizeof(WCHARList));
list->size = number;
if(number>0) {
DWORD i=0;
list->items = newppWCHAR(number);
for(i=0;i<number;i++) {
list->items[i] = NULL;
}
} else {
list->items = NULL;
}
return list;
}
void freeWCHARList(WCHARList ** plist) {
WCHARList * list;
list = * plist;
if(list!=NULL) {
DWORD i=0;
if(list->items!=NULL) {
for(i=0;i<list->size;i++) {
FREE(list->items[i]);
}
FREE(list->items);
}
FREE(*plist);
}
}
LauncherResourceList * newLauncherResourceList(DWORD number) {
LauncherResourceList * list = (LauncherResourceList*) LocalAlloc(LPTR, sizeof(LauncherResourceList));
list->size = number;
if(number > 0) {
DWORD i=0;
list->items = (LauncherResource**) LocalAlloc(LPTR, sizeof(LauncherResource*) * number);
for(i=0;i<number;i++) {
list->items[i] = NULL;
}
} else {
list->items = NULL;
}
return list;
}
void freeLauncherResource(LauncherResource ** file) {
if(*file!=NULL) {
FREE((*file)->path);
FREE((*file)->resolved);
FREE(*file);
}
}
void extractLauncherResource(LauncherProperties * props, LauncherResource ** file, char * name) {
char * typeStr = appendString(appendString(NULL, name), " type");
* file = newLauncherResource();
readNumberWithDebug( props, & ((*file)->type) , typeStr);
if(isOK(props)) {
FREE(typeStr);
if((*file)->type==0) { //bundled
writeMessageA(props, OUTPUT_LEVEL_DEBUG, 1, "... file is bundled", 1);
extractFileToDir(props, & ((*file)->path));
if(!isOK(props)) {
writeMessageA(props, OUTPUT_LEVEL_DEBUG, 1, "Error extracting file!", 1);
return;
} else {
(*file)->resolved = appendStringW(NULL, (*file)->path);
writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "file was succesfully extracted to ", 0);
writeMessageW(props, OUTPUT_LEVEL_DEBUG, 0, (*file)->path, 1);
}
} else {
writeMessageA(props, OUTPUT_LEVEL_DEBUG, 1, "... file is external", 1);
readStringWithDebugW(props, & ((*file)->path), name);
if(!isOK(props)) {
writeMessageA(props, OUTPUT_LEVEL_DEBUG, 1, "Error reading ", 1);
writeMessageA(props, OUTPUT_LEVEL_DEBUG, 1, name, 1);
}
}
} else {
writeMessageA(props, OUTPUT_LEVEL_DEBUG, 1, "Error reading ", 0);
writeMessageA(props, OUTPUT_LEVEL_DEBUG, 1, typeStr, 0);
FREE(typeStr);
}
}
void readWCHARList(LauncherProperties * props, WCHARList ** list, char * name) {
DWORD number = 0;
DWORD i =0;
char * numberStr = appendString(appendString(NULL, "number of "), name);
* list = NULL;
readNumberWithDebug(props, &number, numberStr);
FREE(numberStr);
if(!isOK(props)) return;
* list = newWCHARList(number);
for(i=0;i < (*list)->size ;i++) {
char * nextStr = appendString(appendString(NULL, "next item in "), name);
readStringWithDebugW(props, &((*list)->items[i]), nextStr);
FREE(nextStr);
if(!isOK(props)) return;
}
}
void readLauncherResourceList(LauncherProperties * props, LauncherResourceList ** list, char * name) {
DWORD num = 0;
DWORD i=0;
char * numberStr = appendString(appendString(NULL, "number of "), name);
readNumberWithDebug(props, &num, numberStr);
FREE(numberStr);
if(!isOK(props)) return;
* list = newLauncherResourceList(num);
for(i=0;i<(*list)->size;i++) {
extractLauncherResource(props, & ((*list)->items[i]), "launcher resource");
if(!isOK(props)) {
char * str = appendString(appendString(NULL, "Error processing "), name);
writeMessageA(props, OUTPUT_LEVEL_DEBUG, 1, str, 1);
FREE(str);
break;
}
}
}
void readLauncherProperties(LauncherProperties * props) {
DWORD i=0;
char * str = NULL;
readWCHARList(props, &(props->jvmArguments), "jvm arguments");
if(!isOK(props)) return;
readWCHARList(props, &(props->appArguments), "app arguments");
if(!isOK(props)) return;
readStringWithDebugW(props, &(props->mainClass), "Main Class");
if(!isOK(props)) return;
readStringWithDebugW(props, &(props->testJVMClass), "TestJVM Class");
if(!isOK(props)) return;
readNumberWithDebug( props, &(props->compatibleJavaNumber),
"compatible java");
if(!isOK(props)) return;
if ( props->compatibleJavaNumber > 0 ) {
props->compatibleJava = (JavaCompatible **) LocalAlloc(LPTR, sizeof(JavaCompatible *) * props->compatibleJavaNumber);
for(i=0;i<props->compatibleJavaNumber;i++) {
props->compatibleJava [i] = newJavaCompatible() ;
readStringWithDebugA(props, &str, "min java version");
if(!isOK(props)) return;
props->compatibleJava[i]->minVersion = getJavaVersionFromString(str, &props->status);
FREE(str);
if(!isOK(props)) return;
str = NULL;
readStringWithDebugA(props, &str, "max java version");
if(!isOK(props)) return;
props->compatibleJava[i]->maxVersion = getJavaVersionFromString(str, &props->status);
FREE(str);
if(!isOK(props)) return;
readStringWithDebugA(props, &(props->compatibleJava[i]->vendor) ,
"vendor");
if(!isOK(props)) return;
readStringWithDebugA(props, &(props->compatibleJava[i]->osName) ,
"os name");
if(!isOK(props)) return;
readStringWithDebugA(props, &(props->compatibleJava[i]->osArch) ,
"os arch");
if(!isOK(props)) return;
}
}
readNumberWithDebug( props, &props->bundledNumber, "bundled files");
readBigNumberWithDebug(props, props->bundledSize, "bundled size");
}
void extractJVMData(LauncherProperties * props) {
if(isOK(props)) {
writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "Extracting JVM data... ", 1);
extractLauncherResource(props, &(props->testJVMFile), "testJVM file");
if(!isOK(props)) {
writeMessageA(props, OUTPUT_LEVEL_DEBUG, 1, "Error extracting testJVM file!", 1);
return ;
}
readLauncherResourceList(props, &(props->jvms), "JVMs");
}
}
void extractData(LauncherProperties *props) {
if(isOK(props)) {
writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "Extracting Bundled data... ", 1);
readLauncherResourceList(props, &(props->jars), "bundled and external files");
if(isOK(props)) {
readLauncherResourceList(props, &(props->other), "other data");
}
}
}