Fixes multiple issues in the setup and update functionality on Windows.

cusax-fix
Lyubomir Marinov 15 years ago
parent e1a985a203
commit e05a78a346

@ -356,15 +356,15 @@
</fileset>
</copy>
<!-- copy the windows jre file -->
<copy file="${windows.jre.file}"
tofile="${windows.app.dir}/tmp/jre/jre-windows.exe"/>
<!-- Copy the Windows JRE setup file -->
<copy
file="${windows.jre.file}"
tofile="${windows.app.dir}/tmp/jre/jre-windows.exe" />
<copy
tofile="${windows.app.dir}/tmp/tmp-installer-windows.xml"
file="${inst.resrc}/windows/installer-windows.xml"
filtering="yes"
/>
file="${inst.resrc}/windows/installer-windows.xml"
tofile="${windows.app.dir}/tmp/tmp-installer-windows.xml"
filtering="yes" />
<izpack
input="${windows.app.dir}/tmp/tmp-installer-windows.xml"
@ -415,6 +415,7 @@
<property name="windows.download.link" value="${link.download.windows32}"/>
<property name="windows.package.name" value="${package.name}-${sip-communicator.version}-x86.exe"/>
<property name="windows.arch" value="32"/>
<property name="mingw.home" value="C:/mingw-w64/mingw-w32" />
<antcall target="build-installation-wix-base" />
</target>
@ -425,6 +426,7 @@
<property name="windows.download.link" value="${link.download.windows64}"/>
<property name="windows.package.name" value="${package.name}-${sip-communicator.version}-x64.exe"/>
<property name="windows.arch" value="64"/>
<property name="mingw.home" value="C:/mingw-w64/mingw-w64" />
<antcall target="build-installation-wix-base" />
</target>
@ -450,22 +452,13 @@
<mkdir dir="${light.dir}" />
<copy todir="${light.dir}" overwrite="true">
<fileset dir="${inst.resrc}/windows">
<include name="run.bat" />
<include name="run.exe" />
<include name="sc-logo.ico" />
</fileset>
</copy>
<copy file="${inst.resrc}/windows/up2date.exe"
tofile="${light.dir}/${package.name}-up2date.exe"
overwrite="true"/>
<exec executable="mt.exe" dir="${light.dir}" failonerror="true">
<arg value="-manifest" />
<arg value="${inst.resrc}\windows\up2date.exe.manifest" />
<arg value="-outputresource:${package.name}-up2date.exe;#1" />
</exec>
<exec executable="mt.exe" dir="${light.dir}" failonerror="true">
<arg value="-manifest" />
<arg value="${inst.resrc}\windows\run.exe.manifest" />
<arg value="${inst.resrc}\windows\asInvoker.exe.manifest" />
<arg value="-outputresource:run.exe;#1" />
</exec>
@ -520,19 +513,26 @@
todir="${light.dir}"
overwrite="true" />
<property name="wix.home" value="C:\Program Files\WiX" />
<!-- Execute heat.exe -->
<exec
executable="C:\Program Files\WiX\heat.exe"
executable="${wix.home}\heat.exe"
dir="${light.dir}"
failonerror="true">
<arg value="dir" />
<arg value="." />
<arg value="-nologo" />
<arg value="-ag" />
<arg value="-cg" />
<arg value="ComponentGroup_HeatExe" />
<arg value="-ke" />
<arg value="-out" />
<arg value="${windows.app.dir}\tmp\heat.wxs" />
<arg value="-sfrag" />
<arg value="-suid" />
<arg value="-var" />
<arg value="var.SourceDir" />
</exec>
<xslt
@ -574,15 +574,20 @@
</copy>
<!-- Execute candle.exe -->
<condition property="wix.var.Platform" value="x64" else="x86">
<equals arg1="${windows.arch}" arg2="64" />
</condition>
<exec
executable="C:\Program Files\WiX\candle.exe"
executable="${wix.home}\candle.exe"
dir="${windows.app.dir}/tmp"
failonerror="true">
<arg value="-nologo" />
<arg value="-dPlatform=${wix.var.Platform}" />
<arg value="-ext" />
<arg value="WixUIExtension" />
<arg value="-ext" />
<arg value="WixUtilExtension" />
<arg value="-dSourceDir=light" />
<arg value="installer-windows.wxs" />
</exec>
@ -598,7 +603,7 @@
<!-- Execute light.exe -->
<exec
executable="C:\Program Files\WiX\light.exe"
executable="${wix.home}\light.exe"
dir="${light.dir}"
failonerror="true">
<arg value="-nologo" />
@ -615,7 +620,7 @@
</exec>
<!-- Bootstrap the MSI into an EXE -->
<copy
<!--copy
file="${inst.resrc}/windows/setup.exe"
todir="${windows.app.dir}/tmp"
overwrite="true" />
@ -638,26 +643,31 @@
<copy
file="${windows.app.dir}/tmp/setup.exe"
tofile="${windows.app.dir}/${windows.package.name}"
overwrite="true" />
<!--exec
executable="C:\Program Files\WiX\setupbld.exe"
dir="${light.dir}"
overwrite="true" /-->
<exec
executable="make"
dir="${src}/native/windows/setup"
failonerror="true">
<arg value="MINGW_HOME=${mingw.home}" />
</exec>
<exec
executable="${wix.home}/setupbld.exe"
dir="${windows.app.dir}/tmp"
failonerror="true">
<arg value="-out" />
<arg value="${windows.app.dir}\${windows.package.name}" />
<arg value="-mps" />
<arg value="${windows.app.dir}\tmp\setup.msi" />
<arg value="-ms" />
<arg value="setup.msi" />
<arg value="-setup" />
<arg value="C:\Program Files\WiX\setup.exe" />
</exec-->
<arg value="setup.exe" />
</exec>
<exec executable="mt.exe" dir="${windows.app.dir}" failonerror="true">
<arg value="-manifest" />
<arg value="${inst.resrc}\windows\setup.exe.manifest" />
<arg value="${inst.resrc}\windows\asInvoker.exe.manifest" />
<arg value="-outputresource:${windows.package.name};#1" />
</exec>
<delete dir="${light.dir}" />
<delete dir="${windows.app.dir}/tmp" />
</target>

@ -0,0 +1,21 @@
<?xml encoding="UTF-8" standalone="yes" version="1.0" ?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<dependency>
<dependentAssembly>
<assemblyIdentity
language="*"
name="Microsoft.Windows.Common-Controls"
processorArchitecture="X86"
publicKeyToken="6595b64144ccf1df"
type="win32"
version="6.0.0.0" />
</dependentAssembly>
</dependency>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
</requestedPrivileges>
</security>
</trustInfo>
</assembly>

@ -8,7 +8,7 @@
<xsl:template match="*[local-name()='Wix']">
<Include>
<xsl:apply-templates
select="*[local-name()='Fragment']/*[local-name()='Directory' and @Id='light']/*" />
select="*//*[local-name()='Directory' and @Name='light']/*" />
</Include>
</xsl:template>

@ -8,7 +8,7 @@
<xsl:template match="*[local-name()='Wix']">
<Include>
<xsl:apply-templates
select="*[local-name()='Fragment']/*[local-name()='ComponentGroup']/*" />
select="*//*[local-name()='ComponentGroup' and @Id='ComponentGroup_HeatExe']/*" />
</Include>
</xsl:template>

@ -19,11 +19,11 @@
Comments="@PKG_COMMENTS@"
Compressed="yes"
Description="@PKG_DESCRIPTION@"
InstallPrivileges="elevated"
InstallScope="perMachine"
InstallerVersion="200"
InstallScope="perMachine"
Languages="1033"
Manufacturer="@APP_NAME@"
Platform="$(var.Platform)"
SummaryCodepage="1252" />
<Upgrade Id="@WIX_UPGRADE_CODE@">
@ -206,8 +206,12 @@
IS_AUTOUPDATE = 1
</Show>
<Custom Action="LaunchApplication" After="ExecuteAction">
IS_AUTOUPDATE = 1
</Custom>
<Custom Action="SetIS_AUTOUPDATE" After="AppSearch">
<![CDATA[NOT Installed AND %SIP_COMMUNICATOR_AUTOUPDATE_INSTALLDIR <> ""]]>
<![CDATA[NOT Installed AND SIP_COMMUNICATOR_AUTOUPDATE_INSTALLDIR <> ""]]>
</Custom>
<Custom Action="SetINSTALLDIR" After="SetIS_AUTOUPDATE" />
<Custom Action="SetCREATE_DESKTOP_SHORTCUT" After="SetINSTALLDIR">
@ -269,7 +273,7 @@
<CustomAction
Id="SetINSTALLDIR"
Property="INSTALLDIR"
Value="[%SIP_COMMUNICATOR_AUTOUPDATE_INSTALLDIR]" />
Value="[SIP_COMMUNICATOR_AUTOUPDATE_INSTALLDIR]" />
<CustomAction
Id="SetIS_AUTOUPDATE"
Property="IS_AUTOUPDATE"
@ -299,7 +303,7 @@
<RemoveExistingProducts After="InstallFinalize" />
<Custom Action="SetIS_AUTOUPDATE" After="AppSearch">
<![CDATA[NOT Installed AND %SIP_COMMUNICATOR_AUTOUPDATE_INSTALLDIR <> ""]]>
<![CDATA[NOT Installed AND SIP_COMMUNICATOR_AUTOUPDATE_INSTALLDIR <> ""]]>
</Custom>
<Custom Action="SetINSTALLDIR" After="SetIS_AUTOUPDATE" />
<Custom Action="SetCREATE_DESKTOP_SHORTCUT" After="SetINSTALLDIR">

@ -1,3 +0,0 @@
mkdir "%UserProfile%/.sip-communicator/log"
set PATH=%PATH%;native
start run.exe

@ -1,5 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<dependency><dependentAssembly><assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="X86" publicKeyToken="6595b64144ccf1df" language="*"></assemblyIdentity></dependentAssembly></dependency>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2"><security><requestedPrivileges><requestedExecutionLevel level="asInvoker" uiAccess="false"></requestedExecutionLevel></requestedPrivileges></security></trustInfo>
</assembly>

@ -1,5 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<dependency><dependentAssembly><assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="X86" publicKeyToken="6595b64144ccf1df" language="*"></assemblyIdentity></dependentAssembly></dependency>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2"><security><requestedPrivileges><requestedExecutionLevel level="requireAdministrator" uiAccess="false"></requestedExecutionLevel></requestedPrivileges></security></trustInfo>
</assembly>

@ -1,369 +0,0 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <shellapi.h> /* ShellExecute */
#include <tlhelp32.h> /* CreateToolhelp32Snapshot */
#include <ctype.h> /* isspace */
#include <stdlib.h>
#include <string.h>
#include <tchar.h> /* _istspace */
#ifndef ERROR_ELEVATION_REQUIRED
#define ERROR_ELEVATION_REQUIRED 740
#endif
#ifndef _tcsncicmp
#ifdef _UNICODE
#define _tcsncicmp _wcsnicmp
#else
#define _tcsncicmp _strnicmp
#endif
#endif
DWORD up2date_createProcess(LPCTSTR);
DWORD up2date_displayError(DWORD error);
LPTSTR up2date_getAllowElevation(LPTSTR, BOOL *);
LPTSTR up2date_getBoolArg(LPCTSTR, LPTSTR, BOOL *);
DWORD up2date_getExePath(LPTSTR, DWORD);
DWORD up2date_getParentProcessId(DWORD *);
LPTSTR up2date_getWaitParent(LPTSTR, BOOL *);
LPTSTR up2date_skipWhitespace(LPTSTR);
LPWSTR up2date_str2wstr(LPCSTR);
DWORD up2date_waitParent();
int WINAPI
WinMain(HINSTANCE instance, HINSTANCE prevInstance, LPSTR cmdLine, int cmdShow) {
LPTSTR commandLine;
LPWSTR wCommandLine;
LPWSTR *argv;
int argc;
LPWSTR wDir;
LPWSTR run;
#ifdef _UNICODE
commandLine = up2date_str2wstr(cmdLine);
#else
commandLine = cmdLine;
#endif
if (commandLine) {
BOOL waitParent;
LPTSTR noWaitParentCommandLine;
BOOL allowElevation;
LPTSTR noAllowElevationCommandLine;
DWORD error;
waitParent = FALSE;
noWaitParentCommandLine
= up2date_getWaitParent(commandLine, &waitParent);
if (waitParent)
up2date_waitParent();
allowElevation = FALSE;
noAllowElevationCommandLine
= up2date_getAllowElevation(
noWaitParentCommandLine, &allowElevation);
error = up2date_createProcess(noAllowElevationCommandLine);
if ((ERROR_ELEVATION_REQUIRED == error) && allowElevation) {
TCHAR exePath[MAX_PATH + 1];
if (!up2date_getExePath(exePath, MAX_PATH + 1)) {
SHELLEXECUTEINFO ShExecInfo;
ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
ShExecInfo.hwnd = NULL;
ShExecInfo.lpVerb = TEXT("runas");
ShExecInfo.lpFile = exePath;
ShExecInfo.lpParameters = noAllowElevationCommandLine;
ShExecInfo.lpDirectory = NULL;
ShExecInfo.nShow = SW_HIDE;
ShExecInfo.hInstApp = NULL;
ShellExecuteEx(&ShExecInfo);
WaitForSingleObject(ShExecInfo.hProcess,INFINITE);
#ifdef _UNICODE
wCommandLine = commandLine;
#else
wCommandLine = up2date_str2wstr(commandLine);
if (!wCommandLine)
return ERROR_NOT_ENOUGH_MEMORY;
#endif
argv = CommandLineToArgvW(wCommandLine, &argc);
if (argv)
{
wDir = *(argv + 3);
LPWSTR runExe = L"\\run.exe";
int len = wcslen(wDir);
run = (wchar_t*)(malloc(sizeof(wchar_t) * (len +
wcslen(runExe) + 1)));
wcscpy(run, wDir);
wcscpy(run + len, runExe);
ShellExecuteW(NULL, L"open", run,
NULL, NULL, SW_SHOWDEFAULT);
error = GetLastError();
if (error)
up2date_displayError(error);
free(run);
}
}
} else if (error)
up2date_displayError(error);
if (((LPVOID) commandLine) != ((LPVOID) cmdLine))
free(commandLine);
}
return 0;
}
DWORD
up2date_createProcess(LPCTSTR commandLine) {
LPWSTR *argv;
LPWSTR wCommandLine;
int argc;
DWORD error;
#ifdef _UNICODE
wCommandLine = commandLine;
#else
wCommandLine = up2date_str2wstr(commandLine);
if (!wCommandLine)
return ERROR_NOT_ENOUGH_MEMORY;
#endif
argv = CommandLineToArgvW(wCommandLine, &argc);
if (argv) {
switch (argc) {
case 2: {
LPWSTR environmentVariableName
= up2date_str2wstr("SIP_COMMUNICATOR_AUTOUPDATE_INSTALLDIR");
if (!environmentVariableName)
{
error = ERROR_NOT_ENOUGH_MEMORY;
break;
}
if (!SetEnvironmentVariableW(
environmentVariableName,
*(argv + 1))) {
error = GetLastError();
free(environmentVariableName);
break;
}
free(environmentVariableName);
}
case 1: {
STARTUPINFOW si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
if (CreateProcessW(NULL, *argv, NULL, NULL, FALSE, 0, NULL, NULL,
&si, &pi))
{
error = 0;
WaitForSingleObject( pi.hProcess, INFINITE );
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
else
error = GetLastError();
}
break;
default:
error = 0;
break;
}
LocalFree((HLOCAL) argv);
} else
error = GetLastError();
if (((LPVOID) wCommandLine) != ((LPVOID) commandLine))
free(wCommandLine);
return error;
}
DWORD
up2date_displayError(DWORD error) {
LPTSTR message;
DWORD ret;
if (FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
0,
error,
0,
(LPTSTR) &message,
0,
NULL)) {
TCHAR caption[MAX_PATH + 1];
MessageBox(
NULL,
message,
up2date_getExePath(caption, MAX_PATH + 1) ? NULL : caption,
MB_ICONERROR);
LocalFree((HLOCAL) message);
ret = 0;
} else
ret = GetLastError();
return ret;
}
LPTSTR
up2date_getAllowElevation(LPTSTR commandLine, BOOL *allowElevation) {
return
up2date_getBoolArg(
TEXT("--allow-elevation"),
commandLine,
allowElevation);
}
LPTSTR
up2date_getBoolArg(LPCTSTR argName, LPTSTR commandLine, BOOL *boolValue) {
size_t argNameLength;
BOOL argValue;
argNameLength = _tcslen(argName);
commandLine = up2date_skipWhitespace(commandLine);
if (0 == _tcsncicmp(commandLine, argName, argNameLength)) {
argValue = TRUE;
commandLine
= up2date_skipWhitespace(commandLine + argNameLength);
} else
argValue = FALSE;
if (boolValue)
*boolValue = argValue;
return commandLine;
}
DWORD
up2date_getExePath(LPTSTR exePath, DWORD exePathSize) {
return
GetModuleFileName(NULL, (LPTSTR) exePath, exePathSize)
? 0
: GetLastError();
}
DWORD
up2date_getParentProcessId(DWORD *ppid) {
HANDLE snapshot;
DWORD error;
snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (snapshot == INVALID_HANDLE_VALUE)
error = GetLastError();
else {
PROCESSENTRY32 entry;
entry.dwSize = sizeof(PROCESSENTRY32);
if (Process32First(snapshot, &entry)) {
DWORD pid;
error = 0;
pid = GetCurrentProcessId();
if (ppid)
*ppid = 0;
do {
if (entry.th32ProcessID == pid) {
if (ppid)
*ppid = entry.th32ParentProcessID;
break;
}
if (!Process32Next(snapshot, &entry)) {
error = GetLastError();
break;
}
} while (1);
} else
error = GetLastError();
CloseHandle(snapshot);
}
return error;
}
LPTSTR
up2date_getWaitParent(LPTSTR commandLine, BOOL *waitParent) {
return
up2date_getBoolArg(
TEXT("--wait-parent"),
commandLine,
waitParent);
}
LPTSTR
up2date_skipWhitespace(LPTSTR str) {
TCHAR ch;
while ((ch = *str) && _istspace(ch))
++str;
return str;
}
LPWSTR
up2date_str2wstr(LPCSTR str) {
int tstrSize;
LPWSTR tstr;
tstrSize =
MultiByteToWideChar(CP_THREAD_ACP, 0, str, -1, NULL, 0);
if (tstrSize) {
tstr = (LPWSTR) malloc(tstrSize * sizeof(WCHAR));
if (tstr) {
tstrSize
= MultiByteToWideChar(CP_THREAD_ACP, 0, str, -1, tstr, tstrSize);
if (!tstrSize) {
free(tstr);
tstr = NULL;
}
} else
tstr = NULL;
} else
tstr = NULL;
return tstr;
}
DWORD
up2date_waitParent() {
DWORD error;
DWORD ppid;
error = up2date_getParentProcessId(&ppid);
if (!error) {
HANDLE parentProcess;
parentProcess = OpenProcess(SYNCHRONIZE, FALSE, ppid);
if (parentProcess) {
DWORD event;
error = 0;
do {
event = WaitForSingleObject(parentProcess, INFINITE);
if (WAIT_FAILED == event) {
error = GetLastError();
break;
}
} while (WAIT_TIMEOUT == event);
CloseHandle(parentProcess);
} else
error = GetLastError();
}
return error;
}

@ -1,5 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<dependency><dependentAssembly><assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="X86" publicKeyToken="6595b64144ccf1df" language="*"></assemblyIdentity></dependentAssembly></dependency>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2"><security><requestedPrivileges><requestedExecutionLevel level="asInvoker" uiAccess="false"></requestedExecutionLevel></requestedPrivileges></security></trustInfo>
</assembly>

@ -0,0 +1,27 @@
MINGW_HOME ?= C:/mingw
TARGET_BASENAME ?= setup
TARGET_DIR ?= ../../../../release/windows/tmp
CC = $(MINGW_HOME)/bin/gcc
CPPFLAGS = \
-O2 \
-Wall -Wreturn-type \
-DWINVER=0x0502 -D_WIN32_WINNT=0x0502
LDFLAGS = -mwindows
LIBS =
TARGET ?= $(TARGET_DIR)/$(TARGET_BASENAME).exe
MACHINE = $(shell $(CC) -dumpmachine)
WINDRES = $(MINGW_HOME)/bin/windres
ifneq ("x$(MACHINE)","x")
ifeq ($(wildcard $(MINGW_HOME)/bin/$(MACHINE)-windres.*),$(MINGW_HOME)/bin/$(MACHINE)-windres.exe)
WINDRES = $(MINGW_HOME)/bin/$(MACHINE)-windres
endif
endif
$(TARGET): setup.c $(TARGET_DIR)/setup.res
$(CC) $(CPPFLAGS) $^ $(LDFLAGS) -o $@ $(LIBS)
-$(MINGW_HOME)/$(MACHINE)/bin/strip $(TARGET)
$(TARGET_DIR)/setup.res: setup.rc
$(WINDRES) -I../../../../resources/install/windows $^ -O coff -o $@

@ -0,0 +1,941 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
#include "setup.h"
#include <ctype.h> /* isspace */
#include <string.h>
#include <tchar.h>
#ifndef ERROR_RESOURCE_ENUM_USER_STOP
#define ERROR_RESOURCE_ENUM_USER_STOP 0x3B02
#endif /* #ifndef ERROR_RESOURCE_ENUM_USER_STOP */
#include <shellapi.h>
#ifndef SEE_MASK_NOASYNC
#define SEE_MASK_NOASYNC 0x00000100
#endif /* #ifndef SEE_MASK_NOASYNC */
#include <tlhelp32.h> /* CreateToolhelp32Snapshot */
static LPWSTR Setup_commandLine = NULL;
static LPTSTR Setup_fileName = NULL;
static LPTSTR Setup_productName = NULL;
static BOOL Setup_waitForParentProcess_ = FALSE;
BOOL CALLBACK Setup_enumResNameProc(HMODULE module, LPCTSTR type, LPTSTR name, LONG_PTR param);
static DWORD Setup_executeMsi(LPCTSTR path);
static DWORD Setup_extractAndExecuteMsi(LPVOID ptr, DWORD size);
static LPTSTR Setup_getBoolArg(LPCTSTR argName, LPTSTR commandLine, BOOL *boolValue);
static LPCTSTR Setup_getFileName();
static DWORD Setup_getParentProcess(DWORD *ppid, LPTSTR *fileName);
static LPCTSTR Setup_getProductName();
static int Setup_isWow64Acceptable();
LRESULT CALLBACK Setup_isWow64AcceptableMessageBoxCallWndRetProc(int code, WPARAM wParam, LPARAM lParam);
static DWORD Setup_parseCommandLine(LPSTR cmdLine);
static LPTSTR Setup_skipWhitespace(LPTSTR str);
static LPWSTR Setup_str2wstr(LPCSTR str);
static DWORD Setup_terminateUp2DateExe();
static DWORD Setup_waitForParentProcess();
BOOL CALLBACK
Setup_enumResNameProc(
HMODULE module,
LPCTSTR type, LPTSTR name,
LONG_PTR param)
{
BOOL proceed = TRUE;
DWORD error = ERROR_SUCCESS;
if (!IS_INTRESOURCE(name)
&& (_tcslen(name) > 3)
&& (_tcsnicmp(name, _T("MSI"), 3) == 0))
{
HRSRC rsrc = FindResource(module, name, type);
if (rsrc)
{
DWORD size = SizeofResource(module, rsrc);
if (size)
{
HGLOBAL global = LoadResource(module, rsrc);
if (global)
{
LPVOID ptr = LockResource(global);
if (ptr)
{
proceed = FALSE;
error = Setup_extractAndExecuteMsi(ptr, size);
}
else
error = GetLastError();
}
else
error = GetLastError();
}
else
error = GetLastError();
}
else
error = GetLastError();
}
if (param)
*((DWORD *) param) = error;
return proceed;
}
static DWORD
Setup_executeMsi(LPCTSTR path)
{
DWORD error = ERROR_SUCCESS;
LPWSTR p0, p1, p2, p3;
size_t p0Length, p1Length, p2Length, p3Length;
LPWSTR parameters;
p0 = L"/i \"";
p0Length = wcslen(p0);
#ifdef _UNICODE
p1 = path;
#else
p1 = Setup_str2wstr(path);
#endif /* #ifdef _UNICODE */
if (p1)
p1Length = wcslen(p1);
else
{
error = ERROR_OUTOFMEMORY;
return error;
}
p2 = L"\" ";
p2Length = wcslen(p2);
p3 = Setup_commandLine;
p3Length = p3 ? wcslen(p3) : 0;
parameters
= (LPWSTR)
malloc(
sizeof(wchar_t)
* (p0Length + p1Length + p2Length + p3Length + 1));
if (parameters)
{
LPWSTR str = parameters;
SHELLEXECUTEINFOW sei;
wcsncpy(str, p0, p0Length);
str += p0Length;
wcsncpy(str, p1, p1Length);
str += p1Length;
wcsncpy(str, p2, p2Length);
str += p2Length;
if (p3Length)
{
wcsncpy(str, p3, p3Length);
str += p3Length;
}
*str = 0;
ZeroMemory(&sei, sizeof(sei));
sei.cbSize = sizeof(sei);
sei.fMask
= SEE_MASK_NOCLOSEPROCESS | SEE_MASK_NOASYNC | SEE_MASK_FLAG_NO_UI;
sei.lpVerb = L"open";
sei.lpFile = L"msiexec.exe";
sei.lpParameters = parameters;
sei.nShow = SW_SHOWNORMAL;
if (ShellExecuteExW(&sei) && (((int) (sei.hInstApp)) > 32))
{
if (sei.hProcess)
{
DWORD event;
do
{
event = WaitForSingleObject(sei.hProcess, INFINITE);
if (WAIT_FAILED == event)
{
error = GetLastError();
break;
}
}
while (WAIT_TIMEOUT == event);
CloseHandle(sei.hProcess);
}
}
else
error = GetLastError();
free(parameters);
}
else
error = ERROR_OUTOFMEMORY;
if (((LPVOID) p1) != ((LPVOID) path))
free(p1);
return error;
}
static DWORD
Setup_extractAndExecuteMsi(LPVOID ptr, DWORD size)
{
TCHAR path[MAX_PATH + 1];
DWORD pathSize = sizeof(path) / sizeof(TCHAR);
DWORD tempPathLength = GetTempPath(pathSize, path);
DWORD error = ERROR_SUCCESS;
if (tempPathLength)
{
if (tempPathLength > pathSize)
error = ERROR_NOT_ENOUGH_MEMORY;
else
{
LPCTSTR fileName = Setup_getFileName();
HANDLE file = INVALID_HANDLE_VALUE;
if (fileName)
{
size_t fileNameLength = _tcslen(fileName);
if ((fileNameLength > 4 /* .exe */)
&& (tempPathLength + fileNameLength + 1 <= pathSize))
{
LPTSTR str = path + tempPathLength;
_tcsncpy(str, fileName, fileNameLength - 4);
str += (fileNameLength - 4);
_tcsncpy(str, _T(".msi"), 4);
*(str + 4) = 0;
file
= CreateFile(
path,
GENERIC_WRITE,
0,
NULL,
CREATE_NEW,
FILE_ATTRIBUTE_TEMPORARY,
NULL);
}
if (INVALID_HANDLE_VALUE == file)
{
LPTSTR tempPath;
path[tempPathLength] = 0;
tempPath = _tcsdup(path);
if (tempPath)
{
if (0
== GetTempFileName(
tempPath,
_T("MSI"),
0,
path))
{
error = GetLastError();
}
else
{
file
= CreateFile(
path,
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_TEMPORARY,
NULL);
}
free(tempPath);
}
else
error = ERROR_OUTOFMEMORY;
}
if (INVALID_HANDLE_VALUE != file)
{
DWORD written;
if ((FALSE == WriteFile(file, ptr, size, &written, NULL))
|| (written != size))
{
error = GetLastError();
CloseHandle(file);
}
else
{
if (Setup_waitForParentProcess_)
Setup_waitForParentProcess();
CloseHandle(file);
error = Setup_executeMsi(path);
}
DeleteFile(path);
}
}
}
}
else
error = GetLastError();
return error;
}
static LPTSTR
Setup_getBoolArg(LPCTSTR argName, LPTSTR commandLine, BOOL *boolValue)
{
size_t argNameLength;
BOOL argValue;
argNameLength = _tcslen(argName);
commandLine = Setup_skipWhitespace(commandLine);
if (0 == _tcsnicmp(commandLine, argName, argNameLength))
{
argValue = TRUE;
commandLine = Setup_skipWhitespace(commandLine + argNameLength);
}
else
argValue = FALSE;
if (boolValue)
*boolValue = argValue;
return commandLine;
}
static LPCTSTR
Setup_getFileName()
{
if (!Setup_fileName)
{
TCHAR moduleFileName[MAX_PATH + 1];
DWORD moduleFileNameSize = sizeof(moduleFileName) / sizeof(TCHAR);
DWORD moduleFileNameLength
= GetModuleFileName(NULL, moduleFileName, moduleFileNameSize);
if (moduleFileNameLength)
{
TCHAR *fileNameEnd = moduleFileName + moduleFileNameLength - 1;
TCHAR *fileNameBegin = fileNameEnd;
size_t fileNameLength;
LPTSTR fileName;
for (; fileNameBegin >= moduleFileName; fileNameBegin--)
{
TCHAR c = *fileNameBegin;
if (('\\' == c) || ('/' == c))
break;
}
fileNameBegin
= (fileNameBegin == fileNameEnd)
? moduleFileName
: (fileNameBegin + 1);
fileNameLength = (fileNameEnd - fileNameBegin) + 1;
fileName = (LPTSTR) malloc((fileNameLength + 1) * sizeof(TCHAR));
if (fileName)
{
_tcsncpy(fileName, fileNameBegin, fileNameLength);
*(fileName + fileNameLength) = 0;
Setup_fileName = fileName;
}
}
}
return Setup_fileName;
}
static DWORD
Setup_getParentProcess(DWORD *ppid, LPTSTR *fileName)
{
HANDLE snapshot;
DWORD error;
snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (snapshot == INVALID_HANDLE_VALUE)
error = GetLastError();
else
{
PROCESSENTRY32 entry;
entry.dwSize = sizeof(PROCESSENTRY32);
if (Process32First(snapshot, &entry))
{
DWORD pid;
error = ERROR_SUCCESS;
pid = GetCurrentProcessId();
if (ppid)
*ppid = 0;
do
{
if (entry.th32ProcessID == pid)
{
if (ppid)
*ppid = entry.th32ParentProcessID;
break;
}
if (!Process32Next(snapshot, &entry))
{
error = GetLastError();
break;
}
}
while (1);
} else
error = GetLastError();
if ((ERROR_SUCCESS == error) && fileName && ppid && *ppid)
{
if (Process32First(snapshot, &entry))
{
do
{
if (entry.th32ProcessID == *ppid)
{
*fileName = _tcsdup(entry.szExeFile);
if (NULL == *fileName)
error = ERROR_OUTOFMEMORY;
break;
}
if (!Process32Next(snapshot, &entry))
{
error = GetLastError();
break;
}
}
while (1);
} else
error = GetLastError();
}
CloseHandle(snapshot);
}
return error;
}
static LPCTSTR
Setup_getProductName()
{
if (!Setup_productName)
{
/* TODO Auto-generated method stub */
LPCTSTR fileName = Setup_getFileName();
if (fileName)
{
int fileNameLength = _tcslen(fileName);
if ((fileNameLength > 4)
&& (_tcsnicmp(fileName + fileNameLength - 4, _T(".exe"), 4)
== 0))
{
LPTSTR productName;
fileNameLength -= 4;
productName
= (LPTSTR) malloc((fileNameLength + 1) * sizeof(TCHAR));
if (productName)
{
_tcsncpy(productName, fileName, fileNameLength);
*(productName + fileNameLength) = 0;
Setup_productName = productName;
}
}
if (!Setup_productName)
Setup_productName = (LPTSTR) fileName;
}
}
return Setup_productName;
}
static int
Setup_isWow64Acceptable()
{
HMODULE kernel32 = GetModuleHandle(_T("kernel32"));
int answer = IDYES;
if (kernel32)
{
typedef BOOL (WINAPI *LPISWOW64PROCESS)(HANDLE, PBOOL);
LPISWOW64PROCESS isWow64Process
= (LPISWOW64PROCESS) GetProcAddress(kernel32, _T("IsWow64Process"));
BOOL wow64Process = FALSE;
if (isWow64Process
&& isWow64Process(GetCurrentProcess(), &wow64Process)
&& wow64Process)
{
TCHAR fileName[MAX_PATH + 1];
if (GetModuleFileName(NULL, fileName, sizeof(fileName) / sizeof(TCHAR)))
{
UINT questionId;
UINT buttonType;
DWORD questionLength;
TCHAR question[1024];
#ifdef X64_SETUP_URL
HHOOK hook
= SetWindowsHookEx(
WH_CALLWNDPROCRET,
(HOOKPROC) Setup_isWow64AcceptableMessageBoxCallWndRetProc,
NULL,
GetCurrentThreadId());
if (hook)
{
questionId = IDS_ISWOW64ACCEPTABLE3;
buttonType = MB_YESNOCANCEL | MB_DEFBUTTON3;
}
else
#endif /* #ifdef X64_SETUP_URL */
{
questionId = IDS_ISWOW64ACCEPTABLE2;
buttonType = MB_YESNO;
}
questionLength
= LoadString(
GetModuleHandle(NULL),
questionId,
question,
sizeof(question) / sizeof(TCHAR));
if (questionLength)
{
answer
= MessageBox(
NULL,
question,
fileName,
MB_ICONQUESTION | buttonType);
LocalFree(question);
}
#ifdef X64_SETUP_URL
if (hook)
{
UnhookWindowsHookEx(hook);
switch (answer)
{
case IDNO: // Continue
answer = IDYES;
break;
case IDYES: // Download
answer = IDNO;
ShellExecute(
NULL,
_T("open"),
_T(X64_SETUP_URL),
NULL,
NULL,
SW_SHOWNORMAL);
break;
}
}
#endif /* #ifdef X64_SETUP_URL */
}
}
}
return answer;
}
LRESULT CALLBACK
Setup_isWow64AcceptableMessageBoxCallWndRetProc(
int code,
WPARAM wParam,
LPARAM lParam)
{
CWPRETSTRUCT *cwprs = (CWPRETSTRUCT *) lParam;
if (cwprs && (WM_INITDIALOG == cwprs->message))
{
HWND yes, no;
yes = GetDlgItem(cwprs->hwnd, IDYES);
if (yes)
SendMessage(yes, WM_SETTEXT, 0, (LPARAM) _T("&Download"));
no = GetDlgItem(cwprs->hwnd, IDNO);
if (no)
SendMessage(no, WM_SETTEXT, 0, (LPARAM) _T("&Continue"));
}
return CallNextHookEx(NULL, code, wParam, lParam);
}
static DWORD
Setup_parseCommandLine(LPSTR cmdLine)
{
LPTSTR commandLine;
DWORD error = ERROR_SUCCESS;
#ifdef _UNICODE
if (cmdLine)
{
commandLine = Setup_str2wstr(cmdLine);
if (!commandLine)
error = ERROR_OUTOFMEMORY;
}
else
commandLine = NULL;
#else
commandLine = cmdLine;
#endif /* #ifdef _UNICODE */
if (commandLine)
{
LPTSTR noWaitParentCommandLine
= Setup_getBoolArg(
_T("--wait-parent"),
commandLine,
&Setup_waitForParentProcess_);
/*
* The command line argument --allow-elevation is up2date legacy which
* has to be taken into account by removing it in order to prevent it
* from breaking msiexec.
*/
BOOL up2date;
LPTSTR noAllowElevationCommandLine
= Setup_getBoolArg(
_T("--allow-elevation"),
noWaitParentCommandLine,
&up2date);
size_t noAllowElevationCommandLineLength
= _tcslen(noAllowElevationCommandLine);
TCHAR envVarValue[1 /* " */ + MAX_PATH + 1 /* " */ + 1];
if (!up2date && !noAllowElevationCommandLineLength)
{
DWORD envVarValueSize = (sizeof(envVarValue) / sizeof(TCHAR)) - 2 /* "" */;
DWORD envVarValueLength
= GetEnvironmentVariable(
_T("SIP_COMMUNICATOR_AUTOUPDATE_INSTALLDIR"),
&(envVarValue[1]),
envVarValueSize);
if (envVarValueLength)
{
if (envVarValueLength > envVarValueSize)
error = ERROR_NOT_ENOUGH_MEMORY;
else
{
if ((envVarValueLength >= 2)
&& ('\"' == envVarValue[1])
&& ('\"' == envVarValue[1 + envVarValueLength - 1]))
{
noAllowElevationCommandLine = &(envVarValue[1]);
}
else
{
envVarValue[0] = '\"';
envVarValue[1 + envVarValueLength] = '\"';
envVarValue[1 + envVarValueLength + 1] = 0;
envVarValueLength += 2;
noAllowElevationCommandLine = envVarValue;
}
noAllowElevationCommandLineLength = envVarValueLength;
up2date = TRUE;
}
}
else
{
DWORD envVarError = GetLastError();
if (ERROR_ENVVAR_NOT_FOUND != envVarError)
error = envVarError;
}
}
if (up2date && noAllowElevationCommandLineLength)
{
LPWSTR commandLineW;
#ifdef _UNICODE
commandLineW = noAllowElevationCommandLine;
#else
commandLineW = Setup_str2wstr(noAllowElevationCommandLine);
if (!commandLineW)
error = ERROR_OUTOFMEMORY;
#endif /* #ifdef _UNICODE */
if (commandLineW)
{
int argc;
LPWSTR *argv = CommandLineToArgvW(commandLineW, &argc);
if (argv)
{
if ((1 == argc) || (2 == argc))
{
LPWSTR argv1 = *(argv + (argc - 1));
size_t argv1Length = wcslen(argv1);
if ((argv1Length >= 2)
&& (L'\"' == argv1[0])
&& (L'\"' == argv1[argv1Length - 1]))
{
argv1++;
argv1Length -= 2;
}
if (argv1Length)
{
LPCWSTR propertyBegin
= L"SIP_COMMUNICATOR_AUTOUPDATE_INSTALLDIR=\"";
size_t propertyBeginLength = wcslen(propertyBegin);
LPCWSTR propertyEnd = L"\"";
size_t propertyEndLength = wcslen(propertyEnd);
Setup_commandLine
= (LPWSTR)
malloc(
sizeof(wchar_t)
* (propertyBeginLength
+ argv1Length
+ propertyEndLength
+ 1));
if (Setup_commandLine)
{
LPWSTR str = Setup_commandLine;
wcsncpy(
str,
propertyBegin,
propertyBeginLength);
str += propertyBeginLength;
wcsncpy(str, argv1, argv1Length);
str += argv1Length;
wcsncpy(str, propertyEnd, propertyEndLength);
*(str + propertyEndLength) = 0;
}
else
error = ERROR_OUTOFMEMORY;
}
}
LocalFree(argv);
}
else
error = GetLastError();
if (((LPVOID) commandLineW)
!= ((LPVOID) noAllowElevationCommandLine))
free(commandLineW);
}
}
/*
* If up2date.exe is running while the MSI is being installed, the MSI
* will display a dialog notifying of the fact and asking the user to
* either let it close the application in question (and it will not be
* able to if the user actually chooses the option) or reboot.
*/
if (up2date)
Setup_terminateUp2DateExe();
if (!up2date && noAllowElevationCommandLineLength)
{
#ifdef _UNICODE
Setup_commandLine = _wcsdup(noAllowElevationCommandLine);
#else
Setup_commandLine = Setup_str2wstr(noAllowElevationCommandLine);
#endif /* #ifdef _UNICODE */
if (Setup_commandLine)
{
/*
* At the time of this writing, we expect a single property to
* pass on to msiexec which wants it in the format
* PROPERTY="VALUE" if value contains spaces. Unfortunately,
* ProcessBuilder on the Java side will break it by quoting the
* whole command line argument.
*/
size_t commandLineLength = wcslen(Setup_commandLine);
if ((commandLineLength > 3)
&& (L'"' == *Setup_commandLine)
&& (L'"' == *(Setup_commandLine + (commandLineLength - 2)))
&& (L'"' == *(Setup_commandLine + (commandLineLength - 1))))
{
*(Setup_commandLine + (commandLineLength - 1)) = 0;
Setup_commandLine++;
}
}
else
error = ERROR_OUTOFMEMORY;
}
if (commandLine != cmdLine)
free(commandLine);
}
return error;
}
static LPTSTR
Setup_skipWhitespace(LPTSTR str)
{
TCHAR c;
while ((c = *str) && _istspace(c))
++str;
return str;
}
static LPWSTR
Setup_str2wstr(LPCSTR str)
{
int tstrSize;
LPWSTR tstr;
tstrSize = MultiByteToWideChar(CP_THREAD_ACP, 0, str, -1, NULL, 0);
if (tstrSize)
{
tstr = (LPWSTR) malloc(tstrSize * sizeof(WCHAR));
if (tstr)
{
tstrSize
= MultiByteToWideChar(CP_THREAD_ACP, 0, str, -1, tstr, tstrSize);
if (!tstrSize)
{
free(tstr);
tstr = NULL;
}
}
else
tstr = NULL;
}
else
tstr = NULL;
return tstr;
}
static DWORD
Setup_terminateUp2DateExe()
{
DWORD error;
DWORD ppid = 0;
LPTSTR ppFileName = NULL;
error = Setup_getParentProcess(&ppid, &ppFileName);
if ((ERROR_SUCCESS == error) && ppFileName)
{
size_t ppFileNameLength = _tcslen(ppFileName);
LPCTSTR up2DateExe = _T("up2date.exe");
size_t up2DateExeLength = _tcslen(up2DateExe);
if ((ppFileNameLength >= up2DateExeLength)
&& (_tcsncmp(
ppFileName + (ppFileNameLength - up2DateExeLength),
up2DateExe,
up2DateExeLength)
== 0))
{
HANDLE parentProcess
= OpenProcess(PROCESS_TERMINATE, FALSE, ppid);
if (parentProcess)
{
if (!TerminateProcess(parentProcess, 0))
error = GetLastError();
CloseHandle(parentProcess);
}
else
error = GetLastError();
}
}
return error;
}
static DWORD
Setup_waitForParentProcess()
{
DWORD error;
DWORD ppid = 0;
error = Setup_getParentProcess(&ppid, NULL);
if (ERROR_SUCCESS == error)
{
HANDLE parentProcess = OpenProcess(SYNCHRONIZE, FALSE, ppid);
if (parentProcess)
{
DWORD event;
error = ERROR_SUCCESS;
do
{
event = WaitForSingleObject(parentProcess, INFINITE);
if (WAIT_FAILED == event)
{
error = GetLastError();
break;
}
}
while (WAIT_TIMEOUT == event);
CloseHandle(parentProcess);
}
else
error = GetLastError();
}
return error;
}
int CALLBACK
WinMain(
HINSTANCE instance, HINSTANCE prevInstance,
LPSTR cmdLine,
int cmdShow)
{
DWORD error = ERROR_SUCCESS;
Setup_parseCommandLine(cmdLine);
if ((ERROR_SUCCESS == error)
&& (IDYES == Setup_isWow64Acceptable())
&& (FALSE
== EnumResourceNames(
NULL,
RT_RCDATA,
Setup_enumResNameProc,
(LONG_PTR) &error))
&& (ERROR_SUCCESS == error))
{
DWORD enumResourceNamesError = GetLastError();
if ((ERROR_SUCCESS != enumResourceNamesError)
&& (ERROR_RESOURCE_ENUM_USER_STOP != enumResourceNamesError))
error = enumResourceNamesError;
}
if (ERROR_SUCCESS != error)
{
LPTSTR message;
DWORD messageLength
= FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
error,
LANG_USER_DEFAULT,
(LPTSTR) &message,
0,
NULL);
if (messageLength)
{
MessageBox(
NULL,
message,
Setup_getProductName(),
MB_ICONERROR | MB_OK);
LocalFree(message);
}
}
if (Setup_productName && (Setup_productName != Setup_fileName))
free(Setup_productName);
if (Setup_fileName)
free(Setup_fileName);
return 0;
}

@ -0,0 +1,9 @@
#ifndef _NET_JAVA_SIP_COMMUNICATOR_WINDOWS_SETUP_H_
#define _NET_JAVA_SIP_COMMUNICATOR_WINDOWS_SETUP_H_
#include <windows.h>
#define IDS_ISWOW64ACCEPTABLE2 2
#define IDS_ISWOW64ACCEPTABLE3 3
#endif /* #ifndef _NET_JAVA_SIP_COMMUNICATOR_WINDOWS_SETUP_H_ */

@ -0,0 +1,34 @@
#include "setup.h"
SCLogoIcon ICON sc-logo.ico
STRINGTABLE
BEGIN
IDS_ISWOW64ACCEPTABLE2 "The version of this file is x86 (32-bit) and the version of Windows you're running is x64 (64-bit). It is recommended to install the x64 (64-bit) version of the program.\012\012Continue anyway?"
IDS_ISWOW64ACCEPTABLE3 "The version of this file is x86 (32-bit) and the version of Windows you're running is x64 (64-bit). It is recommended to install the x64 (64-bit) version of the program."
END
1 VERSIONINFO
FILEVERSION 0,0,0,0
FILETYPE VFT_APP
PRODUCTVERSION 0,0,0,0
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904E4"
BEGIN
VALUE "Comments", ""
VALUE "CompanyName", "SIP Communicator"
VALUE "FileDescription", "SIP Communicator Setup"
VALUE "FileVersion", "0.0.0.0"
VALUE "InternalName", "setup"
VALUE "OriginalFilename", "setup.exe"
VALUE "ProductName", "SIP Communicator"
VALUE "ProductVersion", "0.0.0.0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x0409, 1252
END
END

@ -740,11 +740,14 @@ public Component createStartupConfigPanel()
+ ":"),
BorderLayout.WEST);
Component updateCheckBox = createUpdateCheckBox();
Component updateCheckBox = null;
Component autoStartCheckBox = null;
if (OSUtils.IS_WINDOWS)
{
autoStartCheckBox = createAutoStartCheckBox();
updateCheckBox = createUpdateCheckBox();
}
if (updateCheckBox != null && autoStartCheckBox != null)
{

@ -1,18 +1,18 @@
Bundle-Activator: net.java.sip.communicator.plugin.updatechecker.UpdateCheckActivator
Bundle-Name: UpdateCheckPlugin
Bundle-Description: A bundle that implements the UpdateCheck Plugin Package.
Bundle-Description: Checks for software updates
Bundle-Name: Update Checker
Bundle-Vendor: sip-communicator.org
Bundle-Version: 0.0.1
System-Bundle: yes
Import-Package: org.osgi.framework,
net.java.sip.communicator.service.browserlauncher,
net.java.sip.communicator.service.certificate,
net.java.sip.communicator.service.configuration,
net.java.sip.communicator.service.gui,
net.java.sip.communicator.service.protocol,
net.java.sip.communicator.service.resources,
net.java.sip.communicator.service.shutdown,
net.java.sip.communicator.service.version,
net.java.sip.communicator.service.certificate,
net.java.sip.communicator.util,
net.java.sip.communicator.util.swing,
javax.imageio,

Loading…
Cancel
Save