fix assertion failure reported in #5578
[oweals/gnunet.git] / src / util / winproc.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 GNUnet e.V.
4
5      GNUnet is free software: you can redistribute it and/or modify it
6      under the terms of the GNU Affero General Public License as published
7      by the Free Software Foundation, either version 3 of the License,
8      or (at your option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      Affero General Public License for more details.
14     
15      You should have received a copy of the GNU Affero General Public License
16      along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18      SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21 /**
22  * @file util/winproc.c
23  * @brief Functions for MS Windows
24  * @author Nils Durner
25  */
26
27 #include "platform.h"
28 #include "gnunet_crypto_lib.h"
29 #include "gnunet_common.h"
30
31
32 #ifdef MINGW
33
34 static HINSTANCE hNTDLL, hIphlpapi, hAdvapi, hNetapi;
35 #ifdef W32_VEH
36 static void *GNWinVEH_handle = NULL;
37 #endif
38
39 TNtQuerySystemInformation GNNtQuerySystemInformation;
40 TGetIfEntry GNGetIfEntry;
41 TGetIpAddrTable GNGetIpAddrTable;
42 TGetIfTable GNGetIfTable;
43 TOpenSCManager GNOpenSCManager;
44 TCreateService GNCreateService;
45 TCloseServiceHandle GNCloseServiceHandle;
46 TDeleteService GNDeleteService;
47 TRegisterServiceCtrlHandler GNRegisterServiceCtrlHandler;
48 TSetServiceStatus GNSetServiceStatus;
49 TStartServiceCtrlDispatcher GNStartServiceCtrlDispatcher;
50 TControlService GNControlService;
51 TOpenService GNOpenService;
52 TGetBestInterfaceEx GNGetBestInterfaceEx;
53 TGetAdaptersInfo GNGetAdaptersInfo;
54 TNetUserAdd GNNetUserAdd;
55 TNetUserSetInfo GNNetUserSetInfo;
56 TLsaOpenPolicy GNLsaOpenPolicy;
57 TLsaAddAccountRights GNLsaAddAccountRights;
58 TLsaRemoveAccountRights GNLsaRemoveAccountRights;
59 TLsaClose GNLsaClose;
60 TLookupAccountName GNLookupAccountName;
61 TGetFileSecurity GNGetFileSecurity;
62 TInitializeSecurityDescriptor GNInitializeSecurityDescriptor;
63 TGetSecurityDescriptorDacl GNGetSecurityDescriptorDacl;
64 TGetAclInformation GNGetAclInformation;
65 TInitializeAcl GNInitializeAcl;
66 TGetAce GNGetAce;
67 TEqualSid GNEqualSid;
68 TAddAce GNAddAce;
69 TAddAccessAllowedAce GNAddAccessAllowedAce;
70 TSetNamedSecurityInfo GNSetNamedSecurityInfo;
71
72 #define LOG(kind,...) GNUNET_log_from (kind, "util-winproc", __VA_ARGS__)
73 /**
74  * Log (panic) messages from PlibC
75  */
76 void
77 plibc_panic (int err, char *msg)
78 {
79   LOG (((err == INT_MAX) ? GNUNET_ERROR_TYPE_DEBUG : GNUNET_ERROR_TYPE_ERROR),
80        "%s", msg);
81 }
82
83 #ifdef W32_VEH
84 /**
85  * Handles exceptions (useful for debugging).
86  * Issues a DebugBreak() call if the process is being debugged (not really
87  * useful - if the process is being debugged, this handler won't be invoked
88  * anyway). If it is not, runs a debugger from GNUNET_DEBUGGER env var,
89  * substituting first %u in it for PID, and the second one for the event,
90  * that should be set once the debugger attaches itself (otherwise the
91  * only way out of WaitForSingleObject() is to time out after 1 minute).
92  */
93 LONG __stdcall
94 GNWinVEH (PEXCEPTION_POINTERS ExceptionInfo)
95 {
96   char debugger[MAX_PATH + 1];
97   char *debugger_env = NULL;
98   if (IsDebuggerPresent ())
99   {
100     DebugBreak ();
101     return EXCEPTION_CONTINUE_EXECUTION;
102   }
103   debugger_env = getenv ("GNUNET_DEBUGGER");
104   if (debugger_env != NULL)
105   {
106     STARTUPINFO si;
107     PROCESS_INFORMATION pi;
108     HANDLE event;
109     SECURITY_ATTRIBUTES sa;
110     memset (&si, 0, sizeof (si));
111     si.cb = sizeof (si);
112     memset (&pi, 0, sizeof (pi));
113     memset (&sa, 0, sizeof (sa));
114     sa.nLength = sizeof (sa);
115     sa.bInheritHandle = TRUE;
116     event = CreateEvent (&sa, FALSE, FALSE, NULL);
117     snprintf (debugger, MAX_PATH + 1, debugger_env, GetCurrentProcessId (), (uintptr_t) event);
118     debugger[MAX_PATH] = '\0';
119     if (0 != CreateProcessA (NULL, debugger, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi))
120     {
121       CloseHandle (pi.hProcess);
122       CloseHandle (pi.hThread);
123       WaitForSingleObject (event, 60000);
124       CloseHandle (event);
125       if (IsDebuggerPresent ())
126       {
127         return EXCEPTION_CONTINUE_EXECUTION;
128       }
129     }
130     else
131       CloseHandle (event);
132   }
133   return EXCEPTION_CONTINUE_SEARCH;
134 }
135 #endif
136
137 /**
138  * @brief Initialize PlibC and set up Windows environment
139  * @param logging context, NULL means stderr
140  * @return Error code from winerror.h, ERROR_SUCCESS on success
141 */
142 int
143 GNInitWinEnv ()
144 {
145   int ret;
146
147   plibc_initialized ();
148   plibc_set_panic_proc (plibc_panic);
149   ret = plibc_init_utf8 ("GNU", PACKAGE, 1);
150   plibc_set_stat_size_size (sizeof (((struct stat *) 0)->st_size));
151   plibc_set_stat_time_size (sizeof (((struct stat *) 0)->st_mtime));
152   /* don't load other DLLs twice */
153   if (hNTDLL)
154     return ret;
155
156 #ifdef W32_VEH
157   if (GNWinVEH_handle == NULL)
158   {
159     GNWinVEH_handle = AddVectoredExceptionHandler (1, &GNWinVEH);
160     if (GNWinVEH_handle == NULL)
161     {
162       /* This is bad, but what can we do? */
163       printf ("Failed to set up an exception handler!\n");
164     }
165   }
166 #endif
167
168   hNTDLL = LoadLibrary ("ntdll.dll");
169
170   /* Function to get CPU usage under Win NT */
171   if (hNTDLL)
172   {
173     GNNtQuerySystemInformation =
174         (TNtQuerySystemInformation) GetProcAddress (hNTDLL,
175                                                     "NtQuerySystemInformation");
176   }
177   else
178   {
179     GNNtQuerySystemInformation = NULL;
180   }
181
182   /* Functions to get information about a network adapter */
183   hIphlpapi = LoadLibrary ("iphlpapi.dll");
184   if (hIphlpapi)
185   {
186     GNGetIfEntry = (TGetIfEntry) GetProcAddress (hIphlpapi, "GetIfEntry");
187     GNGetIpAddrTable =
188         (TGetIpAddrTable) GetProcAddress (hIphlpapi, "GetIpAddrTable");
189     GNGetIfTable = (TGetIfTable) GetProcAddress (hIphlpapi, "GetIfTable");
190     GNGetBestInterfaceEx =
191         (TGetBestInterfaceEx) GetProcAddress (hIphlpapi, "GetBestInterfaceEx");
192     GNGetAdaptersInfo =
193         (TGetAdaptersInfo) GetProcAddress (hIphlpapi, "GetAdaptersInfo");
194   }
195   else
196   {
197     GNGetIfEntry = NULL;
198     GNGetIpAddrTable = NULL;
199     GNGetIfTable = NULL;
200     GNGetBestInterfaceEx = NULL;
201     GNGetAdaptersInfo = NULL;
202   }
203
204   /* Service & Account functions */
205   hAdvapi = LoadLibrary ("advapi32.dll");
206   if (hAdvapi)
207   {
208     GNOpenSCManager =
209         (TOpenSCManager) GetProcAddress (hAdvapi, "OpenSCManagerA");
210     GNCreateService =
211         (TCreateService) GetProcAddress (hAdvapi, "CreateServiceA");
212     GNCloseServiceHandle =
213         (TCloseServiceHandle) GetProcAddress (hAdvapi, "CloseServiceHandle");
214     GNDeleteService =
215         (TDeleteService) GetProcAddress (hAdvapi, "DeleteService");
216     GNRegisterServiceCtrlHandler =
217         (TRegisterServiceCtrlHandler) GetProcAddress (hAdvapi,
218                                                       "RegisterServiceCtrlHandlerA");
219     GNSetServiceStatus =
220         (TSetServiceStatus) GetProcAddress (hAdvapi, "SetServiceStatus");
221     GNStartServiceCtrlDispatcher =
222         (TStartServiceCtrlDispatcher) GetProcAddress (hAdvapi,
223                                                       "StartServiceCtrlDispatcherA");
224     GNControlService =
225         (TControlService) GetProcAddress (hAdvapi, "ControlService");
226     GNOpenService = (TOpenService) GetProcAddress (hAdvapi, "OpenServiceA");
227
228     GNLsaOpenPolicy =
229         (TLsaOpenPolicy) GetProcAddress (hAdvapi, "LsaOpenPolicy");
230     GNLsaAddAccountRights =
231         (TLsaAddAccountRights) GetProcAddress (hAdvapi, "LsaAddAccountRights");
232     GNLsaRemoveAccountRights =
233         (TLsaRemoveAccountRights) GetProcAddress (hAdvapi,
234                                                   "LsaRemoveAccountRights");
235     GNLsaClose = (TLsaClose) GetProcAddress (hAdvapi, "LsaClose");
236     GNLookupAccountName =
237         (TLookupAccountName) GetProcAddress (hAdvapi, "LookupAccountNameA");
238
239     GNGetFileSecurity =
240         (TGetFileSecurity) GetProcAddress (hAdvapi, "GetFileSecurityA");
241     GNInitializeSecurityDescriptor =
242         (TInitializeSecurityDescriptor) GetProcAddress (hAdvapi,
243                                                         "InitializeSecurityDescriptor");
244     GNGetSecurityDescriptorDacl =
245         (TGetSecurityDescriptorDacl) GetProcAddress (hAdvapi,
246                                                      "GetSecurityDescriptorDacl");
247     GNGetAclInformation =
248         (TGetAclInformation) GetProcAddress (hAdvapi, "GetAclInformation");
249     GNInitializeAcl =
250         (TInitializeAcl) GetProcAddress (hAdvapi, "InitializeAcl");
251     GNGetAce = (TGetAce) GetProcAddress (hAdvapi, "GetAce");
252     GNEqualSid = (TEqualSid) GetProcAddress (hAdvapi, "EqualSid");
253     GNAddAce = (TAddAce) GetProcAddress (hAdvapi, "AddAce");
254     GNAddAccessAllowedAce =
255         (TAddAccessAllowedAce) GetProcAddress (hAdvapi, "AddAccessAllowedAce");
256     GNSetNamedSecurityInfo =
257         (TSetNamedSecurityInfo) GetProcAddress (hAdvapi,
258                                                 "SetNamedSecurityInfoA");
259   }
260   else
261   {
262     GNOpenSCManager = NULL;
263     GNCreateService = NULL;
264     GNCloseServiceHandle = NULL;
265     GNDeleteService = NULL;
266     GNRegisterServiceCtrlHandler = NULL;
267     GNSetServiceStatus = NULL;
268     GNStartServiceCtrlDispatcher = NULL;
269     GNControlService = NULL;
270     GNOpenService = NULL;
271
272     GNLsaOpenPolicy = NULL;
273     GNLsaAddAccountRights = NULL;
274     GNLsaRemoveAccountRights = NULL;
275     GNLsaClose = NULL;
276     GNLookupAccountName = NULL;
277
278     GNGetFileSecurity = NULL;
279     GNInitializeSecurityDescriptor = NULL;
280     GNGetSecurityDescriptorDacl = NULL;
281     GNGetAclInformation = NULL;
282     GNInitializeAcl = NULL;
283     GNGetAce = NULL;
284     GNEqualSid = NULL;
285     GNAddAce = NULL;
286     GNAddAccessAllowedAce = NULL;
287     GNSetNamedSecurityInfo = NULL;
288   }
289
290   /* Account function */
291   hNetapi = LoadLibrary ("netapi32.dll");
292   if (hNetapi)
293   {
294     GNNetUserAdd = (TNetUserAdd) GetProcAddress (hNetapi, "NetUserAdd");
295     GNNetUserSetInfo =
296         (TNetUserSetInfo) GetProcAddress (hNetapi, "NetUserSetInfo");
297   }
298   else
299   {
300     GNNetUserAdd = NULL;
301     GNNetUserSetInfo = NULL;
302   }
303
304   return ret;
305 }
306
307 /**
308  * Clean up Windows environment
309  */
310 void
311 GNShutdownWinEnv ()
312 {
313   plibc_shutdown ();
314
315 #ifdef W32_VEH
316   if (GNWinVEH_handle != NULL)
317   {
318     RemoveVectoredExceptionHandler (GNWinVEH_handle);
319     GNWinVEH_handle = NULL;
320   }
321 #endif
322
323   FreeLibrary (hNTDLL);
324   FreeLibrary (hIphlpapi);
325   FreeLibrary (hAdvapi);
326   FreeLibrary (hNetapi);
327
328   CoUninitialize ();
329 }
330
331 #endif /* MINGW */
332
333 #if !HAVE_ATOLL
334 long long
335 atoll (const char *nptr)
336 {
337   return atol (nptr);
338 }
339 #endif