packet-dcerpc: nca_s_fault_sec_pkg_error
[metze/wireshark/wip.git] / ws_version_info.c
1 /* ws_version_info.c
2  * Routines to report version information for Wireshark programs
3  *
4  * Wireshark - Network traffic analyzer
5  * By Gerald Combs <gerald@wireshark.org>
6  * Copyright 1998 Gerald Combs
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21  */
22
23 #include <config.h>
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <locale.h>
29
30 #ifdef _WIN32
31 #include <windows.h>
32 #endif
33
34 #include <glib.h>
35
36 #ifdef HAVE_ZLIB
37 #include <zlib.h>
38 #endif
39
40 #include "version.h"
41
42 #include "ws_version_info.h"
43
44 #include <wsutil/ws_cpuid.h>
45 #include <wsutil/copyright_info.h>
46 #include <wsutil/os_version_info.h>
47 #include <wsutil/ws_printf.h> /* ws_debug_printf */
48
49 /*
50  * If the string doesn't end with a newline, append one.
51  * Then word-wrap it to 80 columns.
52  */
53 static void
54 end_string(GString *str)
55 {
56         size_t point;
57         char *p, *q;
58
59         point = str->len;
60         if (point == 0 || str->str[point - 1] != '\n')
61                 g_string_append(str, "\n");
62         p = str->str;
63         while (*p != '\0') {
64                 q = strchr(p, '\n');
65                 if (q - p > 80) {
66                         /*
67                          * Break at or before this point.
68                          */
69                         q = p + 80;
70                         while (q > p && *q != ' ')
71                                 q--;
72                         if (q != p)
73                                 *q = '\n';
74                 }
75                 p = q + 1;
76         }
77 }
78
79 static const gchar *
80 get_zlib_compiled_version_info(void)
81 {
82 #ifdef HAVE_ZLIB
83 #ifdef ZLIB_VERSION
84         return "with zlib "ZLIB_VERSION;
85 #else
86         return "with zlib (version unknown)";
87 #endif /* ZLIB_VERSION */
88 #else
89         return "without zlib";
90 #endif /* HAVE_ZLIB */
91 }
92
93 /*
94  * Get various library compile-time versions, put them in a GString,
95  * and return the GString.
96  *
97  * "prepend_info" is called at the start to prepend any additional
98  * information before the standard library information.
99  *
100  * "append_info" is called at the end to append any additional
101  * information after the standard library information.  This is
102  * required in order to, for example, put the Portaudio information
103  * at the end of the string, as we currently don't use Portaudio in
104  * TShark.
105  */
106 GString *
107 get_compiled_version_info(void (*prepend_info)(GString *),
108                           void (*append_info)(GString *))
109 {
110         GString *str;
111
112         str = g_string_new("Compiled ");
113
114         if (sizeof(str) == 4)
115                 g_string_append(str, "(32-bit) ");
116         else
117                 g_string_append(str, "(64-bit) ");
118
119         if (prepend_info) {
120                 (*prepend_info)(str);
121                 g_string_append(str, ", ");
122         }
123
124         /* GLIB */
125         g_string_append(str, "with ");
126         g_string_append_printf(str,
127 #ifdef GLIB_MAJOR_VERSION
128             "GLib %d.%d.%d", GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION,
129             GLIB_MICRO_VERSION);
130 #else
131             "GLib (version unknown)");
132 #endif
133
134         g_string_append_printf(str, ", %s", get_zlib_compiled_version_info());
135
136         /* Additional application-dependent information */
137         if (append_info)
138                 (*append_info)(str);
139         g_string_append(str, ".");
140
141         end_string(str);
142
143         return str;
144 }
145
146 /*
147  * Get the CPU info, and append it to the GString
148  */
149 static void
150 get_cpu_info(GString *str)
151 {
152         guint32 CPUInfo[4];
153         char CPUBrandString[0x40];
154         unsigned nExIds;
155
156         /* http://msdn.microsoft.com/en-us/library/hskdteyh(v=vs.100).aspx */
157
158         /* Calling __cpuid with 0x80000000 as the InfoType argument*/
159         /* gets the number of valid extended IDs.*/
160         if (!ws_cpuid(CPUInfo, 0x80000000))
161                 return;
162         nExIds = CPUInfo[0];
163
164         if( nExIds<0x80000005)
165                 return;
166         memset(CPUBrandString, 0, sizeof(CPUBrandString));
167
168         /* Interpret CPU brand string.*/
169         ws_cpuid(CPUInfo, 0x80000002);
170         memcpy(CPUBrandString, CPUInfo, sizeof(CPUInfo));
171         ws_cpuid(CPUInfo, 0x80000003);
172         memcpy(CPUBrandString + 16, CPUInfo, sizeof(CPUInfo));
173         ws_cpuid(CPUInfo, 0x80000004);
174         memcpy(CPUBrandString + 32, CPUInfo, sizeof(CPUInfo));
175
176         g_string_append_printf(str, "\n%s", CPUBrandString);
177
178         if (ws_cpuid_sse42())
179                 g_string_append(str, " (with SSE4.2)");
180 }
181
182 static void
183 get_mem_info(GString *str _U_)
184 {
185 #ifdef _WIN32
186         MEMORYSTATUSEX statex;
187
188         statex.dwLength = sizeof (statex);
189
190         if (GlobalMemoryStatusEx(&statex))
191                 g_string_append_printf(str, ", with ""%" G_GINT64_MODIFIER "d" "MB of physical memory.\n", statex.ullTotalPhys/(1024*1024));
192 #endif
193 }
194
195 /*
196  * Get compiler information, and append it to the GString.
197  */
198 static void
199 get_compiler_info(GString *str)
200 {
201         /*
202          * See https://sourceforge.net/apps/mediawiki/predef/index.php?title=Compilers
203          * information on various defined strings.
204          *
205          * GCC's __VERSION__ is a nice text string for humans to
206          * read.  The page at sourceforge.net largely describes
207          * numeric #defines that encode the version; if the compiler
208          * doesn't also offer a nice printable string, we try prettifying
209          * the number somehow.
210          */
211 #if defined(__GNUC__) && defined(__VERSION__)
212         /*
213          * Clang and llvm-gcc also define __GNUC__ and __VERSION__;
214          * distinguish between them.
215          */
216 #if defined(__clang__)
217         g_string_append_printf(str, "\n\nBuilt using clang %s.\n", __VERSION__);
218 #elif defined(__llvm__)
219         g_string_append_printf(str, "\n\nBuilt using llvm-gcc %s.\n", __VERSION__);
220 #else /* boring old GCC */
221         g_string_append_printf(str, "\n\nBuilt using gcc %s.\n", __VERSION__);
222 #endif /* llvm */
223 #elif defined(__HP_aCC)
224         g_string_append_printf(str, "\n\nBuilt using HP aCC %d.\n", __HP_aCC);
225 #elif defined(__xlC__)
226         g_string_append_printf(str, "\n\nBuilt using IBM XL C %d.%d\n",
227             (__xlC__ >> 8) & 0xFF, __xlC__ & 0xFF);
228 #ifdef __IBMC__
229         if ((__IBMC__ % 10) != 0)
230                 g_string_append_printf(str, " patch %d", __IBMC__ % 10);
231 #endif /* __IBMC__ */
232         g_string_append_printf(str, "\n");
233 #elif defined(__INTEL_COMPILER)
234         g_string_append_printf(str, "\n\nBuilt using Intel C %d.%d",
235             __INTEL_COMPILER / 100, (__INTEL_COMPILER / 10) % 10);
236         if ((__INTEL_COMPILER % 10) != 0)
237                 g_string_append_printf(str, " patch %d", __INTEL_COMPILER % 10);
238 #ifdef __INTEL_COMPILER_BUILD_DATE
239         g_string_sprinta(str, ", compiler built %04d-%02d-%02d",
240             __INTEL_COMPILER_BUILD_DATE / 10000,
241             (__INTEL_COMPILER_BUILD_DATE / 100) % 100,
242             __INTEL_COMPILER_BUILD_DATE % 100);
243 #endif /* __INTEL_COMPILER_BUILD_DATE */
244         g_string_append_printf(str, "\n");
245 #elif defined(_MSC_FULL_VER)
246 # if _MSC_FULL_VER > 99999999
247         /* Quote from the web:
248          * Bakersfield: DevDiv's upper management determines the scheduling of new major versions.
249          * They also decided to increment the product version from 12 (for VS 2013) to 14 (for VS 2015).
250          * However, the C++ compiler's version incremented normally, from 18 to 19.
251          * (It's larger because the C++ compiler predates the "Visual" in Visual C++.)
252          * XXX? Should we just output the compiler version?
253          */
254     int compiler_major_version = (_MSC_FULL_VER / 10000000), visual_studio_ver;
255
256     if (compiler_major_version < 19) {
257         visual_studio_ver = compiler_major_version - 6;
258     }else{
259         visual_studio_ver = compiler_major_version - 5;
260     }
261
262     g_string_append_printf(str, "\n\nBuilt using Microsoft Visual C++ %d.%d",
263                    visual_studio_ver,
264                                (_MSC_FULL_VER / 100000) % 100);
265 #  if (_MSC_FULL_VER % 100000) != 0
266         g_string_append_printf(str, " build %d",
267                                _MSC_FULL_VER % 100000);
268 #  endif
269 # else
270         g_string_append_printf(str, "\n\nBuilt using Microsoft Visual C++ %d.%d",
271                                (_MSC_FULL_VER / 1000000) - 6,
272                                (_MSC_FULL_VER / 10000) % 100);
273 #  if (_MSC_FULL_VER % 10000) != 0
274         g_string_append_printf(str, " build %d",
275                                _MSC_FULL_VER % 10000);
276 #  endif
277 # endif
278         g_string_append_printf(str, "\n");
279 #elif defined(_MSC_VER)
280         /* _MSC_FULL_VER not defined, but _MSC_VER defined */
281         g_string_append_printf(str, "\n\nBuilt using Microsoft Visual C++ %d.%d\n",
282             (_MSC_VER / 100) - 6, _MSC_VER % 100);
283 #elif defined(__SUNPRO_C)
284         g_string_append_printf(str, "\n\nBuilt using Sun C %d.%d",
285             (__SUNPRO_C >> 8) & 0xF, (__SUNPRO_C >> 4) & 0xF);
286         if ((__SUNPRO_C & 0xF) != 0)
287                 g_string_append_printf(str, " patch %d", __SUNPRO_C & 0xF);
288         g_string_append_printf(str, "\n");
289 #endif
290 }
291
292 /* XXX - is the setlocale() return string opaque? For glibc the separator is ';' */
293 static gchar *
294 get_locale(void)
295 {
296         const gchar *lang;
297         gchar **locv, *loc;
298
299         lang = setlocale(LC_ALL, NULL);
300         if (lang == NULL) {
301                 return NULL;
302         }
303
304         locv = g_strsplit(lang, ";", -1);
305         loc = g_strjoinv(", ", locv);
306         g_strfreev(locv);
307         return loc;
308 }
309
310 /*
311  * Get various library run-time versions, and the OS version, and append
312  * them to the specified GString.
313  *
314  * "additional_info" is called at the end to append any additional
315  * information; this is required in order to, for example, put the
316  * Portaudio information at the end of the string, as we currently
317  * don't use Portaudio in TShark.
318  */
319 GString *
320 get_runtime_version_info(void (*additional_info)(GString *))
321 {
322         GString *str;
323         gchar *lang;
324
325         str = g_string_new("Running on ");
326
327         get_os_version_info(str);
328
329         /*
330          * Locale.
331          *
332          * This returns the C language's locale information; this
333          * returns the locale that's actually in effect, even if
334          * it doesn't happen to match the settings of any of the
335          * locale environment variables.
336          *
337          * On Windows get_locale returns the full language, country
338          * name, and code page, e.g. "English_United States.1252":
339          * https://msdn.microsoft.com/en-us/library/x99tb11d.aspx
340          */
341         if ((lang = get_locale()) != NULL) {
342                 g_string_append_printf(str, ", with locale %s", lang);
343                 g_free(lang);
344         }
345         else {
346                 g_string_append(str, ", with default locale");
347         }
348
349
350         /* Additional application-dependent information */
351         if (additional_info)
352                 (*additional_info)(str);
353
354         /* zlib */
355 #if defined(HAVE_ZLIB) && !defined(_WIN32)
356         g_string_append_printf(str, ", with zlib %s", zlibVersion());
357 #endif
358
359         g_string_append(str, ".");
360
361         /* CPU Info */
362         get_cpu_info(str);
363
364         /* Get info about installed memory Windows only */
365         get_mem_info(str);
366
367         /* Compiler info */
368         get_compiler_info(str);
369
370         end_string(str);
371
372         return str;
373 }
374
375 void
376 show_version(const gchar *prog_name_str, GString *comp_info_str,
377              GString *runtime_info_str)
378 {
379         ws_debug_printf("%s %s\n"
380                "\n"
381                "%s"
382                "\n"
383                "%s"
384                "\n"
385                "%s",
386                prog_name_str, get_ws_vcs_version_info(), get_copyright_info(),
387                comp_info_str->str, runtime_info_str->str);
388 }
389
390 /*
391  * Return a version number string for Wireshark, including, for builds
392  * from a tree checked out from Wireshark's version control system,
393  * something identifying what version was checked out.
394  */
395 const char *
396 get_ws_vcs_version_info(void)
397 {
398 #ifdef VCSVERSION
399         return VERSION " (" VCSVERSION " from " VCSBRANCH ")";
400 #else
401         return VERSION;
402 #endif
403 }
404
405 /*
406  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
407  *
408  * Local variables:
409  * c-basic-offset: 8
410  * tab-width: 8
411  * indent-tabs-mode: t
412  * End:
413  *
414  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
415  * :indentSize=8:tabSize=8:noTabs=false:
416  */