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