-remove find() forking, we pretty much should not need this anymore, and it confused...
[oweals/gnunet.git] / src / util / winproc.c
1 /*
2      This file is part of GNUnet.
3      (C) 2001, 2002, 2003, 2004, 2005, 2006 Christian Grothoff (and other contributing authors)
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      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      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
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, "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
151   /* don't load other DLLs twice */
152   if (hNTDLL)
153     return ret;
154
155 #ifdef W32_VEH
156   if (GNWinVEH_handle == NULL)
157   {
158     GNWinVEH_handle = AddVectoredExceptionHandler (1, &GNWinVEH);
159     if (GNWinVEH_handle == NULL)
160     {
161       /* This is bad, but what can we do? */
162       printf ("Failed to set up an exception handler!\n");
163     }
164   }
165 #endif
166
167   hNTDLL = LoadLibrary ("ntdll.dll");
168
169   /* Function to get CPU usage under Win NT */
170   if (hNTDLL)
171   {
172     GNNtQuerySystemInformation =
173         (TNtQuerySystemInformation) GetProcAddress (hNTDLL,
174                                                     "NtQuerySystemInformation");
175   }
176   else
177   {
178     GNNtQuerySystemInformation = NULL;
179   }
180
181   /* Functions to get information about a network adapter */
182   hIphlpapi = LoadLibrary ("iphlpapi.dll");
183   if (hIphlpapi)
184   {
185     GNGetIfEntry = (TGetIfEntry) GetProcAddress (hIphlpapi, "GetIfEntry");
186     GNGetIpAddrTable =
187         (TGetIpAddrTable) GetProcAddress (hIphlpapi, "GetIpAddrTable");
188     GNGetIfTable = (TGetIfTable) GetProcAddress (hIphlpapi, "GetIfTable");
189     GNGetBestInterfaceEx =
190         (TGetBestInterfaceEx) GetProcAddress (hIphlpapi, "GetBestInterfaceEx");
191     GNGetAdaptersInfo =
192         (TGetAdaptersInfo) GetProcAddress (hIphlpapi, "GetAdaptersInfo");
193   }
194   else
195   {
196     GNGetIfEntry = NULL;
197     GNGetIpAddrTable = NULL;
198     GNGetIfTable = NULL;
199     GNGetBestInterfaceEx = NULL;
200     GNGetAdaptersInfo = NULL;
201   }
202
203   /* Service & Account functions */
204   hAdvapi = LoadLibrary ("advapi32.dll");
205   if (hAdvapi)
206   {
207     GNOpenSCManager =
208         (TOpenSCManager) GetProcAddress (hAdvapi, "OpenSCManagerA");
209     GNCreateService =
210         (TCreateService) GetProcAddress (hAdvapi, "CreateServiceA");
211     GNCloseServiceHandle =
212         (TCloseServiceHandle) GetProcAddress (hAdvapi, "CloseServiceHandle");
213     GNDeleteService =
214         (TDeleteService) GetProcAddress (hAdvapi, "DeleteService");
215     GNRegisterServiceCtrlHandler =
216         (TRegisterServiceCtrlHandler) GetProcAddress (hAdvapi,
217                                                       "RegisterServiceCtrlHandlerA");
218     GNSetServiceStatus =
219         (TSetServiceStatus) GetProcAddress (hAdvapi, "SetServiceStatus");
220     GNStartServiceCtrlDispatcher =
221         (TStartServiceCtrlDispatcher) GetProcAddress (hAdvapi,
222                                                       "StartServiceCtrlDispatcherA");
223     GNControlService =
224         (TControlService) GetProcAddress (hAdvapi, "ControlService");
225     GNOpenService = (TOpenService) GetProcAddress (hAdvapi, "OpenServiceA");
226
227     GNLsaOpenPolicy =
228         (TLsaOpenPolicy) GetProcAddress (hAdvapi, "LsaOpenPolicy");
229     GNLsaAddAccountRights =
230         (TLsaAddAccountRights) GetProcAddress (hAdvapi, "LsaAddAccountRights");
231     GNLsaRemoveAccountRights =
232         (TLsaRemoveAccountRights) GetProcAddress (hAdvapi,
233                                                   "LsaRemoveAccountRights");
234     GNLsaClose = (TLsaClose) GetProcAddress (hAdvapi, "LsaClose");
235     GNLookupAccountName =
236         (TLookupAccountName) GetProcAddress (hAdvapi, "LookupAccountNameA");
237
238     GNGetFileSecurity =
239         (TGetFileSecurity) GetProcAddress (hAdvapi, "GetFileSecurityA");
240     GNInitializeSecurityDescriptor =
241         (TInitializeSecurityDescriptor) GetProcAddress (hAdvapi,
242                                                         "InitializeSecurityDescriptor");
243     GNGetSecurityDescriptorDacl =
244         (TGetSecurityDescriptorDacl) GetProcAddress (hAdvapi,
245                                                      "GetSecurityDescriptorDacl");
246     GNGetAclInformation =
247         (TGetAclInformation) GetProcAddress (hAdvapi, "GetAclInformation");
248     GNInitializeAcl =
249         (TInitializeAcl) GetProcAddress (hAdvapi, "InitializeAcl");
250     GNGetAce = (TGetAce) GetProcAddress (hAdvapi, "GetAce");
251     GNEqualSid = (TEqualSid) GetProcAddress (hAdvapi, "EqualSid");
252     GNAddAce = (TAddAce) GetProcAddress (hAdvapi, "AddAce");
253     GNAddAccessAllowedAce =
254         (TAddAccessAllowedAce) GetProcAddress (hAdvapi, "AddAccessAllowedAce");
255     GNSetNamedSecurityInfo =
256         (TSetNamedSecurityInfo) GetProcAddress (hAdvapi,
257                                                 "SetNamedSecurityInfoA");
258   }
259   else
260   {
261     GNOpenSCManager = NULL;
262     GNCreateService = NULL;
263     GNCloseServiceHandle = NULL;
264     GNDeleteService = NULL;
265     GNRegisterServiceCtrlHandler = NULL;
266     GNSetServiceStatus = NULL;
267     GNStartServiceCtrlDispatcher = NULL;
268     GNControlService = NULL;
269     GNOpenService = NULL;
270
271     GNLsaOpenPolicy = NULL;
272     GNLsaAddAccountRights = NULL;
273     GNLsaRemoveAccountRights = NULL;
274     GNLsaClose = NULL;
275     GNLookupAccountName = NULL;
276
277     GNGetFileSecurity = NULL;
278     GNInitializeSecurityDescriptor = NULL;
279     GNGetSecurityDescriptorDacl = NULL;
280     GNGetAclInformation = NULL;
281     GNInitializeAcl = NULL;
282     GNGetAce = NULL;
283     GNEqualSid = NULL;
284     GNAddAce = NULL;
285     GNAddAccessAllowedAce = NULL;
286     GNSetNamedSecurityInfo = NULL;
287   }
288
289   /* Account function */
290   hNetapi = LoadLibrary ("netapi32.dll");
291   if (hNetapi)
292   {
293     GNNetUserAdd = (TNetUserAdd) GetProcAddress (hNetapi, "NetUserAdd");
294     GNNetUserSetInfo =
295         (TNetUserSetInfo) GetProcAddress (hNetapi, "NetUserSetInfo");
296   }
297   else
298   {
299     GNNetUserAdd = NULL;
300     GNNetUserSetInfo = NULL;
301   }
302
303   return ret;
304 }
305
306 /**
307  * Clean up Windows environment
308  */
309 void
310 GNShutdownWinEnv ()
311 {
312   plibc_shutdown ();
313
314 #ifdef W32_VEH
315   if (GNWinVEH_handle != NULL)
316   {
317     RemoveVectoredExceptionHandler (GNWinVEH_handle);
318     GNWinVEH_handle = NULL;
319   }
320 #endif
321
322   FreeLibrary (hNTDLL);
323   FreeLibrary (hIphlpapi);
324   FreeLibrary (hAdvapi);
325   FreeLibrary (hNetapi);
326
327   CoUninitialize ();
328 }
329
330 #endif /* MINGW */
331
332 #if !HAVE_ATOLL
333 long long
334 atoll (const char *nptr)
335 {
336   return atol (nptr);
337 }
338 #endif