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.

642 lines
16 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. cpls.c
  5. Abstract:
  6. Control Panel applet converters
  7. This source file implements functions needed to convert
  8. Win95 control panel settings into NT format. The most
  9. complex of the structures are the accessibility flag
  10. conversions.
  11. Author:
  12. Jim Schmidt (jimschm) 9-Aug-1996
  13. Revision History:
  14. Jim Schmidt (jimschm) 27-Jul-1998 Added ValFn_AntiAlias
  15. --*/
  16. #include "pch.h"
  17. #include <wingdip.h>
  18. extern PVOID g_NtFontFiles; // in rulehlpr.c
  19. #define BASICS_ON 0x00000001
  20. #define BASICS_AVAILABLE 0x00000002
  21. #define BASICS_HOTKEYACTIVE 0x00000004
  22. #define BASICS_CONFIRMHOTKEY 0x00000008
  23. #define BASICS_HOTKEYSOUND 0x00000010
  24. #define BASICS_INDICATOR 0x00000020
  25. #define SPECIAL_INVERT_OPTION 0x80000000
  26. typedef struct {
  27. LPCTSTR ValueName;
  28. DWORD FlagVal;
  29. } ACCESS_OPTION, *PACCESS_OPTION;
  30. ACCESS_OPTION g_FilterKeys[] = {
  31. S_ACCESS_ON, BASICS_ON,
  32. S_ACCESS_AVAILABLE, BASICS_AVAILABLE,
  33. S_ACCESS_HOTKEYACTIVE, BASICS_HOTKEYACTIVE,
  34. S_ACCESS_CONFIRMHOTKEY, BASICS_CONFIRMHOTKEY,
  35. S_ACCESS_HOTKEYSOUND, BASICS_HOTKEYSOUND,
  36. S_ACCESS_SHOWSTATUSINDICATOR, BASICS_INDICATOR,
  37. S_ACCESS_CLICKON, FKF_CLICKON,
  38. NULL, 0
  39. };
  40. ACCESS_OPTION g_MouseKeys[] = {
  41. S_ACCESS_ON, BASICS_ON,
  42. S_ACCESS_AVAILABLE, BASICS_AVAILABLE,
  43. S_ACCESS_HOTKEYACTIVE, BASICS_HOTKEYACTIVE,
  44. S_ACCESS_CONFIRMHOTKEY, BASICS_CONFIRMHOTKEY,
  45. S_ACCESS_HOTKEYSOUND, BASICS_HOTKEYSOUND,
  46. S_ACCESS_SHOWSTATUSINDICATOR, BASICS_INDICATOR,
  47. S_ACCESS_MODIFIERS, MKF_MODIFIERS|SPECIAL_INVERT_OPTION,
  48. S_ACCESS_REPLACENUMBERS, MKF_REPLACENUMBERS,
  49. NULL, 0
  50. };
  51. ACCESS_OPTION g_StickyKeys[] = {
  52. S_ACCESS_ON, BASICS_ON,
  53. S_ACCESS_AVAILABLE, BASICS_AVAILABLE,
  54. S_ACCESS_HOTKEYACTIVE, BASICS_HOTKEYACTIVE,
  55. S_ACCESS_CONFIRMHOTKEY, BASICS_CONFIRMHOTKEY,
  56. S_ACCESS_HOTKEYSOUND, BASICS_HOTKEYSOUND,
  57. S_ACCESS_SHOWSTATUSINDICATOR, BASICS_INDICATOR,
  58. S_ACCESS_AUDIBLEFEEDBACK, SKF_AUDIBLEFEEDBACK,
  59. S_ACCESS_TRISTATE, SKF_TRISTATE,
  60. S_ACCESS_TWOKEYSOFF, SKF_TWOKEYSOFF,
  61. NULL, 0
  62. };
  63. ACCESS_OPTION g_SoundSentry[] = {
  64. S_ACCESS_ON, BASICS_ON,
  65. S_ACCESS_AVAILABLE, BASICS_AVAILABLE,
  66. S_ACCESS_SHOWSTATUSINDICATOR, BASICS_INDICATOR,
  67. NULL, 0
  68. };
  69. ACCESS_OPTION g_TimeOut[] = {
  70. S_ACCESS_ON, BASICS_ON,
  71. S_ACCESS_ONOFFFEEDBACK, ATF_ONOFFFEEDBACK,
  72. NULL, 0
  73. };
  74. ACCESS_OPTION g_ToggleKeys[] = {
  75. S_ACCESS_ON, BASICS_ON,
  76. S_ACCESS_AVAILABLE, BASICS_AVAILABLE,
  77. S_ACCESS_HOTKEYACTIVE, BASICS_HOTKEYACTIVE,
  78. S_ACCESS_CONFIRMHOTKEY, BASICS_CONFIRMHOTKEY,
  79. S_ACCESS_HOTKEYSOUND, BASICS_HOTKEYSOUND,
  80. S_ACCESS_SHOWSTATUSINDICATOR, BASICS_INDICATOR,
  81. NULL, 0
  82. };
  83. ACCESS_OPTION g_HighContrast[] = {
  84. S_ACCESS_ON, BASICS_ON,
  85. S_ACCESS_AVAILABLE, BASICS_AVAILABLE,
  86. S_ACCESS_HOTKEYACTIVE, BASICS_HOTKEYACTIVE,
  87. S_ACCESS_CONFIRMHOTKEY, BASICS_CONFIRMHOTKEY,
  88. S_ACCESS_HOTKEYSOUND, BASICS_HOTKEYSOUND,
  89. S_ACCESS_SHOWSTATUSINDICATOR, BASICS_INDICATOR,
  90. S_ACCESS_HOTKEYAVAILABLE, HCF_HOTKEYAVAILABLE,
  91. NULL, 0
  92. };
  93. DWORD
  94. ConvertFlags (
  95. IN LPCTSTR Object,
  96. IN PACCESS_OPTION OptionArray
  97. )
  98. {
  99. DATAOBJECT Ob;
  100. DWORD Flags;
  101. DWORD d;
  102. if (!CreateObjectStruct (Object, &Ob, WIN95OBJECT)) {
  103. LOG ((LOG_ERROR, "%s is not a valid object", Object));
  104. return 0;
  105. }
  106. if (!OpenObject (&Ob)) {
  107. DEBUGMSG ((DBG_WARNING, "%s does not exist", Object));
  108. return 0;
  109. }
  110. //
  111. // Get flag settings from Win95 registry and convert them to Flags
  112. //
  113. Flags = 0;
  114. while (OptionArray->ValueName) {
  115. SetRegistryValueName (&Ob, OptionArray->ValueName);
  116. if (GetDwordFromObject (&Ob, &d)) {
  117. //
  118. // Most flags are identical on Win9x and NT, but there's one
  119. // MouseKey flag that needs to be inverted.
  120. //
  121. if (OptionArray->FlagVal & SPECIAL_INVERT_OPTION) {
  122. if (!d) {
  123. Flags |= (OptionArray->FlagVal & (~SPECIAL_INVERT_OPTION));
  124. }
  125. } else if (d) {
  126. Flags |= OptionArray->FlagVal;
  127. }
  128. }
  129. OptionArray++;
  130. FreeObjectVal (&Ob);
  131. }
  132. FreeObjectStruct (&Ob);
  133. return Flags;
  134. }
  135. BOOL
  136. SaveAccessibilityFlags (
  137. IN LPCTSTR ObjectStr,
  138. IN DWORD dw
  139. )
  140. {
  141. DATAOBJECT Ob;
  142. BOOL b = FALSE;
  143. TCHAR FlagBuf[32];
  144. SetLastError (ERROR_SUCCESS);
  145. if (!CreateObjectStruct (ObjectStr, &Ob, WINNTOBJECT)) {
  146. LOG ((LOG_ERROR, "Save Accessibility Flags: can't create object %s", ObjectStr));
  147. return FALSE;
  148. }
  149. if (!(Ob.ValueName)) {
  150. if (!SetRegistryValueName (&Ob, TEXT("Flags"))) {
  151. return FALSE;
  152. }
  153. } else {
  154. DEBUGMSG ((DBG_WARNING, "SaveAccessibilityFlags: Name already exists"));
  155. }
  156. wsprintf (FlagBuf, TEXT("%u"), dw);
  157. SetRegistryType (&Ob, REG_SZ);
  158. ReplaceValue (&Ob, (LPBYTE) FlagBuf, SizeOfString (FlagBuf));
  159. b = WriteObject (&Ob);
  160. FreeObjectStruct (&Ob);
  161. return b;
  162. }
  163. BOOL
  164. pConvertFlagsAndSave (
  165. IN LPCTSTR SrcObject,
  166. IN LPCTSTR DestObject,
  167. IN PACCESS_OPTION OptionArray,
  168. IN DWORD ForceValues
  169. )
  170. {
  171. DWORD d;
  172. d = ConvertFlags (SrcObject, OptionArray);
  173. if (!d) {
  174. return TRUE;
  175. }
  176. DEBUGMSG ((DBG_VERBOSE, "Setting %x and forcing %x for %s", d, ForceValues, DestObject));
  177. return SaveAccessibilityFlags (DestObject, d | ForceValues);
  178. }
  179. //
  180. // Exported helper functions
  181. //
  182. BOOL
  183. RuleHlpr_ConvertFilterKeys (
  184. IN LPCTSTR SrcObjectStr,
  185. IN LPCTSTR DestObjectStr,
  186. IN LPCTSTR User,
  187. IN LPVOID Data
  188. )
  189. {
  190. return pConvertFlagsAndSave (
  191. SrcObjectStr,
  192. DestObjectStr,
  193. g_FilterKeys,
  194. BASICS_HOTKEYSOUND | BASICS_CONFIRMHOTKEY | BASICS_AVAILABLE
  195. );
  196. }
  197. BOOL
  198. RuleHlpr_ConvertOldDisabled (
  199. IN LPCTSTR SrcObjectStr,
  200. IN LPCTSTR DestObjectStr,
  201. IN LPCTSTR User,
  202. IN LPVOID Data
  203. )
  204. {
  205. DATAOBJECT Ob;
  206. DWORD Val;
  207. BOOL b = FALSE;
  208. if (!ReadWin95ObjectString (SrcObjectStr, &Ob)) {
  209. DEBUGMSG ((DBG_WARNING, "RuleHlpr_ConvertOldDisabled failed because ReadWin95ObjectString failed"));
  210. goto c0;
  211. }
  212. //
  213. // Obtain Val from DWORD or string
  214. //
  215. if (!GetDwordFromObject (&Ob, &Val)) {
  216. goto c1;
  217. }
  218. // Our little fixup
  219. if (Val == 32760) {
  220. Val = 0;
  221. } else {
  222. b = TRUE;
  223. goto c1;
  224. }
  225. //
  226. // Regenerate registry value
  227. //
  228. if (Ob.Type == REG_DWORD) {
  229. *((PDWORD) Ob.Value.Buffer) = Val;
  230. } else {
  231. TCHAR NumStr[32];
  232. wsprintf (NumStr, TEXT("%u"), Val);
  233. if (!ReplaceValueWithString (&Ob, NumStr)) {
  234. goto c1;
  235. }
  236. }
  237. if (!WriteWinNTObjectString (DestObjectStr, &Ob)) {
  238. DEBUGMSG ((DBG_WARNING, "RuleHlpr_ConvertOldDisabled failed because WriteWinNTObjectString failed"));
  239. goto c1;
  240. }
  241. b = TRUE;
  242. c1:
  243. FreeObjectStruct (&Ob);
  244. c0:
  245. return b;
  246. }
  247. BOOL
  248. RuleHlpr_ConvertMouseKeys (
  249. IN LPCTSTR SrcObjectStr,
  250. IN LPCTSTR DestObjectStr,
  251. IN LPCTSTR User,
  252. IN LPVOID Data
  253. )
  254. {
  255. return pConvertFlagsAndSave (
  256. SrcObjectStr,
  257. DestObjectStr,
  258. g_MouseKeys,
  259. BASICS_HOTKEYSOUND | BASICS_CONFIRMHOTKEY | BASICS_AVAILABLE
  260. );
  261. }
  262. BOOL
  263. RuleHlpr_ConvertStickyKeys (
  264. IN LPCTSTR SrcObjectStr,
  265. IN LPCTSTR DestObjectStr,
  266. IN LPCTSTR User,
  267. IN LPVOID Data
  268. )
  269. {
  270. return pConvertFlagsAndSave (
  271. SrcObjectStr,
  272. DestObjectStr,
  273. g_StickyKeys,
  274. BASICS_HOTKEYSOUND | BASICS_CONFIRMHOTKEY | BASICS_AVAILABLE
  275. );
  276. }
  277. BOOL
  278. RuleHlpr_ConvertSoundSentry (
  279. IN LPCTSTR SrcObjectStr,
  280. IN LPCTSTR DestObjectStr,
  281. IN LPCTSTR User,
  282. IN LPVOID Data
  283. )
  284. {
  285. return pConvertFlagsAndSave (
  286. SrcObjectStr,
  287. DestObjectStr,
  288. g_SoundSentry,
  289. BASICS_AVAILABLE
  290. );
  291. }
  292. BOOL
  293. RuleHlpr_ConvertTimeOut (
  294. IN LPCTSTR SrcObjectStr,
  295. IN LPCTSTR DestObjectStr,
  296. IN LPCTSTR User,
  297. IN LPVOID Data
  298. )
  299. {
  300. return pConvertFlagsAndSave (
  301. SrcObjectStr,
  302. DestObjectStr,
  303. g_TimeOut,
  304. 0
  305. );
  306. }
  307. BOOL
  308. RuleHlpr_ConvertToggleKeys (
  309. IN LPCTSTR SrcObjectStr,
  310. IN LPCTSTR DestObjectStr,
  311. IN LPCTSTR User,
  312. IN LPVOID Data
  313. )
  314. {
  315. return pConvertFlagsAndSave (
  316. SrcObjectStr,
  317. DestObjectStr,
  318. g_ToggleKeys,
  319. BASICS_HOTKEYSOUND | BASICS_CONFIRMHOTKEY | BASICS_AVAILABLE
  320. );
  321. }
  322. BOOL
  323. RuleHlpr_ConvertHighContrast (
  324. IN LPCTSTR SrcObjectStr,
  325. IN LPCTSTR DestObjectStr,
  326. IN LPCTSTR User,
  327. IN LPVOID Data
  328. )
  329. {
  330. return pConvertFlagsAndSave (
  331. SrcObjectStr,
  332. DestObjectStr,
  333. g_HighContrast,
  334. BASICS_AVAILABLE | BASICS_CONFIRMHOTKEY |
  335. BASICS_INDICATOR | HCF_HOTKEYAVAILABLE |
  336. BASICS_HOTKEYSOUND
  337. );
  338. }
  339. BOOL
  340. ValFn_Fonts (
  341. IN OUT PDATAOBJECT ObPtr
  342. )
  343. /*++
  344. Routine Description:
  345. This routine uses the RuleHlpr_ConvertRegVal simplification routine. See
  346. rulehlpr.c for details. The simplification routine does almost all the work
  347. for us; all we need to do is update the value.
  348. ValFn_Fonts compares the value data against the string table g_NtFontFiles
  349. to suppress copy of font names of files that NT installs. This allows the
  350. font names to change.
  351. Arguments:
  352. ObPtr - Specifies the Win95 data object as specified in wkstamig.inf,
  353. [Win9x Data Conversion] section. The object value is then modified.
  354. After returning, the merge code then copies the data to the NT
  355. destination, which has a new location (specified in wkstamig.inf,
  356. [Map Win9x to WinNT] section).
  357. Return Value:
  358. Tri-state:
  359. TRUE to allow merge code to continue processing (it writes the value)
  360. FALSE and last error == ERROR_SUCCESS to continue, but skip the write
  361. FALSE and last error != ERROR_SUCCESS if an error occurred
  362. --*/
  363. {
  364. LONG rc;
  365. TCHAR FontName[MAX_TCHAR_PATH];
  366. PTSTR p;
  367. BOOL Check;
  368. DATAOBJECT NtObject;
  369. BOOL AlreadyExists;
  370. //
  371. // Require non-empty value data
  372. //
  373. if (!IsObjectRegistryKeyAndVal (ObPtr) ||
  374. !IsRegistryTypeSpecified (ObPtr) ||
  375. !ObPtr->Value.Size ||
  376. !g_NtFontFiles
  377. ) {
  378. SetLastError (ERROR_SUCCESS);
  379. return FALSE;
  380. }
  381. //
  382. // Ignore Win9x font entry if same value name exists on NT
  383. //
  384. if (!DuplicateObjectStruct (&NtObject, ObPtr)) {
  385. return FALSE;
  386. }
  387. DEBUGMSG ((DBG_VERBOSE, "Working on %s [%s]", ObPtr->KeyPtr->KeyString, ObPtr->ValueName));
  388. SetPlatformType (&NtObject, WINNTOBJECT);
  389. SetRegistryKey (&NtObject, TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts"));
  390. FreeObjectVal (&NtObject);
  391. DEBUGMSG ((DBG_VERBOSE, "Reading %s [%s]", NtObject.KeyPtr->KeyString, NtObject.ValueName));
  392. AlreadyExists = ReadObject (&NtObject);
  393. FreeObjectStruct (&NtObject);
  394. if (AlreadyExists) {
  395. DEBUGMSG ((DBG_VERBOSE, "[%s] Already exists", ObPtr->ValueName));
  396. SetLastError (ERROR_SUCCESS);
  397. return FALSE;
  398. }
  399. //
  400. // Look in string table for file name
  401. //
  402. rc = pSetupStringTableLookUpString (
  403. g_NtFontFiles,
  404. (PTSTR) ObPtr->Value.Buffer,
  405. STRTAB_CASE_INSENSITIVE
  406. );
  407. if (rc == -1) {
  408. //
  409. // Check for TTF/TTC match
  410. //
  411. _tcssafecpy (FontName, (PCTSTR) ObPtr->Value.Buffer, MAX_TCHAR_PATH);
  412. p = _tcschr (FontName, TEXT('.'));
  413. if (p) {
  414. p = _tcsinc (p);
  415. if (StringIMatch (p, TEXT("TTF"))) {
  416. StringCopy (p, TEXT("TTC"));
  417. Check = TRUE;
  418. } else if (StringIMatch (p, TEXT("TTC"))) {
  419. StringCopy (p, TEXT("TTF"));
  420. Check = TRUE;
  421. } else {
  422. Check = FALSE;
  423. }
  424. if (Check) {
  425. rc = pSetupStringTableLookUpString (
  426. g_NtFontFiles,
  427. FontName,
  428. STRTAB_CASE_INSENSITIVE
  429. );
  430. }
  431. }
  432. }
  433. if (rc == -1) {
  434. //
  435. // Check for an NT font named FONTU.TTF or FONTU.TTC
  436. //
  437. _tcssafecpy (FontName, (PCTSTR) ObPtr->Value.Buffer, MAX_TCHAR_PATH);
  438. p = _tcschr (FontName, TEXT('.'));
  439. if (p) {
  440. StringCopy (p, TEXT("U.TTF"));
  441. rc = pSetupStringTableLookUpString (
  442. g_NtFontFiles,
  443. FontName,
  444. STRTAB_CASE_INSENSITIVE
  445. );
  446. if (rc == -1) {
  447. StringCopy (p, TEXT("U.TTC"));
  448. rc = pSetupStringTableLookUpString (
  449. g_NtFontFiles,
  450. FontName,
  451. STRTAB_CASE_INSENSITIVE
  452. );
  453. }
  454. }
  455. }
  456. if (rc != -1) {
  457. //
  458. // Font name was in the table, so don't add it twice
  459. //
  460. DEBUGMSG ((DBG_NAUSEA, "Suppressing Win9x font registration for %s", ObPtr->Value.Buffer));
  461. SetLastError (ERROR_SUCCESS);
  462. return FALSE;
  463. } else {
  464. DEBUGMSG ((DBG_VERBOSE, "[%s] Preserving Win9x font info: %s", ObPtr->ValueName, (PCTSTR) ObPtr->Value.Buffer));
  465. }
  466. return TRUE;
  467. }
  468. BOOL
  469. ValFn_AntiAlias (
  470. IN OUT PDATAOBJECT ObPtr
  471. )
  472. /*++
  473. Routine Description:
  474. This routine uses the RuleHlpr_ConvertRegVal simplification routine. See
  475. rulehlpr.c for details. The simplification routine does almost all the work
  476. for us; all we need to do is update the value.
  477. ValFn_AntiAlias changes a 1 to a 2. Win9x uses 1, but NT uses FE_AA_ON,
  478. which is currently 2.
  479. Return Value:
  480. Tri-state:
  481. TRUE to allow merge code to continue processing (it writes the value)
  482. FALSE and last error == ERROR_SUCCESS to continue, but skip the write
  483. FALSE and last error != ERROR_SUCCESS if an error occurred
  484. --*/
  485. {
  486. TCHAR Number[8];
  487. //
  488. // Require non-empty REG_SZ
  489. //
  490. if (!IsObjectRegistryKeyAndVal (ObPtr) ||
  491. !IsRegistryTypeSpecified (ObPtr) ||
  492. !ObPtr->Value.Size ||
  493. !g_NtFontFiles ||
  494. ObPtr->Type != REG_SZ
  495. ) {
  496. DEBUGMSG ((DBG_WARNING, "ValFn_AntiAlias: Data is not valid"));
  497. ReplaceValueWithString (ObPtr, TEXT("0"));
  498. }
  499. else if (_ttoi ((PCTSTR) ObPtr->Value.Buffer)) {
  500. DEBUGMSG ((DBG_NAUSEA, "Switching anti-alias value from 1 to %u", FE_AA_ON));
  501. wsprintf (Number, TEXT("%u"), FE_AA_ON);
  502. ReplaceValueWithString (ObPtr, Number);
  503. }
  504. return TRUE;
  505. }