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.

796 lines
18 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. hwwiz.c
  5. Abstract:
  6. Implements a upgwiz wizard for obtaining hardware information.
  7. Author:
  8. Jim Schmidt (jimschm) 05-Oct-1998
  9. Revision History:
  10. <alias> <date> <comments>
  11. --*/
  12. #include "pch.h"
  13. #include "..\inc\dgdll.h"
  14. DATATYPE g_DataTypes[] = {
  15. {UPGWIZ_VERSION,
  16. "PNP Device Should Be Compatible",
  17. "You specify the PNP device or devices that were incorrectly reported as incompatible.",
  18. 0
  19. },
  20. {UPGWIZ_VERSION,
  21. "PNP Device Should Be Incompatible",
  22. "You specify the PNP device or devices that need to be reported as incompatible.",
  23. 0
  24. },
  25. {UPGWIZ_VERSION,
  26. "PNP Device Has Loss of Functionality",
  27. "A device is compatible, but some functionality is lost.",
  28. 0,
  29. DTF_REQUIRE_TEXT|DTF_ONE_SELECTION,
  30. 1024,
  31. NULL,
  32. "&Text For Incompatibility:"
  33. },
  34. {UPGWIZ_VERSION,
  35. "Compatible Windows 3.1 Driver",
  36. "Use this to completely suppress the generic Win3.1 driver warning for a .386 file.",
  37. 0,
  38. DTF_REQUIRE_DESCRIPTION|DTF_ONE_SELECTION,
  39. 1024,
  40. "&Name of Device that Driver Controls:"
  41. },
  42. {UPGWIZ_VERSION,
  43. "Incompatible Windows 3.1 Driver",
  44. "Use this to give a better problem description to a driver that causes the generic Win3.1 driver warning.",
  45. 0,
  46. DTF_REQUIRE_TEXT|DTF_REQUIRE_DESCRIPTION|DTF_ONE_SELECTION,
  47. 1024,
  48. "&Name of Device that Driver Controls:",
  49. "&Describe The Problem:"
  50. },
  51. {UPGWIZ_VERSION,
  52. "Compatible TWAIN Data Sources",
  53. "Removes the incompatible warning caused by an unknown TWAIN data source."
  54. },
  55. {UPGWIZ_VERSION,
  56. "Compatible Joysticks",
  57. "Removes the incompatible warning caused by an unknown joysticks."
  58. }
  59. };
  60. GROWBUFFER g_DataObjects = GROWBUF_INIT;
  61. POOLHANDLE g_DataObjectPool;
  62. typedef struct {
  63. PCSTR Description;
  64. PCSTR FullPath;
  65. } TWAINPARAM, *PTWAINPARAM;
  66. BOOL
  67. pGeneratePnpOutput (
  68. IN POUTPUTARGS Args,
  69. IN HANDLE File
  70. );
  71. BOOL
  72. pGenerateWin31DriverOutput (
  73. IN POUTPUTARGS Args,
  74. IN HANDLE File
  75. );
  76. BOOL
  77. pGenerateTwainOutput (
  78. IN POUTPUTARGS Args,
  79. IN HANDLE File
  80. );
  81. BOOL
  82. pGenerateJoystickOutput (
  83. IN POUTPUTARGS Args,
  84. IN HANDLE File
  85. );
  86. HINSTANCE g_OurInst;
  87. BOOL
  88. Init (
  89. VOID
  90. )
  91. {
  92. #ifndef UPGWIZ4FLOPPY
  93. return InitToolMode (g_OurInst);
  94. #else
  95. return TRUE;
  96. #endif
  97. }
  98. VOID
  99. Terminate (
  100. VOID
  101. )
  102. {
  103. //
  104. // Local cleanup
  105. //
  106. FreeGrowBuffer (&g_DataObjects);
  107. if (g_DataObjectPool) {
  108. PoolMemDestroyPool (g_DataObjectPool);
  109. }
  110. #ifndef UPGWIZ4FLOPPY
  111. TerminateToolMode (g_OurInst);
  112. #endif
  113. }
  114. BOOL
  115. WINAPI
  116. DllMain (
  117. IN HINSTANCE hInstance,
  118. IN DWORD dwReason,
  119. IN LPVOID lpReserved
  120. )
  121. {
  122. if (dwReason == DLL_PROCESS_DETACH) {
  123. MYASSERT (g_OurInst == hInstance);
  124. Terminate();
  125. }
  126. g_OurInst = hInstance;
  127. return TRUE;
  128. }
  129. UINT
  130. GiveVersion (
  131. VOID
  132. )
  133. {
  134. Init();
  135. return UPGWIZ_VERSION;
  136. }
  137. PDATATYPE
  138. GiveDataTypeList (
  139. OUT PUINT Count
  140. )
  141. {
  142. UINT u;
  143. *Count = sizeof (g_DataTypes) / sizeof (g_DataTypes[0]);
  144. for (u = 0 ; u < *Count ; u++) {
  145. g_DataTypes[u].DataTypeId = u;
  146. }
  147. return g_DataTypes;
  148. }
  149. PDATAOBJECT
  150. GiveDataObjectList (
  151. IN UINT DataTypeId,
  152. OUT PUINT Count
  153. )
  154. {
  155. HARDWARE_ENUM e;
  156. PDATAOBJECT Data;
  157. HINF Inf;
  158. TCHAR Path[MAX_TCHAR_PATH];
  159. TCHAR FullPath[MAX_TCHAR_PATH];
  160. INFSTRUCT is = INITINFSTRUCT_GROWBUFFER;
  161. PCTSTR DriverPath;
  162. PCTSTR DriverFile;
  163. TWAINDATASOURCE_ENUM te;
  164. JOYSTICK_ENUM je;
  165. TWAINPARAM TwainParam;
  166. g_DataObjectPool = PoolMemInitNamedPool ("Data Objects");
  167. if (DataTypeId < 3) {
  168. //
  169. // Enumerate the PNP devices
  170. //
  171. if (EnumFirstHardware (&e, ENUM_ALL_DEVICES, ENUM_WANT_DEV_FIELDS)) {
  172. do {
  173. if (!e.Driver || !e.DeviceDesc || !e.InstanceId) {
  174. continue;
  175. }
  176. Data = (PDATAOBJECT) GrowBuffer (&g_DataObjects, sizeof (DATAOBJECT));
  177. Data->Version = UPGWIZ_VERSION;
  178. Data->NameOrPath = PoolMemDuplicateString (g_DataObjectPool, e.DeviceDesc);
  179. Data->Flags = 0;
  180. Data->DllParam = PoolMemDuplicateString (g_DataObjectPool, e.FullKey);
  181. } while (EnumNextHardware (&e));
  182. }
  183. } else if (DataTypeId >= 3 && DataTypeId < 5) {
  184. //
  185. // Enumerate the .386 candidates
  186. //
  187. wsprintf (Path, TEXT("%s\\system.ini"), g_WinDir);
  188. Inf = InfOpenInfFile (Path);
  189. if (Inf != INVALID_HANDLE_VALUE) {
  190. if (InfFindFirstLine (Inf, TEXT("386Enh"), NULL, &is)) {
  191. do {
  192. DriverPath = InfGetStringField (&is, 1);
  193. if (DriverPath) {
  194. //
  195. // Determine if device driver is known
  196. //
  197. if (_tcsnextc (DriverPath) != TEXT('*')) {
  198. DriverFile = GetFileNameFromPath (DriverPath);
  199. if (!_tcschr (DriverPath, TEXT(':'))) {
  200. if (!SearchPath (
  201. NULL,
  202. DriverFile,
  203. NULL,
  204. MAX_TCHAR_PATH,
  205. FullPath,
  206. NULL
  207. )) {
  208. _tcssafecpy (FullPath, DriverPath, MAX_TCHAR_PATH);
  209. }
  210. } else {
  211. _tcssafecpy (FullPath, DriverPath, MAX_TCHAR_PATH);
  212. }
  213. if (!_tcschr (FullPath, TEXT(':'))) {
  214. continue;
  215. }
  216. Data = (PDATAOBJECT) GrowBuffer (&g_DataObjects, sizeof (DATAOBJECT));
  217. Data->Version = UPGWIZ_VERSION;
  218. Data->NameOrPath = PoolMemDuplicateString (g_DataObjectPool, DriverFile);
  219. Data->Flags = 0;
  220. Data->DllParam = PoolMemDuplicateString (g_DataObjectPool, FullPath);
  221. }
  222. }
  223. } while (InfFindNextLine (&is));
  224. }
  225. InfCloseInfFile (Inf);
  226. InfCleanUpInfStruct (&is);
  227. }
  228. } else if (DataTypeId == 5) {
  229. //
  230. // Enumerate the TWAIN devices
  231. //
  232. if (EnumFirstTwainDataSource (&te)) {
  233. do {
  234. Data = (PDATAOBJECT) GrowBuffer (&g_DataObjects, sizeof (DATAOBJECT));
  235. Data->Version = UPGWIZ_VERSION;
  236. Data->NameOrPath = PoolMemDuplicateString (g_DataObjectPool, te.DisplayName);
  237. Data->Flags = 0;
  238. TwainParam.Description = PoolMemDuplicateString (g_DataObjectPool, te.DisplayName);
  239. TwainParam.FullPath = PoolMemDuplicateString (g_DataObjectPool, te.DataSourceModule);
  240. Data->DllParam = PoolMemGetAlignedMemory (g_DataObjectPool, sizeof (TWAINPARAM));
  241. CopyMemory (Data->DllParam, &TwainParam, sizeof (TWAINPARAM));
  242. } while (EnumNextTwainDataSource (&te));
  243. }
  244. } else if (DataTypeId == 6) {
  245. //
  246. // Enumerate the Joystick
  247. //
  248. if (EnumFirstJoystick (&je)) {
  249. do {
  250. if (!_mbschr (je.JoystickDriver, ':')) {
  251. if (!SearchPath (
  252. NULL,
  253. je.JoystickDriver,
  254. NULL,
  255. MAX_TCHAR_PATH,
  256. Path,
  257. NULL
  258. )) {
  259. continue;
  260. }
  261. } else {
  262. StringCopy (Path, je.JoystickDriver);
  263. }
  264. Data = (PDATAOBJECT) GrowBuffer (&g_DataObjects, sizeof (DATAOBJECT));
  265. Data->Version = UPGWIZ_VERSION;
  266. Data->NameOrPath = PoolMemDuplicateString (g_DataObjectPool, je.JoystickName);
  267. Data->Flags = 0;
  268. TwainParam.Description = PoolMemDuplicateString (g_DataObjectPool, je.JoystickName);
  269. TwainParam.FullPath = PoolMemDuplicateString (g_DataObjectPool, Path);
  270. Data->DllParam = PoolMemGetAlignedMemory (g_DataObjectPool, sizeof (TWAINPARAM));
  271. CopyMemory (Data->DllParam, &TwainParam, sizeof (TWAINPARAM));
  272. } while (EnumNextJoystick (&je));
  273. }
  274. }
  275. *Count = g_DataObjects.End / sizeof (DATAOBJECT);
  276. return (PDATAOBJECT) g_DataObjects.Buf;
  277. }
  278. BOOL
  279. OldGenerateOutput (
  280. IN POUTPUTARGS Args
  281. )
  282. {
  283. return TRUE;
  284. }
  285. //#if 0
  286. BOOL
  287. pWritePnpIdRule (
  288. IN HANDLE File,
  289. IN PHARDWARE_ENUM EnumPtr,
  290. IN PCSTR Description OPTIONAL
  291. )
  292. {
  293. CHAR Path[MAX_MBCHAR_PATH];
  294. CHAR DriverKey[MAX_REGISTRY_KEY];
  295. HKEY Key = NULL;
  296. BOOL b = FALSE;
  297. PCSTR InfPath = NULL;
  298. WIN32_FIND_DATA fd;
  299. HANDLE Find = INVALID_HANDLE_VALUE;
  300. CHAR Buf[2048];
  301. CHAR WinDir[MAX_MBCHAR_PATH];
  302. CHAR StringSectKey[256];
  303. GetWindowsDirectory (WinDir, MAX_MBCHAR_PATH);
  304. if (Description && *Description == 0) {
  305. Description = NULL;
  306. }
  307. //
  308. // Get the driver
  309. //
  310. __try {
  311. if (!EnumPtr->Driver || !EnumPtr->DeviceDesc || !EnumPtr->InstanceId) {
  312. DEBUGMSG ((DBG_WHOOPS, "Enum field missing; should have been screened out of object list"));
  313. __leave;
  314. }
  315. wsprintf (DriverKey, "HKLM\\System\\CurrentControlSet\\Services\\Class\\%s", EnumPtr->Driver);
  316. Key = OpenRegKeyStr (DriverKey);
  317. if (!Key) {
  318. DEBUGMSG ((DBG_WHOOPS, "Can't open %s", DriverKey));
  319. __leave;
  320. }
  321. InfPath = GetRegValueString (Key, "InfPath");
  322. if (!InfPath || *InfPath == 0) {
  323. DEBUGMSG ((DBG_WHOOPS, "No InfPath in %s", DriverKey));
  324. MessageBox (NULL, "Selected device does not have an INF path. The INF path is required.", NULL, MB_OK);
  325. __leave;
  326. }
  327. if (!_mbschr (InfPath, '\\')) {
  328. wsprintf (Path, "%s\\inf\\%s", WinDir, InfPath);
  329. } else {
  330. StringCopy (Path, InfPath);
  331. }
  332. Find = FindFirstFile (Path, &fd);
  333. if (Find == INVALID_HANDLE_VALUE) {
  334. DEBUGMSG ((DBG_WHOOPS, "Can't find %s", Path));
  335. __leave;
  336. }
  337. if (!Description) {
  338. wsprintf (Buf, "%s,,", EnumPtr->DeviceDesc);
  339. } else {
  340. GenerateUniqueStringSectKey ("DV", StringSectKey);
  341. wsprintf (Buf, "%s, %%%s%%,", EnumPtr->DeviceDesc, StringSectKey);
  342. }
  343. if (!WizardWriteColumn (File, Buf, 45)) {
  344. __leave;
  345. }
  346. wsprintf (Buf, "%s,", fd.cFileName);
  347. if (!WizardWriteColumn (File, Buf, 15)) {
  348. __leave;
  349. }
  350. wsprintf (Buf, "FILESIZE(%u),", fd.nFileSizeLow);
  351. if (!WizardWriteRealString (File, Buf)) {
  352. __leave;
  353. }
  354. if (!WizardWriteRealString (File, " PNPID(")) {
  355. __leave;
  356. }
  357. if (!WizardWriteQuotedString (File, EnumPtr->InstanceId)) {
  358. __leave;
  359. }
  360. if (!WizardWriteRealString (File, ")\r\n")) {
  361. __leave;
  362. }
  363. if (Description) {
  364. if (!WizardWriteRealString (File, "[Strings]\r\n")) {
  365. __leave;
  366. }
  367. WriteStringSectKey (File, StringSectKey, Description);
  368. }
  369. b = TRUE;
  370. }
  371. __finally {
  372. if (Key) {
  373. CloseRegKey (Key);
  374. }
  375. if (InfPath) {
  376. MemFree (g_hHeap, 0, InfPath);
  377. }
  378. if (Find != INVALID_HANDLE_VALUE) {
  379. FindClose (Find);
  380. }
  381. }
  382. return b;
  383. }
  384. BOOL
  385. GenerateOutput (
  386. IN POUTPUTARGS Args
  387. )
  388. {
  389. BOOL b = FALSE;
  390. HANDLE File;
  391. CHAR Path[MAX_MBCHAR_PATH];
  392. switch (Args->DataTypeId) {
  393. case 0:
  394. wsprintf (Path, "%s\\comphw.txt", Args->OutboundDir);
  395. break;
  396. case 1:
  397. wsprintf (Path, "%s\\incomphw.txt", Args->OutboundDir);
  398. break;
  399. case 2:
  400. wsprintf (Path, "%s\\hwfnloss.inx", Args->OutboundDir);
  401. break;
  402. case 3:
  403. case 4:
  404. wsprintf (Path, "%s\\win31drv.inx", Args->OutboundDir);
  405. break;
  406. case 5:
  407. wsprintf (Path, "%s\\twain.inx", Args->OutboundDir);
  408. break;
  409. case 6:
  410. wsprintf (Path, "%s\\joystick.inx", Args->OutboundDir);
  411. break;
  412. default:
  413. wsprintf (Path, "%s\\unknown.txt", Args->OutboundDir);
  414. break;
  415. }
  416. printf ("Saving data to %s\n\n", Path);
  417. File = CreateFile (
  418. Path,
  419. GENERIC_WRITE,
  420. 0,
  421. NULL,
  422. OPEN_ALWAYS,
  423. FILE_ATTRIBUTE_NORMAL,
  424. NULL
  425. );
  426. if (File == INVALID_HANDLE_VALUE) {
  427. printf ("Can't open file for output.\n");
  428. return FALSE;
  429. }
  430. __try {
  431. SetFilePointer (File, 0, NULL, FILE_END);
  432. //
  433. // Write [Identification] for all .inx files
  434. //
  435. switch (Args->DataTypeId) {
  436. case 0:
  437. case 1:
  438. break;
  439. default:
  440. if (!WizardWriteRealString (File, "[Identification]\r\n")) {
  441. __leave;
  442. }
  443. break;
  444. }
  445. //
  446. // Write user name and date/time
  447. //
  448. if (!WriteHeader (File)) {
  449. __leave;
  450. }
  451. //
  452. // Generate output depending on the type
  453. //
  454. switch (Args->DataTypeId) {
  455. case 0:
  456. case 1:
  457. case 2:
  458. b = pGeneratePnpOutput (Args, File);
  459. break;
  460. case 3:
  461. case 4:
  462. b = pGenerateWin31DriverOutput (Args, File);
  463. break;
  464. case 5:
  465. b = pGenerateTwainOutput (Args, File);
  466. break;
  467. case 6:
  468. b = pGenerateJoystickOutput (Args, File);
  469. break;
  470. }
  471. //
  472. // Write a final blank line
  473. //
  474. b = b & WizardWriteRealString (File, "\r\n");
  475. }
  476. __finally {
  477. CloseHandle (File);
  478. }
  479. return b;
  480. }
  481. BOOL
  482. pGeneratePnpOutput (
  483. IN POUTPUTARGS Args,
  484. IN HANDLE File
  485. )
  486. {
  487. PDATAOBJECT Data;
  488. UINT Count;
  489. UINT Pos;
  490. HARDWARE_ENUM e;
  491. BOOL b = FALSE;
  492. __try {
  493. Count = g_DataObjects.End / sizeof (DATAOBJECT);
  494. if (EnumFirstHardware (&e, ENUM_ALL_DEVICES, ENUM_WANT_DEV_FIELDS)) {
  495. do {
  496. Data = (PDATAOBJECT) g_DataObjects.Buf;
  497. for (Pos = 0 ; Pos < Count ; Pos++) {
  498. if (StringIMatch ((PCSTR) Data->DllParam, e.FullKey)) {
  499. if (Data->Flags & DOF_SELECTED) {
  500. if (Args->DataTypeId == 2) {
  501. if (!WizardWriteRealString (File, "[MinorProblems]\r\n")) {
  502. __leave;
  503. }
  504. if (!pWritePnpIdRule (File, &e, Args->OptionalText)) {
  505. __leave;
  506. }
  507. } else {
  508. if (!pWritePnpIdRule (File, &e, NULL)) {
  509. __leave;
  510. }
  511. }
  512. }
  513. break;
  514. }
  515. Data++;
  516. }
  517. } while (EnumNextHardware (&e));
  518. }
  519. b = TRUE;
  520. }
  521. __finally {
  522. if (!b) {
  523. AbortHardwareEnum (&e);
  524. }
  525. }
  526. return b;
  527. }
  528. BOOL
  529. pGenerateWin31DriverOutput (
  530. IN POUTPUTARGS Args,
  531. IN HANDLE File
  532. )
  533. {
  534. PDATAOBJECT Data;
  535. UINT Pos;
  536. UINT Count;
  537. BOOL b = FALSE;
  538. Data = (PDATAOBJECT) g_DataObjects.Buf;
  539. Count = g_DataObjects.End / sizeof (DATAOBJECT);
  540. for (Pos = 0 ; Pos < Count ; Pos++) {
  541. if (Data->Flags & DOF_SELECTED) {
  542. b = WriteFileAttributes (
  543. Args,
  544. NULL,
  545. File,
  546. (PCSTR) Data->DllParam,
  547. Args->OptionalText ? "[NonPnpDrivers]" : "[NonPnpDrivers_NoMessage]"
  548. );
  549. break;
  550. }
  551. Data++;
  552. }
  553. return b;
  554. }
  555. BOOL
  556. pGenerateTwainOutput (
  557. IN POUTPUTARGS Args,
  558. IN HANDLE File
  559. )
  560. {
  561. PDATAOBJECT Data;
  562. UINT Pos;
  563. UINT Count;
  564. BOOL b = FALSE;
  565. PTWAINPARAM TwainParam;
  566. Data = (PDATAOBJECT) g_DataObjects.Buf;
  567. Count = g_DataObjects.End / sizeof (DATAOBJECT);
  568. for (Pos = 0 ; Pos < Count ; Pos++) {
  569. if (Data->Flags & DOF_SELECTED) {
  570. TwainParam = (PTWAINPARAM) Data->DllParam;
  571. b = WriteFileAttributes (
  572. Args,
  573. TwainParam->Description,
  574. File,
  575. TwainParam->FullPath,
  576. "[CompatibleFiles]"
  577. );
  578. break;
  579. }
  580. Data++;
  581. }
  582. return b;
  583. }
  584. BOOL
  585. pGenerateJoystickOutput (
  586. IN POUTPUTARGS Args,
  587. IN HANDLE File
  588. )
  589. {
  590. PDATAOBJECT Data;
  591. UINT Pos;
  592. UINT Count;
  593. BOOL b = FALSE;
  594. PTWAINPARAM TwainParam;
  595. Data = (PDATAOBJECT) g_DataObjects.Buf;
  596. Count = g_DataObjects.End / sizeof (DATAOBJECT);
  597. for (Pos = 0 ; Pos < Count ; Pos++) {
  598. if (Data->Flags & DOF_SELECTED) {
  599. TwainParam = (PTWAINPARAM) Data->DllParam;
  600. b = WriteFileAttributes (
  601. Args,
  602. TwainParam->Description,
  603. File,
  604. TwainParam->FullPath,
  605. "[CompatibleFiles]"
  606. );
  607. break;
  608. }
  609. Data++;
  610. }
  611. return b;
  612. }
  613. //#endif