windows-nt/Source/XPSP1/NT/drivers/video/ms/test/vchk/vchk.cpp
2020-09-26 16:20:57 +08:00

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);
}