Index: configure.in
===================================================================
RCS file: /squid/squid/configure.in,v
retrieving revision 1.393
diff -u -p -r1.393 configure.in
--- configure.in	19 Aug 2006 12:40:31 -0000	1.393
+++ configure.in	2 Sep 2006 21:32:22 -0000
@@ -58,6 +58,24 @@ mingw|mingw32|cygwin|cygwin32)
 	;;
 esac
 
+case "$host_os" in
+mingw|mingw32)
+        AM_CONDITIONAL(ENABLE_MINGW32SPECIFIC, true)
+	AC_PATH_PROG(WIN32_PSAPI, psapi.dll, none)
+	CFLAGS="$CFLAGS -mthreads"
+	if test "$ac_cv_path_WIN32_PSAPI" = "none"; then
+		echo "PSAPI.DLL is recommended to run Squid on Windows Platform"
+		echo "Please see PSAPI.DLL section on doc/release-notes/release-2.6.html."
+	else
+		AC_DEFINE(HAVE_WIN32_PSAPI,1,[Define if you have PSAPI.DLL on Windows systems])
+		LIBS="$LIBS -lpsapi"
+	fi
+	;;
+*)
+	AM_CONDITIONAL(ENABLE_MINGW32SPECIFIC, false)
+	;;
+esac
+
 if test -z "$CACHE_HTTP_PORT"; then
 	CACHE_HTTP_PORT="3128"
 fi
@@ -1740,21 +1758,30 @@ if test $ac_cv_have_ext_mallinfo = "yes"
   AC_DEFINE(HAVE_EXT_MALLINFO, 1, [Define if struct mallinfo has mxfast member])
 fi
 
-AC_CACHE_CHECK(for struct rusage,ac_cv_have_struct_rusage, [
-  AC_TRY_COMPILE([
+case "$host_os" in
+  mingw|mingw32)
+    AC_DEFINE(HAVE_STRUCT_RUSAGE)
+    ac_cv_func_getrusage='yes'
+    echo "Using own rusage on Windows."
+    ;;
+  *)      
+    AC_CACHE_CHECK(for struct rusage,ac_cv_have_struct_rusage, [
+      AC_TRY_COMPILE([
 #if HAVE_SYS_TIME_H
 #include <sys/time.h>
 #endif
 #if HAVE_SYS_RESOURCE_H
 #include <sys/resource.h>
 #endif],
-    [struct rusage R;],
-    ac_cv_have_struct_rusage="yes",
-    ac_cv_have_struct_rusage="no")
+        [struct rusage R;],
+        ac_cv_have_struct_rusage="yes",
+        ac_cv_have_struct_rusage="no")
 ])
-if test $ac_cv_have_struct_rusage = "yes" ; then
-  AC_DEFINE(HAVE_STRUCT_RUSAGE, 1, [Define if you have struct rusage])
-fi
+    if test $ac_cv_have_struct_rusage = "yes" ; then
+      AC_DEFINE(HAVE_STRUCT_RUSAGE, 1, [Define if you have struct rusage])
+    fi
+    ;;
+esac
 
 AC_CACHE_CHECK(for ip->ip_hl, ac_cv_have_ip_hl, [
   AC_TRY_COMPILE([#include <sys/types.h>
@@ -2228,6 +2255,13 @@ if test -z "$ac_cv_func_poll"; then
 	esac
 fi
 
+dnl Override statfs detect on MinGW becasue is emulated in source code
+case "$host_os" in
+mingw|mingw32)
+	ac_cv_func_statfs='yes'
+	;;
+esac
+
 dnl Check for library functions
 AC_CHECK_FUNCS(\
 	bcopy \
@@ -2712,6 +2746,12 @@ main() {
 SQUID_MAXFD=`cat conftestval`,
 SQUID_MAXFD=256,
 SQUID_MAXFD=256)
+dnl Microsoft MSVCRT.DLL supports 2048 maximum FDs
+case "$host_os" in
+mingw|mingw32)
+  SQUID_MAXFD="2048"
+  ;;
+esac
 AC_MSG_RESULT($SQUID_MAXFD)
 fi # --with-maxfd SQUID_MAXFD
 AC_DEFINE_UNQUOTED(SQUID_MAXFD, $SQUID_MAXFD, [Maximum number of open filedescriptors])
Index: doc/release-notes/release-2.6.html
===================================================================
RCS file: /squid/squid/doc/release-notes/release-2.6.html,v
retrieving revision 1.30
diff -u -p -r1.30 release-2.6.html
--- doc/release-notes/release-2.6.html	28 Aug 2006 11:43:06 -0000	1.30
+++ doc/release-notes/release-2.6.html	2 Sep 2006 21:32:23 -0000
@@ -261,6 +261,24 @@ squid -O "-D -u 3130" -n squidsvc
 </P>
 <P>
 <DL>
+<DT><B>PSAPI.DLL (Process Status Helper) Considerations</B><DD><P>The process status helper functions make it easier for you to obtain information about
+processes and device drivers running on Microsoft® Windows NT®/Windows® 2000. These
+functions are available in PSAPI.DLL, which is distributed in the Microsoft® Platform
+Software Development Kit (SDK). The same information is generally available through the
+performance data in the registry, but it is more difficult to get to it. PSAPI.DLL is
+freely redistributable.</P>
+<P>PSAPI.DLL is available only on Windows NT, 2000, XP and .NET. The implementation in Squid is
+aware of this, and try to use it only on the rigth platform.</P>
+<P>On Windows NT PSAPI.DLL can be found as component of many applications, if you need it,
+you can find it on Windows NT Resource KIT. If you have problem, it can be
+downloaded from here:
+<A HREF="http://download.microsoft.com/download/platformsdk/Redist/4.0.1371.1/NT4/EN-US/psinst.EXE">http://download.microsoft.com/download/platformsdk/Redist/4.0.1371.1/NT4/EN-US/psinst.EXE</A></P>
+<P>On Windows 2000 and later it is available installing the Windows Support Tools, located on the
+Support\Tools folder of the installation Windows CD-ROM.</P>
+</DL>
+</P>
+<P>
+<DL>
 <DT><B>Registry DNS lookup</B><DD><P>On Windows platforms, if no value is specified in the <EM>dns_nameservers</EM> option on
 squid.conf or in the /etc/resolv.conf file, the list of DNS name servers are
 taken from the Windows registry, both static and dynamic DHCP configurations
@@ -309,6 +327,7 @@ redirect_program c:/winnt/system32/cmd.e
 </LI>
 <LI>Some code sections can make blocking calls.</LI>
 <LI>Some external helpers may not work.</LI>
+<LI>File Descriptors number hard-limited to 2048 when building with MinGW.</LI>
 </UL>
 </P>
 </DL>
Index: doc/release-notes/release-2.6.sgml
===================================================================
RCS file: /squid/squid/doc/release-notes/release-2.6.sgml,v
retrieving revision 1.34
diff -u -p -r1.34 release-2.6.sgml
--- doc/release-notes/release-2.6.sgml	28 Aug 2006 11:43:06 -0000	1.34
+++ doc/release-notes/release-2.6.sgml	2 Sep 2006 21:32:23 -0000
@@ -217,6 +217,28 @@ In the following example the command lin
 </descrip>
 
 <descrip>
+<tag>PSAPI.DLL (Process Status Helper) Considerations</tag>
+
+The process status helper functions make it easier for you to obtain information about
+processes and device drivers running on Microsoft® Windows NT®/Windows® 2000. These
+functions are available in PSAPI.DLL, which is distributed in the Microsoft® Platform
+Software Development Kit (SDK). The same information is generally available through the
+performance data in the registry, but it is more difficult to get to it. PSAPI.DLL is
+freely redistributable.
+
+PSAPI.DLL is available only on Windows NT, 2000, XP and .NET. The implementation in Squid is
+aware of this, and try to use it only on the rigth platform.
+
+On Windows NT PSAPI.DLL can be found as component of many applications, if you need it,
+you can find it on Windows NT Resource KIT. If you have problem, it can be
+downloaded from here:
+<url url="http://download.microsoft.com/download/platformsdk/Redist/4.0.1371.1/NT4/EN-US/psinst.EXE" name="http://download.microsoft.com/download/platformsdk/Redist/4.0.1371.1/NT4/EN-US/psinst.EXE">
+
+On Windows 2000 and later it is available installing the Windows Support Tools, located on the
+Support\Tools folder of the installation Windows CD-ROM.
+</descrip>
+
+<descrip>
 <tag>Registry DNS lookup</tag>
 On Windows platforms, if no value is specified in the <em/dns_nameservers/ option on
 squid.conf or in the /etc/resolv.conf file, the list of DNS name servers are
@@ -256,6 +278,7 @@ redirect_program c:/winnt/system32/cmd.e
 </itemize>
 <item>Some code sections can make blocking calls.
 <item>Some external helpers may not work.
+<item>File Descriptors number hard-limited to 2048 when building on MinGW.
 </itemize>
 </descrip>
 
Index: include/config.h
===================================================================
RCS file: /squid/squid/include/config.h,v
retrieving revision 1.13
diff -u -p -r1.13 config.h
--- include/config.h	1 Sep 2006 13:29:17 -0000	1.13
+++ include/config.h	2 Sep 2006 21:32:23 -0000
@@ -121,6 +121,7 @@
 #elif defined(WIN32) || defined(WINNT) || defined(__WIN32__) || defined(__WIN32)
 #define _SQUID_MSWIN_
 #define _SQUID_WIN32_
+#include "squid_mswin.h"
 
 #elif defined(__APPLE__)
 #define _SQUID_APPLE_
Index: include/util.h
===================================================================
RCS file: /squid/squid/include/util.h,v
retrieving revision 1.65
diff -u -p -r1.65 util.h
--- include/util.h	12 May 2006 22:06:51 -0000	1.65
+++ include/util.h	2 Sep 2006 21:32:23 -0000
@@ -59,7 +59,6 @@ extern char *uudecode(const char *);
 extern char *xstrdup(const char *);
 extern char *xstrndup(const char *, size_t);
 extern const char *xstrerror(void);
-extern const char *xbstrerror(int);
 extern int tvSubMsec(struct timeval, struct timeval);
 extern int tvSubUsec(struct timeval, struct timeval);
 extern double tvSubDsec(struct timeval, struct timeval);
@@ -123,4 +122,33 @@ double drand48(void);
  */
 int statMemoryAccounted(void);
 
+/* CygWin & Windows NT Port */ 
+/* win32lib.c */
+#ifdef _SQUID_MSWIN_
+#if defined(_MSC_VER) /* Microsoft C Compiler ONLY */
+extern int64_t WIN32_strtoll(const char *nptr, char **endptr, int base);
+#endif
+extern int chroot (const char *);
+extern int ftruncate(int, off_t);
+extern int gettimeofday(struct timeval *, struct timezone *);
+extern int inet_aton(const char *, struct in_addr *);
+extern int kill(pid_t, int);
+extern int statfs(const char *, struct statfs *);
+extern int truncate(const char *, off_t);
+extern const char * wsastrerror(int);
+extern struct passwd *getpwnam(char *);
+extern struct group *getgrnam(char *);
+extern uid_t geteuid(void);
+extern uid_t getuid(void);
+extern int setuid(uid_t);
+extern int seteuid(uid_t);
+extern gid_t getgid(void);
+extern gid_t getegid(void);
+extern int setgid(gid_t);
+extern int setegid(gid_t);
+extern const char *WIN32_strerror(int);
+extern void WIN32_maperror(unsigned long);
+extern int WIN32_Close_FD_Socket (int);
+#endif
+
 #endif /* SQUID_UTIL_H */
Index: lib/Makefile.am
===================================================================
RCS file: /squid/squid/lib/Makefile.am,v
retrieving revision 1.8
diff -u -p -r1.8 Makefile.am
--- lib/Makefile.am	27 May 2006 08:58:31 -0000	1.8
+++ lib/Makefile.am	2 Sep 2006 21:32:23 -0000
@@ -24,6 +24,12 @@ else
 LIBSSPWIN32=
 endif
 
+if ENABLE_MINGW32SPECIFIC
+WIN32SRC = win32lib.c
+else
+WIN32SRC=
+endif
+
 EXTRA_LIBRARIES = \
 	libdlmalloc.a \
 	libregex.a \
@@ -37,7 +43,8 @@ noinst_LIBRARIES = \
 EXTRA_libmiscutil_a_SOURCES = \
 	md5.c \
 	snprintf.c \
-	strsep.c
+	strsep.c \
+	win32lib.c
 libmiscutil_a_SOURCES = \
 	Array.c \
 	base64.c \
@@ -59,7 +66,8 @@ libmiscutil_a_SOURCES = \
 	$(STRSEPSOURCE) \
 	stub_memaccount.c \
 	util.c \
-	uudecode.c
+	uudecode.c \
+	$(WIN32SRC)
 libmiscutil_a_LIBADD = \
 	@LIBOBJS@
 # $(top_srcdir)/include/version.h should be a dependency
Index: lib/util.c
===================================================================
RCS file: /squid/squid/lib/util.c,v
retrieving revision 1.92
diff -u -p -r1.92 util.c
--- lib/util.c	26 Jun 2006 15:01:59 -0000	1.92
+++ lib/util.c	2 Sep 2006 21:32:23 -0000
@@ -33,6 +33,8 @@
  *
  */
 
+#ifndef UTIL_C
+#define UTIL_C
 #define _etext etext
 
 #include "config.h"
@@ -739,3 +741,4 @@ default_failure_notify(const char *messa
     write(2, "\n", 1);
     abort();
 }
+#endif /* UTIL_C */
Index: src/Makefile.am
===================================================================
RCS file: /squid/squid/src/Makefile.am,v
retrieving revision 1.54
diff -u -p -r1.54 Makefile.am
--- src/Makefile.am	2 Sep 2006 14:08:42 -0000	1.54
+++ src/Makefile.am	2 Sep 2006 21:32:23 -0000
@@ -62,6 +62,14 @@ else
 WIN32SOURCE = 
 endif
 
+if ENABLE_MINGW32SPECIFIC
+MINGWEXLIB = -lmingwex
+IPC_SOURCE = ipc_win32.c
+else
+MINGWEXLIB =
+IPC_SOURCE = ipc.c
+endif
+
 if USE_POLL
 COMMLOOP_SOURCE = comm_poll.c
 endif
@@ -121,6 +129,7 @@ EXTRA_squid_SOURCES = \
 	comm_select_win32.c \
 	comm_kqueue.c \
 	comm_generic.c \
+	ipc_win32.c \
 	win32.c
 
 squid_SOURCES = \
@@ -172,7 +181,7 @@ squid_SOURCES = \
 	icp_v3.c \
 	ident.c \
 	internal.c \
-	ipc.c \
+	$(IPC_SOURCE) \
 	ipcache.c \
 	$(LEAKFINDERSOURCE) \
 	locrewrite.c \
@@ -250,7 +259,8 @@ squid_LDADD = \
 	@SSLLIB@ \
 	@LIB_EPOLL@ \
 	-lmiscutil \
-	@XTRA_LIBS@
+	@XTRA_LIBS@ \
+	$(MINGWEXLIB)
 
 unlinkd_SOURCES = 
 unlinkd_LDADD = unlinkd-daemon.o
Index: src/cf.data.pre
===================================================================
RCS file: /squid/squid/src/cf.data.pre,v
retrieving revision 1.366
diff -u -p -r1.366 cf.data.pre
--- src/cf.data.pre	2 Sep 2006 14:08:42 -0000	1.366
+++ src/cf.data.pre	2 Sep 2006 21:32:24 -0000
@@ -5042,6 +5042,8 @@ DOC_START
 	processes, these sleep delays will add up and your
 	Squid will not service requests for some amount of time
 	until all the child processes have been started.
+	On Windows value less then 1000 (1 milliseconds) are
+	rounded to 1000.
 DOC_END
 
 NAME: minimum_expiry_time
Index: src/comm.c
===================================================================
RCS file: /squid/squid/src/comm.c,v
retrieving revision 1.355
diff -u -p -r1.355 comm.c
--- src/comm.c	12 Aug 2006 23:27:20 -0000	1.355
+++ src/comm.c	2 Sep 2006 21:32:24 -0000
@@ -33,6 +33,8 @@
  *
  */
 
+#ifndef COMM_C
+#define COMM_C
 #include "squid.h"
 
 #if defined(_SQUID_CYGWIN_)
@@ -1181,3 +1183,4 @@ commCloseAllSockets(void)
 	}
     }
 }
+#endif /* COMM_C */
Index: src/debug.c
===================================================================
RCS file: /squid/squid/src/debug.c,v
retrieving revision 1.91
diff -u -p -r1.91 debug.c
--- src/debug.c	2 Sep 2006 14:16:10 -0000	1.91
+++ src/debug.c	2 Sep 2006 21:32:24 -0000
@@ -48,6 +48,10 @@ static void _db_print_syslog(const char 
 static void _db_print_stderr(const char *format, va_list args);
 static void _db_print_file(const char *format, va_list args);
 
+#ifdef _SQUID_MSWIN_
+extern LPCRITICAL_SECTION dbg_mutex;
+#endif
+
 #ifdef _SQUID_LINUX_
 /* Workaround for crappy glic header files */
 extern int backtrace(void *, int);
@@ -74,6 +78,33 @@ _db_print(va_alist)
 #define args2 args1
 #define args3 args1
 #endif
+#ifdef _SQUID_MSWIN_
+    /* Multiple WIN32 threads may call this simultaneously */
+    if (!dbg_mutex) {
+	HMODULE krnl_lib = GetModuleHandle("Kernel32");
+	BOOL(FAR WINAPI * InitializeCriticalSectionAndSpinCount) 
+	    (LPCRITICAL_SECTION, DWORD) = NULL;
+	if (krnl_lib)
+	    (FARPROC) InitializeCriticalSectionAndSpinCount =
+		GetProcAddress(krnl_lib,
+		"InitializeCriticalSectionAndSpinCount");
+	dbg_mutex = xcalloc(1, sizeof(CRITICAL_SECTION));
+
+	if (InitializeCriticalSectionAndSpinCount) {
+	    /* let multiprocessor systems EnterCriticalSection() fast */
+	    if (!InitializeCriticalSectionAndSpinCount(dbg_mutex, 4000)) {
+		if (debug_log) {
+		    fprintf(debug_log, "FATAL: _db_print: can't initialize critical section\n");
+		    fflush(debug_log);
+		}
+		fprintf(stderr, "FATAL: _db_print: can't initialize critical section\n");
+		abort();
+	    } else
+		InitializeCriticalSection(dbg_mutex);
+	}
+    }
+    EnterCriticalSection(dbg_mutex);
+#endif
     /* give a chance to context-based debugging to print current context */
     if (!Ctx_Lock)
 	ctx_print();
@@ -92,6 +123,9 @@ _db_print(va_alist)
 #if HAVE_SYSLOG
     _db_print_syslog(format, args3);
 #endif
+#ifdef _SQUID_MSWIN_
+    LeaveCriticalSection(dbg_mutex);
+#endif
     va_end(args1);
 #if STDC_HEADERS
     va_end(args2);
Index: src/helper.c
===================================================================
RCS file: /squid/squid/src/helper.c,v
retrieving revision 1.61
diff -u -p -r1.61 helper.c
--- src/helper.c	9 Jul 2006 15:44:32 -0000	1.61
+++ src/helper.c	2 Sep 2006 21:32:24 -0000
@@ -70,6 +70,10 @@ helperOpenServers(helper * hlp)
     int rfd;
     int wfd;
     wordlist *w;
+#ifdef _SQUID_MSWIN_
+    HANDLE hIpc;
+    pid_t pid;
+#endif
     if (hlp->cmdline == NULL)
 	return;
     progname = hlp->cmdline->key;
@@ -94,7 +98,11 @@ helperOpenServers(helper * hlp)
 	    args,
 	    shortname,
 	    &rfd,
-	    &wfd);
+	    &wfd
+#ifdef _SQUID_MSWIN_
+	    , &hIpc, &pid
+#endif
+	    );
 	if (x < 0) {
 	    debug(84, 1) ("WARNING: Cannot run '%s' process.\n", progname);
 	    continue;
@@ -102,7 +110,12 @@ helperOpenServers(helper * hlp)
 	hlp->n_running++;
 	hlp->n_active++;
 	srv = cbdataAlloc(helper_server);
+#ifdef _SQUID_MSWIN_
+	srv->hIpc = hIpc;
+	srv->pid = pid;
+#else
 	srv->pid = x;
+#endif
 	srv->index = k;
 	srv->rfd = rfd;
 	srv->wfd = wfd;
@@ -149,6 +162,11 @@ helperStatefulOpenServers(statefulhelper
     int rfd;
     int wfd;
     wordlist *w;
+#ifdef _SQUID_MSWIN_
+    HANDLE hIpc;
+    pid_t pid;
+#endif
+
     if (hlp->cmdline == NULL)
 	return;
     progname = hlp->cmdline->key;
@@ -173,7 +191,11 @@ helperStatefulOpenServers(statefulhelper
 	    args,
 	    shortname,
 	    &rfd,
-	    &wfd);
+	    &wfd
+#ifdef _SQUID_MSWIN_
+	    , &hIpc, &pid
+#endif
+	    );
 	if (x < 0) {
 	    debug(84, 1) ("WARNING: Cannot run '%s' process.\n", progname);
 	    continue;
@@ -181,7 +203,12 @@ helperStatefulOpenServers(statefulhelper
 	hlp->n_running++;
 	hlp->n_active++;
 	srv = cbdataAlloc(helper_stateful_server);
+#ifdef _SQUID_MSWIN_
+	srv->hIpc = hIpc;
+	srv->pid = pid;
+#else
 	srv->pid = x;
+#endif
 	srv->flags.reserved = 0;
 	srv->stats.submits = 0;
 	srv->index = k;
@@ -439,6 +466,11 @@ void
 helperShutdown(helper * hlp)
 {
     dlink_node *link = hlp->servers.head;
+#ifdef _SQUID_MSWIN_
+    HANDLE hIpc;
+    pid_t pid;
+    int no;
+#endif
     while (link) {
 	int wfd;
 	helper_server *srv;
@@ -468,9 +500,26 @@ helperShutdown(helper * hlp)
 	    continue;
 	}
 	srv->flags.closing = 1;
+#ifdef _SQUID_MSWIN_
+	hIpc = srv->hIpc;
+	pid = srv->pid;
+	no = srv->index + 1;
+	shutdown(srv->wfd, SD_BOTH);
+#endif
 	wfd = srv->wfd;
 	srv->wfd = -1;
 	comm_close(wfd);
+#ifdef _SQUID_MSWIN_
+	if (hIpc) {
+	    if (WaitForSingleObject(hIpc, 5000) != WAIT_OBJECT_0) {
+		getCurrentTime();
+		debug(84, 1) ("helperShutdown: WARNING: %s #%d (%s,%ld) "
+		    "didn't exit in 5 seconds\n",
+		    hlp->id_name, no, hlp->cmdline->key, (long int)pid);
+	    }
+	    CloseHandle(hIpc);
+	}
+#endif
     }
 }
 
@@ -479,6 +528,11 @@ helperStatefulShutdown(statefulhelper * 
 {
     dlink_node *link = hlp->servers.head;
     helper_stateful_server *srv;
+#ifdef _SQUID_MSWIN_
+    HANDLE hIpc;
+    pid_t pid;
+    int no;
+#endif
     int wfd;
     while (link) {
 	srv = link->data;
@@ -507,9 +561,26 @@ helperStatefulShutdown(statefulhelper * 
 	    continue;
 	}
 	srv->flags.closing = 1;
+#ifdef _SQUID_MSWIN_
+	hIpc = srv->hIpc;
+	pid = srv->pid;
+	no = srv->index + 1;
+	shutdown(srv->wfd, SD_BOTH);
+#endif
 	wfd = srv->wfd;
 	srv->wfd = -1;
 	comm_close(wfd);
+#ifdef _SQUID_MSWIN_
+	if (hIpc) {
+	    if (WaitForSingleObject(hIpc, 5000) != WAIT_OBJECT_0) {
+		getCurrentTime();
+		debug(84, 1) ("helperShutdown: WARNING: %s #%d (%s,%ld) "
+		    "didn't exit in 5 seconds\n",
+		    hlp->id_name, no, hlp->cmdline->key, (long int)pid);
+	    }
+	    CloseHandle(hIpc);
+	}
+#endif
     }
 }
 
Index: src/icmp.c
===================================================================
RCS file: /squid/squid/src/icmp.c,v
retrieving revision 1.80
diff -u -p -r1.80 icmp.c
--- src/icmp.c	22 May 2006 19:01:32 -0000	1.80
+++ src/icmp.c	2 Sep 2006 21:32:24 -0000
@@ -50,6 +50,11 @@ static void icmpSend(pingerEchoData * pk
 static void icmpHandleSourcePing(const struct sockaddr_in *from, const char *buf);
 #endif
 
+#ifdef _SQUID_MSWIN_
+static HANDLE hIpc;
+static pid_t pid;
+#endif
+
 static void
 icmpSendEcho(struct in_addr to, int opcode, const char *payload, int len)
 {
@@ -193,7 +198,11 @@ icmpOpen(void)
 	args,
 	"Pinger Socket",
 	&rfd,
-	&wfd);
+	&wfd
+#ifdef _SQUID_MSWIN_
+	, &hIpc, &pid
+#endif
+	);
     if (x < 0)
 	return;
     assert(rfd == wfd);
@@ -212,7 +221,21 @@ icmpClose(void)
     if (icmp_sock < 0)
 	return;
     debug(37, 1) ("Closing Pinger socket on FD %d\n", icmp_sock);
+#ifdef _SQUID_MSWIN_
+    send(icmp_sock, "$shutdown\n", 10, 0);
+#endif
     comm_close(icmp_sock);
+#ifdef _SQUID_MSWIN_
+    if (hIpc) {
+	if (WaitForSingleObject(hIpc, 12000) != WAIT_OBJECT_0) {
+	    getCurrentTime();
+	    debug(37, 1)
+		("icmpClose: WARNING: (pinger,%ld) didn't exit in 12 seconds\n",
+		(long int)pid);
+	}
+	CloseHandle(hIpc);
+    }
+#endif
     icmp_sock = -1;
 #endif
 }
Index: src/protos.h
===================================================================
RCS file: /squid/squid/src/protos.h,v
retrieving revision 1.515
diff -u -p -r1.515 protos.h
--- src/protos.h	2 Sep 2006 14:16:10 -0000	1.515
+++ src/protos.h	2 Sep 2006 21:32:24 -0000
@@ -1232,7 +1232,11 @@ extern int ipcCreate(int type,
     const char *const args[],
     const char *name,
     int *rfd,
-    int *wfd);
+    int *wfd
+#ifdef _SQUID_MSWIN_
+    ,HANDLE * hIpc, pid_t * ppid
+#endif
+);
 
 /* CacheDigest */
 extern CacheDigest *cacheDigestCreate(int capacity, int bpe);
Index: src/squid.h
===================================================================
RCS file: /squid/squid/src/squid.h,v
retrieving revision 1.243
diff -u -p -r1.243 squid.h
--- src/squid.h	19 Aug 2006 12:40:31 -0000	1.243
+++ src/squid.h	2 Sep 2006 21:32:24 -0000
@@ -505,6 +505,17 @@ struct rusage {
 #define IPPROTO_TCP 0
 #endif
 
+
+#if defined(_SQUID_MSWIN_)
+/* Windows lacks getpagesize() prototype */
+#ifndef getpagesize
+extern size_t getpagesize(void);
+#endif
+#if defined(_MSC_VER) /* Microsoft C Compiler ONLY */
+#define strtoll WIN32_strtoll
+#endif
+#endif /* _SQUID_MSWIN_ */
+
 /*
  * Trap attempts to build large file cache support without support for
  * large objects
Index: src/ssl_support.h
===================================================================
RCS file: /squid/squid/src/ssl_support.h,v
retrieving revision 1.5
diff -u -p -r1.5 ssl_support.h
--- src/ssl_support.h	17 May 2006 23:17:05 -0000	1.5
+++ src/ssl_support.h	2 Sep 2006 21:32:24 -0000
@@ -59,4 +59,10 @@ const char *sslGetCAAttribute(SSL * ssl,
 const char *sslGetUserCertificatePEM(SSL * ssl);
 const char *sslGetUserCertificateChainPEM(SSL * ssl);
 
+#ifdef _SQUID_MSWIN_
+
+#define SSL_set_fd(s,f) (SSL_set_fd(s,fd_table[fd].win32.handle))
+
+#endif /* _SQUID_MSWIN_ */
+
 #endif /* SQUID_SSL_SUPPORT_H */
Index: src/stat.c
===================================================================
RCS file: /squid/squid/src/stat.c,v
retrieving revision 1.374
diff -u -p -r1.374 stat.c
--- src/stat.c	15 Aug 2006 19:27:28 -0000	1.374
+++ src/stat.c	2 Sep 2006 21:32:25 -0000
@@ -440,21 +440,37 @@ statFiledescriptors(StoreEntry * sentry)
     int i;
     fde *f;
     storeAppendPrintf(sentry, "Active file descriptors:\n");
+#ifdef _SQUID_MSWIN_
+    storeAppendPrintf(sentry, "%-4s %-10s %-6s %-4s %-7s* %-7s* %-21s %s\n",
+	"File",
+        "Handle",
+#else
     storeAppendPrintf(sentry, "%-4s %-6s %-4s %-7s* %-7s* %-21s %s\n",
 	"File",
+#endif
 	"Type",
 	"Tout",
 	"Nread",
 	"Nwrite",
 	"Remote Address",
 	"Description");
+#ifdef _SQUID_MSWIN_
+    storeAppendPrintf(sentry, "---- ---------- ------ ---- -------- -------- --------------------- ------------------------------\n");
+#else
     storeAppendPrintf(sentry, "---- ------ ---- -------- -------- --------------------- ------------------------------\n");
+#endif
     for (i = 0; i < Squid_MaxFD; i++) {
 	f = &fd_table[i];
 	if (!f->flags.open)
 	    continue;
+#ifdef _SQUID_MSWIN_
+	storeAppendPrintf(sentry, "%4d 0x%-8lX %-6.6s %4d %7" PRINTF_OFF_T "%c %7" PRINTF_OFF_T "%c %-21s %s\n",
+	    i,
+            f->win32.handle,
+#else
 	storeAppendPrintf(sentry, "%4d %-6.6s %4d %7" PRINTF_OFF_T "%c %7" PRINTF_OFF_T "%c %-21s %s\n",
 	    i,
+#endif
 	    fdTypeStr[f->type],
 	    f->timeout_handler ? (int) (f->timeout - squid_curtime) / 60 : 0,
 	    f->bytes_read,
Index: src/structs.h
===================================================================
RCS file: /squid/squid/src/structs.h,v
retrieving revision 1.499
diff -u -p -r1.499 structs.h
--- src/structs.h	2 Sep 2006 14:08:42 -0000	1.499
+++ src/structs.h	2 Sep 2006 21:32:25 -0000
@@ -914,6 +914,11 @@ struct _fde {
 #if USE_SSL
     SSL *ssl;
 #endif
+#ifdef _SQUID_MSWIN_
+struct {
+	long handle;
+    } win32;
+#endif
 };
 
 struct _fileMap {
@@ -2327,6 +2332,9 @@ struct _helper_server {
 	int uses;
 	unsigned int pending;
     } stats;
+#ifdef _SQUID_MSWIN_
+    HANDLE hIpc;
+#endif
 };
 
 
@@ -2356,6 +2364,9 @@ struct _helper_stateful_server {
 	int releases;
     } stats;
     void *data;			/* State data used by the calling routines */
+#ifdef _SQUID_MSWIN_
+    HANDLE hIpc;
+#endif
 };
 
 /*
Index: src/unlinkd.c
===================================================================
RCS file: /squid/squid/src/unlinkd.c,v
retrieving revision 1.52
diff -u -p -r1.52 unlinkd.c
--- src/unlinkd.c	19 Aug 2006 12:40:31 -0000	1.52
+++ src/unlinkd.c	2 Sep 2006 21:32:25 -0000
@@ -74,6 +74,11 @@ main(int argc, char *argv[])
 static int unlinkd_wfd = -1;
 static int unlinkd_rfd = -1;
 
+#ifdef _SQUID_MSWIN_
+static HANDLE hIpc;
+static pid_t pid;
+#endif
+
 #define UNLINKD_QUEUE_LIMIT 20
 
 void
@@ -106,7 +111,11 @@ unlinkdUnlink(const char *path)
 	int x;
 	int i;
 	char rbuf[512];
+#ifdef _SQUID_MSWIN_
+	x = recv(unlinkd_rfd, rbuf, 511, 0);
+#else
 	x = read(unlinkd_rfd, rbuf, 511);
+#endif
 	if (x > 0) {
 	    rbuf[x] = '\0';
 	    for (i = 0; i < x; i++)
@@ -119,7 +128,11 @@ unlinkdUnlink(const char *path)
     assert(l < MAXPATHLEN);
     xstrncpy(buf, path, MAXPATHLEN);
     buf[l++] = '\n';
+#ifdef _SQUID_MSWIN_
+    x = send(unlinkd_wfd, buf, l, 0);
+#else
     x = write(unlinkd_wfd, buf, l);
+#endif
     if (x < 0) {
 	debug(2, 1) ("unlinkdUnlink: write FD %d failed: %s\n",
 	    unlinkd_wfd, xstrerror());
@@ -139,6 +152,28 @@ unlinkdUnlink(const char *path)
 void
 unlinkdClose(void)
 {
+#ifdef _SQUID_MSWIN_
+    if (unlinkd_wfd > -1) {
+	debug(2, 1) ("Closing unlinkd pipe on FD %d\n", unlinkd_wfd);
+	shutdown(unlinkd_wfd, SD_BOTH);
+	comm_close(unlinkd_wfd);
+	if (unlinkd_wfd != unlinkd_rfd)
+	    comm_close(unlinkd_rfd);
+	unlinkd_wfd = -1;
+	unlinkd_rfd = -1;
+    } else
+	debug(2, 0) ("unlinkdClose: WARNING: unlinkd_wfd is %d\n",
+	    unlinkd_wfd);
+    if (hIpc) {
+	if (WaitForSingleObject(hIpc, 5000) != WAIT_OBJECT_0) {
+	    getCurrentTime();
+	    debug(2, 1)
+		("unlinkdClose: WARNING: (unlinkd,%ld) didn't exit in 5 seconds\n",
+		pid);
+	}
+	CloseHandle(hIpc);
+    }
+#else
     if (unlinkd_wfd < 0)
 	return;
     debug(2, 1) ("Closing unlinkd pipe on FD %d\n", unlinkd_wfd);
@@ -147,6 +182,7 @@ unlinkdClose(void)
 	file_close(unlinkd_rfd);
     unlinkd_wfd = -1;
     unlinkd_rfd = -1;
+#endif
 }
 
 void
@@ -157,8 +193,9 @@ unlinkdInit(void)
     struct timeval slp;
     args[0] = "(unlinkd)";
     args[1] = NULL;
-#if HAVE_POLL && defined(_SQUID_OSF_)
+#if (HAVE_POLL && defined(_SQUID_OSF_)) || defined(_SQUID_MSWIN_)
     /* pipes and poll() don't get along on DUNIX -DW */
+    /* On Windows select() will fail on a pipe */
     x = ipcCreate(IPC_STREAM,
 #else
     /* We currently need to use FIFO.. see below */
@@ -168,7 +205,11 @@ unlinkdInit(void)
 	args,
 	"unlinkd",
 	&unlinkd_rfd,
-	&unlinkd_wfd);
+	&unlinkd_wfd
+#ifdef _SQUID_MSWIN_
+	, &hIpc, &pid
+#endif
+	);
     if (x < 0)
 	fatal("Failed to create unlinkd subprocess");
     slp.tv_sec = 0;
Index: src/win32.c
===================================================================
RCS file: /squid/squid/src/win32.c,v
retrieving revision 1.12
diff -u -p -r1.12 win32.c
--- src/win32.c	20 Aug 2006 09:32:28 -0000	1.12
+++ src/win32.c	2 Sep 2006 21:32:25 -0000
@@ -44,6 +44,9 @@
 #ifdef _SQUID_WIN32_
 #include <windows.h>
 #ifdef _SQUID_MSWIN_
+#if HAVE_WIN32_PSAPI
+#include <psapi.h>
+#endif
 #ifndef _MSWSOCK_
 #include <mswsock.h>
 #endif
@@ -59,6 +62,9 @@ static void WIN32_build_argv(char *);
 void WINAPI SquidWinSvcMain(DWORD, char **);
 
 #if defined(_SQUID_MSWIN_)
+static int Win32SockInit(void);
+static void Win32SockCleanup(void);
+extern LPCRITICAL_SECTION dbg_mutex;
 void WIN32_ExceptionHandlerCleanup(void);
 static LPTOP_LEVEL_EXCEPTION_FILTER Win32_Old_ExceptionHandler = NULL;
 #endif /* _SQUID_MSWIN_ */
@@ -330,6 +336,9 @@ WIN32_Abort(int sig)
 void
 WIN32_Exit()
 {
+#ifdef _SQUID_MSWIN_
+    Win32SockCleanup();
+#endif
 #if USE_WIN32_SERVICE
     if (WIN32_run_mode == _WIN_SQUID_RUN_MODE_SERVICE) {
 	if (!Squid_Aborting) {
@@ -339,6 +348,8 @@ WIN32_Exit()
     }
 #endif
 #ifdef _SQUID_MSWIN_
+    if (dbg_mutex)
+	DeleteCriticalSection(dbg_mutex);
     WIN32_ExceptionHandlerCleanup();
 #endif
     _exit(0);
@@ -412,8 +423,15 @@ WIN32_Subsystem_Init(int *argc, char ***
 	svcStatus.dwCheckPoint = 0;
 	svcStatus.dwWaitHint = 10000;
 	SetServiceStatus(svcHandle, &svcStatus);
+#ifdef _SQUID_MSWIN_
+	_setmaxstdio(Squid_MaxFD);
+#endif
     }
 #endif
+#ifdef _SQUID_MSWIN_
+    if (Win32SockInit() < 0)
+	return 1;
+#endif
     return 0;
 }
 
@@ -734,6 +752,152 @@ main(int argc, char **argv)
 #endif
 
 #if defined(_SQUID_MSWIN_)
+static int s_iInitCount = 0;
+
+int
+WIN32_pipe(int handles[2])
+{
+    int new_socket;
+    fde *F = NULL;
+
+    struct sockaddr_in serv_addr;
+    int len = sizeof(serv_addr);
+    u_short handle1_port;
+
+    handles[0] = handles[1] = -1;
+
+    statCounter.syscalls.sock.sockets++;
+    if ((new_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
+	return -1;
+
+    memset((void *) &serv_addr, 0, sizeof(serv_addr));
+    serv_addr.sin_family = AF_INET;
+    serv_addr.sin_port = htons(0);
+    serv_addr.sin_addr = local_addr;
+
+    if (bind(new_socket, (SOCKADDR *) & serv_addr, len) < 0 ||
+	listen(new_socket, 1) < 0 || getsockname(new_socket, (SOCKADDR *) & serv_addr, &len) < 0 ||
+	(handles[1] = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
+	closesocket(new_socket);
+	return -1;
+    }
+    handle1_port = ntohs(serv_addr.sin_port);
+    if (connect(handles[1], (SOCKADDR *) & serv_addr, len) < 0 ||
+	(handles[0] = accept(new_socket, (SOCKADDR *) & serv_addr, &len)) < 0) {
+	closesocket(handles[1]);
+	handles[1] = -1;
+	closesocket(new_socket);
+	return -1;
+    }
+    closesocket(new_socket);
+
+    F = &fd_table[handles[0]];
+    F->local_addr = local_addr;
+    F->local_port = ntohs(serv_addr.sin_port);
+
+    F = &fd_table[handles[1]];
+    F->local_addr = local_addr;
+    xstrncpy(F->ipaddr, inet_ntoa(local_addr), 16);
+    F->remote_port = handle1_port;
+
+    return 0;
+}
+
+int
+WIN32_getrusage(int who, struct rusage *usage)
+{
+#if HAVE_WIN32_PSAPI
+    if ((WIN32_OS_version == _WIN_OS_WINNT) || (WIN32_OS_version == _WIN_OS_WIN2K)
+	|| (WIN32_OS_version == _WIN_OS_WINXP) || (WIN32_OS_version == _WIN_OS_WINNET)) {
+	/* On Windows NT/2000 call PSAPI.DLL for process Memory */
+	/* informations -- Guido Serassio                       */
+	HANDLE hProcess;
+	PROCESS_MEMORY_COUNTERS pmc;
+	hProcess = OpenProcess(PROCESS_QUERY_INFORMATION |
+	    PROCESS_VM_READ,
+	    FALSE, GetCurrentProcessId());
+	{
+	    /* Microsoft CRT doesn't have getrusage function,  */
+	    /* so we get process CPU time information from PSAPI.DLL. */
+	    FILETIME ftCreate, ftExit, ftKernel, ftUser;
+	    if (GetProcessTimes(hProcess, &ftCreate, &ftExit, &ftKernel, &ftUser)) {
+		int64_t tUser64 = (*(int64_t *) & ftUser / 10);
+		int64_t tKernel64 = (*(int64_t *) & ftKernel / 10);
+		usage->ru_utime.tv_sec = (long) (tUser64 / 1000000);
+		usage->ru_stime.tv_sec = (long) (tKernel64 / 1000000);
+		usage->ru_utime.tv_usec = (long) (tUser64 % 1000000);
+		usage->ru_stime.tv_usec = (long) (tKernel64 % 1000000);
+	    } else {
+		CloseHandle(hProcess);
+		return -1;
+	    }
+	}
+	if (GetProcessMemoryInfo(hProcess, &pmc, sizeof(pmc))) {
+	    usage->ru_maxrss = (DWORD) (pmc.WorkingSetSize / getpagesize());
+	    usage->ru_majflt = pmc.PageFaultCount;
+	} else {
+	    CloseHandle(hProcess);
+	    return -1;
+	}
+	CloseHandle(hProcess);
+    }
+#endif
+    return 0;
+}
+
+static int
+Win32SockInit(void)
+{
+    int iVersionRequested;
+    WSADATA wsaData;
+    int err, opt;
+    int optlen = sizeof(opt);
+
+
+    if (s_iInitCount > 0) {
+	s_iInitCount++;
+	return (0);
+    } else if (s_iInitCount < 0)
+	return (s_iInitCount);
+    /* s_iInitCount == 0. Do the initailization */
+    iVersionRequested = MAKEWORD(2, 0);
+    err = WSAStartup((WORD) iVersionRequested, &wsaData);
+    if (err) {
+	s_iInitCount = -1;
+	return (s_iInitCount);
+    }
+    if (LOBYTE(wsaData.wVersion) != 2 ||
+	HIBYTE(wsaData.wVersion) != 0) {
+	s_iInitCount = -2;
+	WSACleanup();
+	return (s_iInitCount);
+    }
+    if (WIN32_OS_version != _WIN_OS_WINNT) {
+	if (getsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (char *) &opt, &optlen)) {
+	    s_iInitCount = -3;
+	    WSACleanup();
+	    return (s_iInitCount);
+	} else {
+	    opt = opt | SO_SYNCHRONOUS_NONALERT;
+	    if (setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (char *) &opt, optlen)) {
+		s_iInitCount = -3;
+		WSACleanup();
+		return (s_iInitCount);
+	    }
+	}
+    }
+    WIN32_Socks_initialized = 1;
+    s_iInitCount++;
+    return (s_iInitCount);
+}
+
+static void
+Win32SockCleanup(void)
+{
+    if (--s_iInitCount == 0)
+	WSACleanup();
+    return;
+}
 
 LONG CALLBACK
 WIN32_ExceptionHandler(EXCEPTION_POINTERS * ep)
@@ -754,9 +918,11 @@ WIN32_ExceptionHandler(EXCEPTION_POINTER
     default:
 	break;
     }
+
     return EXCEPTION_CONTINUE_SEARCH;
 }
 
+
 void
 WIN32_ExceptionHandlerInit()
 {
