Skip to content
93 changes: 29 additions & 64 deletions src/dll_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,70 +46,35 @@ extern "C"

WIN_SPARKLE_API void __cdecl win_sparkle_init()
{
try
{
// finish initialization
if (!Settings::GetLanguage().IsOk())
{
LANGID lang = 0;
if (IsWindowsVistaOrGreater())
{
auto f_GetThreadUILanguage = LOAD_DYNAMIC_FUNC(GetThreadUILanguage, kernel32);
if (f_GetThreadUILanguage)
lang = f_GetThreadUILanguage();
}
if (PRIMARYLANGID(lang) == 0)
{
lang = LANGIDFROMLCID(GetThreadLocale());
}
if (PRIMARYLANGID(lang) != 0)
Settings::SetLanguage(lang);
}

// first things first
UpdateDownloader::CleanLeftovers();

// check for updates
bool checkUpdates;
if ( Settings::ReadConfigValue("CheckForUpdates", checkUpdates) )
{
if ( checkUpdates )
{
static const time_t ONE_DAY = 60*60*24;

time_t lastCheck = 0;
Settings::ReadConfigValue("LastCheckTime", lastCheck);
const time_t currentTime = time(NULL);

// Only check for updates in reasonable intervals:
const int interval = win_sparkle_get_update_check_interval();
if ( currentTime - lastCheck >= interval )
{
// Run the check in background. Only show UI if updates
// are available.
UpdateChecker *check = new UpdateChecker();
check->Start();
}
}
}
else // not yet configured
{
bool didRunOnce;
Settings::ReadConfigValue("DidRunOnce", didRunOnce, false);
if ( !didRunOnce )
{
// Do nothing on the first execution of the app, for better
// first-time impression.
Settings::WriteConfigValue("DidRunOnce", true);
}
else
{
// Only when the app is launched for the second time, ask the
// user for their permission to check for updates.
UI::AskForPermission();
}
}
}
try
{
// finish initialization
if (!Settings::GetLanguage().IsOk())
{
LANGID lang = 0;
if (IsWindowsVistaOrGreater())
{
auto f_GetThreadUILanguage = LOAD_DYNAMIC_FUNC(GetThreadUILanguage, kernel32);
if (f_GetThreadUILanguage)
lang = f_GetThreadUILanguage();
}
if (PRIMARYLANGID(lang) == 0)
{
lang = LANGIDFROMLCID(GetThreadLocale());
}
if (PRIMARYLANGID(lang) != 0)
Settings::SetLanguage(lang);
}

// first things first
UpdateDownloader::CleanLeftovers();

// Run the check in background. Only show UI if updates
// are available.
UpdateChecker *check = new UpdateChecker();
check->Start();
}

CATCH_ALL_EXCEPTIONS
}

Expand Down
31 changes: 24 additions & 7 deletions src/download.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,7 @@ struct InetHandle

~InetHandle()
{
if (m_handle)
{
if (m_callback)
InternetSetStatusCallback(m_handle, NULL);
InternetCloseHandle(m_handle);
}
Close();
}

void SetStatusCallback(INTERNET_STATUS_CALLBACK callback)
Expand All @@ -65,6 +60,17 @@ struct InetHandle
InternetSetStatusCallback(m_handle, m_callback);
}

void Close()
{
if (m_handle)
{
if (m_callback)
InternetSetStatusCallback(m_handle, NULL);
InternetCloseHandle(m_handle);
m_handle = NULL;
}
}

operator HINTERNET() const { return m_handle; }

HINTERNET m_handle;
Expand Down Expand Up @@ -142,6 +148,10 @@ void CALLBACK DownloadInternetStatusCallback(_In_ HINTERNET hInternet,
case INTERNET_STATUS_REQUEST_COMPLETE:
context->eventRequestComplete.Signal();
break;

case INTERNET_STATUS_CONNECTION_CLOSED:
context->conn->Close();
break;
}
}

Expand Down Expand Up @@ -297,7 +307,14 @@ void DownloadFile(const std::string& url, IDownloadSink *sink, Thread *onThread,
}

if (ibuf.dwBufferLength == 0)
break; // all of the file was downloaded
{
// This check is required in case the INTERNET_STATUS_CONNECTION_CLOSED event was
// received (and the handle was closed) during the call to InternetReadFileEx()
if (!conn)
throw Win32Exception();
else
break; // all of the file was downloaded
}

sink->Add(ibuf.lpvBuffer, ibuf.dwBufferLength);
}
Expand Down
74 changes: 31 additions & 43 deletions src/ui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -320,13 +320,11 @@ class WinSparkleDialog : public wxDialog
WinSparkleDialog::WinSparkleDialog()
: wxDialog(NULL, wxID_ANY, _("Software Update"),
wxDefaultPosition, wxDefaultSize,
wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxDIALOG_NO_PARENT)
wxDEFAULT_DIALOG_STYLE | wxDIALOG_NO_PARENT)
{
wxSize dpi = wxClientDC(this).GetPPI();
m_scaleFactor = dpi.y / 96.0;

SetIcon(LoadNamedIcon(UI::GetDllHINSTANCE(), L"UpdateAvailable", GetSystemMetrics(SM_CXSMICON)));

wxSizer *topSizer = new wxBoxSizer(wxHORIZONTAL);

// Load the dialog box icon: the first 48x48 application icon will be loaded, if available,
Expand Down Expand Up @@ -388,7 +386,6 @@ void WinSparkleDialog::SetHeadingFont(wxWindow *win)
// 9pt is base font, 12pt is for "Main instructions". See
// http://msdn.microsoft.com/en-us/library/aa511282%28v=MSDN.10%29.aspx
f.SetPointSize(f.GetPointSize() + 3);
win->SetForegroundColour(wxColour(0x00, 0x33, 0x99));
}
else // Windows XP/2000
{
Expand All @@ -404,8 +401,8 @@ void WinSparkleDialog::SetHeadingFont(wxWindow *win)
Window for communicating with the user
*--------------------------------------------------------------------------*/

const int ID_SKIP_VERSION = wxNewId();
const int ID_REMIND_LATER = wxNewId();
const int ID_REMIND_HOUR = wxNewId();
const int ID_REMIND_TOMORROW = wxNewId();
const int ID_INSTALL = wxNewId();
const int ID_RUN_INSTALLER = wxNewId();

Expand Down Expand Up @@ -435,8 +432,8 @@ class UpdateDialog : public WinSparkleDialog
void OnCloseButton(wxCommandEvent& event);
void OnClose(wxCloseEvent& event);

void OnSkipVersion(wxCommandEvent&);
void OnRemindLater(wxCommandEvent&);
void OnRemindOneHour(wxCommandEvent&);
void OnRemindTomorrow(wxCommandEvent&);
void OnInstall(wxCommandEvent&);

void OnRunInstaller(wxCommandEvent&);
Expand Down Expand Up @@ -532,20 +529,21 @@ UpdateDialog::UpdateDialog()
m_updateButtonsSizer = new wxBoxSizer(wxHORIZONTAL);
m_updateButtonsSizer->Add
(
new wxButton(this, ID_SKIP_VERSION, _("Skip this version")),
new wxButton(this, ID_REMIND_HOUR, _("Remind me in an hour")),
wxSizerFlags().Border(wxRIGHT, PX(20))
);
m_updateButtonsSizer->AddStretchSpacer(1);
m_updateButtonsSizer->Add
(
new wxButton(this, ID_REMIND_LATER, _("Remind me later")),
new wxButton(this, ID_REMIND_TOMORROW, _("Remind me tomorrow")),
wxSizerFlags().Border(wxRIGHT, PX(10))
);
m_updateButtonsSizer->Add
m_updateButtonsSizer->AddStretchSpacer(1);
m_updateButtonsSizer->Add
(
m_installButton = new wxButton(this, ID_INSTALL, _("Install update")),
m_installButton = new wxButton(this, ID_INSTALL, _("Download")),
wxSizerFlags()
);
m_installButton->SetFocus();
m_buttonSizer->Add(m_updateButtonsSizer, wxSizerFlags(1));

m_closeButtonSizer = new wxBoxSizer(wxHORIZONTAL);
Expand All @@ -572,8 +570,8 @@ UpdateDialog::UpdateDialog()
Bind(wxEVT_CLOSE_WINDOW, &UpdateDialog::OnClose, this);
Bind(wxEVT_TIMER, &UpdateDialog::OnTimer, this);
Bind(wxEVT_COMMAND_BUTTON_CLICKED, &UpdateDialog::OnCloseButton, this, wxID_CANCEL);
Bind(wxEVT_COMMAND_BUTTON_CLICKED, &UpdateDialog::OnSkipVersion, this, ID_SKIP_VERSION);
Bind(wxEVT_COMMAND_BUTTON_CLICKED, &UpdateDialog::OnRemindLater, this, ID_REMIND_LATER);
Bind(wxEVT_COMMAND_BUTTON_CLICKED, &UpdateDialog::OnRemindOneHour, this, ID_REMIND_HOUR);
Bind(wxEVT_COMMAND_BUTTON_CLICKED, &UpdateDialog::OnRemindTomorrow, this, ID_REMIND_TOMORROW);
Bind(wxEVT_COMMAND_BUTTON_CLICKED, &UpdateDialog::OnInstall, this, ID_INSTALL);
Bind(wxEVT_COMMAND_BUTTON_CLICKED, &UpdateDialog::OnRunInstaller, this, ID_RUN_INSTALLER);
}
Expand Down Expand Up @@ -629,17 +627,18 @@ void UpdateDialog::OnClose(wxCloseEvent&)
}


void UpdateDialog::OnSkipVersion(wxCommandEvent&)
void UpdateDialog::OnRemindOneHour(wxCommandEvent&)
{
Settings::WriteConfigValue("SkipThisVersion", m_appcast.Version);
static const int ONE_HOUR_IN_SECONDS = 3600;
Settings::WriteConfigValue("UpdateInterval", ONE_HOUR_IN_SECONDS);
Close();
}


void UpdateDialog::OnRemindLater(wxCommandEvent&)
void UpdateDialog::OnRemindTomorrow(wxCommandEvent&)
{
// Just abort the update. Next time it's scheduled to run,
// the user will be prompted.
static const int ONE_DAY_IN_SECONDS = 86400;
Settings::WriteConfigValue("UpdateInterval", ONE_DAY_IN_SECONDS);
Close();
}

Expand Down Expand Up @@ -753,27 +752,12 @@ void UpdateDialog::StateNoUpdateFound(bool installAutomatically)

LayoutChangesGuard guard(this);

m_heading->SetLabel(_("You're up to date!"));

wxString msg;
try
{
msg = wxString::Format
(
_("%s %s is currently the newest version available."),
Settings::GetAppName(),
Settings::GetAppVersion()
);
}
catch ( std::exception& )
{
// GetAppVersion() may fail
msg = "Error: Updates checking not properly configured.";
}
m_heading->SetLabel(_("You are up to date!"));

wxString msg = _("There are no new versions available at this time.");
SetMessage(msg);

m_closeButton->SetLabel(_("Close"));
m_closeButton->SetLabel(_("OK"));
m_closeButton->SetDefault();
EnablePulsing(false);

Expand Down Expand Up @@ -854,8 +838,8 @@ void UpdateDialog::StateUpdateAvailable(const Appcast& info, bool installAutomat
(
wxString::Format
(
_("%s %s is now available (you have %s). Would you like to download it now?"),
appname, ver_new, ver_my
_("You are currently using %s version %s.\nWould you like to download our new version (%s) now?"),
appname, ver_my, ver_new
),
showRelnotes ? RELNOTES_WIDTH : MESSAGE_AREA_WIDTH
);
Expand Down Expand Up @@ -1003,10 +987,14 @@ void UpdateDialog::ShowReleaseNotes(const Appcast& info)

if( !info.ReleaseNotesURL.empty() )
{
m_webBrowser->Navigate
VARIANT varFlags;
varFlags.vt = VT_I4;
varFlags.llVal = (navNoHistory | navNoReadFromCache | navNoWriteToCache);

m_webBrowser->Navigate
(
wxBasicString(info.ReleaseNotesURL),
NULL, // Flags
&varFlags, // Flags
NULL, // TargetFrameName
NULL, // PostData
NULL // Headers
Expand Down Expand Up @@ -1071,7 +1059,7 @@ void UpdateDialog::ShowReleaseNotes(const Appcast& info)
}
}

SetWindowStyleFlag(wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER);
SetWindowStyleFlag(wxDEFAULT_DIALOG_STYLE);
}


Expand Down
Loading