/ windows / pvupdate.cpp
pvupdate.cpp
  1  /*******************************************************************************
  2   * pvupdate.cpp
  3   *
  4   * This module implements update checking routines.
  5   *
  6   * Author: Christopher J. Cason.
  7   *
  8   * ---------------------------------------------------------------------------
  9   * Persistence of Vision Ray Tracer ('POV-Ray') version 3.7.
 10   * Copyright 1991-2013 Persistence of Vision Raytracer Pty. Ltd.
 11   *
 12   * POV-Ray is free software: you can redistribute it and/or modify
 13   * it under the terms of the GNU Affero General Public License as
 14   * published by the Free Software Foundation, either version 3 of the
 15   * License, or (at your option) any later version.
 16   *
 17   * POV-Ray is distributed in the hope that it will be useful,
 18   * but WITHOUT ANY WARRANTY; without even the implied warranty of
 19   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 20   * GNU Affero General Public License for more details.
 21   *
 22   * You should have received a copy of the GNU Affero General Public License
 23   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 24   * ---------------------------------------------------------------------------
 25   * POV-Ray is based on the popular DKB raytracer version 2.12.
 26   * DKBTrace was originally written by David K. Buck.
 27   * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
 28   * ---------------------------------------------------------------------------
 29   * $File: //depot/public/povray/3.x/windows/pvupdate.cpp $
 30   * $Revision: #1 $
 31   * $Change: 6069 $
 32   * $DateTime: 2013/11/06 11:59:40 $
 33   * $Author: chrisc $
 34   *******************************************************************************/
 35  
 36  #define POVWIN_FILE
 37  #define _WIN32_IE COMMONCTRL_VERSION
 38  
 39  #include <windows.h>
 40  #include <wininet.h>
 41  #include <stdio.h>
 42  
 43  #include "pvengine.h"
 44  
 45  // this must be the last file included
 46  #include "syspovdebug.h"
 47  
 48  #pragma comment(lib, "wininet")
 49  
 50  #define HTTPFLAGS       INTERNET_FLAG_NO_UI | INTERNET_FLAG_NO_COOKIES | INTERNET_FLAG_PRAGMA_NOCACHE | INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_RELOAD
 51  
 52  #ifndef INTERNET_CONNECTION_CONFIGURED
 53  #define INTERNET_CONNECTION_CONFIGURED      0x40
 54  #define INTERNET_CONNECTION_OFFLINE         0x20
 55  #define INTERNET_RAS_INSTALLED              0x10
 56  #endif
 57  
 58  #ifndef SM_CMONITORS
 59  #define SM_CMONITORS 80
 60  #endif
 61  
 62  #ifndef SM_REMOTESESSION
 63  #define SM_REMOTESESSION 0x1000
 64  #endif
 65  
 66  #define SCRIPTPATH      "/updates/checkv2"
 67  
 68  using std::string;
 69  
 70  namespace povwin
 71  {
 72  
 73  static char *GetInstallTime (void)
 74  {
 75    HKEY        key ;
 76    DWORD       len ;
 77    static char str [64] ;
 78  
 79    len = sizeof (str) ;
 80    if (RegOpenKeyEx (HKEY_CURRENT_USER, "Software\\POV-Ray", 0, KEY_READ, &key) == ERROR_SUCCESS)
 81    {
 82      if (RegQueryValueEx (key, INSTALLTIMEKEY, 0, NULL, (BYTE *) str, &len) == ERROR_SUCCESS)
 83      {
 84        RegCloseKey (key) ;
 85        return (str) ;
 86      }
 87      RegCloseKey (key) ;
 88    }
 89    return (NULL) ;
 90  }
 91  
 92  bool InternetConnected (void)
 93  {
 94    DWORD       flags ;
 95  
 96    BOOL result = InternetGetConnectedState (&flags, 0) ;
 97    if ((flags & INTERNET_CONNECTION_OFFLINE) != 0)
 98      return (false) ;
 99    return (result != 0) ;
100  }
101  
102  // -1 == error, 0 == no update, 1 == update
103  int IsUpdateAvailable (bool SendSysinfo, char *CurrentVersion, string& NewVersion, string& Info)
104  {
105    int                   result = -1 ;
106    char                  poststr [2048] ;
107    char                  user_agent[128];
108    char                  str[128];
109    char                  *s = poststr ;
110    char                  *InstalledOn ;
111    HDC                   hdc ;
112    HKEY                  key ;
113    DWORD                 len;
114    DWORD                 header = 0 ;
115    DWORD                 n ;
116    FILETIME              file_time ;
117    SYSTEMTIME            system_time ;
118    SYSTEM_INFO           sysinfo ;
119    OSVERSIONINFO         version_info ;
120    MEMORYSTATUSEX        mem_status ;
121  
122    if (!InternetConnected ())
123      return (-1) ;
124    if ((InstalledOn = GetInstallTime ()) == NULL)
125    {
126      GetSystemTime (&system_time) ;
127      if (SystemTimeToFileTime (&system_time, &file_time))
128        reg_printf (true, "Software\\POV-Ray", INSTALLTIMEKEY, "%I64u", ((__int64) file_time.dwHighDateTime << 32) | file_time.dwLowDateTime) ;
129      if ((InstalledOn = GetInstallTime ()) == NULL)
130        InstalledOn = "Unknown" ;
131    }
132    sprintf (user_agent, "POVWIN %s", CurrentVersion) ;
133    HINTERNET iHandle = InternetOpen (user_agent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0) ;
134    if (iHandle == NULL)
135      return (-1) ;
136    HINTERNET cHandle = InternetConnect (iHandle, "winupdate.povray.org", 80, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0) ;
137    if (cHandle == NULL)
138    {
139      InternetCloseHandle (iHandle) ;
140      return (-1) ;
141    }
142    HINTERNET hHandle = HttpOpenRequest (cHandle, "POST", SCRIPTPATH, NULL, NULL, NULL, HTTPFLAGS, 0) ;
143    if (hHandle == NULL)
144    {
145      InternetCloseHandle (iHandle) ;
146      InternetCloseHandle (cHandle) ;
147      return (-1) ;
148    }
149    if (InstalledOn == NULL)
150      InstalledOn = "Unknown" ;
151    s += sprintf (s, "CurrentVersion=%s\n", CurrentVersion) ;
152    s += sprintf (s, "InstallDate=%s\n", InstalledOn) ;
153    if (SendSysinfo)
154    {
155      strcpy (s, "&NoInfo=false\n") ;
156      GetSystemInfo (&sysinfo) ;
157      s += sprintf (s, "CPUArchitecture=0x%04x\n", (DWORD) sysinfo.wProcessorArchitecture) ;
158      s += sprintf (s, "NumberOfCPUs=0x%04x\n", sysinfo.dwNumberOfProcessors) ;
159      s += sprintf (s, "ProcessorType=0x%04x\n", sysinfo.dwProcessorType) ;
160      s += sprintf (s, "ProcessorLevel=0x%04x\n", (DWORD) sysinfo.wProcessorLevel) ;
161      s += sprintf (s, "ProcessorRevision=0x%04x\n", (DWORD) sysinfo.wProcessorRevision) ;
162  
163      version_info.dwOSVersionInfoSize = sizeof (OSVERSIONINFO) ;
164      GetVersionEx (&version_info) ;
165      
166      s += sprintf (s, "OSVersion=%u.%u\n", version_info.dwMajorVersion, version_info.dwMinorVersion) ;
167      s += sprintf (s, "OSBuild=0x%08x\n", version_info.dwBuildNumber) ;
168      s += sprintf (s, "CSDVersion=%s\n", version_info.szCSDVersion) ;
169  
170      hdc = GetDC (NULL) ;
171      s += sprintf (s, "BitsPerPixel=%u\n", GetDeviceCaps (hdc, BITSPIXEL)) ;
172      s += sprintf (s, "HorzRes=%u\n", GetDeviceCaps (hdc, HORZRES)) ;
173      s += sprintf (s, "VertRes=%u\n", GetDeviceCaps (hdc, VERTRES)) ;
174      ReleaseDC (NULL, hdc) ;
175  
176      s += sprintf (s, "NumberOfMonitors=%u\n", GetSystemMetrics (SM_CMONITORS)) ;
177      s += sprintf (s, "HasMouseWheel=%u\n", GetSystemMetrics (SM_MOUSEWHEELPRESENT)) ;
178      s += sprintf (s, "Remote=%u\n", GetSystemMetrics (SM_REMOTESESSION)) ;
179  
180      if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, "HARDWARE\\Description\\System\\CentralProcessor\\0", 0, KEY_READ, &key) == ERROR_SUCCESS)
181      {
182        len = sizeof (n) ;
183        if (RegQueryValueEx (key, "~MHZ", 0, NULL, (BYTE *) &n, &len) == ERROR_SUCCESS)
184          s += sprintf (s, "CPUFrequency=%u\n", n) ;
185  
186        len = sizeof (n) ;
187        if (RegQueryValueEx (key, "FeatureSet", 0, NULL, (BYTE *) &n, &len) == ERROR_SUCCESS)
188          s += sprintf (s, "FeatureSet=0x%08x\n", n) ;
189  
190        len = sizeof (str) ;
191        if (RegQueryValueEx (key, "ProcessorNameString", 0, NULL, (BYTE *) str, &len) == ERROR_SUCCESS)
192          s += sprintf (s, "CPUName=%s\n", str) ;
193  
194        len = sizeof (str) ;
195        if (RegQueryValueEx (key, "Identifier", 0, NULL, (BYTE *) str, &len) == ERROR_SUCCESS)
196          s += sprintf (s, "CPUIdentifier=%s\n", str) ;
197  
198        len = sizeof (str) ;
199        if (RegQueryValueEx (key, "VendorIdentifier", 0, NULL, (BYTE *) str, &len) == ERROR_SUCCESS)
200          s += sprintf (s, "VendorIdentifier=%s\n", str) ;
201  
202        RegCloseKey (key) ;
203      }
204  
205      mem_status.dwLength = sizeof (MEMORYSTATUSEX) ;
206      GlobalMemoryStatusEx(&mem_status) ;
207      s += sprintf (s, "PhysicalMemory=%I64u\n", mem_status.ullTotalPhys) ;
208  
209      if (GetLocaleInfo (LOCALE_USER_DEFAULT, LOCALE_SLANGUAGE, str, sizeof (str)))
210        s += sprintf (s, "DefaultLanguage=%s\n", str) ;
211    }
212    else
213      strcpy (s, "NoInfo=true\n ") ;
214    if (HttpSendRequest (hHandle, NULL, 0, poststr, (DWORD) strlen (poststr)))
215    {
216      result = -3;
217      len = sizeof(str);
218      if (HttpQueryInfo (hHandle, HTTP_QUERY_STATUS_CODE, str, &len, &header))
219      {
220        if (len == 3 && memcmp (str, "200", 3) == 0)
221        {
222          char *reply = new char[131072];
223          if (InternetReadFile (hHandle, reply, 131071, &len))
224          {
225            reply[len] = '\0' ;
226            result = 0 ;
227            if (memcmp (reply, "YES ", 4) == 0)
228            {
229              result = 1 ;
230              Info.clear();
231              NewVersion = reply + 4;
232              string::size_type pos = NewVersion.find(' ');
233              if (pos != string::npos)
234              {
235                Info = NewVersion.substr(pos);
236                NewVersion.resize(pos);
237              }
238              if (NewVersion.length() == 0)
239                result = -4;
240            }
241            else if ((len == 2 && memcmp (reply, "NO", 2) == 0) || (len == 3 && memcmp (reply, "NO\n", 3) == 0))
242              result = 0 ;
243            else if ((len == 6 && memcmp (reply, "BADVER", 6) == 0) || (len == 7 && memcmp (reply, "BADVER\n", 7) == 0))
244              result = -2 ;
245            else
246              result = -4 ;
247          }
248          delete[] reply;
249        }
250      }
251    }
252    InternetCloseHandle (hHandle) ;
253    InternetCloseHandle (cHandle) ;
254    InternetCloseHandle (iHandle) ;
255    return (result) ;
256  }
257  
258  } // end of namespace povwin