Index: native/windows/include/Makefile.inc
===================================================================
--- native/windows/include/Makefile.inc	(revision 1794409)
+++ native/windows/include/Makefile.inc	(working copy)
@@ -284,7 +284,7 @@
 # Always add debugging to the linker
 OPT_LFLAGS = /INCREMENTAL:NO /DEBUG
 !IF "$(BUILD)" == "RELEASE"
-OPT_LFLAGS = /OPT:REF
+OPT_LFLAGS = $(OPT_LFLAGS) /OPT:REF
 !ENDIF
 
 !IF "$(TARGET)" == "EXE"
Index: native/windows/include/rprocess.h
===================================================================
--- native/windows/include/rprocess.h	(revision 1794409)
+++ native/windows/include/rprocess.h	(working copy)
@@ -70,6 +70,7 @@
 
 BOOL        apxProcessRunning(APXHANDLE hProcess);
 DWORD       apxProcessGetPid(APXHANDLE hProcess);
+BOOL        apxProcessClose(APXHANDLE hProcess);
 
 
 __APXEND_DECLS
Index: native/windows/include/apxwin.h
===================================================================
--- native/windows/include/apxwin.h	(revision 1794409)
+++ native/windows/include/apxwin.h	(working copy)
@@ -36,6 +36,8 @@
 #include <zmouse.h>
 #include <richedit.h>
 #include <lm.h>
+#include <tlhelp32.h>
+#include <psapi.h>
 
 #ifndef _INTPTR_T_DEFINED
 #ifdef  _WIN64
Index: native/windows/include/handles.h
===================================================================
--- native/windows/include/handles.h	(revision 1794409)
+++ native/windows/include/handles.h	(working copy)
@@ -144,6 +144,8 @@
 DWORD       apxHandleWait(APXHANDLE hHandle, DWORD dwMilliseconds,
                           BOOL bKill);
 
+DWORD       apxHandleType(APXHANDLE hHandle);
+
 /** General pool memory allocation functions
  */
 LPVOID      apxPoolAlloc(APXHANDLE hPool, DWORD dwSize);
Index: native/windows/apps/prunsrv/prunsrv.c
===================================================================
--- native/windows/apps/prunsrv/prunsrv.c	(revision 1794409)
+++ native/windows/apps/prunsrv/prunsrv.c	(working copy)
@@ -1054,9 +1054,9 @@
             apxLogWrite(APXLOG_MARK_ERROR "Failed executing process");
             goto cleanup;
         } else {
-            apxLogWrite(APXLOG_MARK_DEBUG "Waiting for stop worker to finish...");
+            apxLogWrite(APXLOG_MARK_INFO "Waiting for stop worker to finish...");
             apxHandleWait(hWorker, INFINITE, FALSE);
-            apxLogWrite(APXLOG_MARK_DEBUG "Stop worker finished.");
+            apxLogWrite(APXLOG_MARK_INFO "Stop worker finished.");
         }
         wait_to_die = TRUE;
     }
@@ -1088,11 +1088,29 @@
     if (timeout) {
         FILETIME fts, fte;
         ULARGE_INTEGER s, e;
-        DWORD    nms;
+        DWORD    nms, i;
         /* Wait to give it a chance to die naturally, then kill it. */
-        apxLogWrite(APXLOG_MARK_DEBUG "Waiting for worker to die naturally...");
+        apxLogWrite(APXLOG_MARK_INFO "Waiting for worker to die naturally...");
         GetSystemTimeAsFileTime(&fts);
-        rv = apxHandleWait(gWorker, timeout, TRUE);
+        if (apxHandleType(gWorker) == APXHANDLE_TYPE_PROCESS) {
+            for (i = 0; i < timeout; i += 100) {
+                if (apxProcessRunning(gWorker)) {
+                    Sleep(100);
+                }
+                else {
+                    break;
+                }
+            }
+            if (apxProcessRunning(gWorker)) {
+                apxProcessClose(gWorker);
+                rv = WAIT_ABANDONED;
+            }
+            else
+                rv = WAIT_OBJECT_0;
+        }
+        else {
+            rv = apxHandleWait(gWorker, timeout, TRUE);
+        }
         GetSystemTimeAsFileTime(&fte);
         s.LowPart  = fts.dwLowDateTime;
         s.HighPart = fts.dwHighDateTime;
@@ -1112,7 +1130,8 @@
     }
 
     apxLogWrite(APXLOG_MARK_INFO "Service stop thread completed.");
-    SetEvent(gShutdownEvent);
+    if (gShutdownEvent)
+        SetEvent(gShutdownEvent);
     return rv;
 }
 
@@ -1544,6 +1563,7 @@
         WaitForSingleObject(gShutdownEvent, ONE_MINUTE);
         apxLogWrite(APXLOG_MARK_DEBUG "ShutdownEvent signaled");
         CloseHandle(gShutdownEvent);
+        gShutdownEvent = NULL;
 
         /* This will cause to wait for all threads to exit
          */
Index: native/windows/apps/prunsrv/prunsrv.rc
===================================================================
--- native/windows/apps/prunsrv/prunsrv.rc	(revision 1794409)
+++ native/windows/apps/prunsrv/prunsrv.rc	(working copy)
@@ -23,8 +23,8 @@
 CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "prunsrv.manifest"
 
 1 VERSIONINFO
- FILEVERSION 1,0,15,0
- PRODUCTVERSION 1,0,15,0
+ FILEVERSION 1,0,16,2
+ PRODUCTVERSION 1,0,16,2
  FILEFLAGSMASK 0x3fL
 #if defined(_DEBUG)
  FILEFLAGS 0x03L
Index: native/windows/apps/prunsrv/prunsrv.h
===================================================================
--- native/windows/apps/prunsrv/prunsrv.h	(revision 1794409)
+++ native/windows/apps/prunsrv/prunsrv.h	(working copy)
@@ -25,7 +25,7 @@
 #define _PRUNSRV_H
 
 #undef  PRG_VERSION
-#define PRG_VERSION    "1.0.15.0"
+#define PRG_VERSION    "1.0.16.2"
 #define PRG_REGROOT   L"Apache Software Foundation\\Procrun 2.0"
 
 #endif /* _PRUNSRV_H */
Index: native/windows/src/rprocess.c
===================================================================
--- native/windows/src/rprocess.c	(revision 1794409)
+++ native/windows/src/rprocess.c	(working copy)
@@ -307,6 +307,61 @@
     return rv;
 }
 
+static BOOL TerminateProcessGroup(DWORD pid)
+{
+    DWORD  r;
+    HANDLE h;
+    PROCESSENTRY32W e;
+
+    
+   apxLogWrite(APXLOG_MARK_INFO "TerminateProcessGroup for PID %d.", pid);
+   h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+    if (IS_INVALID_HANDLE(h))
+        return FALSE;
+
+    e.dwSize = (DWORD)sizeof(PROCESSENTRY32W);
+    if (!Process32FirstW(h, &e)) {
+        if (GetLastError() == ERROR_NO_MORE_FILES) {
+            CloseHandle(h);
+            return TRUE;
+        }
+        else {
+            CloseHandle(h);
+            return FALSE;
+        }
+    }
+    do {
+        if (e.th32ParentProcessID == pid) {
+            HANDLE p = OpenProcess(PROCESS_ALL_ACCESS, FALSE, e.th32ProcessID);
+            if (!IS_INVALID_HANDLE(p)) {
+                apxLogWrite(APXLOG_MARK_INFO "Child process %S with PID %d.", e.szExeFile, e.th32ProcessID);
+                if (GetExitCodeProcess(p, &r)) {
+                    if (r == STILL_ACTIVE) {
+                        /* Terminate Children
+                         */
+                        TerminateProcessGroup(e.th32ProcessID); 
+                    }
+                }
+                CloseHandle(p);
+            }
+        }
+
+    } while (Process32NextW(h, &e));
+    CloseHandle(h);
+    h = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
+    if (!IS_INVALID_HANDLE(h)) {
+        if (GetExitCodeProcess(h, &r)) {
+            if (r == STILL_ACTIVE) {
+                /* Terminate Children
+                 */
+                TerminateProcess(h, CHILD_TERMINATE_CODE);
+            }
+        }
+        CloseHandle(h);
+    }    
+    return TRUE;
+}
+
 /* Close the process.
  * Create the remote thread and call the ExitProcess
  * Terminate the process, if all of the above fails.
@@ -314,12 +369,7 @@
 static BOOL __apxProcessClose(APXHANDLE hProcess)
 {
     LPAPXPROCESS lpProc;
-    DYNLOAD_FPTR_DECLARE(CreateRemoteThread);
-    DYNLOAD_FPTR_DECLARE(ExitProcess);
 
-    UINT    uExitCode = CHILD_TERMINATE_CODE; /* Could be any value like my birthday ;-)*/
-    HANDLE  hDup, hRemote;
-
     lpProc = APXHANDLE_DATA(hProcess);
     CHECK_IF_ACTIVE(lpProc);
 
@@ -332,39 +382,7 @@
         goto cleanup;
 
     CHECK_IF_ACTIVE(lpProc);
-
-    /* Try to create the remote thread in the child address space */
-    DYNLOAD_FPTR_ADDRESS(CreateRemoteThread, KERNEL32);
-    if (DuplicateHandle(lpProc->hCurrentProcess,
-                        lpProc->stProcInfo.hProcess,
-                        lpProc->hCurrentProcess,
-                        &hDup,
-                        PROCESS_ALL_ACCESS,
-                        FALSE, 0)) {
-        DYNLOAD_FPTR_ADDRESS(ExitProcess, KERNEL32);
-        /* Now call the ExitProcess from inside the client
-         * This will safely unload all the dll's.
-         */
-        hRemote = DYNLOAD_CALL(CreateRemoteThread)(hDup,
-                                NULL, 0,
-                                (LPTHREAD_START_ROUTINE)DYNLOAD_FPTR(ExitProcess),
-                                (PVOID)&uExitCode, 0, NULL);
-        if (!IS_INVALID_HANDLE(hRemote)) {
-            if (WaitForSingleObject(lpProc->stProcInfo.hProcess,
-                    2000) == WAIT_OBJECT_0) {
-
-            }
-            else {
-                TerminateProcess(lpProc->stProcInfo.hProcess, CHILD_TERMINATE_CODE);
-            }
-            CloseHandle(hRemote);
-        }
-        CloseHandle(hDup);
-        goto cleanup;
-    }
-
-    TerminateProcess(lpProc->stProcInfo.hProcess, CHILD_TERMINATE_CODE);
-
+    TerminateProcessGroup(lpProc->stProcInfo.dwProcessId);
 cleanup:
      /* Close the process handle */
     SAFE_CLOSE_HANDLE(lpProc->stProcInfo.hProcess);
@@ -388,24 +406,27 @@
                 /* Wait for all worker threads to exit */
                 WaitForMultipleObjects(3, lpProc->hWorkerThreads, TRUE, INFINITE);
             }
-            SAFE_CLOSE_HANDLE(lpProc->stProcInfo.hProcess);
+            if (lpProc->dwChildStatus & PROC_INITIALIZED) {
+                SAFE_CLOSE_HANDLE(lpProc->stProcInfo.hProcess);
 
-            /* Close parent side of the pipes */
-            SAFE_CLOSE_HANDLE(lpProc->hChildInpWr);
-            SAFE_CLOSE_HANDLE(lpProc->hChildOutRd);
-            SAFE_CLOSE_HANDLE(lpProc->hChildErrRd);
+                /* Close parent side of the pipes */
+                SAFE_CLOSE_HANDLE(lpProc->hChildInpWr);
+                SAFE_CLOSE_HANDLE(lpProc->hChildOutRd);
+                SAFE_CLOSE_HANDLE(lpProc->hChildErrRd);
 
-            SAFE_CLOSE_HANDLE(lpProc->hWorkerThreads[0]);
-            SAFE_CLOSE_HANDLE(lpProc->hWorkerThreads[1]);
-            SAFE_CLOSE_HANDLE(lpProc->hWorkerThreads[2]);
-            SAFE_CLOSE_HANDLE(lpProc->hUserToken);
-            apxFree(lpProc->szApplicationExec);
-            apxFree(lpProc->szCommandLine);
-            apxFree(lpProc->szWorkingPath);
-            RESTORE_STD_HANDLES(lpProc);
-            SAFE_CLOSE_HANDLE(lpProc->hCurrentProcess);
-            if (lpProc->lpEnvironment)
-                FreeEnvironmentStringsW(lpProc->lpEnvironment);
+                SAFE_CLOSE_HANDLE(lpProc->hWorkerThreads[0]);
+                SAFE_CLOSE_HANDLE(lpProc->hWorkerThreads[1]);
+                SAFE_CLOSE_HANDLE(lpProc->hWorkerThreads[2]);
+                SAFE_CLOSE_HANDLE(lpProc->hUserToken);
+                apxFree(lpProc->szApplicationExec);
+                apxFree(lpProc->szCommandLine);
+                apxFree(lpProc->szWorkingPath);
+                RESTORE_STD_HANDLES(lpProc);
+                SAFE_CLOSE_HANDLE(lpProc->hCurrentProcess);
+                if (lpProc->lpEnvironment)
+                    FreeEnvironmentStringsW(lpProc->lpEnvironment);
+                lpProc->dwChildStatus &= ~PROC_INITIALIZED;
+            }
 
         case WM_QUIT:
             /* The process has finished
@@ -431,31 +452,8 @@
 
 /** Create the process but don't start it
  *
- APXHANDLE
-apxCreateProcessW(APXHANDLE hPool, DWORD dwOptions,
-                  LPAPXFNCALLBACK fnCallback,
-                  LPCWSTR szUsername, LPCWSTR szPassword,
-                  BOOL bLogonAsService)
-{
-    APXHANDLE hProcess;
-    LPAPXPROCESS lpProc;
-    HANDLE hUserToken = NULL;
-    if (szUsername && (APX_GET_OSLEVEL() >= APX_WINVER_NT_4)) {
-        HANDLE hUser;
-#ifndef _UNICODE
-        WCHAR wsUsername[256];
-        WCHAR wsPassword[256];
-        AsciiToWide(szUsername, wsUsername);
-        AsciiToWide(szPassword, wsPassword);
-#else
-        LPCWSTR wsUsername = szUsername;
-        LPCWSTR wsPassword = szPassword;
-#endif
-
  */
-
-
- APXHANDLE
+APXHANDLE
 apxCreateProcessA(APXHANDLE hPool, DWORD dwOptions,
                   LPAPXFNCALLBACK fnCallback,
                   LPCSTR szUsername, LPCSTR szPassword,
@@ -869,6 +867,24 @@
 }
 
 BOOL
+apxProcessClose(APXHANDLE hProcess)
+{
+   LPAPXPROCESS lpProc;
+
+    if (hProcess->dwType != APXHANDLE_TYPE_PROCESS)
+        return FALSE;
+
+    lpProc = APXHANDLE_DATA(hProcess);
+
+    if (lpProc->dwChildStatus & CHILD_RUNNING) {
+        __apxProcessCallback(hProcess, WM_CLOSE, 0, 0);
+        return TRUE;
+    }
+    else
+        return FALSE;
+}
+
+BOOL
 apxProcessRunning(APXHANDLE hProcess)
 {
    LPAPXPROCESS lpProc;
Index: native/windows/src/handles.c
===================================================================
--- native/windows/src/handles.c	(revision 1794409)
+++ native/windows/src/handles.c	(working copy)
@@ -687,3 +687,10 @@
         return WAIT_ABANDONED;
 }
 
+DWORD apxHandleType(APXHANDLE hHandle)
+{
+    if (IS_INVALID_HANDLE(hHandle))
+        return APXHANDLE_TYPE_INVALID;
+    else
+        return hHandle->dwType;
+}
