Index: winsup/utils/Makefile.in
===================================================================
RCS file: /cvs/src/src/winsup/utils/Makefile.in,v
retrieving revision 1.66
diff -p -u -r1.66 Makefile.in
--- winsup/utils/Makefile.in	10 Jul 2007 00:12:54 -0000	1.66
+++ winsup/utils/Makefile.in	2 Aug 2007 23:01:04 -0000
@@ -1,6 +1,6 @@
 # Makefile for Cygwin utilities
 # Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-# 2005, 2006 Red Hat, Inc.
+# 2005, 2006, 2007 Red Hat, Inc.
 
 # This file is part of Cygwin.
 
@@ -99,15 +99,15 @@ else
 	$(CXX) $(MINGW_CXXFLAGS) -o $@ ${wordlist 1,2,$^} -B$(mingw_build)/ $(MINGW_LDFLAGS)
 endif
 
-cygcheck.exe: cygcheck.o path.o dump_setup.o $(MINGW_DEP_LDLIBS)
+cygcheck.exe: cygcheck.o bloda.o path.o dump_setup.o $(MINGW_DEP_LDLIBS)
 ifeq "$(libz)" ""
 	@echo '*** Building cygcheck without package content checking due to missing mingw libz.a.'
 endif
 ifdef VERBOSE
-	$(CXX) $(MINGW_CXXFLAGS) -o $@ ${wordlist 1,3,$^} -B$(mingw_build)/ $(MINGW_LDFLAGS) $(libz)
+	$(CXX) $(MINGW_CXXFLAGS) -o $@ ${wordlist 1,4,$^} -B$(mingw_build)/ $(MINGW_LDFLAGS) $(libz) -lntdll
 else
-	@echo $(CXX) -o $@ ${wordlist 1,3,$^} ${filter-out -B%, $(MINGW_CXXFLAGS) $(MINGW_LDFLAGS)} $(libz);\
-	$(CXX) $(MINGW_CXXFLAGS) -o $@ ${wordlist 1,3,$^} -B$(mingw_build)/ $(MINGW_LDFLAGS) $(libz)
+	@echo $(CXX) -o $@ ${wordlist 1,4,$^} ${filter-out -B%, $(MINGW_CXXFLAGS) $(MINGW_LDFLAGS)} $(libz) -lntdll;\
+	$(CXX) $(MINGW_CXXFLAGS) -o $@ ${wordlist 1,4,$^} -B$(mingw_build)/ $(MINGW_LDFLAGS) $(libz) -lntdll
 endif
 
 dumper.o: dumper.cc dumper.h
@@ -150,6 +150,14 @@ else
 	$(MINGW_CXX) $(zconf_h) $(zlib_h) $c -o $(@D)/$(basename $@)$o $(MINGW_CXXFLAGS) $<
 endif
 
+bloda.o: bloda.cc
+ifdef VERBOSE
+	${MINGW_CXX} $c -o $(@D)/$(basename $@)$o $(MINGW_CXXFLAGS) -I$(updir) $<
+else
+	@echo $(MINGW_CXX) $c -o $(@D)/$(basename $@)$o $(MINGW_CXXFLAGS) ... $^;\
+	${MINGW_CXX} $c -o $(@D)/$(basename $@)$o $(MINGW_CXXFLAGS) -I$(updir) $<
+endif
+
 cygcheck.o: cygcheck.cc
 ifdef VERBOSE
 	${MINGW_CXX} $c -o $(@D)/$(basename $@)$o $(MINGW_CXXFLAGS) -I$(updir) $<
Index: winsup/utils/bloda.cc
===================================================================
RCS file: winsup/utils/bloda.cc
diff -N winsup/utils/bloda.cc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ winsup/utils/bloda.cc	2 Aug 2007 23:01:04 -0000
@@ -0,0 +1,410 @@
+/* bloda.cc
+
+   Copyright 2007 Red Hat, Inc.
+
+   This file is part of Cygwin.
+
+   This software is a copyrighted work licensed under the terms of the
+   Cygwin license.  Please consult the file "CYGWIN_LICENSE" for
+   details. */
+
+#define cygwin_internal cygwin_internal_dontuse
+#include <stdio.h>
+#include <assert.h>
+#include <windows.h>
+#include <ntdef.h>
+#include <ddk/ntstatus.h>
+#include <ddk/ntapi.h>
+#undef cygwin_internal
+
+#undef DEBUGGING
+#ifdef DEBUGGING
+#define dbg_printf(ARGS) printf ARGS ; fflush (NULL)
+#else  /* !DEBUGGING */
+#define dbg_printf(ARGS) do { } while (0)
+#endif /* ?DEBUGGING */
+
+/*  This module detects applications from the Big List of Dodgy Apps,
+  a list of applications that have at some given time been shown to
+  interfere with the operation of cygwin.  It detects the presence of
+  applications on the system by looking for any of four traces an
+  installation might leave: 1) registry keys, 2) files on disk
+  3) running executables 4) loaded dlls or drivers.
+
+  At the time of writing, the BLODA amounts to:-
+
+    Sonic Solutions burning software containing DLA component
+    Norton/MacAffee/Symantec antivirus or antispyware
+    Logitech webcam software with "Logitech process monitor" service
+    Kerio, Agnitum or ZoneAlarm Personal Firewall
+    Iolo System Mechanic/AntiVirus/Firewall
+    LanDesk
+    Windows Defender 
+    Embassy Trust Suite fingerprint reader software containing wxvault.dll
+*/
+
+enum bad_app
+{
+  SONIC,    NORTON,  MACAFFEE,    SYMANTEC,
+  LOGITECH, KERIO,   AGNITUM,     ZONEALARM,
+  IOLO,     LANDESK, WINDEFENDER, EMBASSYTS
+};
+
+struct bad_app_info
+{
+  enum bad_app app_id;
+  const char *details;
+  char found_it;
+};
+
+enum bad_app_det_method
+{
+  HKLMKEY, HKCUKEY, FILENAME, PROCESSNAME, HOOKDLLNAME
+};
+
+struct bad_app_det
+{
+  enum bad_app_det_method type;
+  const char *param;
+  enum bad_app app;
+};
+
+static const struct bad_app_det dodgy_app_detects[] =
+{
+  { PROCESSNAME, "dlactrlw.exe",                                                 SONIC      },
+  { HOOKDLLNAME, "wxvault.dll",                                                  EMBASSYTS  },
+  { HKLMKEY,     "SYSTEM\\CurrentControlSet\\Services\\vsdatant",                ZONEALARM  },
+  { FILENAME,    "%windir%\\System32\\vsdatant.sys",                             ZONEALARM  },
+  { HKLMKEY,     "SYSTEM\\CurrentControlSet\\Services\\lvprcsrv",                LOGITECH   },
+  { PROCESSNAME, "LVPrcSrv.exe",                                                 LOGITECH   },
+  { FILENAME,    "%programfiles%\\common files\\logitech\\lvmvfm\\LVPrcSrv.exe", LOGITECH   },
+}; 
+
+static const size_t num_of_detects = sizeof (dodgy_app_detects) / sizeof (dodgy_app_detects[0]);
+
+static struct bad_app_info big_list_of_dodgy_apps[] =
+{
+  { SONIC,       "Sonic Solutions burning software containing DLA component"              },
+  { NORTON,      "Norton antivirus or antispyware software"                               },
+  { MACAFFEE,    "Macaffee antivirus or antispyware software"                             },
+  { SYMANTEC,    "Symantec antivirus or antispyware software"                             },
+  { LOGITECH,    "Logitech Process Monitor service"                                       },
+  { KERIO,       "Kerio Personal Firewall"                                                },
+  { AGNITUM,     "Agnitum Personal Firewall"                                              },
+  { ZONEALARM,   "ZoneAlarm Personal Firewall"                                            },
+  { IOLO,        "Iolo System Mechanic/AntiVirus/Firewall software"                       },
+  { LANDESK,     "Landesk"                                                                },
+  { WINDEFENDER, "Windows Defender"                                                       },
+  { EMBASSYTS,   "Embassy Trust Suite fingerprint reader software containing wxvault.dll" },
+};
+
+static const size_t num_of_dodgy_apps = sizeof (big_list_of_dodgy_apps) / sizeof (big_list_of_dodgy_apps[0]);
+
+/* This function is not in the ntdll export lib, so it has
+  to be looked up at runtime and called through a pointer.  */
+VOID NTAPI (*pRtlFreeUnicodeString)(PUNICODE_STRING) = NULL;
+
+static PSYSTEM_PROCESSES
+get_process_list (void)
+{
+  int n_procs = 0x100;
+  PSYSTEM_PROCESSES pslist = (PSYSTEM_PROCESSES) malloc (n_procs * sizeof *pslist);
+
+  while (NtQuerySystemInformation (SystemProcessesAndThreadsInformation,
+    pslist, n_procs * sizeof *pslist, 0) == STATUS_INFO_LENGTH_MISMATCH)
+    {
+      n_procs *= 2;
+      free (pslist);
+      pslist = (PSYSTEM_PROCESSES) malloc (n_procs * sizeof *pslist);
+    }
+  return pslist;
+}
+
+static PSYSTEM_MODULE_INFORMATION
+get_module_list (void)
+{
+  int modsize = 0x1000;
+  PSYSTEM_MODULE_INFORMATION modlist = (PSYSTEM_MODULE_INFORMATION) malloc (modsize);
+
+  while (NtQuerySystemInformation (SystemModuleInformation,
+    modlist, modsize, NULL) == STATUS_INFO_LENGTH_MISMATCH)
+    {
+      modsize *= 2;
+      free (modlist);
+      modlist = (PSYSTEM_MODULE_INFORMATION) malloc (modsize);
+    }
+  return modlist;
+}
+
+static bool
+find_process_in_list (PSYSTEM_PROCESSES pslist, PUNICODE_STRING psname)
+{
+  while (1)
+    {
+      if (pslist->ProcessName.Length && pslist->ProcessName.Buffer)
+        {
+          dbg_printf (("%S\n", pslist->ProcessName.Buffer));
+          if (!_wcsicmp (pslist->ProcessName.Buffer, psname->Buffer))
+            return true;
+        }
+      if (!pslist->NextEntryDelta)
+        break;
+      pslist = (PSYSTEM_PROCESSES)(pslist->NextEntryDelta + (char *)pslist);
+    };
+  return false;
+}
+
+static bool
+find_module_in_list (PSYSTEM_MODULE_INFORMATION modlist, const char * const modname)
+{
+  PSYSTEM_MODULE_INFORMATION_ENTRY modptr = &modlist->Module[0];
+  DWORD count = modlist->Count;
+  while (count--)
+    {
+      dbg_printf (("name '%s' offset %d ", &modptr->ImageName[0], modptr->PathLength));
+      dbg_printf (("= '%s'\n", &modptr->ImageName[modptr->PathLength]));
+      if (!_stricmp (&modptr->ImageName[modptr->PathLength], modname))
+        return true;
+      modptr++;
+    }
+  return false;
+}
+
+static bool
+expand_path (const char *path, char *outbuf)
+{
+  char *dst = outbuf;
+  const char *end, *envval;
+  char envvar[MAX_PATH];
+  size_t len;
+
+  while ((dst - outbuf) < MAX_PATH)
+    {
+      if (*path != '%')
+        {
+          if ((*dst++ = *path++) != 0)
+            continue;
+          break;
+        }
+      /* Expand an environ var.  */
+      end = path + 1;
+      while (*end != '%')
+        {
+          /* Watch out for unterminated %  */
+          if (*end++ == 0)
+            {
+              end = NULL;
+              break;
+            }
+        }
+      /* If we didn't find the end, can't expand it.  */
+      if ((end == NULL) || (end == (path + 1)))
+        {
+          /* Unterminated % so copy verbatim.  */
+          *dst++ = *path++;
+          continue;
+        }
+      /* Expand the environment var into the new path.  */
+      if ((end - (path + 1)) >= MAX_PATH)
+        return -1;
+      memcpy (envvar, path + 1, end - (path + 1));
+      envvar[end - (path + 1)] = 0;
+      envval = getenv (envvar);
+      /* If not found, copy env var name verbatim.  */
+      if (envval == NULL)
+        {
+          *dst++ = *path++;
+          continue;
+        }
+      /* Check enough room before copying.  */
+      len = strlen (envval);
+      if ((dst + len - outbuf) >= MAX_PATH)
+        return false;
+      memcpy (dst, envval, len);
+      dst += len;
+      /* And carry on past the end of env var name.  */
+      path = end + 1;
+    }
+  return (dst - outbuf) < MAX_PATH;
+}
+
+static bool 
+detect_dodgy_app (const struct bad_app_det *det, PSYSTEM_PROCESSES pslist, PSYSTEM_MODULE_INFORMATION modlist)
+{
+  HANDLE fh;
+  HKEY hk;
+  UNICODE_STRING unicodename;
+  ANSI_STRING ansiname;
+  NTSTATUS rv;
+  bool found;
+  char expandedname[MAX_PATH];
+
+  switch (det->type)
+    {
+    case HKLMKEY:
+      dbg_printf (("Detect reg key hklm '%s'... ", det->param));
+      if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, det->param, 0, STANDARD_RIGHTS_READ, &hk) == ERROR_SUCCESS)
+        {
+          RegCloseKey (hk);
+          dbg_printf (("found!\n"));
+          return true;
+        }
+      break;
+
+    case HKCUKEY:
+      dbg_printf (("Detect reg key hkcu '%s'... ", det->param));
+      if (RegOpenKeyEx (HKEY_CURRENT_USER, det->param, 0, STANDARD_RIGHTS_READ, &hk) == ERROR_SUCCESS)
+        {
+          RegCloseKey (hk);
+          dbg_printf (("found!\n"));
+          return true;
+        }
+      break;
+
+    case FILENAME:
+      dbg_printf (("Detect filename '%s'... ", det->param));
+      if (!expand_path (det->param, expandedname))
+        {
+          printf ("Expansion failure!\n");
+          break;
+        }
+      dbg_printf (("('%s' after expansion)... ", expandedname));
+      fh = CreateFile (expandedname, 0, FILE_SHARE_READ | FILE_SHARE_WRITE
+        | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, NULL);
+      if (fh != INVALID_HANDLE_VALUE)
+        {
+          CloseHandle (fh);
+          dbg_printf (("found!\n"));
+          return true;
+        }
+      break;
+
+    case PROCESSNAME:
+      dbg_printf (("Detect proc name '%s'... ", det->param));
+      /* Equivalent of RtlInitAnsiString.  */
+      ansiname.Length = ansiname.MaximumLength = strlen (det->param);
+      ansiname.Buffer = (CHAR *) det->param;
+      rv = RtlAnsiStringToUnicodeString (&unicodename, &ansiname, TRUE);
+      if (rv != STATUS_SUCCESS)
+        {
+          printf ("Ansi to unicode conversion failure $%08x\n", (unsigned int) rv);
+          break;
+        }
+      found = find_process_in_list (pslist, &unicodename);
+      if (!pRtlFreeUnicodeString)
+          pRtlFreeUnicodeString = (VOID NTAPI (*)(PUNICODE_STRING)) GetProcAddress (LoadLibrary ("ntdll.dll"), "RtlFreeUnicodeString");
+      if (pRtlFreeUnicodeString)
+        pRtlFreeUnicodeString (&unicodename);
+      else
+        printf ("leaking mem...oops\n");
+      if (found)
+        {
+          dbg_printf (("found!\n"));
+          return true;
+        }
+      break;
+
+    case HOOKDLLNAME:
+      dbg_printf (("Detect hookdll '%s'... ", det->param));
+      if (find_module_in_list (modlist, det->param))
+        {
+          dbg_printf (("found!\n"));
+          return true;
+        }
+      break;
+
+    }
+  dbg_printf (("not found.\n"));
+  return false;
+}
+
+static struct bad_app_info *
+find_dodgy_app_info (enum bad_app which_app)
+{
+  size_t i;
+  for (i = 0; i < num_of_dodgy_apps; i++)
+    {
+      if (big_list_of_dodgy_apps[i].app_id == which_app)
+        return &big_list_of_dodgy_apps[i];
+    }
+  return NULL;
+}
+
+/* External entrypoint called from cygcheck.cc/dump_sysinfo.  */
+void
+dump_dodgy_apps (int verbose)
+{
+  size_t i, n_det = 0;
+  PSYSTEM_PROCESSES pslist;
+  PSYSTEM_MODULE_INFORMATION modlist;
+
+  /* Read system info for detect testing.  */
+  pslist = get_process_list ();
+  modlist = get_module_list ();
+
+  /* Go with builtin list for now; later may enhance to
+  read dodgy apps from a file or download from an URL.  */
+  for (i = 0; i < num_of_dodgy_apps; i++)
+    {
+      big_list_of_dodgy_apps[i].found_it = false;
+    }
+
+  for (i = 0; i < num_of_detects; i++)
+    {
+      const struct bad_app_det *det = &dodgy_app_detects[i];
+      struct bad_app_info *found = find_dodgy_app_info (det->app);
+      bool detected = detect_dodgy_app (det, pslist, modlist);
+
+      /* Not found would mean we coded the lists bad. */
+      assert (found);
+      if (detected)
+        {
+          ++n_det;
+          found->found_it |= (1 << det->type);
+        }
+    }
+  if (n_det)
+    {
+      printf ("\nPotential app conflicts:\n\n");
+      for (i = 0; i < num_of_dodgy_apps; i++)
+        {
+          if (big_list_of_dodgy_apps[i].found_it)
+            {
+              printf ("%s%s", big_list_of_dodgy_apps[i].details, 
+                verbose ? "\nDetected: " : ".\n");
+              if (!verbose)
+                continue;
+              const char *sep = "";
+              if (big_list_of_dodgy_apps[i].found_it & (1 << HKLMKEY))
+                {
+                  printf ("HKLM Registry Key");
+                  sep = ", ";
+                }
+              if (big_list_of_dodgy_apps[i].found_it & (1 << HKCUKEY))
+                {
+                  printf ("%sHKCU Registry Key", sep);
+                  sep = ", ";
+                }
+              if (big_list_of_dodgy_apps[i].found_it & (1 << FILENAME))
+                {
+                  printf ("%sNamed file", sep);
+                  sep = ", ";
+                }
+              if (big_list_of_dodgy_apps[i].found_it & (1 << PROCESSNAME))
+                {
+                  printf ("%sNamed process", sep);
+                  sep = ", ";
+                }
+              if (big_list_of_dodgy_apps[i].found_it & (1 << HOOKDLLNAME))
+                {
+                  printf ("%sLoaded hook DLL", sep);
+                }
+              printf (".\n\n");
+            }
+        }
+    }
+  /* Tidy up allocations.  */
+  free (pslist);
+  free (modlist);
+}
+
Index: winsup/utils/cygcheck.cc
===================================================================
RCS file: /cvs/src/src/winsup/utils/cygcheck.cc,v
retrieving revision 1.95
diff -p -u -r1.95 cygcheck.cc
--- winsup/utils/cygcheck.cc	4 Jun 2007 01:57:16 -0000	1.95
+++ winsup/utils/cygcheck.cc	2 Aug 2007 23:01:04 -0000
@@ -50,9 +50,13 @@ typedef long long longlong;
 typedef __int64 longlong;
 #endif
 
+/* In dump_setup.cc  */
 void dump_setup (int, char **, bool);
 void package_find (int, char **);
 void package_list (int, char **);
+/* In bloda.cc  */
+void dump_dodgy_apps (int verbose);
+
 
 static const char version[] = "$Revision: 1.95 $";
 
@@ -1623,6 +1627,8 @@ dump_sysinfo ()
   if (!cygwin_dll_count)
     puts ("Warning: cygwin1.dll not found on your path");
 
+  dump_dodgy_apps (verbose);
+
   if (is_nt)
     dump_sysinfo_services ();
 }
