Source code of Windows XP (NT5)
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.

516 lines
16 KiB

  1. // vchk.cpp : Defines the entry point for the console application.
  2. //
  3. #include "stdafx.h"
  4. #include "windows.h"
  5. #include "allowed.h"
  6. #include "vchk.h"
  7. #include "ilimpchk.h"
  8. // #include "dispinfo.h"
  9. #include <devguid.h>
  10. #include <setupapi.h>
  11. #include <regstr.h>
  12. #ifdef _DEBUG
  13. #define new DEBUG_NEW
  14. #undef THIS_FILE
  15. static char THIS_FILE[] = __FILE__;
  16. #endif
  17. using namespace std;
  18. /////////////////////////////////////////////////////////////////////////////
  19. // The one and only application object
  20. inline
  21. void
  22. CDrvchkApp::PrintOut (LPCSTR str)
  23. {
  24. if (m_logf)
  25. fprintf (m_logf, "%s", str);
  26. else
  27. cerr << str;
  28. }
  29. inline
  30. void
  31. CDrvchkApp::PrintOut (unsigned num)
  32. {
  33. if (m_logf)
  34. fprintf (m_logf, "%d", num);
  35. else
  36. cerr << num;
  37. }
  38. ModulesAndImports allowed_modules;
  39. ModulesAndImports known_illegal;
  40. ModulesAndImports illegal_msgs;
  41. void BuildInAllowedAndIllegal (void)
  42. {
  43. allowed_modules.SetModule ("VIDEOPRT.SYS");
  44. known_illegal.SetModule ("HAL.dll");
  45. illegal_msgs.SetModule ("HAL.dll");
  46. illegal_msgs.AddImport ("HalAllocateCommonBuffer", "use VideoPortAllocateCommonBuffer");
  47. illegal_msgs.AddImport ("HalFreeCommonBuffer", "use VideoPortFreeCommonBuffer");
  48. known_illegal.AddImport ("HalGetAdapter", "obsolete; see DDK manual");
  49. known_illegal.AddImport ("HalGetBusData", "obsolete; see DDK manual");
  50. known_illegal.AddImport ("HalGetBusDataByOffset"); // warning
  51. known_illegal.AddImport ("HalSetBusData"); // warning
  52. known_illegal.AddImport ("HalSetBusDataByOffset"); // warning
  53. illegal_msgs.AddImport ("KeGetCurrentIrql", "use VideoPortGetCurrentIrql");
  54. illegal_msgs.AddImport ("KfAcquireSpinLock", "use VideoPortAcquireSpinLock");
  55. illegal_msgs.AddImport ("KfReleaseSpinLock", "use VideoPortReleaseSpinLock");
  56. illegal_msgs.AddImport ("READ_PORT_ULONG", "use VideoPortReadPortUlong");
  57. illegal_msgs.AddImport ("WRITE_PORT_ULONG", "use VideoPortWritePortUlong");
  58. known_illegal.SetModule ("NTOSKRNL.EXE");
  59. illegal_msgs.SetModule ("NTOSKRNL.EXE");
  60. known_illegal.AddImport ("MmQuerySystemSize"); // warning
  61. known_illegal.AddImport ("_except_handler3"); // warning
  62. known_illegal.AddImport ("ZwMapViewOfSection"); // warning
  63. known_illegal.AddImport ("ZwUnmapViewOfSection"); // warning
  64. known_illegal.AddImport ("IoAllocateMdl"); // warning
  65. known_illegal.AddImport ("IoFreeMdl"); // warning
  66. known_illegal.AddImport ("MmBuildMdlForNonPagedPool"); // warning
  67. known_illegal.AddImport ("MmGetPhysicalAddress"); // warning
  68. known_illegal.AddImport ("ObReferenceObjectByHandle"); // warning
  69. known_illegal.AddImport ("RtlUnwind"); // warning
  70. known_illegal.AddImport ("ZwOpenSection"); // warning
  71. illegal_msgs.AddImport ("ExAllocatePool", "use VideoPortAllocatePool");
  72. illegal_msgs.AddImport ("ExAllocatePoolWithTag", "use VideoPortAllocatePool");
  73. illegal_msgs.AddImport ("ExFreePool", "use VideoPortFreePool");
  74. illegal_msgs.AddImport ("ExFreePoolWithTag", "use VideoPortFreePool");
  75. illegal_msgs.AddImport ("KeClearEvent", "use VideoPortClearEvent");
  76. illegal_msgs.AddImport ("KeDelayExecutionThread", "use VideoPortStallExecution");
  77. illegal_msgs.AddImport ("KeInitializeDpc", "use VideoPortQueueDpc");
  78. illegal_msgs.AddImport ("KeInsertQueueDpc", "use VideoPortQueueDpc");
  79. illegal_msgs.AddImport ("KeInitializeSpinLock", "use VideoPortXxxSpinLockXxx");
  80. illegal_msgs.AddImport ("KeSetEvent", "use VideoPortSetEvent");
  81. illegal_msgs.AddImport ("MmAllocateContiguousMemory", "use VideoPortAllocateContiguousMemory");
  82. illegal_msgs.AddImport ("READ_REGISTER_UCHAR", "use VideoPortReadRegisterUchar");
  83. illegal_msgs.AddImport ("wcslen", "link to libcntpr.lib instead");
  84. illegal_msgs.AddImport ("WRITE_REGISTER_USHORT", "use VideoPortWriteRegisterUshort");
  85. illegal_msgs.AddImport ("WRITE_REGISTER_UCHAR", "use VideoPortWriteRegisterUchar");
  86. }
  87. int __cdecl _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
  88. {
  89. int nRetCode = 0;
  90. // cerr << ::GetCommandLine() << endl;
  91. // initialize MFC and print and error on failure
  92. if (AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
  93. {
  94. CDrvchkApp theApp;
  95. theApp.InitInstance ();
  96. }
  97. return nRetCode;
  98. }
  99. /////////////////////////////////////////////////////////////////////////////
  100. // CDrvchkApp construction
  101. CDrvchkApp::CDrvchkApp() :
  102. m_logf(NULL),
  103. m_drv_name ("")
  104. {
  105. // TODO: add construction code here,
  106. // Place all significant initialization in InitInstance
  107. }
  108. /////////////////////////////////////////////////////////////////////////////
  109. // The one and only CDrvchkApp object
  110. /*------------------------------------------------------------------------
  111. vchk /drv driver.dll /log logname.log /allow videoptr.sys
  112. /allowed_modules module1.sys FnName1 FnName2 FnName3 /allowed_modules module2.dll FnName4
  113. ------------------------------------------------------------------------*/
  114. void
  115. CommandLine::ParseParam( LPCTSTR lpszParam, BOOL bFlag, BOOL bLast )
  116. {
  117. if (m_parse_error)
  118. return;
  119. CString param (lpszParam);
  120. if (bFlag) {
  121. param.MakeUpper();
  122. if (m_last_flag.GetLength()) {
  123. m_parse_error = TRUE;
  124. m_error_msg = CString("Flag ") + m_last_flag + CString(" requires a parameter.");
  125. } else if ((param==CString("LOG")) || (param==CString("DRV")) || (param==CString("MON")) ||
  126. (param==CString("ALLOW")) || (param==CString("allowed_modules"))) {
  127. m_last_flag = param;
  128. m_first_param = TRUE;
  129. } else {
  130. m_last_flag = "";
  131. m_parse_error = TRUE;
  132. m_error_msg = CString("Unrecognized flag: ") + param;
  133. }
  134. } else {
  135. if (m_last_flag==CString("ALLOW")) {
  136. allowed_modules.SetModule(param);
  137. /*
  138. sprintf (m_allowed, "%s", (LPCSTR)param);
  139. m_allowed += strlen (m_allowed);
  140. m_allowed[0] = 0;
  141. m_allowed[1] = 0;
  142. m_allowed++;
  143. */
  144. } else if (m_last_flag==CString("allowed_modules")) {
  145. if (m_first_param) {
  146. allowed_modules.SetModule(param);
  147. m_first_param = FALSE;
  148. } else {
  149. allowed_modules.AddImport(param);
  150. }
  151. } else if (m_last_flag==CString("DRV")) {
  152. m_drv_fname = param;
  153. m_last_flag="";
  154. } else if (m_last_flag==CString("LOG")) {
  155. m_log_fname = param;
  156. m_last_flag="";
  157. } else if (m_last_flag==CString("MON")) {
  158. if (param.GetLength()==1) {
  159. char c = ((LPCSTR)param)[0];
  160. m_monitor = c - '1';
  161. } else {
  162. m_monitor = -1;
  163. m_error_msg = "bad command line: /MON flag has wrong parameter";
  164. m_parse_error = TRUE;
  165. }
  166. m_last_flag="";
  167. } else {
  168. m_parse_error = TRUE;
  169. m_error_msg = CString("Wrong parameter: ") + param;
  170. m_last_flag="";
  171. }
  172. }
  173. if (bLast) {
  174. if (m_last_flag==CString("LOG") || m_last_flag==CString("DRV")) {
  175. m_parse_error = TRUE;
  176. m_error_msg = CString("Flag ") + m_last_flag + CString(" requires a parameter.");
  177. }
  178. }
  179. }
  180. /////////////////////////////////////////////////////////////////////////////
  181. // CDrvchkApp initialization
  182. BOOL CDrvchkApp::InitInstance()
  183. {
  184. // Standard initialization
  185. // If you are not using these features and wish to reduce the size
  186. m_os_ver_info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  187. GetVersionEx (&m_os_ver_info);
  188. if (m_os_ver_info.dwPlatformId != VER_PLATFORM_WIN32_NT) { // doesn't work on Win9x
  189. PrintOut ("warning: unsupported OS (Win9x), nothing done.\n");
  190. return FALSE;
  191. }
  192. if (m_os_ver_info.dwMajorVersion!=5) { // doesn't work on NT version prior to Win2K
  193. PrintOut ("warning: unsupported OS (");
  194. PrintOut (m_os_ver_info.dwMajorVersion);
  195. PrintOut (".");
  196. PrintOut (m_os_ver_info.dwMinorVersion);
  197. PrintOut ("): nothing done.\n");
  198. return FALSE;
  199. }
  200. ParseCommandLine (m_cmd_line);
  201. BuildInAllowedAndIllegal();
  202. if (m_cmd_line.m_log_fname.GetLength()) {
  203. m_logf = fopen (m_cmd_line.m_log_fname, "a+");
  204. }
  205. if (m_cmd_line.m_parse_error) {
  206. PrintOut ("error: ");
  207. PrintOut ((LPCSTR)m_cmd_line.m_error_msg);
  208. PrintOut ("\n");
  209. } else {
  210. int device_num = m_cmd_line.m_monitor;
  211. if (m_cmd_line.m_drv_fname.GetLength()) {
  212. ChkDriver (m_cmd_line.m_drv_fname);
  213. } else {
  214. HDEVINFO hDevInfo;
  215. SP_DEVINFO_DATA did;
  216. // TCHAR szBuffer[256];
  217. DWORD index = 0;
  218. HKEY hkTest;
  219. HKEY hKey;
  220. ULONG ulType = 0;
  221. DWORD cbData = 0;
  222. DEVMODE dmCurrent;
  223. TCHAR szDeviceDescription[10000];
  224. TCHAR szImagePath[256];
  225. TCHAR szVarImagePath[256];
  226. TCHAR szExpImagePath[256];
  227. CString dev_desc_CtrlSet;
  228. hKey = 0;
  229. //
  230. // Let's find all the video drivers that are installed in the system
  231. //
  232. DISPLAY_DEVICE DisplayDevice;
  233. DisplayDevice.cb = sizeof (DisplayDevice);
  234. // cerr << "looking for device #" << device_num << endl;
  235. for (DWORD d=0, index=0; EnumDisplayDevices(NULL, index, &DisplayDevice, 0); index++) {
  236. // cerr << "device #" << d << endl;
  237. if (DisplayDevice.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER) {
  238. // cerr << "DisplayDevice.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER\n";
  239. continue;
  240. }
  241. if (device_num!=d++) {
  242. // cerr << "device_num!=d\n";
  243. continue;
  244. }
  245. CString service_path = GetServiceRegistryPath (DisplayDevice);
  246. if (!service_path.GetLength()) {
  247. PrintOut ("error: cannot find video service\n");
  248. continue;
  249. }
  250. ///// service known /////
  251. hKey = 0;
  252. cbData = sizeof szImagePath;
  253. if ((RegOpenKeyEx(HKEY_LOCAL_MACHINE, _TEXT(service_path), 0, KEY_READ, &hKey) != ERROR_SUCCESS) ||
  254. (RegQueryValueEx(hKey, _TEXT("ImagePath"), 0, &ulType, (LPBYTE)szImagePath, &cbData) != ERROR_SUCCESS) ||
  255. (cbData == 0)) {
  256. cbData = 0;
  257. PrintOut ("error: cannot find video driver\n");
  258. }
  259. if (hKey)
  260. RegCloseKey(hKey);
  261. if (cbData) {
  262. sprintf (szVarImagePath, "%%WINDIR%%\\%s", szImagePath);
  263. ExpandEnvironmentStrings (szVarImagePath, szExpImagePath, 256);
  264. // cerr << "szExpImagePath = " << szExpImagePath << endl;
  265. ChkDriver (szExpImagePath);
  266. }
  267. } // for each device
  268. } // look for system drivers
  269. } // if no cmd line error
  270. if (m_logf)
  271. fclose (m_logf);
  272. m_logf = NULL;
  273. return TRUE;
  274. }
  275. #define REGISTRY_MACHINE_OFS _tcslen(_TEXT("\\registry\\machine\\"))
  276. CString CDrvchkApp::GetServiceRegistryPath (DISPLAY_DEVICE& DisplayDevice)
  277. {
  278. HKEY hKey = NULL;
  279. CString result_service_path = CString("");;
  280. /*
  281. // dump Display Device
  282. //
  283. FILE* f=fopen("hjhj.txt", "wb");
  284. BYTE* p = (BYTE*)&DisplayDevice;
  285. for (int i=0; i<sizeof(DISPLAY_DEVICE); i++)
  286. fwrite (p+i, 1, 1, f);
  287. fclose(f);
  288. */
  289. TCHAR device_key[256]; // Name of service (drivers)
  290. _tcscpy (device_key, DisplayDevice.DeviceKey+18);
  291. // cut the "\Device0" or "\0000" tail...
  292. TCHAR* pch = _tcsrchr(device_key, _TEXT('\\'));
  293. if (pch != NULL)
  294. *pch = 0;
  295. // cerr << "DisplayDevice.DeviceKey: " << device_key << endl;
  296. switch (m_os_ver_info.dwMinorVersion) {
  297. case 0:
  298. // cerr << "DisplayDevice.DeviceKey: " << device_key << endl;
  299. result_service_path = CString(device_key);
  300. break;
  301. case 1:
  302. {
  303. size_t len = _tcslen(device_key);
  304. sprintf (device_key+len, "\\Video");
  305. // cerr << "DisplayDevice.DeviceKey+REGISTRY_MACHINE_OFS: " << device_key << endl;
  306. BYTE service_name[256];
  307. ULONG ulReserved = 0;
  308. DWORD cbData = sizeof service_name;
  309. CString key_name = device_key;
  310. // cerr << key_name << endl;
  311. if ((RegOpenKeyEx(HKEY_LOCAL_MACHINE, _TEXT(key_name), 0, KEY_READ, &hKey) != ERROR_SUCCESS) ||
  312. (RegQueryValueEx(hKey, _TEXT("Service"), 0, &ulReserved, (LPBYTE)service_name, &cbData) != ERROR_SUCCESS) ||
  313. (cbData == 0)) {
  314. break;
  315. }
  316. // cerr << "Service reg name: " << service_name << endl;
  317. result_service_path = "SYSTEM\\CurrentControlSet\\Services\\";
  318. result_service_path += CString(service_name);
  319. // cerr << "Service reg path: " << (LPCSTR)result_service_path << endl;
  320. }
  321. break;
  322. default:
  323. PrintOut ("warning: unknown system version 5.");
  324. PrintOut (m_os_ver_info.dwMinorVersion);
  325. PrintOut ("\n");
  326. }
  327. if (hKey)
  328. RegCloseKey(hKey);
  329. return result_service_path;
  330. }
  331. void CDrvchkApp::ChkDriver (CString drv_name)
  332. {
  333. m_drv_name = drv_name;
  334. cerr << (LPCSTR)m_drv_name << endl;
  335. InitIllegalImportsSearch (m_drv_name, "INIT");
  336. if (CheckDriverAndPrintResults ()) {
  337. PrintOut ("success: no illegal imports in ");
  338. PrintOut (m_drv_name);
  339. PrintOut ("\n");
  340. }
  341. }
  342. BOOL CDrvchkApp::CheckDriverAndPrintResults ()
  343. {
  344. Names Modules = CheckSectionsForImports ();
  345. if (!Modules.Ptr) {
  346. PrintOut ("error: cannot retrieve import information from ");
  347. PrintOut (m_drv_name);
  348. PrintOut ("\n");
  349. return FALSE;
  350. }
  351. int errors_found = 0;
  352. for (int i=0;
  353. i<Modules.Num;
  354. Modules.Ptr = GetNextName(Modules.Ptr), i++) {
  355. Names Imports = GetImportsList (Modules.Ptr);
  356. // cerr << "Checking " << (LPCSTR)Modules.Ptr << endl;
  357. CString module_name (Modules.Ptr);
  358. if (allowed_modules.IsModule(module_name)) {
  359. // cerr << "ALLOWED " << (LPCSTR)module_name << endl;
  360. continue;
  361. }
  362. BOOL KnownIllegals = known_illegal.IsModule(module_name);
  363. if (KnownIllegals) {
  364. // cerr << "KNOWN ILLEGALS FROM " << (LPCSTR)module_name << endl;
  365. }
  366. LPSTR ImportsPtr = Imports.Ptr;
  367. // cerr << "Imports.Num = " << Imports.Num << endl;
  368. for (int j=0;
  369. j<Imports.Num;
  370. Imports.Ptr = GetNextName (Imports.Ptr), j++) {
  371. // cerr << "j=" << j << "\n";
  372. CString msg = "";
  373. CString ImportFnName = CString(Modules.Ptr) +
  374. CString("!") +
  375. CString(Imports.Ptr);
  376. if (KnownIllegals && known_illegal.Lookup(Imports.Ptr, msg))
  377. PrintOut ("warning: ");
  378. else {
  379. errors_found ++;
  380. illegal_msgs.Lookup(Imports.Ptr, msg);
  381. PrintOut ("error: ");
  382. }
  383. PrintOut (m_drv_name);
  384. PrintOut (": ");
  385. PrintOut (ImportFnName);
  386. if (msg.GetLength()) {
  387. PrintOut (" -- ");
  388. PrintOut (msg);
  389. }
  390. PrintOut ("\n");
  391. }
  392. if (ImportsPtr)
  393. HeapFree (GetProcessHeap(), 0, ImportsPtr);
  394. }
  395. /*
  396. char buf[1024];
  397. sprintf (buf, "%d modules; %d imports", Modules.Num, errors_found);
  398. if (m_listf) {
  399. fprintf (m_listf, "\n%s\n\n", buf);
  400. }
  401. */
  402. return (errors_found==0);
  403. }