3 Copyright 2007 Red Hat, Inc.
5 This file is part of Cygwin.
7 This software is a copyrighted work licensed under the terms of the
8 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
11 #define cygwin_internal cygwin_internal_dontuse
16 #include <ddk/ntstatus.h>
17 #include <ddk/ntapi.h>
18 #undef cygwin_internal
22 #define dbg_printf(ARGS) printf ARGS ; fflush (NULL)
23 #else /* !DEBUGGING */
24 #define dbg_printf(ARGS) do { } while (0)
25 #endif /* ?DEBUGGING */
27 /* This module detects applications from the Big List of Dodgy Apps,
28 a list of applications that have at some given time been shown to
29 interfere with the operation of cygwin. It detects the presence of
30 applications on the system by looking for any of four traces an
31 installation might leave: 1) registry keys, 2) files on disk
32 3) running executables 4) loaded dlls or drivers.
34 At the time of writing, the BLODA amounts to:-
36 Sonic Solutions burning software containing DLA component
37 Norton/MacAffee/Symantec antivirus or antispyware
38 Logitech webcam software with "Logitech process monitor" service
39 Kerio, Agnitum or ZoneAlarm Personal Firewall
40 Iolo System Mechanic/AntiVirus/Firewall
43 Embassy Trust Suite fingerprint reader software containing wxvault.dll
44 ByteMobile laptop optimization client
46 A live version is now being maintained in the Cygwin FAQ, at
47 http://cygwin.com/faq/faq.using.html#faq.using.bloda
53 SONIC
, NORTON
, MACAFFEE
, SYMANTEC
,
54 LOGITECH
, KERIO
, AGNITUM
, ZONEALARM
,
55 IOLO
, LANDESK
, WINDEFENDER
, EMBASSYTS
,
66 enum bad_app_det_method
68 HKLMKEY
, HKCUKEY
, FILENAME
, PROCESSNAME
, HOOKDLLNAME
73 enum bad_app_det_method type
;
78 static const struct bad_app_det dodgy_app_detects
[] =
80 { PROCESSNAME
, "dlactrlw.exe", SONIC
},
81 { HOOKDLLNAME
, "wxvault.dll", EMBASSYTS
},
82 { HKLMKEY
, "SYSTEM\\CurrentControlSet\\Services\\vsdatant", ZONEALARM
},
83 { FILENAME
, "%windir%\\System32\\vsdatant.sys", ZONEALARM
},
84 { HKLMKEY
, "SYSTEM\\CurrentControlSet\\Services\\lvprcsrv", LOGITECH
},
85 { PROCESSNAME
, "LVPrcSrv.exe", LOGITECH
},
86 { FILENAME
, "%programfiles%\\common files\\logitech\\lvmvfm\\LVPrcSrv.exe", LOGITECH
},
87 { FILENAME
, "%windir%\\System32\\bmnet.dll", BYTEMOBILE
},
90 static const size_t num_of_detects
= sizeof (dodgy_app_detects
) / sizeof (dodgy_app_detects
[0]);
92 static struct bad_app_info big_list_of_dodgy_apps
[] =
94 { SONIC
, "Sonic Solutions burning software containing DLA component" },
95 { NORTON
, "Norton antivirus or antispyware software" },
96 { MACAFFEE
, "Macaffee antivirus or antispyware software" },
97 { SYMANTEC
, "Symantec antivirus or antispyware software" },
98 { LOGITECH
, "Logitech Process Monitor service" },
99 { KERIO
, "Kerio Personal Firewall" },
100 { AGNITUM
, "Agnitum Personal Firewall" },
101 { ZONEALARM
, "ZoneAlarm Personal Firewall" },
102 { IOLO
, "Iolo System Mechanic/AntiVirus/Firewall software" },
103 { LANDESK
, "Landesk" },
104 { WINDEFENDER
, "Windows Defender" },
105 { EMBASSYTS
, "Embassy Trust Suite fingerprint reader software containing wxvault.dll" },
106 { BYTEMOBILE
, "ByteMobile laptop optimization client" },
109 static const size_t num_of_dodgy_apps
= sizeof (big_list_of_dodgy_apps
) / sizeof (big_list_of_dodgy_apps
[0]);
111 static PSYSTEM_PROCESSES
112 get_process_list (void)
115 PSYSTEM_PROCESSES pslist
= (PSYSTEM_PROCESSES
) malloc (n_procs
* sizeof *pslist
);
117 while (NtQuerySystemInformation (SystemProcessesAndThreadsInformation
,
118 pslist
, n_procs
* sizeof *pslist
, 0) == STATUS_INFO_LENGTH_MISMATCH
)
122 pslist
= (PSYSTEM_PROCESSES
) malloc (n_procs
* sizeof *pslist
);
127 static PSYSTEM_MODULE_INFORMATION
128 get_module_list (void)
130 int modsize
= 0x1000;
131 PSYSTEM_MODULE_INFORMATION modlist
= (PSYSTEM_MODULE_INFORMATION
) malloc (modsize
);
133 while (NtQuerySystemInformation (SystemModuleInformation
,
134 modlist
, modsize
, NULL
) == STATUS_INFO_LENGTH_MISMATCH
)
138 modlist
= (PSYSTEM_MODULE_INFORMATION
) malloc (modsize
);
144 find_process_in_list (PSYSTEM_PROCESSES pslist
, PUNICODE_STRING psname
)
148 if (pslist
->ProcessName
.Length
&& pslist
->ProcessName
.Buffer
)
150 dbg_printf (("%S\n", pslist
->ProcessName
.Buffer
));
151 if (!_wcsicmp (pslist
->ProcessName
.Buffer
, psname
->Buffer
))
154 if (!pslist
->NextEntryDelta
)
156 pslist
= (PSYSTEM_PROCESSES
)(pslist
->NextEntryDelta
+ (char *)pslist
);
162 find_module_in_list (PSYSTEM_MODULE_INFORMATION modlist
, const char * const modname
)
164 PSYSTEM_MODULE_INFORMATION_ENTRY modptr
= &modlist
->Module
[0];
165 DWORD count
= modlist
->Count
;
168 dbg_printf (("name '%s' offset %d ", &modptr
->ImageName
[0], modptr
->PathLength
));
169 dbg_printf (("= '%s'\n", &modptr
->ImageName
[modptr
->PathLength
]));
170 if (!_stricmp (&modptr
->ImageName
[modptr
->PathLength
], modname
))
178 expand_path (const char *path
, char *outbuf
)
181 const char *end
, *envval
;
182 char envvar
[MAX_PATH
];
185 while ((dst
- outbuf
) < MAX_PATH
)
189 if ((*dst
++ = *path
++) != 0)
193 /* Expand an environ var. */
197 /* Watch out for unterminated % */
204 /* If we didn't find the end, can't expand it. */
205 if ((end
== NULL
) || (end
== (path
+ 1)))
207 /* Unterminated % so copy verbatim. */
211 /* Expand the environment var into the new path. */
212 if ((end
- (path
+ 1)) >= MAX_PATH
)
214 memcpy (envvar
, path
+ 1, end
- (path
+ 1));
215 envvar
[end
- (path
+ 1)] = 0;
216 envval
= getenv (envvar
);
217 /* If not found, copy env var name verbatim. */
223 /* Check enough room before copying. */
224 len
= strlen (envval
);
225 if ((dst
+ len
- outbuf
) >= MAX_PATH
)
227 memcpy (dst
, envval
, len
);
229 /* And carry on past the end of env var name. */
232 return (dst
- outbuf
) < MAX_PATH
;
236 detect_dodgy_app (const struct bad_app_det
*det
, PSYSTEM_PROCESSES pslist
, PSYSTEM_MODULE_INFORMATION modlist
)
240 UNICODE_STRING unicodename
;
241 ANSI_STRING ansiname
;
244 char expandedname
[MAX_PATH
];
249 dbg_printf (("Detect reg key hklm '%s'... ", det
->param
));
250 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE
, det
->param
, 0, STANDARD_RIGHTS_READ
, &hk
) == ERROR_SUCCESS
)
253 dbg_printf (("found!\n"));
259 dbg_printf (("Detect reg key hkcu '%s'... ", det
->param
));
260 if (RegOpenKeyEx (HKEY_CURRENT_USER
, det
->param
, 0, STANDARD_RIGHTS_READ
, &hk
) == ERROR_SUCCESS
)
263 dbg_printf (("found!\n"));
269 dbg_printf (("Detect filename '%s'... ", det
->param
));
270 if (!expand_path (det
->param
, expandedname
))
272 printf ("Expansion failure!\n");
275 dbg_printf (("('%s' after expansion)... ", expandedname
));
276 fh
= CreateFile (expandedname
, 0, FILE_SHARE_READ
| FILE_SHARE_WRITE
277 | FILE_SHARE_DELETE
, NULL
, OPEN_EXISTING
, 0, NULL
);
278 if (fh
!= INVALID_HANDLE_VALUE
)
281 dbg_printf (("found!\n"));
287 dbg_printf (("Detect proc name '%s'... ", det
->param
));
288 /* Equivalent of RtlInitAnsiString. */
289 ansiname
.Length
= ansiname
.MaximumLength
= strlen (det
->param
);
290 ansiname
.Buffer
= (CHAR
*) det
->param
;
291 rv
= RtlAnsiStringToUnicodeString (&unicodename
, &ansiname
, TRUE
);
292 if (rv
!= STATUS_SUCCESS
)
294 printf ("Ansi to unicode conversion failure $%08x\n", (unsigned int) rv
);
297 found
= find_process_in_list (pslist
, &unicodename
);
298 RtlFreeUnicodeString (&unicodename
);
301 dbg_printf (("found!\n"));
307 dbg_printf (("Detect hookdll '%s'... ", det
->param
));
308 if (find_module_in_list (modlist
, det
->param
))
310 dbg_printf (("found!\n"));
316 dbg_printf (("not found.\n"));
320 static struct bad_app_info
*
321 find_dodgy_app_info (enum bad_app which_app
)
324 for (i
= 0; i
< num_of_dodgy_apps
; i
++)
326 if (big_list_of_dodgy_apps
[i
].app_id
== which_app
)
327 return &big_list_of_dodgy_apps
[i
];
332 /* External entrypoint called from cygcheck.cc/dump_sysinfo. */
334 dump_dodgy_apps (int verbose
)
337 PSYSTEM_PROCESSES pslist
;
338 PSYSTEM_MODULE_INFORMATION modlist
;
340 /* Read system info for detect testing. */
341 pslist
= get_process_list ();
342 modlist
= get_module_list ();
344 /* Go with builtin list for now; later may enhance to
345 read dodgy apps from a file or download from an URL. */
346 for (i
= 0; i
< num_of_dodgy_apps
; i
++)
348 big_list_of_dodgy_apps
[i
].found_it
= false;
351 for (i
= 0; i
< num_of_detects
; i
++)
353 const struct bad_app_det
*det
= &dodgy_app_detects
[i
];
354 struct bad_app_info
*found
= find_dodgy_app_info (det
->app
);
355 bool detected
= detect_dodgy_app (det
, pslist
, modlist
);
357 /* Not found would mean we coded the lists bad. */
362 found
->found_it
|= (1 << det
->type
);
367 printf ("\nPotential app conflicts:\n\n");
368 for (i
= 0; i
< num_of_dodgy_apps
; i
++)
370 if (big_list_of_dodgy_apps
[i
].found_it
)
372 printf ("%s%s", big_list_of_dodgy_apps
[i
].details
,
373 verbose
? "\nDetected: " : ".\n");
376 const char *sep
= "";
377 if (big_list_of_dodgy_apps
[i
].found_it
& (1 << HKLMKEY
))
379 printf ("HKLM Registry Key");
382 if (big_list_of_dodgy_apps
[i
].found_it
& (1 << HKCUKEY
))
384 printf ("%sHKCU Registry Key", sep
);
387 if (big_list_of_dodgy_apps
[i
].found_it
& (1 << FILENAME
))
389 printf ("%sNamed file", sep
);
392 if (big_list_of_dodgy_apps
[i
].found_it
& (1 << PROCESSNAME
))
394 printf ("%sNamed process", sep
);
397 if (big_list_of_dodgy_apps
[i
].found_it
& (1 << HOOKDLLNAME
))
399 printf ("%sLoaded hook DLL", sep
);
405 /* Tidy up allocations. */