517 lines
16 KiB
C++
517 lines
16 KiB
C++
|
// vchk.cpp : Defines the entry point for the console application.
|
||
|
//
|
||
|
|
||
|
#include "stdafx.h"
|
||
|
#include "windows.h"
|
||
|
#include "allowed.h"
|
||
|
#include "vchk.h"
|
||
|
#include "ilimpchk.h"
|
||
|
// #include "dispinfo.h"
|
||
|
#include <devguid.h>
|
||
|
#include <setupapi.h>
|
||
|
#include <regstr.h>
|
||
|
|
||
|
#ifdef _DEBUG
|
||
|
#define new DEBUG_NEW
|
||
|
#undef THIS_FILE
|
||
|
static char THIS_FILE[] = __FILE__;
|
||
|
#endif
|
||
|
|
||
|
using namespace std;
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// The one and only application object
|
||
|
|
||
|
inline
|
||
|
void
|
||
|
CDrvchkApp::PrintOut (LPCSTR str)
|
||
|
{
|
||
|
if (m_logf)
|
||
|
fprintf (m_logf, "%s", str);
|
||
|
else
|
||
|
cerr << str;
|
||
|
}
|
||
|
|
||
|
inline
|
||
|
void
|
||
|
CDrvchkApp::PrintOut (unsigned num)
|
||
|
{
|
||
|
if (m_logf)
|
||
|
fprintf (m_logf, "%d", num);
|
||
|
else
|
||
|
cerr << num;
|
||
|
}
|
||
|
|
||
|
ModulesAndImports allowed_modules;
|
||
|
ModulesAndImports known_illegal;
|
||
|
ModulesAndImports illegal_msgs;
|
||
|
|
||
|
void BuildInAllowedAndIllegal (void)
|
||
|
{
|
||
|
allowed_modules.SetModule ("VIDEOPRT.SYS");
|
||
|
|
||
|
known_illegal.SetModule ("HAL.dll");
|
||
|
illegal_msgs.SetModule ("HAL.dll");
|
||
|
|
||
|
illegal_msgs.AddImport ("HalAllocateCommonBuffer", "use VideoPortAllocateCommonBuffer");
|
||
|
illegal_msgs.AddImport ("HalFreeCommonBuffer", "use VideoPortFreeCommonBuffer");
|
||
|
|
||
|
known_illegal.AddImport ("HalGetAdapter", "obsolete; see DDK manual");
|
||
|
known_illegal.AddImport ("HalGetBusData", "obsolete; see DDK manual");
|
||
|
|
||
|
|
||
|
known_illegal.AddImport ("HalGetBusDataByOffset"); // warning
|
||
|
known_illegal.AddImport ("HalSetBusData"); // warning
|
||
|
known_illegal.AddImport ("HalSetBusDataByOffset"); // warning
|
||
|
|
||
|
illegal_msgs.AddImport ("KeGetCurrentIrql", "use VideoPortGetCurrentIrql");
|
||
|
illegal_msgs.AddImport ("KfAcquireSpinLock", "use VideoPortAcquireSpinLock");
|
||
|
illegal_msgs.AddImport ("KfReleaseSpinLock", "use VideoPortReleaseSpinLock");
|
||
|
illegal_msgs.AddImport ("READ_PORT_ULONG", "use VideoPortReadPortUlong");
|
||
|
illegal_msgs.AddImport ("WRITE_PORT_ULONG", "use VideoPortWritePortUlong");
|
||
|
|
||
|
|
||
|
known_illegal.SetModule ("NTOSKRNL.EXE");
|
||
|
illegal_msgs.SetModule ("NTOSKRNL.EXE");
|
||
|
known_illegal.AddImport ("MmQuerySystemSize"); // warning
|
||
|
known_illegal.AddImport ("_except_handler3"); // warning
|
||
|
known_illegal.AddImport ("ZwMapViewOfSection"); // warning
|
||
|
known_illegal.AddImport ("ZwUnmapViewOfSection"); // warning
|
||
|
known_illegal.AddImport ("IoAllocateMdl"); // warning
|
||
|
known_illegal.AddImport ("IoFreeMdl"); // warning
|
||
|
known_illegal.AddImport ("MmBuildMdlForNonPagedPool"); // warning
|
||
|
known_illegal.AddImport ("MmGetPhysicalAddress"); // warning
|
||
|
known_illegal.AddImport ("ObReferenceObjectByHandle"); // warning
|
||
|
known_illegal.AddImport ("RtlUnwind"); // warning
|
||
|
known_illegal.AddImport ("ZwOpenSection"); // warning
|
||
|
|
||
|
illegal_msgs.AddImport ("ExAllocatePool", "use VideoPortAllocatePool");
|
||
|
illegal_msgs.AddImport ("ExAllocatePoolWithTag", "use VideoPortAllocatePool");
|
||
|
illegal_msgs.AddImport ("ExFreePool", "use VideoPortFreePool");
|
||
|
illegal_msgs.AddImport ("ExFreePoolWithTag", "use VideoPortFreePool");
|
||
|
illegal_msgs.AddImport ("KeClearEvent", "use VideoPortClearEvent");
|
||
|
illegal_msgs.AddImport ("KeDelayExecutionThread", "use VideoPortStallExecution");
|
||
|
illegal_msgs.AddImport ("KeInitializeDpc", "use VideoPortQueueDpc");
|
||
|
illegal_msgs.AddImport ("KeInsertQueueDpc", "use VideoPortQueueDpc");
|
||
|
illegal_msgs.AddImport ("KeInitializeSpinLock", "use VideoPortXxxSpinLockXxx");
|
||
|
illegal_msgs.AddImport ("KeSetEvent", "use VideoPortSetEvent");
|
||
|
illegal_msgs.AddImport ("MmAllocateContiguousMemory", "use VideoPortAllocateContiguousMemory");
|
||
|
illegal_msgs.AddImport ("READ_REGISTER_UCHAR", "use VideoPortReadRegisterUchar");
|
||
|
illegal_msgs.AddImport ("wcslen", "link to libcntpr.lib instead");
|
||
|
illegal_msgs.AddImport ("WRITE_REGISTER_USHORT", "use VideoPortWriteRegisterUshort");
|
||
|
illegal_msgs.AddImport ("WRITE_REGISTER_UCHAR", "use VideoPortWriteRegisterUchar");
|
||
|
}
|
||
|
|
||
|
int __cdecl _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
|
||
|
{
|
||
|
int nRetCode = 0;
|
||
|
|
||
|
// cerr << ::GetCommandLine() << endl;
|
||
|
|
||
|
// initialize MFC and print and error on failure
|
||
|
if (AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
|
||
|
{
|
||
|
CDrvchkApp theApp;
|
||
|
theApp.InitInstance ();
|
||
|
}
|
||
|
|
||
|
return nRetCode;
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// CDrvchkApp construction
|
||
|
|
||
|
CDrvchkApp::CDrvchkApp() :
|
||
|
m_logf(NULL),
|
||
|
m_drv_name ("")
|
||
|
{
|
||
|
// TODO: add construction code here,
|
||
|
// Place all significant initialization in InitInstance
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// The one and only CDrvchkApp object
|
||
|
|
||
|
/*------------------------------------------------------------------------
|
||
|
|
||
|
vchk /drv driver.dll /log logname.log /allow videoptr.sys
|
||
|
|
||
|
/allowed_modules module1.sys FnName1 FnName2 FnName3 /allowed_modules module2.dll FnName4
|
||
|
|
||
|
------------------------------------------------------------------------*/
|
||
|
|
||
|
void
|
||
|
CommandLine::ParseParam( LPCTSTR lpszParam, BOOL bFlag, BOOL bLast )
|
||
|
{
|
||
|
|
||
|
if (m_parse_error)
|
||
|
return;
|
||
|
|
||
|
CString param (lpszParam);
|
||
|
|
||
|
if (bFlag) {
|
||
|
|
||
|
param.MakeUpper();
|
||
|
|
||
|
if (m_last_flag.GetLength()) {
|
||
|
m_parse_error = TRUE;
|
||
|
m_error_msg = CString("Flag ") + m_last_flag + CString(" requires a parameter.");
|
||
|
} else if ((param==CString("LOG")) || (param==CString("DRV")) || (param==CString("MON")) ||
|
||
|
(param==CString("ALLOW")) || (param==CString("allowed_modules"))) {
|
||
|
m_last_flag = param;
|
||
|
m_first_param = TRUE;
|
||
|
} else {
|
||
|
m_last_flag = "";
|
||
|
m_parse_error = TRUE;
|
||
|
m_error_msg = CString("Unrecognized flag: ") + param;
|
||
|
}
|
||
|
|
||
|
} else {
|
||
|
|
||
|
if (m_last_flag==CString("ALLOW")) {
|
||
|
allowed_modules.SetModule(param);
|
||
|
/*
|
||
|
sprintf (m_allowed, "%s", (LPCSTR)param);
|
||
|
m_allowed += strlen (m_allowed);
|
||
|
m_allowed[0] = 0;
|
||
|
m_allowed[1] = 0;
|
||
|
m_allowed++;
|
||
|
*/
|
||
|
} else if (m_last_flag==CString("allowed_modules")) {
|
||
|
|
||
|
if (m_first_param) {
|
||
|
allowed_modules.SetModule(param);
|
||
|
m_first_param = FALSE;
|
||
|
} else {
|
||
|
allowed_modules.AddImport(param);
|
||
|
}
|
||
|
|
||
|
} else if (m_last_flag==CString("DRV")) {
|
||
|
m_drv_fname = param;
|
||
|
m_last_flag="";
|
||
|
} else if (m_last_flag==CString("LOG")) {
|
||
|
m_log_fname = param;
|
||
|
m_last_flag="";
|
||
|
} else if (m_last_flag==CString("MON")) {
|
||
|
if (param.GetLength()==1) {
|
||
|
char c = ((LPCSTR)param)[0];
|
||
|
m_monitor = c - '1';
|
||
|
} else {
|
||
|
m_monitor = -1;
|
||
|
m_error_msg = "bad command line: /MON flag has wrong parameter";
|
||
|
m_parse_error = TRUE;
|
||
|
}
|
||
|
m_last_flag="";
|
||
|
} else {
|
||
|
m_parse_error = TRUE;
|
||
|
m_error_msg = CString("Wrong parameter: ") + param;
|
||
|
m_last_flag="";
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (bLast) {
|
||
|
if (m_last_flag==CString("LOG") || m_last_flag==CString("DRV")) {
|
||
|
m_parse_error = TRUE;
|
||
|
m_error_msg = CString("Flag ") + m_last_flag + CString(" requires a parameter.");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// CDrvchkApp initialization
|
||
|
|
||
|
BOOL CDrvchkApp::InitInstance()
|
||
|
{
|
||
|
// Standard initialization
|
||
|
// If you are not using these features and wish to reduce the size
|
||
|
|
||
|
m_os_ver_info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
||
|
GetVersionEx (&m_os_ver_info);
|
||
|
if (m_os_ver_info.dwPlatformId != VER_PLATFORM_WIN32_NT) { // doesn't work on Win9x
|
||
|
PrintOut ("warning: unsupported OS (Win9x), nothing done.\n");
|
||
|
return FALSE;
|
||
|
}
|
||
|
if (m_os_ver_info.dwMajorVersion!=5) { // doesn't work on NT version prior to Win2K
|
||
|
PrintOut ("warning: unsupported OS (");
|
||
|
PrintOut (m_os_ver_info.dwMajorVersion);
|
||
|
PrintOut (".");
|
||
|
PrintOut (m_os_ver_info.dwMinorVersion);
|
||
|
PrintOut ("): nothing done.\n");
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
ParseCommandLine (m_cmd_line);
|
||
|
BuildInAllowedAndIllegal();
|
||
|
|
||
|
if (m_cmd_line.m_log_fname.GetLength()) {
|
||
|
m_logf = fopen (m_cmd_line.m_log_fname, "a+");
|
||
|
}
|
||
|
|
||
|
if (m_cmd_line.m_parse_error) {
|
||
|
|
||
|
PrintOut ("error: ");
|
||
|
PrintOut ((LPCSTR)m_cmd_line.m_error_msg);
|
||
|
PrintOut ("\n");
|
||
|
|
||
|
} else {
|
||
|
|
||
|
int device_num = m_cmd_line.m_monitor;
|
||
|
|
||
|
if (m_cmd_line.m_drv_fname.GetLength()) {
|
||
|
|
||
|
ChkDriver (m_cmd_line.m_drv_fname);
|
||
|
|
||
|
} else {
|
||
|
|
||
|
HDEVINFO hDevInfo;
|
||
|
SP_DEVINFO_DATA did;
|
||
|
// TCHAR szBuffer[256];
|
||
|
DWORD index = 0;
|
||
|
HKEY hkTest;
|
||
|
|
||
|
HKEY hKey;
|
||
|
ULONG ulType = 0;
|
||
|
DWORD cbData = 0;
|
||
|
DEVMODE dmCurrent;
|
||
|
TCHAR szDeviceDescription[10000];
|
||
|
TCHAR szImagePath[256];
|
||
|
TCHAR szVarImagePath[256];
|
||
|
TCHAR szExpImagePath[256];
|
||
|
|
||
|
CString dev_desc_CtrlSet;
|
||
|
|
||
|
hKey = 0;
|
||
|
|
||
|
//
|
||
|
// Let's find all the video drivers that are installed in the system
|
||
|
//
|
||
|
DISPLAY_DEVICE DisplayDevice;
|
||
|
DisplayDevice.cb = sizeof (DisplayDevice);
|
||
|
|
||
|
// cerr << "looking for device #" << device_num << endl;
|
||
|
|
||
|
for (DWORD d=0, index=0; EnumDisplayDevices(NULL, index, &DisplayDevice, 0); index++) {
|
||
|
|
||
|
// cerr << "device #" << d << endl;
|
||
|
|
||
|
if (DisplayDevice.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER) {
|
||
|
// cerr << "DisplayDevice.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER\n";
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (device_num!=d++) {
|
||
|
// cerr << "device_num!=d\n";
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
CString service_path = GetServiceRegistryPath (DisplayDevice);
|
||
|
|
||
|
if (!service_path.GetLength()) {
|
||
|
PrintOut ("error: cannot find video service\n");
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
///// service known /////
|
||
|
|
||
|
hKey = 0;
|
||
|
cbData = sizeof szImagePath;
|
||
|
if ((RegOpenKeyEx(HKEY_LOCAL_MACHINE, _TEXT(service_path), 0, KEY_READ, &hKey) != ERROR_SUCCESS) ||
|
||
|
(RegQueryValueEx(hKey, _TEXT("ImagePath"), 0, &ulType, (LPBYTE)szImagePath, &cbData) != ERROR_SUCCESS) ||
|
||
|
(cbData == 0)) {
|
||
|
cbData = 0;
|
||
|
PrintOut ("error: cannot find video driver\n");
|
||
|
}
|
||
|
|
||
|
if (hKey)
|
||
|
RegCloseKey(hKey);
|
||
|
|
||
|
if (cbData) {
|
||
|
sprintf (szVarImagePath, "%%WINDIR%%\\%s", szImagePath);
|
||
|
ExpandEnvironmentStrings (szVarImagePath, szExpImagePath, 256);
|
||
|
// cerr << "szExpImagePath = " << szExpImagePath << endl;
|
||
|
ChkDriver (szExpImagePath);
|
||
|
}
|
||
|
|
||
|
|
||
|
} // for each device
|
||
|
|
||
|
} // look for system drivers
|
||
|
|
||
|
} // if no cmd line error
|
||
|
|
||
|
if (m_logf)
|
||
|
fclose (m_logf);
|
||
|
m_logf = NULL;
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
#define REGISTRY_MACHINE_OFS _tcslen(_TEXT("\\registry\\machine\\"))
|
||
|
|
||
|
CString CDrvchkApp::GetServiceRegistryPath (DISPLAY_DEVICE& DisplayDevice)
|
||
|
{
|
||
|
HKEY hKey = NULL;
|
||
|
CString result_service_path = CString("");;
|
||
|
/*
|
||
|
// dump Display Device
|
||
|
//
|
||
|
FILE* f=fopen("hjhj.txt", "wb");
|
||
|
BYTE* p = (BYTE*)&DisplayDevice;
|
||
|
for (int i=0; i<sizeof(DISPLAY_DEVICE); i++)
|
||
|
fwrite (p+i, 1, 1, f);
|
||
|
fclose(f);
|
||
|
*/
|
||
|
|
||
|
TCHAR device_key[256]; // Name of service (drivers)
|
||
|
|
||
|
_tcscpy (device_key, DisplayDevice.DeviceKey+18);
|
||
|
|
||
|
// cut the "\Device0" or "\0000" tail...
|
||
|
TCHAR* pch = _tcsrchr(device_key, _TEXT('\\'));
|
||
|
if (pch != NULL)
|
||
|
*pch = 0;
|
||
|
|
||
|
// cerr << "DisplayDevice.DeviceKey: " << device_key << endl;
|
||
|
|
||
|
switch (m_os_ver_info.dwMinorVersion) {
|
||
|
|
||
|
case 0:
|
||
|
// cerr << "DisplayDevice.DeviceKey: " << device_key << endl;
|
||
|
result_service_path = CString(device_key);
|
||
|
break;
|
||
|
|
||
|
case 1:
|
||
|
{
|
||
|
size_t len = _tcslen(device_key);
|
||
|
sprintf (device_key+len, "\\Video");
|
||
|
// cerr << "DisplayDevice.DeviceKey+REGISTRY_MACHINE_OFS: " << device_key << endl;
|
||
|
|
||
|
BYTE service_name[256];
|
||
|
ULONG ulReserved = 0;
|
||
|
DWORD cbData = sizeof service_name;
|
||
|
CString key_name = device_key;
|
||
|
// cerr << key_name << endl;
|
||
|
|
||
|
if ((RegOpenKeyEx(HKEY_LOCAL_MACHINE, _TEXT(key_name), 0, KEY_READ, &hKey) != ERROR_SUCCESS) ||
|
||
|
(RegQueryValueEx(hKey, _TEXT("Service"), 0, &ulReserved, (LPBYTE)service_name, &cbData) != ERROR_SUCCESS) ||
|
||
|
(cbData == 0)) {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// cerr << "Service reg name: " << service_name << endl;
|
||
|
result_service_path = "SYSTEM\\CurrentControlSet\\Services\\";
|
||
|
result_service_path += CString(service_name);
|
||
|
// cerr << "Service reg path: " << (LPCSTR)result_service_path << endl;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
PrintOut ("warning: unknown system version 5.");
|
||
|
PrintOut (m_os_ver_info.dwMinorVersion);
|
||
|
PrintOut ("\n");
|
||
|
}
|
||
|
|
||
|
if (hKey)
|
||
|
RegCloseKey(hKey);
|
||
|
return result_service_path;
|
||
|
}
|
||
|
|
||
|
void CDrvchkApp::ChkDriver (CString drv_name)
|
||
|
{
|
||
|
m_drv_name = drv_name;
|
||
|
cerr << (LPCSTR)m_drv_name << endl;
|
||
|
InitIllegalImportsSearch (m_drv_name, "INIT");
|
||
|
if (CheckDriverAndPrintResults ()) {
|
||
|
PrintOut ("success: no illegal imports in ");
|
||
|
PrintOut (m_drv_name);
|
||
|
PrintOut ("\n");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
BOOL CDrvchkApp::CheckDriverAndPrintResults ()
|
||
|
{
|
||
|
|
||
|
Names Modules = CheckSectionsForImports ();
|
||
|
|
||
|
if (!Modules.Ptr) {
|
||
|
PrintOut ("error: cannot retrieve import information from ");
|
||
|
PrintOut (m_drv_name);
|
||
|
PrintOut ("\n");
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
int errors_found = 0;
|
||
|
|
||
|
for (int i=0;
|
||
|
i<Modules.Num;
|
||
|
Modules.Ptr = GetNextName(Modules.Ptr), i++) {
|
||
|
|
||
|
Names Imports = GetImportsList (Modules.Ptr);
|
||
|
|
||
|
// cerr << "Checking " << (LPCSTR)Modules.Ptr << endl;
|
||
|
|
||
|
CString module_name (Modules.Ptr);
|
||
|
|
||
|
if (allowed_modules.IsModule(module_name)) {
|
||
|
// cerr << "ALLOWED " << (LPCSTR)module_name << endl;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
BOOL KnownIllegals = known_illegal.IsModule(module_name);
|
||
|
if (KnownIllegals) {
|
||
|
// cerr << "KNOWN ILLEGALS FROM " << (LPCSTR)module_name << endl;
|
||
|
}
|
||
|
|
||
|
LPSTR ImportsPtr = Imports.Ptr;
|
||
|
|
||
|
// cerr << "Imports.Num = " << Imports.Num << endl;
|
||
|
|
||
|
for (int j=0;
|
||
|
j<Imports.Num;
|
||
|
Imports.Ptr = GetNextName (Imports.Ptr), j++) {
|
||
|
|
||
|
// cerr << "j=" << j << "\n";
|
||
|
CString msg = "";
|
||
|
|
||
|
CString ImportFnName = CString(Modules.Ptr) +
|
||
|
CString("!") +
|
||
|
CString(Imports.Ptr);
|
||
|
|
||
|
if (KnownIllegals && known_illegal.Lookup(Imports.Ptr, msg))
|
||
|
PrintOut ("warning: ");
|
||
|
else {
|
||
|
errors_found ++;
|
||
|
illegal_msgs.Lookup(Imports.Ptr, msg);
|
||
|
PrintOut ("error: ");
|
||
|
}
|
||
|
|
||
|
PrintOut (m_drv_name);
|
||
|
PrintOut (": ");
|
||
|
PrintOut (ImportFnName);
|
||
|
if (msg.GetLength()) {
|
||
|
PrintOut (" -- ");
|
||
|
PrintOut (msg);
|
||
|
}
|
||
|
PrintOut ("\n");
|
||
|
}
|
||
|
|
||
|
|
||
|
if (ImportsPtr)
|
||
|
HeapFree (GetProcessHeap(), 0, ImportsPtr);
|
||
|
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
char buf[1024];
|
||
|
sprintf (buf, "%d modules; %d imports", Modules.Num, errors_found);
|
||
|
|
||
|
if (m_listf) {
|
||
|
fprintf (m_listf, "\n%s\n\n", buf);
|
||
|
}
|
||
|
*/
|
||
|
|
||
|
return (errors_found==0);
|
||
|
}
|
||
|
|