working again
[oweals/gnunet.git] / src / util / winproc.c
index aa4757f4a949dec828a62aabf7199eb1f12b2826..18fa368a9572d5586e3f46728ef5351a644f748a 100644 (file)
@@ -4,7 +4,7 @@
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 2, or (at your
+     by the Free Software Foundation; either version 3, or (at your
      option) any later version.
 
      GNUnet is distributed in the hope that it will be useful, but
  */
 
 #include "platform.h"
+#include "gnunet_crypto_lib.h"
 #include "gnunet_common.h"
 
-#define DEBUG_WINPROC 0
 
 #ifdef MINGW
 
 static HINSTANCE hNTDLL, hIphlpapi, hAdvapi, hNetapi;
+#ifdef W32_VEH
+static void *GNWinVEH_handle = NULL;
+#endif
 
 TNtQuerySystemInformation GNNtQuerySystemInformation;
 TGetIfEntry GNGetIfEntry;
@@ -46,8 +49,8 @@ TSetServiceStatus GNSetServiceStatus;
 TStartServiceCtrlDispatcher GNStartServiceCtrlDispatcher;
 TControlService GNControlService;
 TOpenService GNOpenService;
-TGetBestInterface GNGetBestInterface;
-TGetAdaptersInfo GGetAdaptersInfo;
+TGetBestInterfaceEx GNGetBestInterfaceEx;
+TGetAdaptersInfo GNGetAdaptersInfo;
 TNetUserAdd GNNetUserAdd;
 TNetUserSetInfo GNNetUserSetInfo;
 TLsaOpenPolicy GNLsaOpenPolicy;
@@ -73,11 +76,64 @@ TSetNamedSecurityInfo GNSetNamedSecurityInfo;
 void
 plibc_panic (int err, char *msg)
 {
-  LOG (((err ==
-        INT_MAX) ? GNUNET_ERROR_TYPE_DEBUG : GNUNET_ERROR_TYPE_ERROR),
+  LOG (((err == INT_MAX) ? GNUNET_ERROR_TYPE_DEBUG : GNUNET_ERROR_TYPE_ERROR),
        "%s", msg);
 }
 
+#ifdef W32_VEH
+/**
+ * Handles exceptions (useful for debugging).
+ * Issues a DebugBreak() call if the process is being debugged (not really
+ * useful - if the process is being debugged, this handler won't be invoked
+ * anyway). If it is not, runs a debugger from GNUNET_DEBUGGER env var,
+ * substituting first %u in it for PID, and the second one for the event,
+ * that should be set once the debugger attaches itself (otherwise the
+ * only way out of WaitForSingleObject() is to time out after 1 minute).
+ */
+LONG __stdcall
+GNWinVEH (PEXCEPTION_POINTERS ExceptionInfo)
+{
+  char debugger[MAX_PATH + 1];
+  char *debugger_env = NULL;
+  if (IsDebuggerPresent ())
+  {
+    DebugBreak ();
+    return EXCEPTION_CONTINUE_EXECUTION;
+  }
+  debugger_env = getenv ("GNUNET_DEBUGGER");
+  if (debugger_env != NULL)
+  {
+    STARTUPINFO si;
+    PROCESS_INFORMATION pi;
+    HANDLE event;
+    SECURITY_ATTRIBUTES sa;
+    memset (&si, 0, sizeof (si));
+    si.cb = sizeof (si);
+    memset (&pi, 0, sizeof (pi));
+    memset (&sa, 0, sizeof (sa));
+    sa.nLength = sizeof (sa);
+    sa.bInheritHandle = TRUE;
+    event = CreateEvent (&sa, FALSE, FALSE, NULL);
+    snprintf (debugger, MAX_PATH + 1, debugger_env, GetCurrentProcessId (), (uintptr_t) event);
+    debugger[MAX_PATH] = '\0';
+    if (0 != CreateProcessA (NULL, debugger, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi))
+    {
+      CloseHandle (pi.hProcess);
+      CloseHandle (pi.hThread);
+      WaitForSingleObject (event, 60000);
+      CloseHandle (event);
+      if (IsDebuggerPresent ())
+      {
+        return EXCEPTION_CONTINUE_EXECUTION;
+      }
+    }
+    else
+      CloseHandle (event);
+  }
+  return EXCEPTION_CONTINUE_SEARCH;
+}
+#endif
+
 /**
  * @brief Initialize PlibC and set up Windows environment
  * @param logging context, NULL means stderr
@@ -90,149 +146,159 @@ GNInitWinEnv ()
 
   plibc_initialized ();
   plibc_set_panic_proc (plibc_panic);
-  ret = plibc_init ("GNU", PACKAGE);
+  ret = plibc_init_utf8 ("GNU", PACKAGE, 1);
 
   /* don't load other DLLs twice */
   if (hNTDLL)
     return ret;
 
+#ifdef W32_VEH
+  if (GNWinVEH_handle == NULL)
+  {
+    GNWinVEH_handle = AddVectoredExceptionHandler (1, &GNWinVEH);
+    if (GNWinVEH_handle == NULL)
+    {
+      /* This is bad, but what can we do? */
+      printf ("Failed to set up an exception handler!\n");
+    }
+  }
+#endif
+
   hNTDLL = LoadLibrary ("ntdll.dll");
 
   /* Function to get CPU usage under Win NT */
   if (hNTDLL)
-    {
-      GNNtQuerySystemInformation =
-       (TNtQuerySystemInformation) GetProcAddress (hNTDLL,
-                                                   "NtQuerySystemInformation");
-    }
+  {
+    GNNtQuerySystemInformation =
+        (TNtQuerySystemInformation) GetProcAddress (hNTDLL,
+                                                    "NtQuerySystemInformation");
+  }
   else
-    {
-      GNNtQuerySystemInformation = NULL;
-    }
+  {
+    GNNtQuerySystemInformation = NULL;
+  }
 
   /* Functions to get information about a network adapter */
   hIphlpapi = LoadLibrary ("iphlpapi.dll");
   if (hIphlpapi)
-    {
-      GNGetIfEntry = (TGetIfEntry) GetProcAddress (hIphlpapi, "GetIfEntry");
-      GNGetIpAddrTable =
-       (TGetIpAddrTable) GetProcAddress (hIphlpapi, "GetIpAddrTable");
-      GNGetIfTable = (TGetIfTable) GetProcAddress (hIphlpapi, "GetIfTable");
-      GNGetBestInterface =
-       (TGetBestInterface) GetProcAddress (hIphlpapi, "GetBestInterface");
-      GGetAdaptersInfo =
-       (TGetAdaptersInfo) GetProcAddress (hIphlpapi, "GetAdaptersInfo");
-    }
+  {
+    GNGetIfEntry = (TGetIfEntry) GetProcAddress (hIphlpapi, "GetIfEntry");
+    GNGetIpAddrTable =
+        (TGetIpAddrTable) GetProcAddress (hIphlpapi, "GetIpAddrTable");
+    GNGetIfTable = (TGetIfTable) GetProcAddress (hIphlpapi, "GetIfTable");
+    GNGetBestInterfaceEx =
+        (TGetBestInterfaceEx) GetProcAddress (hIphlpapi, "GetBestInterfaceEx");
+    GNGetAdaptersInfo =
+        (TGetAdaptersInfo) GetProcAddress (hIphlpapi, "GetAdaptersInfo");
+  }
   else
-    {
-      GNGetIfEntry = NULL;
-      GNGetIpAddrTable = NULL;
-      GNGetIfTable = NULL;
-      GNGetBestInterface = NULL;
-      GGetAdaptersInfo = NULL;
-    }
+  {
+    GNGetIfEntry = NULL;
+    GNGetIpAddrTable = NULL;
+    GNGetIfTable = NULL;
+    GNGetBestInterfaceEx = NULL;
+    GNGetAdaptersInfo = NULL;
+  }
 
   /* Service & Account functions */
   hAdvapi = LoadLibrary ("advapi32.dll");
   if (hAdvapi)
-    {
-      GNOpenSCManager =
-       (TOpenSCManager) GetProcAddress (hAdvapi, "OpenSCManagerA");
-      GNCreateService =
-       (TCreateService) GetProcAddress (hAdvapi, "CreateServiceA");
-      GNCloseServiceHandle =
-       (TCloseServiceHandle) GetProcAddress (hAdvapi, "CloseServiceHandle");
-      GNDeleteService =
-       (TDeleteService) GetProcAddress (hAdvapi, "DeleteService");
-      GNRegisterServiceCtrlHandler =
-       (TRegisterServiceCtrlHandler) GetProcAddress (hAdvapi,
-                                                     "RegisterServiceCtrlHandlerA");
-      GNSetServiceStatus =
-       (TSetServiceStatus) GetProcAddress (hAdvapi, "SetServiceStatus");
-      GNStartServiceCtrlDispatcher =
-       (TStartServiceCtrlDispatcher) GetProcAddress (hAdvapi,
-                                                     "StartServiceCtrlDispatcherA");
-      GNControlService =
-       (TControlService) GetProcAddress (hAdvapi, "ControlService");
-      GNOpenService = (TOpenService) GetProcAddress (hAdvapi, "OpenServiceA");
+  {
+    GNOpenSCManager =
+        (TOpenSCManager) GetProcAddress (hAdvapi, "OpenSCManagerA");
+    GNCreateService =
+        (TCreateService) GetProcAddress (hAdvapi, "CreateServiceA");
+    GNCloseServiceHandle =
+        (TCloseServiceHandle) GetProcAddress (hAdvapi, "CloseServiceHandle");
+    GNDeleteService =
+        (TDeleteService) GetProcAddress (hAdvapi, "DeleteService");
+    GNRegisterServiceCtrlHandler =
+        (TRegisterServiceCtrlHandler) GetProcAddress (hAdvapi,
+                                                      "RegisterServiceCtrlHandlerA");
+    GNSetServiceStatus =
+        (TSetServiceStatus) GetProcAddress (hAdvapi, "SetServiceStatus");
+    GNStartServiceCtrlDispatcher =
+        (TStartServiceCtrlDispatcher) GetProcAddress (hAdvapi,
+                                                      "StartServiceCtrlDispatcherA");
+    GNControlService =
+        (TControlService) GetProcAddress (hAdvapi, "ControlService");
+    GNOpenService = (TOpenService) GetProcAddress (hAdvapi, "OpenServiceA");
 
-      GNLsaOpenPolicy =
-       (TLsaOpenPolicy) GetProcAddress (hAdvapi, "LsaOpenPolicy");
-      GNLsaAddAccountRights =
-       (TLsaAddAccountRights) GetProcAddress (hAdvapi,
-                                              "LsaAddAccountRights");
-      GNLsaRemoveAccountRights =
-       (TLsaRemoveAccountRights) GetProcAddress (hAdvapi,
-                                                 "LsaRemoveAccountRights");
-      GNLsaClose = (TLsaClose) GetProcAddress (hAdvapi, "LsaClose");
-      GNLookupAccountName =
-       (TLookupAccountName) GetProcAddress (hAdvapi, "LookupAccountNameA");
+    GNLsaOpenPolicy =
+        (TLsaOpenPolicy) GetProcAddress (hAdvapi, "LsaOpenPolicy");
+    GNLsaAddAccountRights =
+        (TLsaAddAccountRights) GetProcAddress (hAdvapi, "LsaAddAccountRights");
+    GNLsaRemoveAccountRights =
+        (TLsaRemoveAccountRights) GetProcAddress (hAdvapi,
+                                                  "LsaRemoveAccountRights");
+    GNLsaClose = (TLsaClose) GetProcAddress (hAdvapi, "LsaClose");
+    GNLookupAccountName =
+        (TLookupAccountName) GetProcAddress (hAdvapi, "LookupAccountNameA");
 
-      GNGetFileSecurity =
-       (TGetFileSecurity) GetProcAddress (hAdvapi, "GetFileSecurityA");
-      GNInitializeSecurityDescriptor =
-       (TInitializeSecurityDescriptor) GetProcAddress (hAdvapi,
-                                                       "InitializeSecurityDescriptor");
-      GNGetSecurityDescriptorDacl =
-       (TGetSecurityDescriptorDacl) GetProcAddress (hAdvapi,
-                                                    "GetSecurityDescriptorDacl");
-      GNGetAclInformation =
-       (TGetAclInformation) GetProcAddress (hAdvapi, "GetAclInformation");
-      GNInitializeAcl =
-       (TInitializeAcl) GetProcAddress (hAdvapi, "InitializeAcl");
-      GNGetAce = (TGetAce) GetProcAddress (hAdvapi, "GetAce");
-      GNEqualSid = (TEqualSid) GetProcAddress (hAdvapi, "EqualSid");
-      GNAddAce = (TAddAce) GetProcAddress (hAdvapi, "AddAce");
-      GNAddAccessAllowedAce =
-       (TAddAccessAllowedAce) GetProcAddress (hAdvapi,
-                                              "AddAccessAllowedAce");
-      GNSetNamedSecurityInfo =
-       (TSetNamedSecurityInfo) GetProcAddress (hAdvapi,
-                                               "SetNamedSecurityInfoA");
-    }
+    GNGetFileSecurity =
+        (TGetFileSecurity) GetProcAddress (hAdvapi, "GetFileSecurityA");
+    GNInitializeSecurityDescriptor =
+        (TInitializeSecurityDescriptor) GetProcAddress (hAdvapi,
+                                                        "InitializeSecurityDescriptor");
+    GNGetSecurityDescriptorDacl =
+        (TGetSecurityDescriptorDacl) GetProcAddress (hAdvapi,
+                                                     "GetSecurityDescriptorDacl");
+    GNGetAclInformation =
+        (TGetAclInformation) GetProcAddress (hAdvapi, "GetAclInformation");
+    GNInitializeAcl =
+        (TInitializeAcl) GetProcAddress (hAdvapi, "InitializeAcl");
+    GNGetAce = (TGetAce) GetProcAddress (hAdvapi, "GetAce");
+    GNEqualSid = (TEqualSid) GetProcAddress (hAdvapi, "EqualSid");
+    GNAddAce = (TAddAce) GetProcAddress (hAdvapi, "AddAce");
+    GNAddAccessAllowedAce =
+        (TAddAccessAllowedAce) GetProcAddress (hAdvapi, "AddAccessAllowedAce");
+    GNSetNamedSecurityInfo =
+        (TSetNamedSecurityInfo) GetProcAddress (hAdvapi,
+                                                "SetNamedSecurityInfoA");
+  }
   else
-    {
-      GNOpenSCManager = NULL;
-      GNCreateService = NULL;
-      GNCloseServiceHandle = NULL;
-      GNDeleteService = NULL;
-      GNRegisterServiceCtrlHandler = NULL;
-      GNSetServiceStatus = NULL;
-      GNStartServiceCtrlDispatcher = NULL;
-      GNControlService = NULL;
-      GNOpenService = NULL;
+  {
+    GNOpenSCManager = NULL;
+    GNCreateService = NULL;
+    GNCloseServiceHandle = NULL;
+    GNDeleteService = NULL;
+    GNRegisterServiceCtrlHandler = NULL;
+    GNSetServiceStatus = NULL;
+    GNStartServiceCtrlDispatcher = NULL;
+    GNControlService = NULL;
+    GNOpenService = NULL;
 
-      GNLsaOpenPolicy = NULL;
-      GNLsaAddAccountRights = NULL;
-      GNLsaRemoveAccountRights = NULL;
-      GNLsaClose = NULL;
-      GNLookupAccountName = NULL;
+    GNLsaOpenPolicy = NULL;
+    GNLsaAddAccountRights = NULL;
+    GNLsaRemoveAccountRights = NULL;
+    GNLsaClose = NULL;
+    GNLookupAccountName = NULL;
 
-      GNGetFileSecurity = NULL;
-      GNInitializeSecurityDescriptor = NULL;
-      GNGetSecurityDescriptorDacl = NULL;
-      GNGetAclInformation = NULL;
-      GNInitializeAcl = NULL;
-      GNGetAce = NULL;
-      GNEqualSid = NULL;
-      GNAddAce = NULL;
-      GNAddAccessAllowedAce = NULL;
-      GNSetNamedSecurityInfo = NULL;
-    }
+    GNGetFileSecurity = NULL;
+    GNInitializeSecurityDescriptor = NULL;
+    GNGetSecurityDescriptorDacl = NULL;
+    GNGetAclInformation = NULL;
+    GNInitializeAcl = NULL;
+    GNGetAce = NULL;
+    GNEqualSid = NULL;
+    GNAddAce = NULL;
+    GNAddAccessAllowedAce = NULL;
+    GNSetNamedSecurityInfo = NULL;
+  }
 
   /* Account function */
   hNetapi = LoadLibrary ("netapi32.dll");
   if (hNetapi)
-    {
-      GNNetUserAdd = (TNetUserAdd) GetProcAddress (hNetapi, "NetUserAdd");
-      GNNetUserSetInfo =
-       (TNetUserSetInfo) GetProcAddress (hNetapi, "NetUserSetInfo");
-    }
+  {
+    GNNetUserAdd = (TNetUserAdd) GetProcAddress (hNetapi, "NetUserAdd");
+    GNNetUserSetInfo =
+        (TNetUserSetInfo) GetProcAddress (hNetapi, "NetUserSetInfo");
+  }
   else
-    {
-      GNNetUserAdd = NULL;
-      GNNetUserSetInfo = NULL;
-    }
+  {
+    GNNetUserAdd = NULL;
+    GNNetUserSetInfo = NULL;
+  }
 
   return ret;
 }
@@ -245,6 +311,14 @@ GNShutdownWinEnv ()
 {
   plibc_shutdown ();
 
+#ifdef W32_VEH
+  if (GNWinVEH_handle != NULL)
+  {
+    RemoveVectoredExceptionHandler (GNWinVEH_handle);
+    GNWinVEH_handle = NULL;
+  }
+#endif
+
   FreeLibrary (hNTDLL);
   FreeLibrary (hIphlpapi);
   FreeLibrary (hAdvapi);