1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
|
// Unicode support by Jim Park -- 08/20/2007
#include "makensisw.h"
#include "update.h"
#include <wininet.h>
#include "utils.h" // OpenUrlInDefaultBrowser
#define mbtitle "NSIS Update"
static LPSTR InetGetErrorStringAllocA(DWORD ec)
{
LPSTR buf;
DWORD flags = FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_IGNORE_INSERTS;
if (FormatMessageA(flags|FORMAT_MESSAGE_FROM_SYSTEM, 0, ec, 0, (LPSTR) &buf, 0, 0))
return buf;
HMODULE hMod = LoadSysLibrary("WinInet");
if (hMod && FormatMessageA(flags|FORMAT_MESSAGE_FROM_HMODULE, hMod, ec, 0, (LPSTR) &buf, 0, 0))
return buf;
#if 0 // We are not using WinHttp* functions
hMod = LoadSysLibrary("WinHTTP");
if (hMod && FormatMessageA(flags|FORMAT_MESSAGE_FROM_HMODULE, hMod, ec, 0, (LPSTR) &buf, 0, 0))
return buf;
#endif
return NULL;
}
static void InetWorkOnline(HINTERNET hInet)
{
//msdn.microsoft.com/en-us/library/Aa768170#Supporting Offline Browsing in Applications and Components
DWORD cbio = sizeof(DWORD), op32;
if (InternetQueryOption(hInet, INTERNET_OPTION_CONNECTED_STATE, &op32, &cbio))
{
if (INTERNET_STATE_DISCONNECTED_BY_USER & op32)
{
INTERNET_CONNECTED_INFO ci = { INTERNET_STATE_CONNECTED, 0 };
InternetSetOption(hInet, INTERNET_OPTION_CONNECTED_STATE, &ci, sizeof(ci));
}
}
}
static DWORD InetSynchronousReadFile(HINTERNET hConn, void*Buffer, DWORD cbBuffer, DWORD*pcbReceived)
{
*pcbReceived = 0;
for (DWORD cbio;;)
{
if (!cbBuffer)
break;
if (!InternetReadFile(hConn, Buffer, cbBuffer, &cbio))
return GetLastError();
if (!cbio)
break; // EOF, we are done.
Buffer = ((char*)Buffer) + cbio, cbBuffer -= cbio;
(*pcbReceived) += cbio;
}
return ERROR_SUCCESS;
}
static DWORD CALLBACK UpdateCheckWebrequestThread(LPVOID ThreadParam)
{
char buf[300];
wsprintfA(buf, "%s%s", NSIS_UC_URL, g_sdata.brandingv);
InternetAttemptConnect(0);
UINT mbicon = MB_ICONINFORMATION;
LPCSTR msg = NULL;
HINTERNET hInet = InternetOpenA("MakeNSISw (WinInet)", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
DWORD gle = GetLastError();
if (hInet)
{
InetWorkOnline(hInet);
// Note: InternetOpenUrlW does not handle the http headers in the same way, be careful if you stop forcing the A version
static const CHAR httpheaders[] = "Accept:*/*\r\n";
DWORD connflags = INTERNET_FLAG_NO_UI|INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS;
connflags |= INTERNET_FLAG_NO_CACHE_WRITE|INTERNET_FLAG_NO_COOKIES;
connflags |= INTERNET_FLAG_PRAGMA_NOCACHE|INTERNET_FLAG_RELOAD;
//if ((32|buf[4]) == 's') connflags |= INTERNET_FLAG_SECURE;
HINTERNET hConn = InternetOpenUrlA(hInet, buf, httpheaders, -1, connflags, 0);
gle = GetLastError();
if (hConn)
{
char response[30+1];
DWORD cbRecv;
gle = InetSynchronousReadFile(hConn, response, sizeof(response)-1, &cbRecv);
if (!gle)
{
response[cbRecv] = '\0';
switch(response[0])
{
case '0':
msg = "There is no update available for NSIS at this time.";
break;
case '1':
case '2':
if (cbRecv > 2 && '|' == response[1])
{
const char *reltypestr = '1' == response[0] ? "it" : "this preview release";
wsprintfA(buf, "NSIS %.50s is now available. Would you like to download %s now?", response+2, reltypestr);
mbicon = MB_ICONQUESTION, msg = buf;
break;
}
// fall through
default:
gle = ERROR_INVALID_DATA;
}
}
InternetCloseHandle(hConn);
}
InternetCloseHandle(hInet);
}
HWND hwndOwner = (HWND) ThreadParam;
// Hopefully we don't end up with a race where our main window has been closed
// and the HWND has been reused just as this thread completes its work
if (IsWindow(hwndOwner))
{
if (!msg)
{
LPSTR dynbuf = InetGetErrorStringAllocA(gle);
wsprintfA(buf, "There was a problem checking for updates, please try again later.\n\nError: %u %.200s", gle, dynbuf ? dynbuf : "");
mbicon = MB_ICONSTOP, msg = buf;
LocalFree(dynbuf);
}
UINT mbtype = MB_ICONQUESTION == mbicon ? MB_YESNO : MB_OK;
int mbret = MessageBoxA(hwndOwner, msg, mbtitle, mbtype|mbicon);
if (mbret == IDYES && mbtype == MB_YESNO)
{
OpenUrlInDefaultBrowser(hwndOwner, NSIS_DL_URL);
}
EnableMenuItem(g_sdata.menu, IDM_NSISUPDATE, MF_ENABLED);
}
return 0;
}
void CheckForUpdate()
{
if (strstr(g_sdata.brandingv, "cvs"))
{
MessageBoxA(g_sdata.hwnd, "Cannot check for new version of nightly builds. To update, download a new nightly build.", mbtitle, MB_OK|MB_ICONSTOP);
return;
}
EnableMenuItem(g_sdata.menu, IDM_NSISUPDATE, MF_GRAYED);
DWORD tid;
CloseHandle(CreateThread(NULL, 0, UpdateCheckWebrequestThread, (LPVOID) g_sdata.hwnd, 0, &tid));
}
|