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.

1417 lines
36 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. condmsg.c
  5. Abstract:
  6. Win95upg.inf has a section named [Conditional Incompatibilities] where the
  7. lines in the section have the following syntax:
  8. %group%, %subgroup%, %object%, %msg% [,<function>[,<argument>]]
  9. %group% - A predefined root group number
  10. %subgroup% - A localized subgroup displayed in the UI
  11. %object% - The file, directory or registry location in which the message
  12. is associated with
  13. %msg% - A localized message
  14. <function> - A function that determines if the message should be added to the
  15. incompatible report
  16. <argument> - An optional string parameter that is passed to <function.>
  17. The code below implements the functions that are used in Win95upg.inf.
  18. Author:
  19. Marc Whitten (marcw) 3-Apr-1997
  20. Revision History:
  21. marcw 21-Jan-1999 Stale Beta messages removed.
  22. marcw 10-Sep-1997 OSR2 beta warning added.
  23. jimschm 06-Jul-1997 Added "object" to everything
  24. jimschm 25-Jun-1997 Protocols warning
  25. jimschm 28-May-1997 Hardware Profile warning
  26. marcw 25-Apr-1997 <argument> ability passed.
  27. jimschm 08-Apr-1997 Generalized
  28. --*/
  29. #include "pch.h"
  30. #include "sysmigp.h"
  31. #include "hwcomp.h"
  32. //
  33. // Function type declaration
  34. //
  35. typedef BOOL (TEST_FUNCTION_PROTOTYPE)(PCTSTR Object,
  36. PCTSTR GroupBase,
  37. PCTSTR Description,
  38. PCTSTR Argument
  39. );
  40. typedef TEST_FUNCTION_PROTOTYPE * TEST_FUNCTION;
  41. //
  42. // Array of supported functions
  43. //
  44. #define FUNCTION_LIST \
  45. DECLARATION_MACRO(SysAgentExtension) \
  46. DECLARATION_MACRO(ArePasswordProvidersPresent) \
  47. DECLARATION_MACRO(DoesRegKeyExist) \
  48. DECLARATION_MACRO(DoRegKeyValuesExist) \
  49. DECLARATION_MACRO(IsWin95Osr2) \
  50. DECLARATION_MACRO(IsMSNInstalled) \
  51. DECLARATION_MACRO(IsRasServerEnabled) \
  52. DECLARATION_MACRO(IsDefValueEqual) \
  53. //
  54. // Declare the function prototypes
  55. //
  56. #define DECLARATION_MACRO(x) BOOL x (PCTSTR Object, \
  57. PCTSTR GroupBase, \
  58. PCTSTR Description, \
  59. PCTSTR Argument \
  60. );
  61. FUNCTION_LIST
  62. #undef DECLARATION_MACRO
  63. //
  64. // Create a lookup array
  65. //
  66. typedef struct {
  67. PCTSTR Name;
  68. TEST_FUNCTION Proc;
  69. } FUNCTION_LIST_ELEMENT,*PFUNCTION_LIST_ELEMENT;
  70. #define DECLARATION_MACRO(x) {#x, x},
  71. FUNCTION_LIST_ELEMENT g_TestFunctionList[] = {
  72. FUNCTION_LIST /*,*/
  73. {NULL, NULL}
  74. };
  75. #undef DECLARATION_MACRO
  76. //
  77. // Function to locate Proc given a string
  78. //
  79. TEST_FUNCTION
  80. pFindTestFunction (
  81. IN PCTSTR FunctionStr
  82. )
  83. /*++
  84. Routine Description:
  85. pFindTestFunction searches the test function table declared above for
  86. a specified function name and returns a pointer to the actual function
  87. or NULL if the function does not exist.
  88. Arguments:
  89. FunctionStr - Specifies the name of function to find.
  90. Return Value:
  91. A pointer to the corresponding code, or NULL if the function does not exist.
  92. --*/
  93. {
  94. INT Index;
  95. for (Index = 0 ; g_TestFunctionList[Index].Name ; Index++) {
  96. if (StringIMatch (g_TestFunctionList[Index].Name, FunctionStr)) {
  97. return g_TestFunctionList[Index].Proc;
  98. }
  99. }
  100. DEBUGMSG ((DBG_ERROR,"SysMig: %s is not a valid test function.", FunctionStr));
  101. return NULL;
  102. }
  103. PTSTR
  104. pGetFieldUsingPool (
  105. IN OUT POOLHANDLE Pool,
  106. IN INFCONTEXT *pic,
  107. IN INT Field
  108. )
  109. /*++
  110. Routine Description:
  111. This function retrieves a string field using the Setup APIs but uses
  112. PoolMem for allocation.
  113. Arguments:
  114. Pool - Specifies a handle to a valid pool (from PoolMemInitPool). Memory
  115. is allocated from this pool.
  116. pic - Specifies the INF section and line being queried.
  117. Field - Specifies the field to retrieve.
  118. Return Value:
  119. A pointer to the field text, allocated in Pool, or NULL if the field was
  120. not found or an error is encountered.
  121. --*/
  122. {
  123. DWORD SizeNeeded;
  124. PTSTR String;
  125. if (!SetupGetStringField (pic, Field, NULL, 0, &SizeNeeded)) {
  126. DEBUGMSG ((DBG_ERROR, "SysMig: SetupGetStringField failed for field %u.", Field));
  127. return NULL;
  128. }
  129. String = PoolMemCreateString (Pool, SizeNeeded);
  130. if (!SetupGetStringField (pic, Field, String, SizeNeeded, NULL)) {
  131. DEBUGMSG ((DBG_ERROR,"SysMig: SetupGetStringField failed for field %u.", Field));
  132. return NULL;
  133. }
  134. return String;
  135. }
  136. PCTSTR
  137. pTranslateGroupString (
  138. IN POOLHANDLE AllocPool,
  139. IN UINT GroupId
  140. )
  141. /*++
  142. Routine Description:
  143. pTranslateGroupString converts a standard group number (1-based) into a
  144. message ID, then loads the string resource. The group string is then
  145. copied into the specified pool.
  146. In win95upg.txt, the list is defined as:
  147. 1 - Hardware That Does Not Support Windows NT 5.0
  148. 2 - General Information
  149. 3 - Settings That Will Not Be Upgraded
  150. 4 - Software That Does Not Support Windows NT 5.0
  151. 5 - Software That Will Require Reinstallation
  152. 6 - Software with Minor Incompatibilities
  153. 7 - Software to Be Uninstalled by Setup
  154. 8 - Upgrade Pack Information
  155. Arguments:
  156. AllocPool - Specifies the pool to allocate the return string from
  157. GroupId - Specifies a one-based ID that identifies the group. The
  158. definition of the ID is hard-coded here.
  159. Return Value:
  160. A pointer to the string, or NULL if an invalid group was specified.
  161. --*/
  162. {
  163. PCTSTR ResStr;
  164. PCTSTR ResSubStr;
  165. PTSTR ReturnStr = NULL;
  166. UINT SubGroupId = 0;
  167. switch (GroupId) {
  168. case 0:
  169. GroupId = MSG_BLOCKING_ITEMS_ROOT;
  170. break;
  171. case 1:
  172. GroupId = MSG_INCOMPATIBLE_HARDWARE_ROOT;
  173. break;
  174. case 2:
  175. GroupId = MSG_INSTALL_NOTES_ROOT;
  176. break;
  177. case 3:
  178. GroupId = MSG_LOSTSETTINGS_ROOT;
  179. break;
  180. case 4:
  181. GroupId = MSG_INCOMPATIBLE_ROOT;
  182. SubGroupId = MSG_INCOMPATIBLE_DETAIL_SUBGROUP;
  183. break;
  184. case 5:
  185. GroupId = MSG_REINSTALL_ROOT;
  186. SubGroupId = MSG_REINSTALL_DETAIL_SUBGROUP;
  187. break;
  188. case 6:
  189. GroupId = MSG_MINOR_PROBLEM_ROOT;
  190. break;
  191. case 7:
  192. GroupId = MSG_INCOMPATIBLE_ROOT;
  193. SubGroupId = MSG_AUTO_UNINSTALL_SUBGROUP;
  194. break;
  195. case 8:
  196. GroupId = MSG_MIGDLL_ROOT;
  197. break;
  198. default:
  199. return NULL;
  200. }
  201. ResStr = GetStringResource (GroupId);
  202. if (ResStr) {
  203. if (SubGroupId) {
  204. ResSubStr = GetStringResource (SubGroupId);
  205. if (ResSubStr) {
  206. //
  207. // We count the nul twice, assuming the nul is the same
  208. // size as a backslash.
  209. //
  210. ReturnStr = PoolMemGetAlignedMemory (
  211. AllocPool,
  212. SizeOfString (ResStr) + SizeOfString (ResSubStr)
  213. );
  214. wsprintf (ReturnStr, TEXT("%s\\%s"), ResStr, ResSubStr);
  215. FreeStringResource (ResSubStr);
  216. }
  217. } else {
  218. ReturnStr = PoolMemDuplicateString (AllocPool, ResStr);
  219. }
  220. FreeStringResource (ResStr);
  221. }
  222. return ReturnStr;
  223. }
  224. VOID
  225. pConditionalIncompatibilities (
  226. VOID
  227. )
  228. /*++
  229. Routine Description:
  230. Processes the Conditional Incompatibilities section of WIN95UPG.INF, and does
  231. other conditional incompatibility processing. Incompatibilities are added
  232. via the API in w95upg\ui.
  233. Arguments:
  234. none
  235. Return Value:
  236. none
  237. --*/
  238. {
  239. INFCONTEXT context;
  240. POOLHANDLE aPool;
  241. PTSTR descriptionString;
  242. PTSTR functionString;
  243. PTSTR argumentString;
  244. TCHAR buffer[32];
  245. static INT msgId = 0;
  246. PCTSTR objectString;
  247. PTSTR completeString;
  248. TEST_FUNCTION Proc;
  249. PCTSTR SubGroupString;
  250. PCTSTR GroupString;
  251. UINT GroupId;
  252. BOOL fr;
  253. BOOL negate;
  254. aPool = PoolMemInitNamedPool ("Conditional Incompatibilities");
  255. if (aPool) {
  256. if (SetupFindFirstLine (
  257. g_Win95UpgInf,
  258. S_CONDITIONAL_INCOMPATIBILITIES,
  259. NULL,
  260. &context
  261. )
  262. ) {
  263. //
  264. // Load in the standard group name
  265. //
  266. do {
  267. //
  268. // Get the group number
  269. //
  270. GroupString = pGetFieldUsingPool (aPool, &context, 1);
  271. if (!GroupString) {
  272. continue;
  273. }
  274. GroupId = _tcstoul (GroupString, NULL, 10);
  275. GroupString = pTranslateGroupString (aPool, GroupId);
  276. if (!GroupString) {
  277. DEBUGMSG ((DBG_WHOOPS, "Invalid group ID: %u", GroupId));
  278. continue;
  279. }
  280. //
  281. // Get the subgroup string
  282. //
  283. SubGroupString = pGetFieldUsingPool (aPool, &context, 2);
  284. if (!SubGroupString) {
  285. DEBUGMSG ((DBG_WHOOPS, "Field 2 required in conditional message lines"));
  286. continue;
  287. }
  288. if (*SubGroupString) {
  289. completeString = (PTSTR) PoolMemGetMemory (
  290. aPool,
  291. SizeOfString (GroupString) +
  292. SizeOfString (SubGroupString) +
  293. 2 * sizeof (TCHAR)
  294. );
  295. StringCopy (completeString, GroupString);
  296. StringCopy (AppendWack (completeString), SubGroupString);
  297. } else {
  298. completeString = (PTSTR) GroupString;
  299. }
  300. //
  301. // Get the object string
  302. //
  303. objectString = pGetFieldUsingPool (aPool, &context, 3);
  304. if (!objectString) {
  305. DEBUGMSG ((DBG_WHOOPS, "Field 3 required in conditional message lines"));
  306. continue;
  307. }
  308. //
  309. // Get the description
  310. //
  311. descriptionString = pGetFieldUsingPool (aPool, &context, 4);
  312. if (!descriptionString) {
  313. DEBUGMSG ((DBG_WHOOPS, "Field 4 required in conditional message lines"));
  314. continue;
  315. }
  316. //
  317. // If the field count is greater than two, there is a
  318. // function string..
  319. //
  320. if (SetupGetFieldCount (&context) > 4) {
  321. argumentString = NULL;
  322. //
  323. // Read in the functionString..
  324. //
  325. functionString = pGetFieldUsingPool (aPool, &context, 5);
  326. if (!functionString) {
  327. continue;
  328. }
  329. negate = *functionString == TEXT('!');
  330. if (negate) {
  331. functionString++;
  332. }
  333. if (SetupGetFieldCount(&context) > 5) {
  334. //
  335. // Read in the argument string.
  336. //
  337. argumentString = pGetFieldUsingPool(aPool,&context, 6);
  338. }
  339. //
  340. // Find the function to call..
  341. //
  342. Proc = pFindTestFunction (functionString);
  343. if (!Proc) {
  344. continue;
  345. }
  346. fr = Proc (objectString, completeString, descriptionString,argumentString);
  347. if (!negate && !fr || negate && fr) {
  348. continue;
  349. }
  350. }
  351. if (!objectString[0]) {
  352. DEBUGMSG ((DBG_WARNING, "Manufacturing an object for %s message", completeString));
  353. objectString = buffer;
  354. msgId++;
  355. wsprintf (buffer, "msg%u", msgId);
  356. }
  357. MsgMgr_ObjectMsg_Add (objectString, completeString, descriptionString);
  358. } while (SetupFindNextLine (&context,&context));
  359. }
  360. else {
  361. DEBUGMSG ((DBG_VERBOSE,"SysMig: %s not found in win95upg.inf.", S_CONDITIONAL_INCOMPATIBILITIES));
  362. }
  363. }
  364. PoolMemDestroyPool(aPool);
  365. }
  366. DWORD
  367. ConditionalIncompatibilities (
  368. IN DWORD Request
  369. )
  370. {
  371. switch (Request) {
  372. case REQUEST_QUERYTICKS:
  373. return TICKS_CONDITIONAL_INCOMPATIBILITIES;
  374. case REQUEST_RUN:
  375. pConditionalIncompatibilities ();
  376. return ERROR_SUCCESS;
  377. default:
  378. DEBUGMSG ((DBG_ERROR, "Bad parameter in ConditionalIncompatibilities"));
  379. }
  380. return 0;
  381. }
  382. BOOL
  383. pIsDefaultSystemAgent (
  384. PCTSTR SageSubKey
  385. )
  386. {
  387. INFCONTEXT context;
  388. if (SetupFindFirstLine (
  389. g_Win95UpgInf,
  390. S_SAGE_EXCLUSIONS,
  391. SageSubKey,
  392. &context
  393. )) {
  394. return TRUE;
  395. }
  396. return FALSE;
  397. }
  398. BOOL
  399. SysAgentExtension (
  400. IN PCTSTR Object,
  401. IN PCTSTR GroupBase,
  402. IN PCTSTR Description,
  403. IN PCTSTR Argument
  404. )
  405. /*++
  406. Routine Description:
  407. Produces conditional incompatibilities based on the presense of the
  408. system agent extension, which is part of the Win95 plus pack but
  409. not supported by NT.
  410. Arguments:
  411. Object - Unused
  412. GroupBase - A WIN95UPG.INF-specified group name that is used
  413. as the base of the message. The actual group name
  414. stored in the registry is appended for the UI.
  415. Description - A WIN95UPG.INF-specified description
  416. Argument - Unused
  417. Return Value:
  418. FALSE, because we add the incompatibility message ourself.
  419. Comments:
  420. SAGE-aware programs declare themselves as such by creating a key in
  421. HKLM\Software\Microsoft\Plus!\System Agent\SAGE. The name of the key
  422. can be anything the program wants, but it should contain the following
  423. values:
  424. Program= Name of the program's .EXE file. This must be the same
  425. .EXE name under which the program's PerApp path is
  426. registered. You may append a command line parameter
  427. indicating unattended operation (see Settings=,
  428. below).
  429. Friendly Name= Display name that System Agent will use in populating
  430. the drop-down list in its "Schedule a program" dialog
  431. box.
  432. Settings= 1-bit binary field indicating whether program has a
  433. Settings dialog box. If "Settings = "Settings = 0",
  434. but the application supports an interactive mode, then
  435. the "Program=" value should contain a command-line
  436. parameter that tells your program it's being run by
  437. SAGE, so that it knows to run in an unattended
  438. fashion, for example, "DRVSPACE.EXE /noprompt" or
  439. "MyApp.EXE /SAGERUN".
  440. Result Codes Optional key containing a set of value pairs mapping
  441. an exit code to a string describing the meaning of
  442. that exit code. For example, for SCANDSKW, the
  443. Result Codes key may contain a value such as:
  444. 0="ScanDisk completed successfully; no errors were
  445. found." This is to allow SAGE to keep a
  446. human-comprehensible log of the results of the
  447. programs it runs. In addition to the value pairs,
  448. this key should also contain a String value named
  449. "Success", which indicates the highest value for an
  450. exit code that designates that the program completed
  451. successfully. The value names should be string
  452. values, specified in decimal; the allowable range is
  453. 032767.
  454. --*/
  455. {
  456. REGKEY_ENUM e;
  457. PCTSTR Data;
  458. PCTSTR Module;
  459. TCHAR FullKey[MAX_REGISTRY_KEY];
  460. PCTSTR Group;
  461. PCTSTR FullPathKeyStr;
  462. PCTSTR FullPath;
  463. HKEY ExtensionKey;
  464. HKEY AppPathsKey;
  465. //
  466. // Scan HKLM\Software\Microsoft\Plus!\System Agent\SAGE for
  467. // subkeys, then throw messages out for each friendly name.
  468. //
  469. if (EnumFirstRegKeyStr (&e, S_SAGE)) {
  470. do {
  471. ExtensionKey = OpenRegKey (e.KeyHandle, e.SubKeyName);
  472. if (ExtensionKey) {
  473. Data = GetRegValueData (ExtensionKey, S_SAGE_FRIENDLY_NAME);
  474. if (Data && *Data) {
  475. // Create full object string
  476. wsprintf (FullKey, TEXT("%s\\%s"), S_SAGE, e.SubKeyName);
  477. // Test win95upg.inf to see if this is a standard agent
  478. if (!pIsDefaultSystemAgent (e.SubKeyName)) {
  479. // Generate group string
  480. Group = JoinPaths (GroupBase, Data);
  481. // Get the full path for this EXE
  482. FullPath = NULL;
  483. Module = GetRegValueData (ExtensionKey, S_SAGE_PROGRAM);
  484. if (Module && *Module) {
  485. FullPathKeyStr = JoinPaths (S_SKEY_APP_PATHS, Module);
  486. AppPathsKey = OpenRegKeyStr (FullPathKeyStr);
  487. if (AppPathsKey) {
  488. FullPath = GetRegValueData (AppPathsKey, S_EMPTY);
  489. if (!(*FullPath)) {
  490. MemFree (g_hHeap, 0, FullPath);
  491. FullPath = NULL;
  492. }
  493. CloseRegKey (AppPathsKey);
  494. }
  495. FreePathString (FullPathKeyStr);
  496. MemFree (g_hHeap, 0, Module);
  497. }
  498. // Add message
  499. if ((!FullPath) || (!IsFileMarkedForAnnounce (FullPath))) {
  500. MsgMgr_ObjectMsg_Add (FullPath?FullPath:FullKey, Group, Description);
  501. }
  502. // Cleanup
  503. FreePathString (Group);
  504. if (FullPath) {
  505. MemFree (g_hHeap, 0 , FullPath);
  506. FullPath = NULL;
  507. }
  508. }
  509. MemFree (g_hHeap, 0, Data);
  510. }
  511. CloseRegKey (ExtensionKey);
  512. }
  513. } while (EnumNextRegKey (&e));
  514. }
  515. return FALSE; // pretend like it's not installed
  516. }
  517. BOOL
  518. DoesRegKeyExist (
  519. IN PCTSTR Object,
  520. IN PCTSTR GroupBase,
  521. IN PCTSTR Description,
  522. IN PCTSTR Argument
  523. )
  524. /*++
  525. Routine Description:
  526. Returns TRUE if the registry key specified in Argument exists,
  527. forcing an incompatibility message to be generated.
  528. Arguments:
  529. Object - Specifies the registry key to examine
  530. GroupBase - A WIN95UPG.INF-specified group name
  531. Description - A WIN95UPG.INF-specified description
  532. Argument - Unused
  533. Return Value:
  534. TRUE if the registry key exists, or FALSE if it is not. TRUE
  535. forces the message to be added to the report.
  536. --*/
  537. {
  538. BOOL rKeyExists = FALSE;
  539. HKEY key = NULL;
  540. if (Object) {
  541. key = OpenRegKeyStr (Object);
  542. }
  543. if (key) {
  544. rKeyExists = TRUE;
  545. CloseRegKey (key);
  546. }
  547. return rKeyExists;
  548. }
  549. BOOL
  550. DoRegKeyValuesExist (
  551. IN PCTSTR Object,
  552. IN PCTSTR GroupBase,
  553. IN PCTSTR Description,
  554. IN PCTSTR Argument
  555. )
  556. /*++
  557. Routine Description:
  558. Returns TRUE if the registry key specified in Argument exists,
  559. and has at least one named value, forcing an incompatibility
  560. message to be generated.
  561. Arguments:
  562. Object - A WIN95UPG.INF-specified registry key
  563. GroupBase - A WIN95UPG.INF-specified group name
  564. Description - A WIN95UPG.INF-specified description
  565. Argument - Unused
  566. Return Value:
  567. TRUE if the registry key exists, or FALSE if it is not. TRUE
  568. forces the message to be added to the report.
  569. --*/
  570. {
  571. BOOL ValuesExists = FALSE;
  572. HKEY key = NULL;
  573. REGVALUE_ENUM e;
  574. if (Argument) {
  575. key = OpenRegKeyStr (Argument);
  576. }
  577. if (key) {
  578. if (EnumFirstRegValue (&e, key)) {
  579. do {
  580. if (e.ValueName[0]) {
  581. ValuesExists = TRUE;
  582. break;
  583. }
  584. } while (EnumNextRegValue (&e));
  585. }
  586. CloseRegKey (key);
  587. }
  588. return ValuesExists;
  589. }
  590. BOOL
  591. IsWin95Osr2 (
  592. IN PCTSTR Object,
  593. IN PCTSTR GroupBase,
  594. IN PCTSTR Description,
  595. IN PCTSTR Argument
  596. )
  597. {
  598. return ISWIN95_OSR2();
  599. }
  600. BOOL
  601. IsMSNInstalled (
  602. IN PCTSTR Object,
  603. IN PCTSTR GroupBase,
  604. IN PCTSTR Description,
  605. IN PCTSTR Argument
  606. )
  607. {
  608. HKEY key = NULL;
  609. PCTSTR Data = NULL;
  610. BOOL installed = FALSE;
  611. if (Object) {
  612. key = OpenRegKeyStr (Object);
  613. }
  614. if (key) {
  615. Data = (PCTSTR) GetRegKeyData (key, S_EMPTY);
  616. if (Data) {
  617. if (DoesFileExist (Data)) {
  618. installed = TRUE;
  619. }
  620. MemFree (g_hHeap, 0, Data);
  621. }
  622. CloseRegKey (key);
  623. }
  624. //
  625. // Special cases
  626. //
  627. if (installed) {
  628. //
  629. // Win98 -- make sure setup GUID was deleted
  630. //
  631. key = OpenRegKeyStr (TEXT("HKLM\\Software\\Classes\\CLSID\\{4b876a40-11d1-811e-00c04fb98eec}"));
  632. if (key) {
  633. installed = FALSE;
  634. CloseRegKey (key);
  635. }
  636. }
  637. if (installed) {
  638. //
  639. // Win95 -- make sure SignUpDone flag is written
  640. //
  641. key = OpenRegKeyStr (TEXT("HKLM\\Software\\Microsoft\\MOS\\SoftwareInstalled"));
  642. if (key) {
  643. CloseRegKey (key);
  644. } else {
  645. installed = FALSE;
  646. }
  647. }
  648. return installed;
  649. }
  650. BOOL
  651. IsRasServerEnabled (
  652. IN PCTSTR Object,
  653. IN PCTSTR GroupBase,
  654. IN PCTSTR Description,
  655. IN PCTSTR Argument
  656. )
  657. {
  658. BOOL rAddMessage = FALSE;
  659. HKEY key;
  660. PBYTE data;
  661. if (!Object) {
  662. return FALSE;
  663. }
  664. key = OpenRegKeyStr (Object);
  665. if (key) {
  666. data = GetRegValueData (key, TEXT("Enabled"));
  667. if (data) {
  668. if ((*(PDWORD)data) == 1) {
  669. rAddMessage = TRUE;
  670. }
  671. MemFree (g_hHeap, 0, data);
  672. }
  673. CloseRegKey (key);
  674. }
  675. return rAddMessage;
  676. }
  677. BOOL
  678. ArePasswordProvidersPresent (
  679. IN PCTSTR Object,
  680. IN PCTSTR GroupBase,
  681. IN PCTSTR Description,
  682. IN PCTSTR Argument
  683. )
  684. /*++
  685. Routine Description:
  686. Adds incompatibility messages for all password providers, excluding
  687. password providers of known components such as the Microsoft
  688. Networking Client or the Microsoft Client for NetWare.
  689. Arguments:
  690. Object - Unused
  691. GroupBase - A WIN95UPG.INF-specified group name
  692. Description - A WIN95UPG.INF-specified description
  693. Argument - Unused
  694. Return Value:
  695. Always FALSE.
  696. --*/
  697. {
  698. REGKEY_ENUM e;
  699. PCTSTR data;
  700. HKEY key;
  701. INFCONTEXT ic;
  702. TCHAR FullKey[MAX_REGISTRY_KEY];
  703. PCTSTR FullGroup;
  704. PCTSTR IncompatibleSoftware;
  705. IncompatibleSoftware = GetStringResource (MSG_INCOMPATIBLE_ROOT);
  706. if (!IncompatibleSoftware) {
  707. return FALSE;
  708. }
  709. if (EnumFirstRegKeyStr (&e, S_PASSWORDPROVIDER)) {
  710. do {
  711. //
  712. // See if this is a known password provider.
  713. //
  714. if (SetupFindFirstLine (
  715. g_Win95UpgInf,
  716. S_SUPPORTED_PASSWORD_PROVIDERS,
  717. e.SubKeyName,
  718. &ic
  719. )) {
  720. continue;
  721. }
  722. //
  723. // This is an unsupported password provider key. Add a message.
  724. //
  725. key = OpenRegKey (e.KeyHandle, e.SubKeyName);
  726. if (key) {
  727. data = GetRegValueData (key, S_PASSWORDPROVIDER_DESCRIPTION);
  728. if (data) {
  729. wsprintf (FullKey, TEXT("%s\\%s"), S_PASSWORDPROVIDER, e.SubKeyName);
  730. FullGroup = JoinPaths (IncompatibleSoftware, data);
  731. MsgMgr_ObjectMsg_Add(
  732. FullKey, // Object name
  733. FullGroup, // Message title
  734. Description // Message text
  735. );
  736. FreePathString (FullGroup);
  737. MemFree (g_hHeap, 0, data);
  738. }
  739. CloseRegKey (key);
  740. }
  741. } while (EnumNextRegKey (&e));
  742. }
  743. FreeStringResource (IncompatibleSoftware);
  744. //
  745. // Since we build the message ourselves, just return FALSE. This will
  746. // keep the ConditionalMessage function from adding this twice.
  747. //
  748. return FALSE;
  749. }
  750. BOOL
  751. IsDefValueEqual (
  752. IN PCTSTR Object,
  753. IN PCTSTR GroupBase,
  754. IN PCTSTR Description,
  755. IN PCTSTR Argument
  756. )
  757. {
  758. HKEY key = NULL;
  759. PCTSTR Data = NULL;
  760. BOOL equal = FALSE;
  761. if (Object) {
  762. key = OpenRegKeyStr (Object);
  763. }
  764. if (key) {
  765. Data = (PCTSTR) GetRegKeyData (key, S_EMPTY);
  766. if (Data) {
  767. if (StringIMatch (Data, Argument)) {
  768. equal = TRUE;
  769. }
  770. MemFree (g_hHeap, 0, Data);
  771. }
  772. CloseRegKey (key);
  773. }
  774. return equal;
  775. }
  776. VOID
  777. pHardwareProfileWarning (
  778. VOID
  779. )
  780. /*++
  781. Routine Description:
  782. Produces incompatibility messages for all hardware profiles that
  783. have different hardware configurations. The upgrade cannot maintain
  784. the list of disabled hardware in a hardware profile, so a warning
  785. is generated.
  786. Arguments:
  787. none
  788. Return Value:
  789. none
  790. --*/
  791. {
  792. REGKEY_ENUM e;
  793. REGKEY_ENUM e2;
  794. HKEY ProfileKey;
  795. HKEY EnumKey;
  796. HKEY ConfigDbKey;
  797. DWORD Config;
  798. TCHAR FriendlyName[MAX_PATH];
  799. PCTSTR MsgGroup;
  800. PCTSTR RootGroup;
  801. PCTSTR HwProfiles;
  802. PCTSTR Data;
  803. TCHAR FullKey[MAX_REGISTRY_KEY];
  804. UINT Profiles;
  805. //
  806. // How many hardware profiles? If just one, don't give a warning.
  807. //
  808. Profiles = 0;
  809. if (EnumFirstRegKeyStr (&e, S_CONFIG_KEY)) {
  810. do {
  811. Profiles++;
  812. } while (EnumNextRegKey (&e));
  813. }
  814. if (Profiles < 2) {
  815. DEBUGMSG ((DBG_VERBOSE, "Hardware profiles: %u, suppressed all warnings", Profiles));
  816. return;
  817. }
  818. //
  819. // Enumerate the hardware profiles in HKLM\Config
  820. //
  821. if (EnumFirstRegKeyStr (&e, S_CONFIG_KEY)) {
  822. do {
  823. //
  824. // Determine if profile has an Enum key
  825. //
  826. ProfileKey = OpenRegKey (e.KeyHandle, e.SubKeyName);
  827. if (ProfileKey) {
  828. EnumKey = OpenRegKey (ProfileKey, S_ENUM_SUBKEY);
  829. if (EnumKey) {
  830. //
  831. // Determine if Enum key is empty
  832. //
  833. if (EnumFirstRegKey (&e2, EnumKey)) {
  834. AbortRegKeyEnum (&e2);
  835. //
  836. // Obtain friendly name for config
  837. //
  838. ConfigDbKey = OpenRegKeyStr (S_FRIENDLYNAME_KEY);
  839. if (ConfigDbKey) {
  840. Config = _ttoi (e.SubKeyName);
  841. wsprintf (FriendlyName, S_FRIENDLYNAME_SPRINTF, Config);
  842. Data = GetRegValueData (ConfigDbKey, FriendlyName);
  843. if (Data) {
  844. //
  845. // Put message in incompatibility report
  846. //
  847. wsprintf (FullKey, TEXT("%s\\%s"), S_CONFIG_KEY, e.SubKeyName);
  848. //
  849. // Generate Msg and MsgGroup
  850. //
  851. RootGroup = GetStringResource (MSG_INSTALL_NOTES_ROOT);
  852. MYASSERT (RootGroup);
  853. HwProfiles = GetStringResource (MSG_HWPROFILES_SUBGROUP);
  854. MYASSERT (HwProfiles);
  855. MsgGroup = JoinPaths (RootGroup, HwProfiles);
  856. MYASSERT (MsgGroup);
  857. FreeStringResource (RootGroup);
  858. FreeStringResource (HwProfiles);
  859. RootGroup = MsgGroup;
  860. MsgGroup = JoinPaths (RootGroup, Data);
  861. MYASSERT (MsgGroup);
  862. FreePathString (RootGroup);
  863. //
  864. // Add the message and clean up
  865. //
  866. MsgMgr_ObjectMsg_Add (FullKey, MsgGroup, S_EMPTY);
  867. FreePathString (MsgGroup);
  868. MemFree (g_hHeap, 0, Data);
  869. }
  870. ELSE_DEBUGMSG ((DBG_ERROR, "Hardware profile lacks friendly name"));
  871. CloseRegKey (ConfigDbKey);
  872. }
  873. ELSE_DEBUGMSG ((DBG_ERROR, "Hardware profile lacks config DB key"));
  874. if (!ConfigDbKey) {
  875. LOG ((LOG_ERROR, "Hardware profile lacks config DB key"));
  876. }
  877. }
  878. CloseRegKey (EnumKey);
  879. }
  880. CloseRegKey (ProfileKey);
  881. }
  882. } while (EnumNextRegKey (&e));
  883. }
  884. }
  885. DWORD
  886. HardwareProfileWarning (
  887. IN DWORD Request
  888. )
  889. {
  890. switch (Request) {
  891. case REQUEST_QUERYTICKS:
  892. return TICKS_HARDWARE_PROFILE_WARNING;
  893. case REQUEST_RUN:
  894. pHardwareProfileWarning ();
  895. return ERROR_SUCCESS;
  896. default:
  897. DEBUGMSG ((DBG_ERROR, "Bad parameter in HardwareProfileWarning"));
  898. }
  899. return 0;
  900. }
  901. VOID
  902. pUnsupportedProtocolsWarning (
  903. VOID
  904. )
  905. /*++
  906. Routine Description:
  907. Produces incompatibility messages for network protocols that
  908. do not ship with equivalent versions on NT.
  909. Arguments:
  910. none
  911. Return Value:
  912. none
  913. --*/
  914. {
  915. PCTSTR NetworkProtocols;
  916. PCTSTR Message;
  917. PCTSTR ArgArray[2];
  918. REGKEY_ENUM e;
  919. HKEY ProtocolKey, BindingKey, DriverKey;
  920. REGKEY_ENUM ProtocolEnum;
  921. INFCONTEXT ic;
  922. PCTSTR Driver, DriverDesc, Mfg;
  923. DWORD MsgId;
  924. TCHAR DriverKeyStr[MAX_REGISTRY_KEY];
  925. TCHAR FullKey[MAX_REGISTRY_KEY];
  926. //
  927. // Enumerate the HKLM\Enum\Network key
  928. //
  929. if (EnumFirstRegKeyStr (&e, S_ENUM_NETWORK_KEY)) {
  930. do {
  931. //
  932. // Check win95upg.inf to see if the network protocol is known
  933. //
  934. if (SetupFindFirstLine (
  935. g_Win95UpgInf,
  936. S_SUPPORTED_PROTOCOLS,
  937. e.SubKeyName,
  938. &ic
  939. )) {
  940. // It is, skip to next protocol
  941. continue;
  942. }
  943. //
  944. // A warning message must be generated. We must take the first
  945. // subkey of the protocol, query its Driver value, and look up
  946. // the DriverDesc in HKLM\System\CCS\Services\Class\<driver>.
  947. //
  948. ProtocolKey = OpenRegKey (e.KeyHandle, e.SubKeyName);
  949. if (ProtocolKey) {
  950. if (EnumFirstRegKey (&ProtocolEnum, ProtocolKey)) {
  951. BindingKey = OpenRegKey (ProtocolKey, ProtocolEnum.SubKeyName);
  952. if (BindingKey) {
  953. Driver = (PCTSTR) GetRegValueDataOfType (
  954. BindingKey,
  955. S_DRIVER,
  956. REG_SZ
  957. );
  958. if (Driver) {
  959. //
  960. // We now know the driver... let's get the
  961. // driver description.
  962. //
  963. wsprintf (DriverKeyStr, S_CLASS_KEY TEXT("\\%s"), Driver);
  964. MemFree (g_hHeap, 0, Driver);
  965. DriverKey = OpenRegKeyStr (DriverKeyStr);
  966. if (DriverKey) {
  967. DriverDesc = (PCTSTR) GetRegValueDataOfType (
  968. DriverKey,
  969. S_DRIVERDESC,
  970. REG_SZ
  971. );
  972. if (DriverDesc) {
  973. //
  974. // Obtain the manufacturer for use in message.
  975. // If the manufacturer is not known, display
  976. // a generic message.
  977. //
  978. Mfg = (PCTSTR) GetRegValueDataOfType (
  979. BindingKey,
  980. S_MFG,
  981. REG_SZ
  982. );
  983. if (!Mfg) {
  984. MsgId = MSG_UNSUPPORTED_PROTOCOL;
  985. } else {
  986. MsgId = MSG_UNSUPPORTED_PROTOCOL_KNOWN_MFG;
  987. }
  988. ArgArray[0] = DriverDesc;
  989. ArgArray[1] = Mfg;
  990. NetworkProtocols = ParseMessageID (MSG_NETWORK_PROTOCOLS, ArgArray);
  991. if(Mfg && StringIMatch(Mfg, TEXT("Microsoft"))){
  992. Message = ParseMessageID (MSG_UNSUPPORTED_PROTOCOL_FROM_MICROSOFT, ArgArray);
  993. }
  994. else {
  995. Message = ParseMessageID (MsgId, ArgArray);
  996. }
  997. MYASSERT (NetworkProtocols && Message);
  998. wsprintf (FullKey, TEXT("%s\\%s"), S_ENUM_NETWORK_KEY, e.SubKeyName);
  999. MsgMgr_ObjectMsg_Add (FullKey, NetworkProtocols, Message);
  1000. if (Mfg) {
  1001. MemFree (g_hHeap, 0, Mfg);
  1002. }
  1003. MemFree (g_hHeap, 0, DriverDesc);
  1004. }
  1005. }
  1006. CloseRegKey (DriverKey);
  1007. }
  1008. CloseRegKey (BindingKey);
  1009. }
  1010. }
  1011. CloseRegKey (ProtocolKey);
  1012. }
  1013. } while (EnumNextRegKey (&e));
  1014. }
  1015. }
  1016. DWORD
  1017. UnsupportedProtocolsWarning (
  1018. IN DWORD Request
  1019. )
  1020. {
  1021. switch (Request) {
  1022. case REQUEST_QUERYTICKS:
  1023. return TICKS_UNSUPPORTED_PROTOCOLS_WARNING;
  1024. case REQUEST_RUN:
  1025. pUnsupportedProtocolsWarning ();
  1026. return ERROR_SUCCESS;
  1027. default:
  1028. DEBUGMSG ((DBG_ERROR, "Bad parameter in UnsupportedProtocolWarning"));
  1029. }
  1030. return 0;
  1031. }