blob: cf0423bb90942a3074a6a4c188a60c2a51fd8737 [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 <wchar.h>
#include <windows.h>
#include <winnls.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "StringUtils.h"
const char * JVM_NOT_FOUND_PROP = "nlw.jvm.notfoundmessage";
const char * JVM_USER_DEFINED_ERROR_PROP = "nlw.jvm.usererror";
const char * JVM_UNSUPPORTED_VERSION_PROP = "nlw.jvm.unsupportedversion";
const char * NOT_ENOUGH_FREE_SPACE_PROP = "nlw.freespace";
const char * CANT_CREATE_TEMP_DIR_PROP = "nlw.tmpdir";
const char * INTEGRITY_ERROR_PROP = "nlw.integrity";
const char * OUTPUT_ERROR_PROP = "nlw.output.error";
const char * JAVA_PROCESS_ERROR_PROP = "nlw.java.process.error";
const char * EXTERNAL_RESOURE_LACK_PROP = "nlw.missing.external.resource";
const char * BUNDLED_JVM_EXTRACT_ERROR_PROP = "nlw.bundled.jvm.extract.error";
const char * BUNDLED_JVM_VERIFY_ERROR_PROP = "nlw.bundled.jvm.verify.error";
const char * ARG_OUTPUT_PROPERTY = "nlw.arg.output";
const char * ARG_JAVA_PROP = "nlw.arg.javahome";
const char * ARG_DEBUG_PROP = "nlw.arg.verbose";
const char * ARG_TMP_PROP = "nlw.arg.tempdir";
const char * ARG_CPA_PROP = "nlw.arg.classpatha";
const char * ARG_CPP_PROP = "nlw.arg.classpathp";
const char * ARG_EXTRACT_PROP = "nlw.arg.extract";
const char * ARG_DISABLE_SPACE_CHECK = "nlw.arg.disable.space.check";
const char * ARG_LOCALE_PROP = "nlw.arg.locale";
const char * ARG_SILENT_PROP = "nlw.arg.silent";
const char * ARG_HELP_PROP = "nlw.arg.help";
const char * MSG_CREATE_TMPDIR = "nlw.msg.create.tmpdir";
const char * MSG_EXTRACT_DATA = "nlw.msg.extract";
const char * MSG_JVM_SEARCH = "nlw.msg.jvmsearch";
const char * MSG_SET_OPTIONS = "nlw.msg.setoptions";
const char * MSG_RUNNING = "nlw.msg.running";
const char * MSG_TITLE = "nlw.msg.title";
const char * MSG_MESSAGEBOX_TITLE = "nlw.msg.messagebox.title";
const char * MSG_PROGRESS_TITLE = "nlw.msg.progress.title";
const char * EXIT_BUTTON_PROP = "nlw.msg.button.error" ;
const char * MAIN_WINDOW_TITLE = "nlw.msg.main.title" ;
//adds string the the initial string and modifies totalWCHARs and capacity
// initial - the beginning of the string
// size - pointer to the value that contains the length of the initial string
// It is modified to store returning string length
// addString - additional string
//
void freeI18NMessages(LauncherProperties * props) {
if(props->i18nMessages!=NULL) {
DWORD i=0;
for(i=0;i<props->I18N_PROPERTIES_NUMBER;i++) {
FREE(props->i18nMessages->properties[i]);
FREE(props->i18nMessages->strings[i]);
}
FREE(props->i18nMessages->properties);
FREE(props->i18nMessages->strings);
FREE(props->i18nMessages);
}
}
char * searchA(const char * wcs1, const char * wcs2) {
char *cp = (char *) wcs1;
char *s1, *s2;
if ( !*wcs2) {
return (char *)wcs1;
}
while (*cp) {
s1 = cp;
s2 = (char *) wcs2;
while ( *s1 && *s2 && !(*s1-*s2) ) {
s1++, s2++;
}
if (!*s2) {
return(cp);
}
cp++;
}
return(NULL);
}
WCHAR * searchW(const WCHAR * wcs1, const WCHAR * wcs2) {
WCHAR *cp = (WCHAR *) wcs1;
WCHAR *s1, *s2;
if ( !*wcs2) {
return (WCHAR *)wcs1;
}
while (*cp) {
s1 = cp;
s2 = (WCHAR *) wcs2;
while ( *s1 && *s2 && !(*s1-*s2) ) {
s1++, s2++;
}
if (!*s2) {
return(cp);
}
cp++;
}
return(NULL);
}
void getI18nPropertyTitleDetail(LauncherProperties * props, const char * name, WCHAR ** title, WCHAR ** detail) {
const WCHAR * prop = getI18nProperty(props,name);
WCHAR * detailStringSep = searchW(prop, L"\n");
if(detailStringSep == NULL) {
*title = appendStringW(NULL, prop);
*detail = NULL;
} else {
DWORD dif = getLengthW(prop) - getLengthW(detailStringSep);
*title = appendStringNW(NULL, 0, prop, dif);
*detail = appendStringW(NULL, prop + (dif + 1));
}
}
const WCHAR * getI18nProperty(LauncherProperties * props, const char * name) {
if(name==NULL) return NULL;
if(name!=NULL && props->i18nMessages!=NULL) {
DWORD i;
for(i=0;i<props->I18N_PROPERTIES_NUMBER;i++) {
char * pr = props->i18nMessages->properties[i];
if(pr!=NULL) { // hope so it`s true
if(lstrcmpA(name, pr)==0) {
return props->i18nMessages->strings[i];
}
}
}
}
return getDefaultString(name);
}
WCHAR * getDefaultString(const char *name) {
if(lstrcmpA(name, JVM_NOT_FOUND_PROP)==0) {
return L"Can`t find suitable JVM. Specify it with %s argument";
} else if(lstrcmpA(name, NOT_ENOUGH_FREE_SPACE_PROP)==0) {
return L"Not enought free space at %s";
} else if(lstrcmpA(name, CANT_CREATE_TEMP_DIR_PROP)==0) {
return L"Can`t create temp directory %s";
} else if(lstrcmpA(name, INTEGRITY_ERROR_PROP)==0) {
return L"Integrity error. File %s is corrupted";
} else if(lstrcmpA(name, JVM_USER_DEFINED_ERROR_PROP)==0) {
return L"Can`t find JVM at %s";
} else if(lstrcmpA(name, JVM_UNSUPPORTED_VERSION_PROP)==0) {
return L"Unsupported JVM at %s";
} else if(lstrcmpA(name, OUTPUT_ERROR_PROP)==0) {
return L"Can`t create file %s.\nError: %s";
} else if(lstrcmpA(name, JAVA_PROCESS_ERROR_PROP)==0) {
return L"Java error:\n%s";
} else if(lstrcmpA(name, ARG_JAVA_PROP)==0) {
return L"%s Using specified JVM";
} else if(lstrcmpA(name, ARG_OUTPUT_PROPERTY)==0) {
return L"%s Output all stdout/stderr to the file";
} else if(lstrcmpA(name, ARG_DEBUG_PROP)==0) {
return L"%s Use verbose output";
} else if(lstrcmpA(name, ARG_TMP_PROP)==0) {
return L"%s Use specified temporary dir for extracting data";
} else if(lstrcmpA(name, ARG_CPA_PROP)==0) {
return L"%s Append classpath";
} else if(lstrcmpA(name, ARG_CPP_PROP)==0) {
return L"%s Prepend classpath";
} else if(lstrcmpA(name, ARG_EXTRACT_PROP)==0) {
return L"%s Extract all data";
} else if(lstrcmpA(name, ARG_HELP_PROP)==0) {
return L"%s Using this help";
} else if(lstrcmpA(name, ARG_DISABLE_SPACE_CHECK)==0) {
return L"%s Disable free space check";
} else if(lstrcmpA(name, ARG_LOCALE_PROP )==0) {
return L"%s Use specified locale for messagess";
} else if(lstrcmpA(name, ARG_SILENT_PROP )==0) {
return L"%s Run silently";
} else if(lstrcmpA(name, MSG_CREATE_TMPDIR)==0) {
return L"Creating tmp directory...";
} else if(lstrcmpA(name, MSG_EXTRACT_DATA)==0) {
return L"Extracting data...";
} else if(lstrcmpA(name, MSG_JVM_SEARCH)==0) {
return L"Finding JVM...";
} else if(lstrcmpA(name, MSG_RUNNING)==0) {
return L"Running JVM...";
} else if(lstrcmpA(name, MSG_SET_OPTIONS)==0) {
return L"Setting command options...";
} else if(lstrcmpA(name, MSG_MESSAGEBOX_TITLE)==0) {
return L"Message";
} else if(lstrcmpA(name, MSG_PROGRESS_TITLE)==0) {
return L"Running";
} else if(lstrcmpA(name, EXIT_BUTTON_PROP)==0) {
return L"Exit";
} else if(lstrcmpA(name, MAIN_WINDOW_TITLE)==0) {
return L"NBI Launcher";
} else if(lstrcmpA(name, EXTERNAL_RESOURE_LACK_PROP)==0) {
return L"Can`t run launcher\nThe following file is missing : %s";
} else if(lstrcmpA(name, BUNDLED_JVM_EXTRACT_ERROR_PROP)==0) {
return L"Can`t run prepare bundled JVM";
} else if(lstrcmpA(name, BUNDLED_JVM_VERIFY_ERROR_PROP)==0) {
return L"Can`t run verify bundled JVM";
}
return NULL;
}
DWORD getLengthA(const char * message) {
return (message!=NULL) ? lstrlenA(message) : 0;
}
DWORD getLengthW(const WCHAR * message) {
return (message!=NULL) ? lstrlenW(message) : 0;
}
//adds string the the initial string
char * appendStringN(char * initial, DWORD initialLength, const char * addString, DWORD addStringLength) {
DWORD length = initialLength + addStringLength + 1;
if (length > 1) {
char * tmp = newpChar(length+1);
DWORD i=0;
if(initialLength!=0) {
for(i=0;i<initialLength;i++) {
tmp[i]=initial[i];
}
FREE(initial);
}
for(i=0;i<addStringLength;i++) {
tmp[i+initialLength] = addString[i];
}
return tmp;
} else {
return NULL;
}
}
char * appendString(char * initial, const char * addString) {
return appendStringN(initial, getLengthA(initial), addString, getLengthA(addString));
}
//adds string the the initial string
WCHAR * appendStringNW(WCHAR * initial, DWORD initialLength, const WCHAR * addString, DWORD addStringLength) {
DWORD length = initialLength + addStringLength + 1;
if(length>1) {
WCHAR * tmp = newpWCHAR(length+1);
DWORD i=0;
if(initialLength!=0) {
for(i=0;i<initialLength;i++) {
tmp[i]=initial[i];
}
FREE(initial);
}
for(i=0;i<addStringLength;i++) {
tmp[i+initialLength] = addString[i];
}
tmp[length] = 0;
return tmp;
} else {
return NULL;
}
}
WCHAR * appendStringW(WCHAR * initial, const WCHAR * addString) {
return appendStringNW(initial, getLengthW(initial), addString, getLengthW(addString));
}
WCHAR * escapeString(const WCHAR * string) {
DWORD length = getLengthW(string);
WCHAR *result = newpWCHAR(length * 2 + 4);
DWORD i=0;
DWORD r=0;
DWORD bsCounter = 0;
int quoting = searchW(string, L" ") || searchW(string, L"\t");
if(quoting) {
result[r++] = '\"';
}
for(i=0;i<length;i++) {
const WCHAR c = string[i];
switch(c) {
case '\\' :
bsCounter++;
break;
case '"':
bsCounter++;
do {
result[r++] = '\\';
bsCounter--;
} while(bsCounter>0);
default:
bsCounter = 0;
break;
}
result[r++] = c;
}
if(quoting) {
while(bsCounter>0) {
result[r++] = '\\';
bsCounter--;
}
result[r++] = '\"';
}
result[r] = '\0';
return result;
}
char * DWORDtoCHARN(DWORD value, int fillZeros) {
int digits = 0;
DWORD tmpValue = value;
int i = 0;
char * str;
do {
digits++;
tmpValue = tmpValue / 10;
} while(tmpValue!=0);
tmpValue = value;
if(digits < fillZeros) {
digits = fillZeros;
}
str = (char*) LocalAlloc(LPTR, sizeof(char)*(digits +1));
str[digits] = '\0';
for(i=0;i<digits;i++) {
str [digits - i - 1] = '0' + (char) (tmpValue - ((tmpValue / 10) * 10));
tmpValue = tmpValue / 10;
}
return str;
}
WCHAR * DWORDtoWCHARN(DWORD value, int fillZeros) {
int digits = 0;
DWORD tmpValue = value;
int i = 0;
WCHAR * str;
do {
digits++;
tmpValue = tmpValue / 10;
} while(tmpValue!=0);
tmpValue = value;
if(digits < fillZeros) {
digits = fillZeros;
}
str = (WCHAR*) LocalAlloc(LPTR, sizeof(WCHAR)*(digits +1));
str[digits] = L'\0';
for(i=0;i<digits;i++) {
str [digits - i - 1] = L'0' + (WCHAR) (tmpValue - ((tmpValue / 10) * 10));
tmpValue = tmpValue / 10;
}
return str;
}
WCHAR * DWORDtoWCHAR(DWORD value) {
return DWORDtoWCHARN(value, 0);
}
char * DWORDtoCHAR(DWORD value) {
return DWORDtoCHARN(value,0);
}
char * long2charN(long value, int fillZeros) {
int digits = 0;
long tmpValue = value;
int i = 0;
char * str;
do {
digits++;
tmpValue = tmpValue / 10;
} while(tmpValue!=0);
tmpValue = value;
if(digits < fillZeros) {
digits = fillZeros;
}
str = (char*) LocalAlloc(LPTR, sizeof(char)*(digits +1));
str[digits] = '\0';
for(i=0;i<digits;i++) {
str [digits - i - 1] = '0' + (char) (tmpValue - ((tmpValue / 10) * 10));
tmpValue = tmpValue / 10;
}
return str;
}
char * long2char(long value) {
return long2charN(value,0);
}
char * word2charN(WORD value, int fillZeros) {
int digits = 0;
WORD tmpValue = value;
int i = 0;
char * str;
do {
digits++;
tmpValue = tmpValue / 10;
} while(tmpValue!=0);
tmpValue = value;
if(digits < fillZeros) {
digits = fillZeros;
}
str = (char*) LocalAlloc(LPTR, sizeof(char)*(digits +1));
str[digits] = '\0';
for(i=0;i<digits;i++) {
str [digits - i - 1] = '0' + (char) (tmpValue - ((tmpValue / 10) * 10));
tmpValue = tmpValue / 10;
}
return str;
}
char * word2char(WORD value) {
return word2charN(value,0);
}
char * int64ttoCHAR(int64t* value) {
if(value->High==0) {
return DWORDtoCHAR(value->Low);
} else {
char * high = DWORDtoCHAR(value->High);
char * low = DWORDtoCHAR(value->Low);
DWORD highLength = getLengthA(high);
DWORD lowLength = getLengthA(low);
char * str = newpChar(highLength + lowLength + 9);
DWORD i = 0;
str[0] = '[';
str[1] = 'H';
str[2] = ']';
str[3] = '[';
str[4] = 'L';
str[5] = ']';
str[6] = '=';
for(i = 0; i < highLength; i++) {
str [7 + i] = high[i];
}
str [7 + highLength] =L',';
for(i = 0; i < lowLength;i++) {
str [8 + highLength + i] = low[i];
}
str [8 + highLength + lowLength] = '\0';
FREE(high);
FREE(low);
return str;
}
}
WCHAR * int64ttoWCHAR(int64t*value) {
if(value->High==0) {
return DWORDtoWCHAR(value->Low);
} else {
WCHAR * high = DWORDtoWCHAR(value->High);
WCHAR * low = DWORDtoWCHAR(value->Low);
DWORD highLength = getLengthW(high);
DWORD lowLength = getLengthW(low);
WCHAR * str = newpWCHAR(highLength + lowLength + 9);
DWORD i = 0;
str[0] = L'[';
str[1] = L'H';
str[2] = L']';
str[3] = L'[';
str[4] = L'L';
str[5] = L']';
str[6] = L'=';
for(i = 0; i < highLength;i++) {
str [7 + i] = high[i];
}
str [7 + highLength] = L',';
for(i = 0; i < lowLength;i++) {
str [8 + highLength + i] = low[i];
}
str [8 + highLength + lowLength] = L'\0';
FREE(high);
FREE(low);
return str;
}
}
void freeStringList(StringListEntry **ss) {
while ( (*ss) !=NULL) {
StringListEntry * tmp = (*ss)->next;
FREE((*ss)->string);
FREE((*ss));
* ss = tmp;
}
}
DWORD inList(StringListEntry * top, WCHAR * str) {
StringListEntry * tmp = top;
while(tmp!=NULL) {
if(lstrcmpW(tmp->string, str)==0) {
return 1;
}
tmp = tmp->next;
}
return 0;
}
StringListEntry * addStringToList(StringListEntry * top, WCHAR * str) {
StringListEntry * ss = (StringListEntry*) LocalAlloc(LPTR,sizeof(StringListEntry));
ss->string = appendStringW(NULL, str);
ss->next = top;
return ss;
}
DWORD getLineSeparatorNumber(char *str) {
DWORD result = 0;
char *ptr = str;
if(ptr!=NULL) {
while((ptr = searchA(ptr, "\n"))!=NULL) {
ptr++;
result++;
if(ptr==NULL) break;
}
}
return result;
}
char *toCharN(const WCHAR * string, DWORD n) {
DWORD len = 0;
DWORD length = 0;
char * str = NULL;
if(string==NULL) return NULL;
//static DWORD excludeCodepages [] = { 50220, 50221, 50222, 50225, 50227, 50229, 52936, 54936, 57002, 57003, 57004, 57005, 57006, 57007, 57008, 57009, 57010, 57011, 65000, 42};
//int symbols = 0;
len = getLengthW(string);
if(n<len) len = n;
length = WideCharToMultiByte(CP_ACP, 0, string, len, NULL, 0, 0, NULL);
str = newpChar(length+1);
WideCharToMultiByte(CP_ACP, 0, string, len, str, length, 0, NULL);
return str;
}
char * toChar(const WCHAR * string) {
return toCharN(string, getLengthW(string));
}
WCHAR *createWCHAR(SizedString * sz) {
char * str = sz->bytes;
DWORD len = sz->length;
int unicodeFlags;
DWORD i;
char * string = NULL;
char * ptr = NULL;
WCHAR * wstr = NULL;
if(str==NULL) return NULL;
//static DWORD excludeCodepages [] = { 50220, 50221, 50222, 50225, 50227, 50229, 52936, 54936, 57002, 57003, 57004, 57005, 57006, 57007, 57008, 57009, 57010, 57011, 65000, 42};
string = appendStringN(NULL, 0 , str, len);
ptr = string;
unicodeFlags = -1 ;
if(len>=2) {
BOOL hasBOM = (*ptr == '\xFF' && *(ptr+1) == '\xFE');
BOOL hasReverseBOM = (*ptr == '\xFE' && *(ptr+1) == '\xFF');
if (IsTextUnicode(string, len, &unicodeFlags) || hasBOM || hasReverseBOM) {
//text is unicode
len-= 2;
ptr+= 2;
if (unicodeFlags & IS_TEXT_UNICODE_REVERSE_SIGNATURE || hasReverseBOM) {
//we need to change bytes order
char c;
for (i = 0 ; i < len/2 ; i++) {
c = ptr [2 * i] ;
ptr [2 * i] = ptr [2 * i + 1] ;
ptr [2 * i + 1] = c;
}
}
}
}
wstr = newpWCHAR(len/2+1);
for(i=0;i<len/2;i++) {
ptr[2*i] = (ptr[2*i]) & 0xFF;
ptr[2*i+1] = (ptr[2*i+1])& 0xFF;
wstr[i] = ((unsigned char) ptr[2*i]) + (((unsigned char)ptr[2*i+1]) << 8);
}
FREE(string);
return wstr;
}
WCHAR *toWCHARn(char * str, DWORD n) {
DWORD len = 0;
DWORD length = 0;
WCHAR * wstr = NULL;
if(str==NULL) return NULL;
//static DWORD excludeCodepages [] = { 50220, 50221, 50222, 50225, 50227, 50229, 52936, 54936, 57002, 57003, 57004, 57005, 57006, 57007, 57008, 57009, 57010, 57011, 65000, 42};
len = getLengthA(str);
if(n<len) len = n;
length = MultiByteToWideChar(CP_ACP, 0, str, len, NULL, 0);
wstr = newpWCHAR(length+1);
MultiByteToWideChar(CP_ACP, 0, str, len, wstr, length);
return wstr;
}
WCHAR * toWCHAR( char *string) {
return toWCHARn(string, getLengthA(string));
}
SizedString * createSizedString() {
SizedString * s = (SizedString*)LocalAlloc(LPTR,sizeof(SizedString));
s->bytes = NULL;
s->length = 0;
return s;
}
void freeSizedString(SizedString ** s) {
if(*s!=NULL) {
FREE((*s)->bytes);
FREE((*s));
*s = NULL;
}
}
WCHAR * getLocaleName() {
LANGID langID = LANGIDFROMLCID(GetUserDefaultLCID());
LCID localeID = MAKELCID(langID, SORT_DEFAULT);
const DWORD MAX_LENGTH = 512;
WCHAR * lang = newpWCHAR(MAX_LENGTH);
WCHAR * country = newpWCHAR(MAX_LENGTH);
WCHAR * locale = NULL;
GetLocaleInfoW(localeID, LOCALE_SISO639LANGNAME, lang, MAX_LENGTH);
GetLocaleInfoW(localeID, LOCALE_SISO3166CTRYNAME, country, MAX_LENGTH);
locale = appendStringW(appendStringW(appendStringW(NULL, lang), L"_"), country);
FREE(country);
FREE(lang);
return locale;
}
WCHAR * newpWCHAR(DWORD length) {
WCHAR * res = (WCHAR*) LocalAlloc(LPTR,sizeof(WCHAR) * length);
ZERO(res, length * sizeof(WCHAR));
return res;
}
WCHAR ** newppWCHAR(DWORD length) {
return (WCHAR**) LocalAlloc(LPTR,sizeof(WCHAR *) * length);
}
char * newpChar(DWORD length) {
char * res = (char*) LocalAlloc(LPTR,sizeof(char) * length);
ZERO(res, length * sizeof(char));
return res;
}
char ** newppChar(DWORD length) {
return (char**) LocalAlloc(LPTR,sizeof(char*) * length);
}
int compare(int64t * size, DWORD value) {
if (size->High > 0) return 1;
if (size->Low > value)
return 1;
else if(size->Low == value)
return 0;
else //if(size->Low < value)
return -1;
}
int compareInt64t(int64t * a1, int64t * a2) {
if (a1->High > a2->High) {
return 1;
} else if(a1->High == a2->High) {
if (a1->Low > a2->Low) {
return 1;
} else if(a1->Low == a2->Low) {
return 0;
}
}
return -1;
}
void plus(int64t * size, DWORD value) {
if(value!=0) {
if((MAXDWORD - size->Low) >= (value - 1)) {
size->Low = size->Low + value;
} else {
size->High = size->High + 1;
size->Low = value - (MAXDWORD - size->Low) - 1;
}
}
}
void multiply(int64t * size, DWORD value) {
if(value==0) {
size->Low = 0;
size->High = 0;
} else {
DWORD i = 0;
DWORD low = size->Low;
DWORD high = size->High;
size->High = 0;
for(; i < value - 1 ; i++) {
plus(size, low);
}
size->High += high * value;
}
}
void minus(int64t * size, DWORD value) {
if(value!=0) {
if(size->Low < value) {
size->High = size->High -1;
size->Low = size->Low + (MAXDWORD - value) + 1;
} else {
size->Low = size->Low - value;
}}
}
int64t * newint64_t(DWORD low, DWORD high) {
int64t * res = (int64t *) LocalAlloc(LPTR,sizeof(int64t));
res->Low = low;
res->High = high;
return res;
}
WCHAR * getErrorDescription(DWORD dw) {
WCHAR * lpMsgBuf;
WCHAR * lpDisplayBuf = NULL;
WCHAR * res = DWORDtoWCHAR(dw);
FormatMessageW( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR) &lpMsgBuf, 0, NULL );
lpDisplayBuf = appendStringW(lpDisplayBuf, L"Error code (");
lpDisplayBuf = appendStringW(lpDisplayBuf, res);
lpDisplayBuf = appendStringW(lpDisplayBuf, L"): ");
lpDisplayBuf = appendStringW(lpDisplayBuf, lpMsgBuf);
FREE(lpMsgBuf);
FREE(res);
return lpDisplayBuf;
}
WCHAR * formatMessageW(const WCHAR* message, const DWORD varArgsNumber, ...) {
DWORD totalLength=getLengthW(message);
DWORD counter=0;
WCHAR * result = NULL;
va_list ap;
va_start(ap, varArgsNumber);
while((counter++)<varArgsNumber) {
WCHAR * arg = va_arg( ap, WCHAR * );
totalLength+=getLengthW(arg);
}
va_end(ap);
result = newpWCHAR(totalLength + 1);
va_start(ap, varArgsNumber);
wvsprintfW(result, message, ap);
va_end(ap);
return result;
}
DWORD isOK(LauncherProperties * props) {
return (props->status == ERROR_OK);
}