Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1051 lines
36 KiB

// vchk.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#pragma hdrstop
#include "vchk.h"
#include "allowed.h"
#include "ilimpchk.h"
//#include <devguid.h>
#include <setupapi.h>
//#include <regstr.h>
#include <cfgmgr32.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
using namespace std;
//////////////////////////////////////////////////////////////////////////////
//#define VCHK_TRACE_ON 1
#ifdef VCHK_TRACE_ON
const char* VchkTraceGetName(const char* szName)
{
const char* szLastSeg = szName;
const char* szSlash = strchr(szName, '\\');
while (szSlash) {
++szSlash;
szLastSeg = szSlash;
szSlash = strchr(szSlash, '\\');
}
return szLastSeg;
}
#define VCHK_TRACE(x) {cerr << " [" << VchkTraceGetName(__FILE__) << ":" << __LINE__ << "] " << x;}
#else
#define VCHK_TRACE(x)
#endif
/////////////////////////////////////////////////////////////////////////////
// Enumerates display devices
typedef class CDisplayDeviceEnum {
public:
static bool IsDigitsOnly(const char* sz);
CDisplayDeviceEnum();
~CDisplayDeviceEnum() {free(Buffer);}
bool IsValid() const {return bValid;}
bool Next();
CString GetMiniportPath();
DWORD GetDeviceId() {return iEnum;}
DWORD GetLastError() {return dwLastError;}
const char* GetLastErrorStr() {return szLastError;}
void MarkDevice(DISPLAY_DEVICE& r_DisplayDevice);
void UnmarkDevice();
bool IsMarkedDevice();
private:
static const GUID const displayClassGUID;
BYTE* Buffer;
size_t BufferSize;
bool bValid;
DWORD iEnum;
HDEVINFO hDevInfo;
SP_DEVINFO_DATA DeviceInfoData;
HKEY hMarkedKey;
DWORD dwLastError;
const char* szLastError;
bool ReallocBuffer(size_t NewSize)
{
if (NewSize > BufferSize) {
void* p = realloc(Buffer, NewSize);
if (!p) return false;
Buffer = (PBYTE)p;
BufferSize = NewSize;
}
return true;
}
void MarkKey(HKEY hKey);
void UnmarkKey();
bool IsMarkedDEVINST(DEVINST DevInst);
} typedef_CDisplayDeviceEnum;
/////////////////////////////////////////////////////////////////////////////
// CDisplayDeviceEnum implementation
/////////////////////////////////////////////////////////////////////////////
// CDisplayDeviceEnum::IsDigitsOnly
bool CDisplayDeviceEnum::IsDigitsOnly(const char* sz)
{
if (!sz || !*sz) return false;
while (('0' <= *sz) && (*sz <= '9')) ++sz;
return !*sz;
}
/////////////////////////////////////////////////////////////////////////////
// CDisplayDeviceEnum constants
const GUID const CDisplayDeviceEnum::displayClassGUID =
{0x4d36e968L, 0xe325, 0x11ce, {0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18}};
/////////////////////////////////////////////////////////////////////////////
// CDisplayDeviceEnum constructor
CDisplayDeviceEnum::CDisplayDeviceEnum() :
bValid(true),
Buffer(NULL),
BufferSize(0),
iEnum(0),
hDevInfo(INVALID_HANDLE_VALUE),
hMarkedKey(NULL),
dwLastError(0),
szLastError(NULL)
{
ZeroMemory(&DeviceInfoData, sizeof(DeviceInfoData));
DeviceInfoData.cbSize = sizeof(DeviceInfoData);
ReallocBuffer(MAX_PATH + 1);
// Get Device Info Set for display class GUID
hDevInfo = SetupDiGetClassDevs(&displayClassGUID, // class guid
NULL, // Enumerator
NULL, // top level window
DIGCF_PRESENT);
if (hDevInfo != INVALID_HANDLE_VALUE) {
Next();
} else {
dwLastError = GetLastError();
szLastError = "SetupDiGetClassDevs failure";
bValid = false;
}
}
/////////////////////////////////////////////////////////////////////////////
// CDisplayDeviceEnum::Next() - gets next device into scope
bool CDisplayDeviceEnum::Next()
{
if (!bValid) return false;
// get device info for the device in the Device Info Set at index iEnum
if (SetupDiEnumDeviceInfo(hDevInfo, // device info set
iEnum, // member index
&DeviceInfoData)) // Device Info data
{
++iEnum;
} else {
dwLastError = GetLastError();
szLastError = "SetupDiEnumDeviceInfo failure";
bValid = false;
}
return bValid;
}
/////////////////////////////////////////////////////////////////////////////
// CDisplayDeviceEnum::GetMiniportPath() - gets miniport of current device
CString CDisplayDeviceEnum::GetMiniportPath()
{
DWORD BufferSizeNeeded = BufferSize;
DWORD DataT;
// Get Registry Information for the Device
// First time through is to find out how much memory we need to allocate.
// Second time actually gives us the information we want.
while (!SetupDiGetDeviceRegistryProperty(hDevInfo, // device info set
&DeviceInfoData, // info for the device we want to retrieve
SPDRP_SERVICE, // Specify that we want the service name
&DataT,
Buffer, // this should return the service name
BufferSizeNeeded,
&BufferSizeNeeded))
{
DWORD dwError = GetLastError();
if (dwError == ERROR_INSUFFICIENT_BUFFER) {
if (ReallocBuffer(BufferSizeNeeded)) continue;
szLastError = "Not enough memory";
} else {
szLastError = "SetupDiGetDeviceRegistryProperty failure";
}
dwLastError = dwError;
bValid = false;
return CString();
}
// get miniport path
CString sRegPath("System\\CurrentControlSet\\Services\\");
sRegPath += (LPCSTR)Buffer;
// open the services key, find the service, and get the image path
HKEY hkService;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
(LPCSTR)sRegPath,
0,
KEY_READ,
&hkService) != ERROR_SUCCESS)
{
dwLastError = GetLastError();
szLastError = "RegOpenKeyEx failure";
bValid = false;
return CString();
}
if (!ReallocBuffer(MAX_PATH)) {
dwLastError = -1;
szLastError = "Not enough memory";
bValid = false;
return CString();
}
DWORD cb = BufferSize;
ZeroMemory(Buffer, cb);
if (RegQueryValueEx(hkService,
"ImagePath",
NULL,
NULL,
(LPBYTE)Buffer,
&cb) != ERROR_SUCCESS)
{
dwLastError = GetLastError();
szLastError = "RegQueryValueEx failure";
bValid = false;
return CString();
}
return CString((const char*)Buffer);
}
/////////////////////////////////////////////////////////////////////////////
// CDisplayDeviceEnum::MarkDevice(DISPLAY_DEVICE&)
//
// XXX olegk (it is really XXX level of hack)
// we will mark the child monitor subkey and than will be searching for
// children with marked keys later in IsMarkedDevice()
//
void CDisplayDeviceEnum::MarkDevice(DISPLAY_DEVICE& r_DisplayDevice)
{
if (hMarkedKey) UnmarkDevice();
VCHK_TRACE("-------- Marking Device ----------\n");
VCHK_TRACE("ID : " << r_DisplayDevice.DeviceID << endl);
VCHK_TRACE("Key : " << r_DisplayDevice.DeviceKey << endl);
VCHK_TRACE("Name : " << r_DisplayDevice.DeviceName << endl);
VCHK_TRACE("String : " << r_DisplayDevice.DeviceString << endl);
DISPLAY_DEVICE MonitorInfo;
MonitorInfo.cb = sizeof(MonitorInfo);
if (!EnumDisplayDevices(r_DisplayDevice.DeviceName, 0, &MonitorInfo, 0)) {
VCHK_TRACE("Can't get monitor info for " <<
r_DisplayDevice.DeviceString << ' ' <<
r_DisplayDevice.DeviceName << endl);
return;
}
CString sKey;
// XXX olegk - Assume that all device keys are under HKEY_LOCAL_MACHINE
{
const CHAR szMachineRegPath[] = "\\REGISTRY\\Machine\\";
if (_strnicmp(szMachineRegPath,
MonitorInfo.DeviceKey,
sizeof(szMachineRegPath) - 1))
{
dwLastError = DWORD(-1);
szLastError = "Invalid registry path (must be under HKEY_LOCAL_MACHINE)";
VCHK_TRACE("Invalid registry path " << MonitorInfo.DeviceKey << endl);
return;
}
sKey = (LPCSTR)(MonitorInfo.DeviceKey) + sizeof(szMachineRegPath) - 1;
}
HKEY hKey;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
(LPCSTR)sKey,
0,
KEY_READ,
&hKey) != ERROR_SUCCESS)
{
// Do nothing - no service will be found
DWORD dwError = GetLastError();
VCHK_TRACE("RegOpenKeyEx failure " << dwError << " : " << r_DisplayDevice.DeviceKey << endl);
return;
}
VCHK_TRACE("Marked Key: " << (LPCSTR)sKey << endl);
MarkKey(hKey);
}
/////////////////////////////////////////////////////////////////////////////
// CDisplayDeviceEnum::UnmarkDevice(DISPLAY_DEVICE&)
void CDisplayDeviceEnum::UnmarkDevice()
{
UnmarkKey();
}
/////////////////////////////////////////////////////////////////////////////
// CDisplayDeviceEnum::IsMarkedDevice()
bool CDisplayDeviceEnum::IsMarkedDevice()
{
const size_t nMaxLevel = 10; // XXX olegk - I can't imagine more than 3 but...
DEVINST DevInstStack[nMaxLevel];
size_t nLevel = 0;
if (CM_Get_Child(&DevInstStack[nLevel], DeviceInfoData.DevInst, 0) != CR_SUCCESS) return false;
while (!IsMarkedDEVINST(DevInstStack[nLevel])) {
if ((nLevel < nMaxLevel) &&
(CM_Get_Child(&DevInstStack[nLevel + 1],
DevInstStack[nLevel],
0) == CR_SUCCESS))
{
++nLevel;
continue;
}
while (CM_Get_Sibling(&DevInstStack[nLevel], DevInstStack[nLevel], 0) != CR_SUCCESS) {
if (!nLevel) return false; // End of search (no marker have been found)
--nLevel;
}
}
return true;
}
/////////////////////////////////////////////////////////////////////////////
// CDisplayDeviceEnum::MarkKey(...)
void CDisplayDeviceEnum::MarkKey(HKEY hKey)
{
UnmarkKey();
hMarkedKey = hKey;
}
/////////////////////////////////////////////////////////////////////////////
// CDisplayDeviceEnum::UnmarkKey(...)
void CDisplayDeviceEnum::UnmarkKey()
{
if (!hMarkedKey) return;
RegCloseKey(hMarkedKey);
hMarkedKey = NULL;
}
/////////////////////////////////////////////////////////////////////////////
// CDisplayDeviceEnum::IsMarkedDEVINST(...)
bool CDisplayDeviceEnum::IsMarkedDEVINST(DEVINST DevInst)
{
bool bIsMarked = false;
HKEY hKey;
if (CM_Open_DevNode_Key(DevInst,
KEY_READ, // IN REGSAM samDesired,
0, // IN ULONG ulHardwareProfile,
RegDisposition_OpenExisting,
&hKey, //OUT PHKEY phkDevice,
CM_REGISTRY_SOFTWARE) == CR_SUCCESS)
{
extern bool IsTheSameRegKey(HKEY, HKEY);
bIsMarked = IsTheSameRegKey(hMarkedKey, hKey);
RegCloseKey(hKey);
}
return bIsMarked;
}
/////////////////////////////////////////////////////////////////////////////
// The one and only application object
void
CDrvchkApp::PrintOut (LPCSTR str)
{
if (m_logf)
fprintf (m_logf, "%s", str);
else
cerr << str;
}
void
CDrvchkApp::PrintOut (unsigned num)
{
if (m_logf)
fprintf (m_logf, "%u", num);
else
cerr << num;
}
inline
void
CDrvchkApp::ListOut (LPCSTR str)
{
if (m_listf)
fprintf (m_listf, "%s", str);
}
void
CDrvchkApp::ListOut (unsigned num)
{
if (m_listf)
fprintf (m_listf, "%u", num);
}
ModulesAndImports allowed_modules;
ModulesAndImports allowed_imports;
ModulesAndImports known_illegal;
ModulesAndImports illegal_msgs;
void SetCurrentModule(const char* szModule)
{
allowed_imports.SetModule(szModule);
illegal_msgs.SetModule(szModule);
known_illegal.SetModule(szModule);
}
#define VCHK_WARN known_illegal.AddImport
#define VCHK_FAIL illegal_msgs.AddImport
#define VCHK_ALLOW allowed_imports.AddImport
void BuildInAllowedAndIllegal (void)
{
SetCurrentModule("HAL.DLL");
VCHK_FAIL ("HalAllocateCommonBuffer", "use VideoPortAllocateCommonBuffer");
VCHK_FAIL ("HalFreeCommonBuffer", "use VideoPortFreeCommonBuffer");
VCHK_WARN ("HalGetAdapter", "obsolete; see DDK manual");
VCHK_WARN ("HalGetBusData", "obsolete; see DDK manual");
VCHK_WARN ("HalGetBusDataByOffset");
VCHK_WARN ("HalSetBusData", "obsolete; see DDK manual");
VCHK_WARN ("HalSetBusDataByOffset");
VCHK_WARN ("HalTranslateBusAddress");
VCHK_FAIL ("KeGetCurrentIrql", "use VideoPortGetCurrentIrql");
VCHK_FAIL ("KeQueryPerformanceCounter", "use VideoPortQueryPerformanceCounter");
VCHK_FAIL ("KfAcquireSpinLock", "use VideoPortAcquireSpinLock");
VCHK_FAIL ("KfReleaseSpinLock", "use VideoPortReleaseSpinLock");
VCHK_FAIL ("READ_PORT_ULONG", "use VideoPortReadPortUlong");
VCHK_FAIL ("WRITE_PORT_ULONG", "use VideoPortWritePortUlong");
SetCurrentModule ("NTOSKRNL.EXE");
VCHK_ALLOW ("_except_handler3");
VCHK_FAIL ("ExAllocatePool", "use VideoPortAllocatePool");
VCHK_FAIL ("ExAllocatePoolWithTag", "use VideoPortAllocatePool");
VCHK_FAIL ("ExFreePool", "use VideoPortFreePool");
VCHK_FAIL ("ExFreePoolWithTag", "use VideoPortFreePool");
VCHK_WARN ("ExIsProcessorFeaturePresent");
VCHK_WARN ("ExQueueWorkItem");
VCHK_WARN ("IoAllocateMdl");
VCHK_WARN ("IoCreateNotificationEvent");
VCHK_WARN ("IoCreateSynchronizationEvent");
VCHK_WARN ("IoFreeMdl");
VCHK_WARN ("IoGetCurrentProcess");
VCHK_FAIL ("IoReportDetectedDevice");
VCHK_FAIL ("IoReportResourceForDetection");
VCHK_WARN ("KeCancelTimer");
VCHK_FAIL ("KeClearEvent", "use VideoPortClearEvent");
VCHK_FAIL ("KeDelayExecutionThread", "use VideoPortStallExecution");
VCHK_FAIL ("KeInitializeDpc", "use VideoPortQueueDpc");
VCHK_FAIL ("KeInitializeSpinLock", "use VideoPortXxxSpinLockXxx");
VCHK_WARN ("KeInitializeTimer");
VCHK_WARN ("KeInitializeTimerEx");
VCHK_FAIL ("KeInsertQueueDpc", "use VideoPortQueueDpc");
VCHK_WARN ("KeQuerySystemTime");
VCHK_WARN ("KeRestoreFloatingPointState");
VCHK_WARN ("KeSaveFloatingPointState");
VCHK_FAIL ("KeSetEvent", "use VideoPortSetEvent");
VCHK_WARN ("KeSetTimer");
VCHK_WARN ("KeSetTimerEx");
VCHK_FAIL ("MmAllocateContiguousMemory", "use VideoPortAllocateContiguousMemory");
VCHK_WARN ("MmAllocateNonCachedMemory");
VCHK_WARN ("MmBuildMdlForNonPagedPool");
VCHK_WARN ("MmFreeContiguousMemory");
VCHK_WARN ("MmFreeNonCachedMemory");
VCHK_WARN ("MmGetPhysicalAddress");
VCHK_WARN ("MmIsAddressValid");
VCHK_WARN ("MmMapIoSpace");
VCHK_WARN ("MmMapLockedPages");
VCHK_WARN ("MmMapLockedPagesSpecifyCache");
VCHK_WARN ("MmProbeAndLockPages");
VCHK_WARN ("MmQuerySystemSize");
VCHK_WARN ("MmUnlockPages");
VCHK_WARN ("MmUnmapIoSpace");
VCHK_WARN ("MmUnmapLockedPages");
VCHK_WARN ("ObReferenceObjectByHandle");
VCHK_WARN ("PsGetCurrentProcessId");
VCHK_WARN ("PsGetVersion");
VCHK_FAIL ("READ_REGISTER_UCHAR", "use VideoPortReadRegisterUchar");
VCHK_WARN ("RtlAnsiStringToUnicodeString");
VCHK_WARN ("RtlAppendUnicodeStringToString");
VCHK_WARN ("RtlCheckRegistryKey");
VCHK_WARN ("RtlCompareMemory");
VCHK_WARN ("RtlCopyUnicodeString");
VCHK_WARN ("RtlCreateRegistryKey");
VCHK_WARN ("RtlFreeAnsiString");
VCHK_WARN ("RtlFreeUnicodeString");
VCHK_WARN ("RtlInitAnsiString");
VCHK_WARN ("RtlInitUnicodeString");
VCHK_WARN ("RtlIntegerToUnicodeString");
VCHK_WARN ("RtlQueryRegistryValues");
VCHK_WARN ("RtlTimeToTimeFields");
VCHK_WARN ("RtlUnicodeStringToAnsiString");
VCHK_WARN ("RtlUnicodeToMultiByteN");
VCHK_WARN ("RtlUnwind");
VCHK_WARN ("RtlWriteRegistryValue");
VCHK_FAIL ("wcslen", "link to libcntpr.lib instead");
VCHK_FAIL ("WRITE_REGISTER_UCHAR", "use VideoPortWriteRegisterUchar");
VCHK_FAIL ("WRITE_REGISTER_USHORT", "use VideoPortWriteRegisterUshort");
VCHK_WARN ("ZwClose");
VCHK_WARN ("ZwCreateFile");
VCHK_WARN ("ZwEnumerateValueKey");
VCHK_WARN ("ZwMapViewOfSection");
VCHK_WARN ("ZwOpenKey");
VCHK_WARN ("ZwOpenSection");
VCHK_WARN ("ZwQueryValueKey");
VCHK_WARN ("ZwSetSystemInformation");
VCHK_WARN ("ZwUnmapViewOfSection");
VCHK_WARN ("ZwWriteFile");
}
/////////////////////////////////////////////////////////////////////////////
// main
int __cdecl _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
// 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_listf(NULL),
m_drv_name ("")
{
// TODO: add construction code here,
// Place all significant initialization in InitInstance
}
/////////////////////////////////////////////////////////////////////////////
// The one and only CDrvchkApp object
void
CommandLine::ParseParam( LPCTSTR lpszParam, BOOL bFlag, BOOL bLast )
{
if (m_parse_error != parseOK)
return;
CString param (lpszParam);
if (bFlag) {
param.MakeUpper();
if ((param==CString("?")) || (param == CString("HELP")) || (param == CString("H"))) {
m_parse_error = parseHelp;
} else if ((param==CString("?IMP")) || (param==CString("IMP?"))) {
m_parse_error = parseHelpImports;
} else if (m_last_flag.GetLength() && m_first_param) {
m_parse_error = parseError;
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("LIST")) || (param==CString("LST")) || (param==CString("LS")) ||
(param==CString("LIS")) || (param==CString("ALLOW"))) {
if (bLast) {
m_parse_error = parseError;
m_error_msg = CString("Flag ") + param + CString(" requires a parameter.");
} else {
m_last_flag = param;
m_first_param = TRUE;
}
} else {
m_last_flag = CString();
m_parse_error = parseError;
m_error_msg = CString("Invalid flag: ") + param;
}
} else {
if (m_last_flag==CString("ALLOW")) {
m_first_param = FALSE;
int nSplit = param.Find('!');
if (nSplit != -1) {
CString module = param.Left(nSplit);
CString import = param.Mid(nSplit + 1);
if (module.GetLength() && import.GetLength()) {
allowed_imports.SetModule(module);
allowed_imports.AddImport(import, "allowed by command line");
} else {
m_parse_error = parseError;
m_error_msg = CString("Bad parameter format for flag: ") + m_last_flag;
}
} else {
allowed_modules.SetModule(param);
}
} else if (m_last_flag==CString("DRV")) {
if (m_monitor >= 1) {
m_error_msg = "bad command line: Conflicting flags MON and DRV";
m_parse_error = parseError;
}
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("LIST") ||
m_last_flag==CString("LST") ||
m_last_flag==CString("LIS") ||
m_last_flag==CString("LS")) {
m_list_fname = param;
m_last_flag="";
} else if (m_last_flag==CString("MON")) {
if ((param.GetLength()==1) &&
(((LPCSTR)param)[0] >= '1') &&
(((LPCSTR)param)[0] <= '9'))
{
if (m_drv_fname.GetLength()) {
m_error_msg = "bad command line: Conflicting flags MON and DRV";
m_parse_error = parseError;
}
char c = ((LPCSTR)param)[0];
m_monitor = c - '0';
} else {
m_error_msg = "bad command line: MON flag has invalid parameter";
m_parse_error = parseError;
}
m_last_flag="";
} else {
m_parse_error = parseError;
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 = parseError;
m_error_msg = CString("Flag ") + m_last_flag + CString(" requires a parameter.");
}
}
}
/////////////////////////////////////////////////////////////////////////////
// CDrvchkApp initialization
const char* szHelp =
"Copyright (C) Microsoft Corporation. All rights reserved.\n"
"\n"
"usage: vchk [-?] [-LOG logfile] [-DRV drvname | -MON id] [-LIST listname]\n"
" [-ALLOW module[!import] [module[!import]] ...]\n"
"\n"
"where: -? displays this help\n"
" -IMP? dumps imports tables that check performed against\n"
" -LOG specifies output file name (if file already exists then new data\n"
" will be appended to it)\n"
" -DRV specifies the full name of the driver's binary to check\n"
" -MON specifies 1-based numeric id of the display adapter to check\n"
" -LIST specifies the file for summary (if file already exists then new\n"
" data will be appended to it)\n"
" -ALLOW specifies allowed imports\n"
" module: name of allowed module (if no import specified then all\n"
" imports from the module will be allowed)\n"
" import: specific import name\n"
"\n"
" if neither -MON nor -DRV switches used then all currently active video\n"
" drivers will be checked\n"
"\n"
"Example:\n"
" vchk -log c:\\log.out -list con -allow HAL.DLL!HalGetBusData VIDEOPORT.SYS\n";
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
if (m_os_ver_info.dwMajorVersion < 5) { // XXX olegk - will it work in the future????
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_logf) m_logf = fopen (m_cmd_line.m_log_fname, "a");
}
if (m_cmd_line.m_list_fname.GetLength()) {
m_listf = fopen (m_cmd_line.m_list_fname, "a+");
if (!m_listf) m_listf = fopen (m_cmd_line.m_list_fname, "a");
}
switch (m_cmd_line.m_parse_error) {
case CommandLine::parseOK: {
int device_num = m_cmd_line.m_monitor;
if (m_cmd_line.m_drv_fname.GetLength()) {
ChkDriver (m_cmd_line.m_drv_fname);
} else {
DWORD cbData = 0;
DEVMODE dmCurrent;
TCHAR szDeviceDescription[10000];
TCHAR szImagePath[MAX_PATH + 1];
TCHAR szVarImagePath[MAX_PATH + 1];
TCHAR szExpImagePath[MAX_PATH + 1];
DISPLAY_DEVICE DisplayDevice, *pDisplayDevice = NULL;
CString dev_desc_CtrlSet;
int nNonMirroringDevice = 0;
//
// Find non mirroring display device #device_num if needed
//
if (device_num >= 1) {
ZeroMemory(&DisplayDevice, sizeof(DisplayDevice));
DisplayDevice.cb = sizeof(DisplayDevice);
DWORD i, nNonMirrorDev;
for (i = 0, nNonMirrorDev = 0; EnumDisplayDevices(NULL, i, &DisplayDevice, 0); ++i) {
if (DisplayDevice.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER) continue; // skip mirroring drivers
if (device_num == ++nNonMirroringDevice) {
pDisplayDevice = &DisplayDevice;
break;
}
}
if (!pDisplayDevice) {
PrintOut ("error: cannot find video service\n");
break;
}
}
//
// Let's find all the video drivers that are installed in the system
//
CDisplayDeviceEnum DevEnum;
bool bDevFound = false;
if (pDisplayDevice) DevEnum.MarkDevice(*pDisplayDevice);
while (DevEnum.IsValid()) {
if (!pDisplayDevice || DevEnum.IsMarkedDevice()) {
bDevFound = true;
CString sMiniportPath = DevEnum.GetMiniportPath();
if (!sMiniportPath.GetLength()) {
sprintf (szDeviceDescription, "error: cannot find video service #%d\n", DevEnum.GetDeviceId());
PrintOut (szDeviceDescription);
VCHK_TRACE("error: " << szDeviceDescription <<
"\n " << DevEnum.GetLastError() << " " << DevEnum.GetLastErrorStr() << endl)
break;
}
sprintf (szVarImagePath, "%%WINDIR%%\\%s", (LPCSTR)sMiniportPath);
ExpandEnvironmentStrings (szVarImagePath, szExpImagePath, MAX_PATH);
VCHK_TRACE("Checking miniport " << szExpImagePath << endl)
ChkDriver (szExpImagePath);
}
DevEnum.Next();
}
if (!bDevFound) PrintOut ("error: cannot find video service\n");
} // look for system drivers
} // parseOK
break;
case CommandLine::parseHelp: {
CString Filename, Version, Description, Copyright;
{
CHAR szModuleName[MAX_PATH + 1];
ZeroMemory(szModuleName, sizeof(szModuleName));
if (GetModuleFileName(m_hInstance, szModuleName, MAX_PATH)) {
DWORD dw = 0;
DWORD dwVerLen = GetFileVersionInfoSize(szModuleName, &dw);
if (dwVerLen) {
PBYTE Buffer = (PBYTE)malloc(dwVerLen + 1);
PVOID pValue;
if (Buffer &&
GetFileVersionInfo(szModuleName, dw, dwVerLen, Buffer))
{
UINT ValLen;
if (VerQueryValue(Buffer, "\\StringFileInfo\\000004B0\\OriginalFilename", &pValue, &ValLen)); {
Filename = CString((LPCSTR)pValue, ValLen);
}
if (VerQueryValue(Buffer, "\\StringFileInfo\\000004b0\\ProductVersion", &pValue, &ValLen));
Version = CString((LPCSTR)pValue, ValLen);
if (VerQueryValue(Buffer, "\\StringFileInfo\\000004b0\\FileDescription", &pValue, &ValLen));
Description = CString((LPCSTR)pValue, ValLen);
}
free(Buffer);
}
}
}
cout << endl << (Filename.GetLength() ? (LPCSTR)Filename : "VCHK.EXE!");
if (Version.GetLength()) cout << " " << (LPCSTR)Version;
if (Description.GetLength()) cout << ": " << (LPCSTR)Description;
cout << endl;
cout << szHelp;
} // parseHelp
break;
case CommandLine::parseHelpImports: {
BuildInAllowedAndIllegal();
cout << "\n--- Illegal imports (errors) --------------\n\n";
illegal_msgs.Dump(cout);
cout << "\n--- Known illegal imports (warnings) ------\n\n";
known_illegal.Dump(cout);
cout << "\n--- Allowed imports -----------------------\n\n";
allowed_imports.Dump(cout);
cout << "\n--- Allowed modules -----------------------\n\n";
allowed_modules.Dump(cout);
} // parseHelpImports
break;
default:
PrintOut ("error: ");
PrintOut (m_cmd_line.m_error_msg.GetLength() ? (LPCSTR)m_cmd_line.m_error_msg : "unknown failure");
PrintOut ("\nUse vchk -? for help.\n");
} // switch
if (m_logf)
fclose (m_logf);
m_logf = NULL;
if (m_listf)
fclose (m_listf);
m_listf = NULL;
return TRUE;
}
void CDrvchkApp::ChkDriver (CString drv_name)
{
m_drv_name = drv_name;
cerr << (LPCSTR)m_drv_name << endl;
if (!InitIllegalImportsSearch (m_drv_name, "INIT")) {
PrintOut ("error: can't perform check in ");
PrintOut (m_drv_name);
PrintOut (", check the name and path please\n");
} else 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;
int warnings_found = 0;
bool bad_data = false;
for (int i=0;
i<Modules.Num;
Modules.Ptr = GetNextName(Modules.Ptr), i++) {
Names Imports = GetImportsList (Modules.Ptr);
if (!Imports.Num) {
bad_data = true;
break;
}
VCHK_TRACE("Checking " << (LPCSTR)Modules.Ptr << endl)
CString module_name (Modules.Ptr);
module_name.MakeUpper();
if (allowed_modules.IsModule(module_name)) {
//
// The whole module is allowed, no errors on any import
// from this module.
//
VCHK_TRACE("Allowed module " << (LPCSTR)module_name << endl)
continue;
}
BOOL KnownIllegals = known_illegal.IsModule(module_name);
if (KnownIllegals) {
VCHK_TRACE("Known Illegals from " << (LPCSTR)module_name << endl)
}
BOOL IllegalMsgs = illegal_msgs.IsModule(module_name);
if (IllegalMsgs) {
VCHK_TRACE("Illegal Imports from " << (LPCSTR)module_name << endl)
}
BOOL AllowedImports = allowed_imports.IsModule(module_name);
if (AllowedImports) {
VCHK_TRACE("Allowed Imports from " << (LPCSTR)module_name << endl)
}
LPSTR ImportsPtr = Imports.Ptr;
for (int j=0;
j<Imports.Num;
Imports.Ptr = GetNextName (Imports.Ptr), j++) {
if (allowed_imports.Lookup(Imports.Ptr)) continue;
CString msg = "";
CString ImportFnName = module_name +
CString("!") +
CString(Imports.Ptr);
if (KnownIllegals && known_illegal.Lookup(Imports.Ptr, msg)) {
PrintOut ("warning: ");
++warnings_found;
} else if (AllowedImports && allowed_imports.Lookup(Imports.Ptr)) {
continue; // Ignore allowed import
} else if (IllegalMsgs && illegal_msgs.Lookup(Imports.Ptr, msg)) {
PrintOut ("error: ");
++errors_found;
} else {
PrintOut ("warning: "); // Default case; now we make it warning too, but keep it
++warnings_found; // a separate case for very probable future changes.
}
PrintOut (m_drv_name);
PrintOut (": ");
PrintOut (ImportFnName);
if (msg.GetLength()) {
PrintOut (" -- ");
PrintOut (msg);
}
PrintOut ("\n");
}
if (ImportsPtr) HeapFree (GetProcessHeap(), 0, ImportsPtr);
}
CString drv_bin_name;
for (int i=m_drv_name.GetLength()-1; i>=0; i--) {
if (m_drv_name.GetAt(i)=='\\') {
drv_bin_name = ((LPCSTR)m_drv_name) + i + 1;
break;
}
}
BOOL skip_it = FALSE;
if (m_drv_name.Find("\\wdm\\") != -1) {
skip_it = TRUE;
}
char buf[256];
if (skip_it) {
sprintf (buf, "SKIP WDM:");
} else if (bad_data) {
sprintf (buf, "WRONG_BINARY:");
} else if (errors_found!=0) {
sprintf (buf, "ERRORS: ");
} else if (warnings_found!=0) {
sprintf (buf, "WARNINGS:");
} else {
sprintf (buf, "SUCCESS:");
}
ListOut (buf);
sprintf (buf, "\t%3d errors\t%3d warnings\t%s\n", errors_found, warnings_found, (LPCSTR)drv_bin_name);
ListOut (buf);
return (errors_found==0);
}