Index: /gsdl/trunk/runtime-src/src/w32apachectl/starthttpd.cpp
===================================================================
--- /gsdl/trunk/runtime-src/src/w32apachectl/starthttpd.cpp	(revision 19345)
+++ /gsdl/trunk/runtime-src/src/w32apachectl/starthttpd.cpp	(revision 19345)
@@ -0,0 +1,113 @@
+
+/******************************************************************************
+ Code derived from the following at http://www.microsoft.com/msj/0698/win320698.aspx
+ Module name: MainApp.cpp
+ Written by:  Jeffrey Richter
+ Purpose:     Runs a set of processes with the ability to kill them all.
+******************************************************************************/
+ 
+ //#define UNICODE
+ //#define _UNICODE
+ 
+#define STRICT
+#include <Windows.h>
+#include <process.h>
+#include <tchar.h>
+#include <stdio.h>
+ 
+/******************************************************************************
+  This program launches the httpd.exe process and sets it up with an event
+  to respond to when it is required to terminate.
+*******************************************************************************/
+ 
+///////////////////////////////////////////////////////////////////////////////
+
+// Event used to forcibly kill the spawned Process Group
+// Used to terminate the httpd.exe (upon receiving this event, a Ctrl-C is sent)
+HANDLE g_heventTerminateProcessGroup = NULL;
+ 
+///////////////////////////////////////////////////////////////////////////////
+ 
+unsigned int _stdcall StartProcessGroup(void* pv) 
+{
+  // Construct the path of our spawn-helper application
+  TCHAR szCmdLine[MAX_PATH];
+  GetModuleFileName(NULL, szCmdLine, MAX_PATH);
+  *(_tcsrchr(szCmdLine, __TEXT('\\')) + 1) = 0; // truncate EXE filename
+  _stprintf(_tcschr(szCmdLine, 0), __TEXT("StartHttpdChild.exe %d"), 
+	    g_heventTerminateProcessGroup);
+  
+  // Our command-line arguments indicate the process that we want to run
+  for (int x = 2; x < __argc; x++) {
+    _tcscat(szCmdLine, __TEXT(" ")); 
+    _tcscat(szCmdLine, __targv[x]); 
+  }
+  
+  STARTUPINFO si = { sizeof(si) };
+  si.dwFlags     = STARTF_USESHOWWINDOW;
+  si.wShowWindow = SW_HIDE;  // Processes in the Process Group are hidden
+  
+  PROCESS_INFORMATION pi;
+  
+  // Spawn the process (make sure it inherits our event handle)
+  BOOL f = CreateProcess(NULL, szCmdLine, NULL, NULL, TRUE, 
+			 CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi);
+  
+  DWORD dw = 0;  // Return value
+  
+  if (f) {
+    // The process was sucessfully spawned, wait for it to terminate
+    CloseHandle(pi.hThread);
+    WaitForSingleObject(pi.hProcess, INFINITE);
+    GetExitCodeProcess(pi.hProcess, &dw);  // Its exit code is ours
+    CloseHandle(pi.hProcess);
+  } else {
+    // Couldn't spawn the process group application
+  }
+  return(dw);
+}
+ 
+////////////////////////////////////////////////////////////////////////////////
+
+// If using the following non-GUI method definition, need to launch
+// the StartHttpd.exe program with: cmd /c StartHttpd.exe
+// int _tmain( int argc, TCHAR *argv[] ) 
+
+
+extern "C" int WINAPI _tWinMain(HINSTANCE hinst, HINSTANCE hinstExePrev, 
+                                 LPTSTR pszCmdLine, int nShowCmd) 
+{
+  if(__argc != 3) {
+    MessageBox(NULL, "Usage: starthttpd.exe <event-name> <httpd.exe program path>",
+	       TEXT("Error"), MB_OK);
+    return(1);
+  }
+  
+  DWORD dwThreadId;
+  
+  // Create an inheritable event handle to use as our IPC mechanism
+  // to terminate the processes in the process group
+  // NOTE: Keep this handle forthe entire lifetime of this application
+  
+  g_heventTerminateProcessGroup = CreateEvent(NULL, TRUE, FALSE, __argv[1]);
+  SetHandleInformation(g_heventTerminateProcessGroup, 
+		       HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT);
+  
+  // Spawn the processes in the process group.
+  ResetEvent(g_heventTerminateProcessGroup);   // Do this before each spawn
+  HANDLE hThread = (HANDLE) _beginthreadex(NULL, 0, StartProcessGroup, 
+					   NULL, 0, (UINT*) &dwThreadId);
+  
+  WaitForSingleObject(hThread, INFINITE);
+  
+  // The spawned processes have terminated, clean up
+  CloseHandle(hThread);
+  
+  // When this application is terminating, close the event
+  CloseHandle(g_heventTerminateProcessGroup);
+  
+  return(0);
+}
+ 
+//////////////////////////////// End of File //////////////////////////////////
+
Index: /gsdl/trunk/runtime-src/src/w32apachectl/starthttpdchild.cpp
===================================================================
--- /gsdl/trunk/runtime-src/src/w32apachectl/starthttpdchild.cpp	(revision 19345)
+++ /gsdl/trunk/runtime-src/src/w32apachectl/starthttpdchild.cpp	(revision 19345)
@@ -0,0 +1,76 @@
+/******************************************************************************
+ Code derived from the following at http://www.microsoft.com/msj/0698/win320698.aspx
+ Module name: SmallApp.cpp
+ Written by:  Jeffrey Richter
+ Purpose:     Spawn helper that kills everything in its Process Group.
+******************************************************************************/
+ 
+//#define UNICODE
+//#define _UNICODE
+ 
+#define STRICT
+#include <Windows.h>
+#include <process.h>
+#include <tchar.h>
+#include <stdio.h>
+ 
+///////////////////////////////////////////////////////////////////////////////
+ 
+/******************************************************************************
+    Sends the Ctrl-C to all processes spawned in this process' own console.
+    (Sends Ctrl-C to the two connected httpd.exe instances launched together)
+*******************************************************************************/
+
+extern "C" int  _tmain(int argc, TCHAR* argv[]) 
+{
+  
+  // Make sure that we've been passed the right number of arguments
+  if (argc < 3) {
+       _tprintf(
+		__TEXT("Usage: %s (InheritableEventHandle) (CommandLineToSpawn)\n"), 
+		argv[0]);
+       return(0);
+  }
+  
+  // Construct the full command line
+  TCHAR szCmdLine[MAX_PATH] = { 0 };
+  for (int x = 2; x < argc; x++) {
+    _tcscat(szCmdLine, argv[x]); 
+    _tcscat(szCmdLine, __TEXT(" ")); 
+  }
+  
+  STARTUPINFO         si = { sizeof(si) };
+  PROCESS_INFORMATION pi = { 0 };
+  DWORD dwExitCode = 0;
+  
+  HANDLE h[2];
+  h[0] = (HANDLE) _ttoi(argv[1]);  // The inherited event handle
+  
+  // Spawn the other processes as part of this Process Group
+  BOOL f = CreateProcess(NULL, szCmdLine, NULL, NULL, TRUE, 
+			 0, NULL, NULL, &si, &pi);
+  
+  if (f) {
+    CloseHandle(pi.hThread);
+    h[1] = pi.hProcess;
+    
+    // Wait for the spawned-process to die or for the event
+    // indicating that the processes should be forcibly killed.
+    switch (WaitForMultipleObjects(2, h, FALSE, INFINITE)) {
+    case WAIT_OBJECT_0 + 0:  // Force termination
+      GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0);
+      WaitForSingleObject(pi.hProcess, INFINITE);
+      break;
+      
+    case WAIT_OBJECT_0 + 1:  // App terminated normally
+      // Make its exit code our exit code
+      GetExitCodeProcess(pi.hProcess, &dwExitCode);
+      break;
+    }
+    CloseHandle(pi.hProcess);
+  }
+  CloseHandle(h[0]);   // Close the inherited event handle
+  return(dwExitCode);
+}
+ 
+//////////////////////////////// End of File //////////////////////////////////
Index: /gsdl/trunk/runtime-src/src/w32apachectl/stophttpd.cpp
===================================================================
--- /gsdl/trunk/runtime-src/src/w32apachectl/stophttpd.cpp	(revision 19345)
+++ /gsdl/trunk/runtime-src/src/w32apachectl/stophttpd.cpp	(revision 19345)
@@ -0,0 +1,83 @@
+#define STRICT
+#include <Windows.h>
+#include <process.h>
+#include <tchar.h>
+#include <stdio.h>
+
+#ifdef PLATFORM_SDK
+#include <strsafe.h>
+#endif
+
+// Helper function for displaying error codes
+void ErrorExit(char* lpszFunction) 
+{ 
+  // Retrieve the system error message for the last-error code
+  
+  char* lpMsgBuf = NULL;
+  char* lpDisplayBuf = NULL;
+  DWORD dw = GetLastError(); 
+  
+  FormatMessage(
+		FORMAT_MESSAGE_ALLOCATE_BUFFER | 
+		FORMAT_MESSAGE_FROM_SYSTEM |
+		FORMAT_MESSAGE_IGNORE_INSERTS,
+		NULL,
+		dw,
+		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+		(char*) &lpMsgBuf,
+		0, NULL );
+  
+  // Display the error message and exit the process
+  //lpDisplayBuf = new char[(lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR)];
+  lpDisplayBuf = (char*)LocalAlloc(LMEM_ZEROINIT, 
+				   (lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR)); 
+  
+#ifdef PLATFORM_SDK
+  StringCchPrintf((LPTSTR)lpDisplayBuf, 
+		  LocalSize(lpDisplayBuf) / sizeof(TCHAR),
+		  TEXT("%s Failed with error %d: %s"), 
+		  lpszFunction, dw, lpMsgBuf); 
+#else
+  _stprintf(lpDisplayBuf, __TEXT("%s\nFailed with error %d: %s"), lpszFunction, dw, lpMsgBuf);
+#endif
+  
+  MessageBox(NULL, lpDisplayBuf, TEXT("Error"), MB_OK); 
+  
+  fprintf(stderr,"Cleaning up\n");    
+
+  LocalFree(lpMsgBuf);
+  LocalFree(lpDisplayBuf);
+  ExitProcess(dw); 
+}
+
+// If using the following non-GUI method definition, need to launch
+// the StartHttpd.exe program with: cmd /c
+// (which would make it a detached process - with its own console)
+// int _tmain( int argc, TCHAR *argv[] )
+ 
+extern "C" int WINAPI _tWinMain(HINSTANCE hinst, HINSTANCE hinstExePrev, 
+                                 LPTSTR pszCmdLine, int nShowCmd) 
+{
+  if(__argc != 2) {
+    MessageBox(NULL, __TEXT("Usage: stophttpd.exe <event-name>"),
+	       TEXT("Error"), MB_OK);
+    return(1);
+  }
+  
+  // open (get) the existing named event object that the StartHttpd.exe is listening for.
+  // The event object's name is what is given in the command line
+  HANDLE g_heventTerminateProcessGroup = OpenEvent(EVENT_ALL_ACCESS,TRUE, __argv[1]);
+  
+  // send the termination event
+  if (SetEvent(g_heventTerminateProcessGroup)==0) {
+    // do error popup ExitError
+    
+    ErrorExit(TEXT("Failed to send termination event: httpd.exe needs to be terminated manually."));
+    fprintf(stderr, "Failed to send termination event: httpd.exe needs to be terminated manually.\n");
+  }
+  
+  //Sleep(3000);
+  
+  return(0);
+}
+
Index: /gsdl/trunk/runtime-src/src/w32apachectl/win32.mak
===================================================================
--- /gsdl/trunk/runtime-src/src/w32apachectl/win32.mak	(revision 19345)
+++ /gsdl/trunk/runtime-src/src/w32apachectl/win32.mak	(revision 19345)
@@ -0,0 +1,110 @@
+###########################################################################
+#
+# win32 makefile -- getgw
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 1999-2008  The New Zealand Digital Library Project
+#
+#
+# This program 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 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+#
+# To compile all these up on their own, just need a .bat file containing:
+#
+# CL /MT starthttpdchild.cpp kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib
+#
+# CL /MT starthttpd.cpp kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib
+#
+# CL /MT stophttpd.cpp kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib
+#
+# See:
+# http://c.ittoolbox.com/groups/technical-functional/cpp-l/error-c2065-_beginthread-undeclared-identifier-how-to-solve-this-239497
+# http://www.gamedev.net/community/forums/topic.asp?topic_id=304779
+# http://www.codeguru.com/forum/showthread.php?t=179647
+# http://support.microsoft.com/kb/138400
+###########################################################################
+
+GSDLHOME = ..\..\..
+
+
+GSDL_VC4 = 0
+LOCAL_LIBRARY = 0
+DLL = 0
+DLLDEBUG = 0
+
+
+!IF $(GSDL_VC4)
+CPPFLAGS = -GX
+!ELSE
+CPPFLAGS = -EHsc
+!ENDIF
+
+CPPFLAGS = $(CPPFLAGS) -MT 
+
+CC = cl
+DEFS = -D__WIN32__ -DHAVE_CONFIG_H -DPARADOCNUM -D_LITTLE_ENDIAN -DSHORT_SUFFIX -D_CRT_SECURE_NO_DEPRECATE
+WINLIBS = kernel32.lib user32.lib gdi32.lib winspool.lib \
+          comdlg32.lib advapi32.lib shell32.lib ole32.lib \
+          oleaut32.lib uuid.lib
+
+!IF $(GSDL_VC4)
+DEFS = $(DEFS) -DGSDL_NAMESPACE_BROKEN -DGSDL_USE_IOS_H -D__STL_NO_NEW_IOSTREAMS
+INCLUDES = $(INCLUDES) -I"$(COMMON_PACKAGES_DIR)\windows\stlport\stlport"
+!ENDIF
+
+!IF $(LOCAL_LIBRARY)
+DEFS = $(DEFS) -DGSDL_LOCAL_LIBRARY
+!ENDIF
+
+
+COMPILE = $(CC) -nologo -c $(CPPFLAGS) $(DEFS) $(INCLUDES)
+LINK = $(CC) -nologo $(LDFLAGS) -Fe"$@"
+
+.SUFFIXES:
+.SUFFIXES: .cpp .obj
+.cpp.obj:
+	$(COMPILE) $< 
+
+OBJECTS = starthttpdchild.obj starthttpd.obj stophttpd.obj
+EXEC    = starthttpdchild.exe starthttpd.exe stophttpd.exe
+
+all: $(EXEC)
+
+install: $(EXEC)
+	if NOT EXIST "$(GSDLHOME)\bin\windows" mkdir "$(GSDLHOME)\bin\windows"
+	for %%f in ($(EXEC)) do (copy %%f "$(GSDLHOME)\bin\windows")
+
+clean:
+	del *.obj
+	del $(EXEC)
+
+distclean:
+	del *.obj
+	del $(EXEC)
+	del "$(GSDLHOME)\bin\windows\starthttpdchild.exe"	
+	del "$(GSDLHOME)\bin\windows\starthttpd.exe"
+	del "$(GSDLHOME)\bin\windows\stophttpd.exe"
+
+starthttpdchild.exe: starthttpdchild.obj
+	$(LINK) starthttpdchild.obj $(WINLIBS)
+
+starthttpd.exe: starthttpd.obj
+	$(LINK) starthttpd.obj $(WINLIBS) 
+
+stophttpd.exe: stophttpd.obj
+	$(LINK)  stophttpd.obj $(WINLIBS)
