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.
 /*
      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
 
      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
      option) any later version.
 
      GNUnet is distributed in the hope that it will be useful, but
  */
 
 #include "platform.h"
  */
 
 #include "platform.h"
+#include "gnunet_crypto_lib.h"
 #include "gnunet_common.h"
 
 #include "gnunet_common.h"
 
-#define DEBUG_WINPROC 0
 
 #ifdef MINGW
 
 static HINSTANCE hNTDLL, hIphlpapi, hAdvapi, hNetapi;
 
 #ifdef MINGW
 
 static HINSTANCE hNTDLL, hIphlpapi, hAdvapi, hNetapi;
+#ifdef W32_VEH
+static void *GNWinVEH_handle = NULL;
+#endif
 
 TNtQuerySystemInformation GNNtQuerySystemInformation;
 TGetIfEntry GNGetIfEntry;
 
 TNtQuerySystemInformation GNNtQuerySystemInformation;
 TGetIfEntry GNGetIfEntry;
@@ -46,8 +49,8 @@ TSetServiceStatus GNSetServiceStatus;
 TStartServiceCtrlDispatcher GNStartServiceCtrlDispatcher;
 TControlService GNControlService;
 TOpenService GNOpenService;
 TStartServiceCtrlDispatcher GNStartServiceCtrlDispatcher;
 TControlService GNControlService;
 TOpenService GNOpenService;
-TGetBestInterface GNGetBestInterface;
-TGetAdaptersInfo GGetAdaptersInfo;
+TGetBestInterfaceEx GNGetBestInterfaceEx;
+TGetAdaptersInfo GNGetAdaptersInfo;
 TNetUserAdd GNNetUserAdd;
 TNetUserSetInfo GNNetUserSetInfo;
 TLsaOpenPolicy GNLsaOpenPolicy;
 TNetUserAdd GNNetUserAdd;
 TNetUserSetInfo GNNetUserSetInfo;
 TLsaOpenPolicy GNLsaOpenPolicy;
@@ -66,16 +69,70 @@ TAddAce GNAddAce;
 TAddAccessAllowedAce GNAddAccessAllowedAce;
 TSetNamedSecurityInfo GNSetNamedSecurityInfo;
 
 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)
 {
 /**
  * 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
 
 /**
  * @brief Initialize PlibC and set up Windows environment
@@ -89,12 +146,25 @@ GNInitWinEnv ()
 
   plibc_initialized ();
   plibc_set_panic_proc (plibc_panic);
 
   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;
 
   /* 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 */
   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");
     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
         (TGetAdaptersInfo) GetProcAddress (hIphlpapi, "GetAdaptersInfo");
   }
   else
@@ -127,8 +197,8 @@ GNInitWinEnv ()
     GNGetIfEntry = NULL;
     GNGetIpAddrTable = NULL;
     GNGetIfTable = NULL;
     GNGetIfEntry = NULL;
     GNGetIpAddrTable = NULL;
     GNGetIfTable = NULL;
-    GNGetBestInterface = NULL;
-    GGetAdaptersInfo = NULL;
+    GNGetBestInterfaceEx = NULL;
+    GNGetAdaptersInfo = NULL;
   }
 
   /* Service & Account functions */
   }
 
   /* Service & Account functions */
@@ -242,6 +312,14 @@ GNShutdownWinEnv ()
 {
   plibc_shutdown ();
 
 {
   plibc_shutdown ();
 
+#ifdef W32_VEH
+  if (GNWinVEH_handle != NULL)
+  {
+    RemoveVectoredExceptionHandler (GNWinVEH_handle);
+    GNWinVEH_handle = NULL;
+  }
+#endif
+
   FreeLibrary (hNTDLL);
   FreeLibrary (hIphlpapi);
   FreeLibrary (hAdvapi);
   FreeLibrary (hNTDLL);
   FreeLibrary (hIphlpapi);
   FreeLibrary (hAdvapi);