//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 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 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 printJavaProperties(LauncherProperties * props, JavaProperties * javaProps) { if(javaProps!=NULL) { char * jv = getJavaVersionFormatted(javaProps); writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "Current Java:", 1); writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, " javaHome: ", 0); writeMessageW(props, OUTPUT_LEVEL_NORMAL, 0, javaProps->javaHome, 1); writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, " javaExe: ", 0); writeMessageW(props, OUTPUT_LEVEL_NORMAL, 0, javaProps->javaExe, 1); writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, " version: ", 0); writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, jv, 1); writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, " vendor: ", 0); writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, javaProps->vendor, 1); writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, " os.name: ", 0); writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, javaProps->osName, 1); writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, " os.arch: ", 0); writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, javaProps->osArch, 1); FREE(jv); } }
void unpackJars(LauncherProperties * props, WCHAR * jvmDir, WCHAR * startDir, WCHAR * unpack200exe) { DWORD attrs; DWORD dwError; DWORD count = 0 ; if(!isOK(props)) return; attrs = GetFileAttributesW(startDir); if(attrs==INVALID_FILE_ATTRIBUTES) { writeErrorA(props, OUTPUT_LEVEL_DEBUG, 1, "Error! Can`t get attributes of the file : ", startDir, GetLastError()); return; } if(attrs & FILE_ATTRIBUTE_DIRECTORY) { // is directory WIN32_FIND_DATAW FindFileData; HANDLE hFind = INVALID_HANDLE_VALUE; WCHAR * DirSpec = appendStringW(appendStringW(NULL, startDir), L"\\*" ); // Find the first file in the directory. hFind = FindFirstFileW(DirSpec, &FindFileData); if (hFind == INVALID_HANDLE_VALUE) { writeErrorA(props, OUTPUT_LEVEL_DEBUG, 1, "Error! Can`t file with pattern ", DirSpec, GetLastError()); } else { // List all the other files in the directory. writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "... listing directory ", 0); writeMessageW(props, OUTPUT_LEVEL_DEBUG, 0, startDir, 1); while (FindNextFileW(hFind, &FindFileData) != 0 && isOK(props)) { if(lstrcmpW(FindFileData.cFileName, L".")!=0 && lstrcmpW(FindFileData.cFileName, L"..")!=0) { WCHAR * child = NULL; child = appendStringW(appendStringW(appendStringW(NULL, startDir), FILE_SEP), FindFileData.cFileName); if(isDirectory(child)) { writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "... directory : ", 0); writeMessageW(props, OUTPUT_LEVEL_DEBUG, 0, child, 1); unpackJars(props, jvmDir, child, unpack200exe); } else if(searchW(FindFileData.cFileName, JAR_PACK_GZ_SUFFIX)!=NULL) { WCHAR * jarName = appendStringW(appendStringW( appendStringW(NULL, startDir), FILE_SEP), appendStringNW(NULL, 0, FindFileData.cFileName, getLengthW(FindFileData.cFileName) - getLengthW(PACK_GZ_SUFFIX))); WCHAR * unpackCommand = NULL; writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "... packed jar : ", 0); writeMessageW(props, OUTPUT_LEVEL_DEBUG, 0, child, 1); writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "... jar name : ", 0); writeMessageW(props, OUTPUT_LEVEL_DEBUG, 0, jarName, 1); appendCommandLineArgument(&unpackCommand, unpack200exe); appendCommandLineArgument(&unpackCommand, child); appendCommandLineArgument(&unpackCommand, jarName); executeCommand(props, unpackCommand, NULL, UNPACK200_EXTRACTION_TIMEOUT, props->stdoutHandle, props->stderrHandle, NORMAL_PRIORITY_CLASS); FREE(unpackCommand); if(!isOK(props)) { if(props->status==ERROR_PROCESS_TIMEOUT) { writeMessageA(props, OUTPUT_LEVEL_DEBUG, 1, "... could not unpack file : timeout", 1); } else { writeMessageA(props, OUTPUT_LEVEL_DEBUG, 1, "... an error occured unpacking the file", 1); } props->exitCode = props->status; } FREE(jarName); } FREE(child); } } dwError = GetLastError(); FindClose(hFind); if (dwError != ERROR_NO_MORE_FILES) { writeErrorA(props, OUTPUT_LEVEL_DEBUG, 1, "Error! Can`t find file with pattern : ", DirSpec, dwError); } } FREE(DirSpec); } }
void searchCurrentJavaRegistry(LauncherProperties * props, BOOL access64key) { DWORD i=0; WCHAR ** keys = JAVA_REGISTRY_KEYS; DWORD k=0; WCHAR * buffer = newpWCHAR(MAX_LEN_VALUE_NAME); HKEY rootKeys [2] = {HKEY_LOCAL_MACHINE, HKEY_CURRENT_USER}; DWORD rootKeysNumber = sizeof(rootKeys)/sizeof(HKEY); DWORD keysNumber = sizeof(JAVA_REGISTRY_KEYS)/sizeof(WCHAR*); DWORD status = ERROR_OK; writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "Search java in CurrentVersion values...", 1); for ( k = 0; k < rootKeysNumber; k++) { for(i=0; i < keysNumber;i++) { if(isTerminated(props)) { return; } else { WCHAR * value = getStringValue(rootKeys[k], keys[i], CURRENT_VERSION, access64key); if(value!=NULL) { WCHAR *javaHome = getStringValuePC(rootKeys[k], keys[i], value, JAVA_HOME, access64key); writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "... ", 0); writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, (rootKeys[k]==HKEY_LOCAL_MACHINE) ? "HKEY_LOCAL_MACHINE" : "HKEY_CURRENT_USER", 0); writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "\\", 0); writeMessageW(props, OUTPUT_LEVEL_NORMAL, 0, keys[i], 0); writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "\\", 0); writeMessageW(props, OUTPUT_LEVEL_NORMAL, 0, CURRENT_VERSION, 0); writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "->", 0); writeMessageW(props, OUTPUT_LEVEL_NORMAL, 0, value, 0); writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "[", 0); writeMessageW(props, OUTPUT_LEVEL_NORMAL, 0, JAVA_HOME, 0); writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "] = ", 0); writeMessageW(props, OUTPUT_LEVEL_NORMAL, 0, javaHome, 1); FREE(value); trySetCompatibleJava(javaHome, props); FREE(javaHome); if(props->java!=NULL) { FREE(buffer); return; } } } } } // we found no CurrentVersion java... just search for other possible keys writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "Search java in other values...", 1); for(k=0;k<rootKeysNumber;k++) { for(i=0;i<keysNumber;i++) { HKEY hkey = 0; DWORD index = 0 ; if (RegOpenKeyExW(rootKeys[k], keys[i], 0, KEY_READ | ((access64key && IsWow64) ? KEY_WOW64_64KEY : 0), &hkey) == ERROR_SUCCESS) { DWORD number = 0; if (RegQueryInfoKeyW(hkey, NULL, NULL, NULL, &number, NULL, NULL, NULL, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) { DWORD err = 0; do { DWORD size = MAX_LEN_VALUE_NAME; buffer[0] = 0; err = RegEnumKeyExW(hkey, index, buffer, &size, NULL, NULL, NULL, NULL); if (err == ERROR_SUCCESS) { WCHAR * javaHome = getJavaHomeValue(keys[i], buffer, access64key); status = ERROR_OK; writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, (rootKeys[k]==HKEY_LOCAL_MACHINE) ? "HKEY_LOCAL_MACHINE" : "HKEY_CURRENT_USER", 0); writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "\\", 0); writeMessageW(props, OUTPUT_LEVEL_NORMAL, 0, keys[i], 0); writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "\\", 0); writeMessageW(props, OUTPUT_LEVEL_NORMAL, 0, buffer, 0); writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "[", 0); writeMessageW(props, OUTPUT_LEVEL_NORMAL, 0, JAVA_HOME, 0); writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "] = ", 0); writeMessageW(props, OUTPUT_LEVEL_NORMAL, 0, javaHome, 1); trySetCompatibleJava(javaHome, props); FREE(javaHome); if(props->java!=NULL) { i = keysNumber; // to the end of cycles k = rootKeysNumber; break; } } index++; } while (err == ERROR_SUCCESS); } } if (hkey != 0) { RegCloseKey(hkey); } } } FREE(buffer); return; }
DWORD getJavaPropertiesFromOutput(LauncherProperties * props, char *str, JavaProperties ** javaProps) { DWORD separators = getLineSeparatorNumber(str); DWORD result = ERROR_INPUTOUPUT; * javaProps = NULL; if(separators == TEST_JAVA_PARAMETERS) { char * start; char * end; char * javaVersion; char * javaVmVersion; char * javaVendor; char * osName; char * osArch; char * string; JavaVersion * vers; start = str; end = searchA(start, "\n"); javaVersion = appendStringN(NULL, 0, start, getLengthA(start) - getLengthA(end)-1); writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, " java.version = ", 0); writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, javaVersion, 1); start = end + 1; end = searchA(start, "\n"); javaVmVersion = appendStringN(NULL, 0, start, getLengthA(start) - getLengthA(end)-1); writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, " java.vm.version = ", 0); writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, javaVmVersion, 1); start = end + 1; end = searchA(start, "\n"); javaVendor = appendStringN(NULL, 0, start, getLengthA(start) - getLengthA(end)-1); writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, " java.vendor = ", 0); writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, javaVendor, 1); start = end + 1; end = searchA(start, "\n"); osName = appendStringN(NULL, 0, start, getLengthA(start) - getLengthA(end)-1); writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, " os.name = ", 0); writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, osName, 1); start = end + 1; end = searchA(start, "\n"); osArch = appendStringN(NULL, 0, start, getLengthA(start) - getLengthA(end)-1); writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, " os.arch = ", 0); writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, osArch, 2); string = javaVersion; if(javaVmVersion!=NULL) { string = searchA(javaVmVersion, javaVersion); if(string==NULL) { string = javaVersion; } } writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "... getting java version from string : ", 0); writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, string, 1); vers = getJavaVersionFromString(string, & result); if(javaProps != NULL) { writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "... some java there", 1); * javaProps = (JavaProperties *) LocalAlloc(LPTR, sizeof(JavaProperties)); (*javaProps)->version = vers; (*javaProps)->vendor = javaVendor; (*javaProps)->osName = osName; (*javaProps)->osArch = osArch; (*javaProps)->javaHome = NULL; (*javaProps)->javaExe = NULL; } else { writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "... no java there", 1); FREE(javaVendor); FREE(osName); FREE(osArch); } FREE(javaVmVersion); FREE(javaVersion); } return result; }
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); } }
// 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; } } }