Don't shadow the system() function
[oweals/gnunet.git] / src / util / winproc.c
index 9594c5d6f78181890cf416e0551320e359f8aff2..7f020c6dc79c579cd66b75fd1472b25f6f2ce6fb 100644 (file)
@@ -1,10 +1,10 @@
 /*
      This file is part of GNUnet.
-     (C) 2001, 2002, 2003, 2004, 2005, 2006 Christian Grothoff (and other contributing authors)
+     Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 Christian Grothoff (and other contributing authors)
 
      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;
@@ -66,16 +69,70 @@ TAddAce GNAddAce;
 TAddAccessAllowedAce GNAddAccessAllowedAce;
 TSetNamedSecurityInfo GNSetNamedSecurityInfo;
 
+#define LOG(kind,...) GNUNET_log_from (kind, "winproc", __VA_ARGS__)
 /**
  * Log (panic) messages from PlibC
  */
 void
 plibc_panic (int err, char *msg)
 {
-  GNUNET_log (((err ==
-                INT_MAX) ? GNUNET_ERROR_TYPE_DEBUG : GNUNET_ERROR_TYPE_ERROR),
-              "%s", msg);
+  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
@@ -89,12 +146,25 @@ GNInitWinEnv ()
 
   plibc_initialized ();
   plibc_set_panic_proc (plibc_panic);
-  ret = plibc_init ("GNU", PACKAGE);
-
+  ret = plibc_init_utf8 ("GNU", PACKAGE, 1);
+  plibc_set_stat_size_size (sizeof (((struct stat *) 0)->st_size));
+  plibc_set_stat_time_size (sizeof (((struct stat *) 0)->st_mtime));
   /* 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 */
@@ -117,9 +187,9 @@ GNInitWinEnv ()
     GNGetIpAddrTable =
         (TGetIpAddrTable) GetProcAddress (hIphlpapi, "GetIpAddrTable");
     GNGetIfTable = (TGetIfTable) GetProcAddress (hIphlpapi, "GetIfTable");
-    GNGetBestInterface =
-        (TGetBestInterface) GetProcAddress (hIphlpapi, "GetBestInterface");
-    GGetAdaptersInfo =
+    GNGetBestInterfaceEx =
+        (TGetBestInterfaceEx) GetProcAddress (hIphlpapi, "GetBestInterfaceEx");
+    GNGetAdaptersInfo =
         (TGetAdaptersInfo) GetProcAddress (hIphlpapi, "GetAdaptersInfo");
   }
   else
@@ -127,8 +197,8 @@ GNInitWinEnv ()
     GNGetIfEntry = NULL;
     GNGetIpAddrTable = NULL;
     GNGetIfTable = NULL;
-    GNGetBestInterface = NULL;
-    GGetAdaptersInfo = NULL;
+    GNGetBestInterfaceEx = NULL;
+    GNGetAdaptersInfo = NULL;
   }
 
   /* Service & Account functions */
@@ -242,6 +312,14 @@ GNShutdownWinEnv ()
 {
   plibc_shutdown ();
 
+#ifdef W32_VEH
+  if (GNWinVEH_handle != NULL)
+  {
+    RemoveVectoredExceptionHandler (GNWinVEH_handle);
+    GNWinVEH_handle = NULL;
+  }
+#endif
+
   FreeLibrary (hNTDLL);
   FreeLibrary (hIphlpapi);
   FreeLibrary (hAdvapi);