-check return value
[oweals/gnunet.git] / src / util / win.cc
index 594b9a2109f4e2e90585da2157b8c9b04ad42b9b..7b67c9e83a25e4cd2fae09572af9f85e2e2517bb 100644 (file)
@@ -620,7 +620,7 @@ EnumNICs3 (struct EnumNICs3_results **results, int *results_count)
 void\r
 EnumNICs3_free (struct EnumNICs3_results *r)\r
 {\r
-  GNUNET_free (r);\r
+  GNUNET_free_non_null (r);\r
 }\r
 \r
 \r
@@ -1261,6 +1261,75 @@ char *winErrorStr(const char *prefix, int dwErr)
   return ret;\r
 }\r
 \r
+/**
+ * Terminate a process by creating a remote thread within it,
+ * which proceeds to call ExitProcess() inside that process.
+ * Safer than TerminateProcess ().
+ *
+ * Code is from From http://private-storm.de/2009/08/11/case-terminateprocess/
+ *
+ * @param hProcess handle of a process to terminate
+ * @param uExitCode exit code to use for ExitProcess()
+ * @param dwTimeout number of ms to wait for the process to terminate
+ * @return TRUE on success, FALSE on failure (check last error for the code)
+ */
+BOOL\r
+SafeTerminateProcess (HANDLE hProcess, UINT uExitCode, DWORD dwTimeout)\r
+{\r
+  DWORD dwTID, dwCode, dwErr = 0;\r
+  HANDLE hProcessDup = INVALID_HANDLE_VALUE;\r
+  HANDLE hRT = NULL;\r
+  HINSTANCE hKernel = GetModuleHandle ("Kernel32");\r
+  BOOL bSuccess = FALSE;\r
+\r
+  BOOL bDup = DuplicateHandle (GetCurrentProcess (), hProcess,\r
+      GetCurrentProcess (), &hProcessDup, PROCESS_ALL_ACCESS,\r
+      FALSE, 0);\r
+\r
+  /* Detect the special case where the process is\r
+   * already dead...\r
+   */\r
+  if (GetExitCodeProcess (bDup ? hProcessDup : hProcess, &dwCode) &&\r
+      (STILL_ACTIVE ==  dwCode))\r
+  {\r
+    FARPROC pfnExitProc;\r
+\r
+    pfnExitProc = GetProcAddress (hKernel, "ExitProcess");\r
+\r
+    hRT = CreateRemoteThread ((bDup) ? hProcessDup : hProcess, NULL, 0,\r
+        (LPTHREAD_START_ROUTINE) pfnExitProc, (PVOID) uExitCode, 0, &dwTID);\r
+\r
+    dwErr = GetLastError ();\r
+  }\r
+  else\r
+  {\r
+    dwErr = ERROR_PROCESS_ABORTED;\r
+  }\r
+\r
+  if (hRT)\r
+  {\r
+    /* Must wait process to terminate to\r
+     * guarantee that it has exited...\r
+     */\r
+    DWORD dwWaitResult = WaitForSingleObject ((bDup) ? hProcessDup : hProcess,\r
+        dwTimeout);\r
+    if (dwWaitResult == WAIT_TIMEOUT)\r
+      dwErr = WAIT_TIMEOUT;\r
+    else\r
+      dwErr = GetLastError ();\r
+\r
+    CloseHandle (hRT);\r
+    bSuccess = dwErr == NO_ERROR;\r
+  }\r
+\r
+  if (bDup)\r
+    CloseHandle (hProcessDup);\r
+\r
+  SetLastError (dwErr);\r
+\r
+  return bSuccess;\r
+}
+\r
 } /* extern "C" */\r
 \r
 #endif\r