replace SPDX identifier GPL-2.0+ with GPL-2.0-or-later.
[metze/wireshark/wip.git] / wsutil / win32-utils.c
1 /* win32-utils.c
2  * Win32 utility routines
3  *
4  * Wireshark - Network traffic analyzer
5  * By Gerald Combs <gerald@wireshark.org>
6  * Copyright 2006 Gerald Combs
7  *
8  * SPDX-License-Identifier: GPL-2.0-or-later
9  */
10
11 #include "win32-utils.h"
12
13 /* Quote the argument element if necessary, so that it will get
14  * reconstructed correctly in the C runtime startup code.  Note that
15  * the unquoting algorithm in the C runtime is really weird, and
16  * rather different than what Unix shells do. See stdargv.c in the C
17  * runtime sources (in the Platform SDK, in src/crt).
18  *
19  * Stolen from GLib's protect_argv(), an internal routine that quotes
20  * string in an argument list so that they arguments will be handled
21  * correctly in the command-line string passed to CreateProcess()
22  * if that string is constructed by gluing those strings together.
23  */
24 gchar *
25 protect_arg (const gchar *argv)
26 {
27     gchar *new_arg;
28     const gchar *p = argv;
29     gchar *q;
30     gint len = 0;
31     gboolean need_dblquotes = FALSE;
32
33     while (*p) {
34         if (*p == ' ' || *p == '\t')
35             need_dblquotes = TRUE;
36         else if (*p == '"')
37             len++;
38         else if (*p == '\\') {
39             const gchar *pp = p;
40
41             while (*pp && *pp == '\\')
42                 pp++;
43             if (*pp == '"')
44                 len++;
45         }
46         len++;
47         p++;
48     }
49
50     q = new_arg = g_malloc (len + need_dblquotes*2 + 1);
51     p = argv;
52
53     if (need_dblquotes)
54         *q++ = '"';
55
56     while (*p) {
57         if (*p == '"')
58             *q++ = '\\';
59         else if (*p == '\\') {
60             const gchar *pp = p;
61
62             while (*pp && *pp == '\\')
63                 pp++;
64             if (*pp == '"')
65                 *q++ = '\\';
66         }
67         *q++ = *p;
68         p++;
69     }
70
71     if (need_dblquotes)
72         *q++ = '"';
73     *q++ = '\0';
74
75     return new_arg;
76 }
77
78 /*
79  * Generate a string for a Win32 error.
80  */
81 #define ERRBUF_SIZE    1024
82 const char *
83 win32strerror(DWORD error)
84 {
85     static char errbuf[ERRBUF_SIZE+1];
86     size_t errlen;
87     char *p;
88
89     FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
90                    NULL, error, 0, errbuf, ERRBUF_SIZE, NULL);
91
92     /*
93      * "FormatMessage()" "helpfully" sticks CR/LF at the end of the
94      * message.  Get rid of it.
95      */
96     errlen = strlen(errbuf);
97     if (errlen >= 2) {
98         errbuf[errlen - 1] = '\0';
99         errbuf[errlen - 2] = '\0';
100     }
101     p = strchr(errbuf, '\0');
102     g_snprintf(p, (gulong)(sizeof errbuf - (p-errbuf)), " (%lu)", error);
103     return errbuf;
104 }
105
106 /*
107  * Generate a string for a Win32 exception code.
108  */
109 const char *
110 win32strexception(DWORD exception)
111 {
112     static char errbuf[ERRBUF_SIZE+1];
113     static const struct exception_msg {
114         int code;
115         char *msg;
116     } exceptions[] = {
117         { EXCEPTION_ACCESS_VIOLATION, "Access violation" },
118         { EXCEPTION_ARRAY_BOUNDS_EXCEEDED, "Array bounds exceeded" },
119         { EXCEPTION_BREAKPOINT, "Breakpoint" },
120         { EXCEPTION_DATATYPE_MISALIGNMENT, "Data type misalignment" },
121         { EXCEPTION_FLT_DENORMAL_OPERAND, "Denormal floating-point operand" },
122         { EXCEPTION_FLT_DIVIDE_BY_ZERO, "Floating-point divide by zero" },
123         { EXCEPTION_FLT_INEXACT_RESULT, "Floating-point inexact result" },
124         { EXCEPTION_FLT_INVALID_OPERATION, "Invalid floating-point operation" },
125         { EXCEPTION_FLT_OVERFLOW, "Floating-point overflow" },
126         { EXCEPTION_FLT_STACK_CHECK, "Floating-point stack check" },
127         { EXCEPTION_FLT_UNDERFLOW, "Floating-point underflow" },
128         { EXCEPTION_GUARD_PAGE, "Guard page violation" },
129         { EXCEPTION_ILLEGAL_INSTRUCTION, "Illegal instruction" },
130         { EXCEPTION_IN_PAGE_ERROR, "Page-in error" },
131         { EXCEPTION_INT_DIVIDE_BY_ZERO, "Integer divide by zero" },
132         { EXCEPTION_INT_OVERFLOW, "Integer overflow" },
133         { EXCEPTION_INVALID_DISPOSITION, "Invalid disposition" },
134         { EXCEPTION_INVALID_HANDLE, "Invalid handle" },
135         { EXCEPTION_NONCONTINUABLE_EXCEPTION, "Non-continuable exception" },
136         { EXCEPTION_PRIV_INSTRUCTION, "Privileged instruction" },
137         { EXCEPTION_SINGLE_STEP, "Single-step complete" },
138         { EXCEPTION_STACK_OVERFLOW, "Stack overflow" },
139         { 0, NULL }
140     };
141 #define N_EXCEPTIONS    (sizeof exceptions / sizeof exceptions[0])
142     int i;
143
144     for (i = 0; i < N_EXCEPTIONS; i++) {
145         if (exceptions[i].code == exception)
146             return exceptions[i].msg;
147     }
148     g_snprintf(errbuf, (gulong)sizeof errbuf, "Exception 0x%08x", exception);
149     return errbuf;
150 }
151
152 /*
153  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
154  *
155  * Local Variables:
156  * c-basic-offset: 2
157  * tab-width: 8
158  * indent-tabs-mode: nil
159  * End:
160  *
161  * ex: set shiftwidth=2 tabstop=8 expandtab:
162  * :indentSize=2:tabSize=8:noTabs=true:
163  */