Bug 322206 - Firefox net / stub installer - Inet background download code. r=bbondy
authorRobert Strong <robert.bugzilla@gmail.com>
Fri, 28 Sep 2012 15:45:41 -0700
changeset 108558 506dc963450ff8f91e1841e2c79c2b282f4f99e2
parent 108557 6e4ad6f5f8cf56e4904627c2a4209566c3cc2411
child 108559 6b15c193e5edb4992556f525730bf652879a7dc9
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersbbondy
bugs322206
milestone18.0a1
Bug 322206 - Firefox net / stub installer - Inet background download code. r=bbondy
other-licenses/nsis/Contrib/InetBgDL/InetBgDL.cpp
other-licenses/nsis/Contrib/InetBgDL/InetBgDL.dsp
other-licenses/nsis/Contrib/InetBgDL/InetBgDL.dsw
other-licenses/nsis/Contrib/InetBgDL/InetBgDL.h
new file mode 100644
--- /dev/null
+++ b/other-licenses/nsis/Contrib/InetBgDL/InetBgDL.cpp
@@ -0,0 +1,393 @@
+//
+// Copyright (C) Anders Kjersem. Licensed under the zlib/libpng license
+//
+
+#include "InetBgDL.h"
+
+#define USERAGENT _T("NSIS InetBgDL (Mozilla)")
+
+#define STATUS_COMPLETEDALL 0
+#define STATUS_INITIAL 202
+#define STATUS_CONNECTING STATUS_INITIAL //102
+#define STATUS_DOWNLOADING STATUS_INITIAL
+#define STATUS_ERR_GETLASTERROR 418 //HTTP: I'm a teapot: Win32 error code in $3
+#define STATUS_ERR_LOCALFILEWRITEERROR 450 //HTTP: MS parental control extension
+#define STATUS_ERR_CANCELLED 499
+
+typedef DWORD FILESIZE_T; // Limit to 4GB for now...
+#define FILESIZE_UNKNOWN (-1)
+
+HINSTANCE g_hInst;
+NSIS::stack_t*g_pLocations = NULL;
+HANDLE g_hThread = NULL;
+volatile UINT g_FilesTotal = 0;
+volatile UINT g_FilesCompleted = 0;
+volatile UINT g_Status = STATUS_INITIAL;
+volatile FILESIZE_T g_cbCurrXF;
+volatile FILESIZE_T g_cbCurrTot = FILESIZE_UNKNOWN;
+CRITICAL_SECTION g_CritLock;
+UINT g_N_CCH;
+PTSTR g_N_Vars;
+
+#define NSISPI_INITGLOBALS(N_CCH, N_Vars) do { \
+  g_N_CCH = N_CCH; \
+  g_N_Vars = N_Vars; \
+  } while(0)
+
+#define ONELOCKTORULETHEMALL
+#ifdef ONELOCKTORULETHEMALL
+#define TaskLock_AcquireExclusive() EnterCriticalSection(&g_CritLock)
+#define TaskLock_ReleaseExclusive() LeaveCriticalSection(&g_CritLock)
+#define StatsLock_AcquireExclusive() TaskLock_AcquireExclusive()
+#define StatsLock_ReleaseExclusive() TaskLock_ReleaseExclusive()
+#define StatsLock_AcquireShared() StatsLock_AcquireExclusive()
+#define StatsLock_ReleaseShared() StatsLock_ReleaseExclusive()
+#endif
+
+PTSTR NSIS_SetRegStr(UINT Reg, LPCTSTR Value)
+{
+  PTSTR s = g_N_Vars + (Reg * g_N_CCH);
+  lstrcpy(s, Value);
+  return s;
+}
+#define NSIS_SetRegStrEmpty(r) NSIS_SetRegStr(r, _T(""))
+void NSIS_SetRegUINT(UINT Reg, UINT Value)
+{
+  TCHAR buf[32];
+  wsprintf(buf, _T("%u"), Value);
+  NSIS_SetRegStr(Reg, buf);
+}
+#define StackFreeItem(pI) GlobalFree(pI)
+NSIS::stack_t* StackPopItem(NSIS::stack_t**ppST)
+{
+  if (*ppST)
+  {
+    NSIS::stack_t*pItem = *ppST;
+    *ppST = pItem->next;
+    return pItem;
+  }
+  return NULL;
+}
+
+void Reset()
+{
+  TaskLock_AcquireExclusive();
+#ifndef ONELOCKTORULETHEMALL
+  StatsLock_AcquireExclusive();
+#endif
+  g_FilesTotal = 0; // This causes the Task thread to exit the transfer loop
+  if (g_hThread)
+  {
+    if (WAIT_OBJECT_0 != WaitForSingleObject(g_hThread, 10 * 1000))
+    {
+      TerminateThread(g_hThread, ERROR_OPERATION_ABORTED);
+    }
+    CloseHandle(g_hThread);
+  }
+  g_hThread = NULL;
+  g_FilesTotal = 0;
+  g_FilesCompleted = 0;
+  g_Status = STATUS_INITIAL;
+#ifndef ONELOCKTORULETHEMALL
+  StatsLock_ReleaseExclusive();
+#endif
+  for (NSIS::stack_t*pTmpTast,*pTask = g_pLocations; pTask ;)
+  {
+    pTmpTast = pTask;
+    pTask = pTask->next;
+    StackFreeItem(pTmpTast);
+  }
+  g_pLocations = NULL;
+  TaskLock_ReleaseExclusive();
+}
+
+UINT_PTR __cdecl NSISPluginCallback(UINT Event)
+{
+  switch(Event)
+  {
+  case NSPIM_UNLOAD:
+    Reset();
+    break;
+  }
+  return NULL;
+}
+
+DWORD CALLBACK TaskThreadProc(LPVOID ThreadParam)
+{
+  NSIS::stack_t *pURL,*pFile;
+  HINTERNET hInetSes = NULL;
+  HANDLE hLocalFile;
+  bool completedFile = false;
+startnexttask:
+  hLocalFile = INVALID_HANDLE_VALUE;
+  pFile = NULL;
+  TaskLock_AcquireExclusive();
+  pURL = g_pLocations;
+  if (pURL)
+  {
+    pFile = pURL->next;
+    g_pLocations = pFile->next;
+  }
+#ifndef ONELOCKTORULETHEMALL
+  StatsLock_AcquireExclusive();
+#endif
+  if (completedFile) {
+    ++g_FilesCompleted;
+  }
+  completedFile = false;
+  g_cbCurrXF = 0;
+  g_cbCurrTot = FILESIZE_UNKNOWN;
+  if (!pURL)
+  {
+    if (g_FilesTotal)
+    {
+      if (g_FilesTotal == g_FilesCompleted) {
+        g_Status = STATUS_COMPLETEDALL;
+      }
+    }
+    g_hThread = NULL;
+  }
+#ifndef ONELOCKTORULETHEMALL
+  StatsLock_ReleaseExclusive();
+#endif
+  TaskLock_ReleaseExclusive();
+
+  if (!pURL)
+  {
+    if (0)
+    {
+diegle:
+      DWORD gle = GetLastError();
+      //TODO? if (ERROR_INTERNET_EXTENDED_ERROR==gle) InternetGetLastResponseInfo(...)
+      g_Status = STATUS_ERR_GETLASTERROR;
+    }
+    if (hInetSes)
+    {
+      InternetCloseHandle(hInetSes);
+    }
+    if (INVALID_HANDLE_VALUE != hLocalFile)
+    {
+      CloseHandle(hLocalFile);
+    }
+    StackFreeItem(pURL);
+    StackFreeItem(pFile);
+    return 0;
+  }
+
+  if (!hInetSes)
+  {
+    hInetSes = InternetOpen(USERAGENT, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
+    if (!hInetSes)
+    {
+      goto diegle;
+    }
+
+    //msdn.microsoft.com/library/default.asp?url=/workshop/components/offline/offline.asp#Supporting Offline Browsing in Applications and Components
+    ULONG longOpt;
+    DWORD cbio = sizeof(ULONG);
+    if (InternetQueryOption(hInetSes, INTERNET_OPTION_CONNECTED_STATE, &longOpt, &cbio))
+    {
+      if (INTERNET_STATE_DISCONNECTED_BY_USER&longOpt)
+      {
+        INTERNET_CONNECTED_INFO ci = {INTERNET_STATE_CONNECTED, 0};
+        InternetSetOption(hInetSes, INTERNET_OPTION_CONNECTED_STATE, &ci, sizeof(ci));
+      }
+    }
+  }
+
+  DWORD ec = ERROR_SUCCESS;
+  hLocalFile = CreateFile(pFile->text,GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_DELETE,NULL,CREATE_ALWAYS,0,NULL);
+  if (INVALID_HANDLE_VALUE == hLocalFile) {
+    goto diegle;
+  }
+
+  const DWORD IOUFTPFlags = INTERNET_FLAG_PASSIVE;
+  const DWORD IOURedirFlags = INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP | INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS;
+  const DWORD IOUCacheFlags = INTERNET_FLAG_RESYNCHRONIZE | INTERNET_FLAG_NO_CACHE_WRITE;
+  const DWORD IOUCookieFlags = INTERNET_FLAG_NO_COOKIES;
+  DWORD IOUFlags = IOUFTPFlags | IOURedirFlags | IOUCacheFlags | IOUCookieFlags | INTERNET_FLAG_NO_UI | INTERNET_FLAG_EXISTING_CONNECT;
+  HINTERNET hInetFile = InternetOpenUrl(hInetSes, pURL->text, NULL, 0, IOUFlags, NULL);
+  if (!hInetFile) {
+    goto diegle;
+  }
+
+  FILESIZE_T cbThisFile;
+  DWORD cbio = sizeof(cbThisFile);
+  if (!HttpQueryInfo(hInetFile, HTTP_QUERY_CONTENT_LENGTH|HTTP_QUERY_FLAG_NUMBER, &cbThisFile, &cbio, NULL))
+  {
+    cbThisFile = FILESIZE_UNKNOWN;
+  }
+
+  for(;;)
+  {
+#if PLUGIN_DEBUG
+    const UINT cbBufXF = 512;
+    BYTE bufXF[cbBufXF];
+#else
+    const UINT cbBufXF = 4096;
+    BYTE*bufXF = (BYTE*) pURL->text;
+#endif
+    DWORD cbio,cbXF;
+    BOOL retXF = InternetReadFile(hInetFile, bufXF, cbBufXF, &cbio);
+    if (!retXF)
+    {
+      ec = GetLastError();
+      TRACE1(_T("InternetReadFile failed, gle=%u\n"), ec);
+      break;
+    }
+    if (0 == cbio)
+    {
+      ASSERT(ERROR_SUCCESS == ec);
+      // EOF or broken connection?
+      // TODO: Can InternetQueryDataAvailable detect this?
+
+      TRACE2(_T("InternetReadFile true with 0 cbio, cbThisFile=%d gle=%u\n"), cbThisFile, GetLastError());
+      // If we haven't transferred all of the file, and we know how big the file
+      // is, and we have no more data to read from the HTTP request, then set a
+      // broken pipe error. Reading without StatsLock is ok in this thread.
+      if (FILESIZE_UNKNOWN != cbThisFile && g_cbCurrXF != cbThisFile)
+      {
+        ec = ERROR_BROKEN_PIPE;
+      }
+
+      break;
+    }
+
+    if (0==g_FilesTotal)
+    {
+      TRACEA("0==g_FilesTotal, aborting transfer loop...\n");
+      ec = ERROR_CANCELLED;
+      break;
+    }
+
+    cbXF = cbio;
+    if (cbXF)
+    {
+      retXF = WriteFile(hLocalFile, bufXF, cbXF, &cbio, NULL);
+      if (!retXF || cbXF!=cbio)
+      {
+        ec = GetLastError();
+        break;
+      }
+
+      StatsLock_AcquireExclusive();
+      if (FILESIZE_UNKNOWN != cbThisFile) {
+        g_cbCurrTot = cbThisFile;
+      }
+      g_cbCurrXF += cbXF;
+      StatsLock_ReleaseExclusive();
+    }
+  }
+
+  TRACE2(_T("TaskThreadProc completed %s, ec=%u\n"), pURL->text, ec);
+  InternetCloseHandle(hInetFile);
+  if (ERROR_SUCCESS == ec) {
+    if (INVALID_HANDLE_VALUE != hLocalFile) {
+      CloseHandle(hLocalFile);
+      hLocalFile = INVALID_HANDLE_VALUE;
+    }
+    StackFreeItem(pURL);
+    StackFreeItem(pFile);
+    ++completedFile;
+  }
+  else
+  {
+    SetLastError(ec);
+    goto diegle;
+  }
+  goto startnexttask;
+}
+
+NSISPIEXPORTFUNC Get(HWND hwndNSIS, UINT N_CCH, TCHAR*N_Vars, NSIS::stack_t**ppST, NSIS::xparams_t*pX)
+{
+  pX->RegisterPluginCallback(g_hInst, NSISPluginCallback);
+  for (;;)
+  {
+    NSIS::stack_t*pURL = StackPopItem(ppST);
+    if (!pURL) {
+      break;
+    }
+
+    if (0==lstrcmp(pURL->text,_T("/END")))
+    {
+freeurlandexit:
+      StackFreeItem(pURL);
+      break;
+    }
+    if (0==lstrcmp(pURL->text,_T("/RESET")))
+    {
+      StackFreeItem(pURL);
+      Reset();
+      continue;
+    }
+
+    NSIS::stack_t*pFile = StackPopItem(ppST);
+    if (!pFile) {
+      goto freeurlandexit;
+    }
+
+    TaskLock_AcquireExclusive();
+
+    pFile->next = NULL;
+    pURL->next = pFile;
+    NSIS::stack_t*pTasksTail = g_pLocations;
+    while(pTasksTail && pTasksTail->next) pTasksTail = pTasksTail->next;
+    if (pTasksTail)
+    {
+      pTasksTail->next = pURL;
+    }
+    else
+    {
+      g_pLocations = pURL;
+    }
+
+    if (!g_hThread)
+    {
+      DWORD tid;tid;
+      g_hThread = CreateThread(NULL, 0, TaskThreadProc, NULL, 0, &tid);
+    }
+
+    if (!g_hThread) {
+      goto freeurlandexit;
+    }
+
+#ifndef ONELOCKTORULETHEMALL
+    StatsLock_AcquireExclusive();
+#endif
+    ++g_FilesTotal;
+#ifndef ONELOCKTORULETHEMALL
+    StatsLock_ReleaseExclusive();
+#endif
+    TaskLock_ReleaseExclusive();
+  }
+}
+
+NSISPIEXPORTFUNC GetStats(HWND hwndNSIS, UINT N_CCH, TCHAR*N_Vars, NSIS::stack_t**ppST, NSIS::xparams_t*pX)
+{
+  NSISPI_INITGLOBALS(N_CCH, N_Vars);
+  StatsLock_AcquireShared();
+  NSIS_SetRegUINT(0, g_Status);
+  NSIS_SetRegUINT(1, g_FilesCompleted);
+  NSIS_SetRegUINT(2, g_FilesTotal - g_FilesCompleted);
+  NSIS_SetRegUINT(3, g_cbCurrXF);
+  NSIS_SetRegStrEmpty(4);
+  if (FILESIZE_UNKNOWN != g_cbCurrTot) {
+    NSIS_SetRegUINT(4, g_cbCurrTot);
+  }
+  StatsLock_ReleaseShared();
+}
+
+EXTERN_C BOOL WINAPI _DllMainCRTStartup(HMODULE hInst, UINT Reason, LPVOID pCtx)
+{
+  if (DLL_PROCESS_ATTACH==Reason)
+  {
+    g_hInst=hInst;
+    InitializeCriticalSection(&g_CritLock);
+  }
+  return TRUE;
+}
+
+BOOL WINAPI DllMain(HINSTANCE hInst, ULONG Reason, LPVOID pCtx)
+{
+  return _DllMainCRTStartup(hInst, Reason, pCtx);
+}
new file mode 100644
--- /dev/null
+++ b/other-licenses/nsis/Contrib/InetBgDL/InetBgDL.dsp
@@ -0,0 +1,159 @@
+# Microsoft Developer Studio Project File - Name="InetBgDL" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=InetBgDL - Win32 Debug Unicode
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "InetBgDL.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "InetBgDL.mak" CFG="InetBgDL - Win32 Debug Unicode"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "InetBgDL - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "InetBgDL - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "InetBgDL - Win32 Release Unicode" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "InetBgDL - Win32 Debug Unicode" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "InetBgDL - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "InetBgDL_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "InetBgDL_EXPORTS" /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comctl32.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"DllMain" /dll /machine:I386 /nodefaultlib /out:"../../Plugins/InetBgDL.dll" /opt:nowin98
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "InetBgDL - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "InetBgDL_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "InetBgDL_EXPORTS" /YX /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+
+!ELSEIF  "$(CFG)" == "InetBgDL - Win32 Release Unicode"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "InetBgDL___Win32_Release_Unicode"
+# PROP BASE Intermediate_Dir "InetBgDL___Win32_Release_Unicode"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release_Unicode"
+# PROP Intermediate_Dir "Release_Unicode"
+# PROP Ignore_Export_Lib 1
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "InetBgDL_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O1 /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "InetBgDL_EXPORTS" /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comctl32.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"DllMain" /dll /machine:I386 /nodefaultlib /out:"../../Plugins/InetBgDL.dll" /opt:nowin98
+# SUBTRACT BASE LINK32 /pdb:none
+# ADD LINK32 wininet.lib kernel32.lib user32.lib gdi32.lib winspool.lib comctl32.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /entry:"DllMain" /dll /machine:I386 /out:"./Unicode/InetBgDL.dll" /opt:nowin98
+# SUBTRACT LINK32 /pdb:none /nodefaultlib
+
+!ELSEIF  "$(CFG)" == "InetBgDL - Win32 Debug Unicode"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "InetBgDL___Win32_Debug_Unicode"
+# PROP BASE Intermediate_Dir "InetBgDL___Win32_Debug_Unicode"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug_Unicode"
+# PROP Intermediate_Dir "Debug_Unicode"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "InetBgDL_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "InetBgDL_EXPORTS" /YX /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+
+!ENDIF 
+
+# Begin Target
+
+# Name "InetBgDL - Win32 Release"
+# Name "InetBgDL - Win32 Debug"
+# Name "InetBgDL - Win32 Release Unicode"
+# Name "InetBgDL - Win32 Debug Unicode"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\InetBgDL.cpp
+# End Source File
+# End Group
+# End Target
+# End Project
new file mode 100644
--- /dev/null
+++ b/other-licenses/nsis/Contrib/InetBgDL/InetBgDL.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "InetBgDL"=.\InetBgDL.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
new file mode 100644
--- /dev/null
+++ b/other-licenses/nsis/Contrib/InetBgDL/InetBgDL.h
@@ -0,0 +1,58 @@
+//
+// Copyright (C) Anders Kjersem. Licensed under the zlib/libpng license
+//
+
+#if (defined(_MSC_VER) && !defined(_DEBUG))
+  #pragma comment(linker,"/opt:nowin98")
+  #pragma comment(linker,"/ignore:4078")
+  #pragma comment(linker,"/merge:.rdata=.text")
+#endif
+
+#ifdef UNICODE
+# ifndef _UNICODE
+#    define _UNICODE
+#  endif
+#endif
+
+#define _WIN32_WINNT 0x0400
+#include <windows.h>
+#include <tchar.h>
+#include <wininet.h>
+
+#if defined(_DEBUG) || 0
+#  define PLUGIN_DEBUG 1
+#  define TRACE2(fmt,p1,p2) do {TCHAR b[666];wsprintf(b,fmt,p1,p2);OutputDebugString(b);}while(0)
+#  define TRACEA OutputDebugStringA
+#else
+#  define TRACE2(fmt,p1,p2)
+#  define TRACEA(fmt)
+#endif
+#define TRACE1(fmt,p1) TRACE2(fmt,p1,0)
+
+#ifndef ASSERT
+#  define ASSERT(x)
+#endif
+
+#define NSISPIEXPORTFUNC EXTERN_C void __declspec(dllexport) __cdecl
+
+namespace NSIS {
+
+#define NSISCALL __stdcall
+typedef struct _xparams_t {
+  LPVOID xx1;//exec_flags_type *exec_flags;
+  int (NSISCALL *ExecuteCodeSegment)(int, HWND);
+  void (NSISCALL *validate_filename)(TCHAR*);
+  int (NSISCALL *RegisterPluginCallback)(HMODULE,LPVOID);
+} xparams_t;
+typedef struct _stack_t {
+  struct _stack_t *next;
+  TCHAR text[1];
+} stack_t;
+
+} // namespace NSIS
+
+enum NSPIM 
+{
+  NSPIM_UNLOAD,
+  NSPIM_GUIUNLOAD,
+};