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.

1215 lines
26 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. config.c
  5. Abstract:
  6. This file implements the windows 9x side configuration functionality of the upgrade project.
  7. This includes unattend behavior and command line options in addition to the normal set of
  8. configuration duties.
  9. Author:
  10. Marc R. Whitten (marcw)
  11. Revision History:
  12. ovidiut 14-Mar-2000 Added encrypted passwords support
  13. marcw 15-Oct-1998 Cleaned up unattend options.
  14. jimschm 23-Sep-1998 Removed operation code
  15. jimschm 01-May-1998 Removed MikeCo plugtemp.inf crap
  16. marcw 10-Dec-1997 Added UserPassword unattend setting.
  17. calinn 19-Nov-1997 Added g_Boot16, enables 16 bit environment boot option
  18. marcw 13-Nov-1997 Unattend settings changed to get closer to a final state.
  19. marcw 12-Aug-1997 We now respect setup's unattend flag.
  20. marcw 21-Jul-1997 Added FAIR flag.
  21. marcw 26-May-1997 Added lots and lots of comments.
  22. --*/
  23. #include "pch.h"
  24. USEROPTIONS g_ConfigOptions;
  25. PVOID g_OptionsTable;
  26. #undef BOOLOPTION
  27. #undef MULTISZOPTION
  28. #undef STRINGOPTION
  29. #undef INTOPTION
  30. #undef TRISTATEOPTION
  31. typedef BOOL (OPTIONHANDLERFUN)(PTSTR, PVOID * Option, PTSTR Value);
  32. typedef OPTIONHANDLERFUN * POPTIONHANDLERFUN;
  33. BOOL pHandleBoolOption (PTSTR, PVOID *, PTSTR);
  34. BOOL pHandleIntOption (PTSTR, PVOID *, PTSTR);
  35. BOOL pHandleTriStateOption (PTSTR, PVOID *, PTSTR);
  36. BOOL pHandleMultiSzOption (PTSTR, PVOID *, PTSTR);
  37. BOOL pHandleStringOption (PTSTR, PVOID *, PTSTR);
  38. BOOL pHandleSaveReportTo (PTSTR, PVOID *, PTSTR);
  39. BOOL pHandleBoot16 (PTSTR, PVOID *, PTSTR);
  40. BOOL pGetDefaultPassword (PTSTR, PVOID *, PTSTR);
  41. typedef struct {
  42. PTSTR OptionName;
  43. PVOID Option;
  44. POPTIONHANDLERFUN DefaultHandler;
  45. POPTIONHANDLERFUN SpecialHandler;
  46. PVOID Default;
  47. } OPTIONSTRUCT, *POPTIONSTRUCT;
  48. typedef struct {
  49. PTSTR Alias;
  50. PTSTR Option;
  51. } ALIASSTRUCT, *PALIASSTRUCT;
  52. #define BOOLOPTION(o,h,d) {TEXT(#o), &(g_ConfigOptions.##o), pHandleBoolOption, (h), (PVOID) (BOOL) (d) ? S_YES : S_NO},
  53. #define INTOPTION(o,h,d) {TEXT(#o), &(g_ConfigOptions.##o), pHandleIntOption, (h), (PVOID)(d)},
  54. #define TRISTATEOPTION(o,h,d) {TEXT(#o), &(g_ConfigOptions.##o), pHandleTriStateOption, (h), (PVOID) (INT) (d == TRISTATE_AUTO)? S_AUTO: (d == TRISTATE_YES)? S_YES : S_NO},
  55. #define MULTISZOPTION(o,h,d) {TEXT(#o), &(g_ConfigOptions.##o), pHandleMultiSzOption, (h), (PVOID) (d)},
  56. #define STRINGOPTION(o,h,d) {TEXT(#o), &(g_ConfigOptions.##o), pHandleStringOption, (h), (PVOID) (d)},
  57. OPTIONSTRUCT g_OptionsList[] = {OPTION_LIST /*,*/ {NULL,NULL,NULL,NULL}};
  58. #define ALIAS(a,o) {TEXT(#a),TEXT(#o)},
  59. ALIASSTRUCT g_AliasList[] = {ALIAS_LIST /*,*/ {NULL,NULL}};
  60. #define HANDLEOPTION(Os,Value) {Os->SpecialHandler ? \
  61. Os->SpecialHandler (Os->OptionName,Os->Option,Value) : \
  62. Os->DefaultHandler (Os->OptionName,Os->Option,Value); \
  63. }
  64. BOOL
  65. Cfg_CreateWorkDirectories (
  66. VOID
  67. )
  68. {
  69. /*++
  70. Routine Description:
  71. This routine is responsible for creating the main win9xupg working directories. It should not
  72. be called until after the user has chosen to upgrade his system. In practice, this means that
  73. we must not create our directories when winnt32 calls us to init as this is done before the
  74. user chooses wether to upgrade or do a clean install.
  75. Arguments:
  76. None.
  77. Return Value:
  78. None.
  79. --*/
  80. DWORD rc;
  81. FILE_ENUM e;
  82. if (EnumFirstFile (&e, g_TempDir, FALSE)) {
  83. do {
  84. if (e.Directory) {
  85. CreateEmptyDirectory (e.FullPath);
  86. }
  87. } while (EnumNextFile (&e));
  88. }
  89. rc = CreateEmptyDirectory (g_PlugInTempDir);
  90. if (rc != ERROR_SUCCESS) {
  91. return FALSE;
  92. }
  93. return TRUE;
  94. }
  95. BOOL
  96. pInitUserOptions (
  97. VOID
  98. )
  99. {
  100. POPTIONSTRUCT os;
  101. BOOL rSuccess = TRUE;
  102. os = g_OptionsList;
  103. while (os->OptionName) {
  104. //
  105. // Set the default value.
  106. //
  107. HANDLEOPTION(os, os->Default);
  108. //
  109. // Add the option struct to a string table for quick retrieval.
  110. //
  111. if (-1 == pSetupStringTableAddStringEx (
  112. g_OptionsTable,
  113. os->OptionName,
  114. STRTAB_CASE_INSENSITIVE,
  115. (PBYTE) &os,
  116. sizeof (POPTIONSTRUCT)
  117. )) {
  118. LOG ((LOG_ERROR, "User Options: Can't add to string table"));
  119. rSuccess = FALSE;
  120. break;
  121. }
  122. os++;
  123. }
  124. return rSuccess;
  125. }
  126. POPTIONSTRUCT
  127. pFindOption (
  128. PTSTR OptionName
  129. )
  130. {
  131. /*++
  132. Routine Description:
  133. Given an option name, pFindOption returns the associated option struct.
  134. Arguments:
  135. OptionName - The name of the option to find.
  136. Return Value:
  137. a valid option struct if successful, NULL otherwise.
  138. --*/
  139. POPTIONSTRUCT rOption = NULL;
  140. UINT rc;
  141. //
  142. // find the matching option struct for this, and
  143. // call the handler.
  144. //
  145. rc = pSetupStringTableLookUpStringEx (
  146. g_OptionsTable,
  147. OptionName,
  148. STRTAB_CASE_INSENSITIVE,
  149. (PBYTE) &rOption,
  150. sizeof (POPTIONSTRUCT)
  151. );
  152. DEBUGMSG_IF ((rc == -1, DBG_WARNING, "Unknown option found: %s", OptionName));
  153. return rOption;
  154. }
  155. VOID
  156. pReadUserOptionsFromUnattendFile (
  157. VOID
  158. )
  159. /*++
  160. Routine Description:
  161. This function reads all available win9xupg options from an unattend.txt
  162. file passed to winnt32.
  163. Arguments:
  164. None.
  165. Return Value:
  166. None.
  167. --*/
  168. {
  169. POPTIONSTRUCT os;
  170. INFSTRUCT is = INITINFSTRUCT_POOLHANDLE;
  171. PTSTR option;
  172. PTSTR value;
  173. HINF unattendInf;
  174. if (*g_UnattendScriptFile) {
  175. unattendInf = InfOpenInfFile (*g_UnattendScriptFile);
  176. if (unattendInf != INVALID_HANDLE_VALUE) {
  177. if (InfFindFirstLine (unattendInf, S_WIN9XUPGRADE, NULL, &is)) {
  178. //
  179. // Enumerate through each of the options, call the
  180. //
  181. do {
  182. option = InfGetStringField (&is, 0);
  183. value = InfGetLineText (&is);
  184. //
  185. // find the matching option struct for this, and
  186. // call the handler.
  187. //
  188. os = pFindOption (option);
  189. if (os) {
  190. HANDLEOPTION(os, value);
  191. }
  192. } while (InfFindNextLine (&is));
  193. }
  194. if (InfFindFirstLine (unattendInf, S_UNINSTALL, NULL, &is)) {
  195. //
  196. // Enumerate through each of the options, call the
  197. //
  198. do {
  199. option = InfGetStringField (&is, 0);
  200. value = InfGetLineText (&is);
  201. //
  202. // find the matching option struct for this, and
  203. // call the handler.
  204. //
  205. os = pFindOption (option);
  206. if (os) {
  207. HANDLEOPTION(os, value);
  208. }
  209. } while (InfFindNextLine (&is));
  210. }
  211. InfCloseInfFile (unattendInf);
  212. }
  213. }
  214. InfCleanUpInfStruct (&is);
  215. }
  216. VOID
  217. pReadUserOptionsFromCommandLine (
  218. VOID
  219. )
  220. /*++
  221. Routine Description:
  222. This function processes all of the win9xupg command line options that were
  223. passed into winnt32 (those starting with /#U:) winnt32 has already packaged
  224. this list (minus the /#U:) into a nice multisz for us.
  225. Arguments:
  226. None.
  227. Return Value:
  228. None.
  229. --*/
  230. {
  231. MULTISZ_ENUM e;
  232. PTSTR option;
  233. PTSTR value;
  234. PTSTR equals;
  235. POPTIONSTRUCT os;
  236. if (*g_CmdLineOptions) {
  237. //
  238. // We have data to parse, run through the multisz.
  239. //
  240. if (EnumFirstMultiSz (&e, *g_CmdLineOptions)) {
  241. do {
  242. option = (PTSTR) e.CurrentString;
  243. value = NULL;
  244. equals = _tcschr (option, TEXT('='));
  245. if (equals) {
  246. value = _tcsinc (equals);
  247. *equals = 0;
  248. }
  249. os = pFindOption (option);
  250. if (os) {
  251. HANDLEOPTION (os, value);
  252. }
  253. if (equals) {
  254. *equals = TEXT('=');
  255. }
  256. } while (EnumNextMultiSz (&e));
  257. }
  258. }
  259. }
  260. VOID
  261. pCreateNetCfgIni (
  262. VOID
  263. )
  264. {
  265. /*++
  266. Routine Description:
  267. pCreateNetCfgIni creates a very basic netcfg.ini file. This will cause many
  268. networking messages to be dumped to the debugger during Network
  269. Installation in GUI mode. The file is deleted at the end of setup, if we
  270. created it.
  271. Arguments:
  272. None.
  273. Return Value:
  274. None.
  275. --*/
  276. HANDLE h;
  277. PTSTR path;
  278. PTSTR content =
  279. TEXT("[Default]\r\n")
  280. TEXT("OutputToDebug=1\r\n\r\n")
  281. TEXT("[OptErrors]\r\n")
  282. TEXT("OutputToDebug=0\r\n\r\n")
  283. TEXT("[EsLocks]\r\n")
  284. TEXT("OutputToDebug=0\r\n");
  285. UINT unused;
  286. path = JoinPaths(g_WinDir,TEXT("netcfg.ini"));
  287. //
  288. // Create the netcfg.ini file, and fill in its content. Note that we do
  289. // not want to overwrite a netcfg.ini file that may previously exist.
  290. //
  291. h = CreateFile (
  292. path,
  293. GENERIC_READ | GENERIC_WRITE,
  294. 0, // No sharing.
  295. NULL, // No inheritance.
  296. CREATE_NEW,
  297. FILE_ATTRIBUTE_NORMAL,
  298. NULL // No template file.
  299. );
  300. if (h != INVALID_HANDLE_VALUE) {
  301. if (!WriteFile (h,(PVOID) content, ByteCount(content), &unused, NULL)) {
  302. LOG((LOG_ERROR,"Error writing netcfg.ini."));
  303. }
  304. CloseHandle(h);
  305. }
  306. ELSE_DEBUGMSG((DBG_WARNING,"pCreateNetCfgIni: Could not create file. Probably already exists.."));
  307. FreePathString(path);
  308. }
  309. VOID
  310. pInitAliases (
  311. VOID
  312. )
  313. {
  314. /*++
  315. Routine Description:
  316. This functions initializes any aliases specified within unattend.h. These
  317. aliases may be used instead of the option they refer to.
  318. Arguments:
  319. None.
  320. Return Value:
  321. None.
  322. --*/
  323. PALIASSTRUCT alias;
  324. POPTIONSTRUCT option;
  325. alias = g_AliasList;
  326. while (alias->Alias) {
  327. option = pFindOption (alias->Option);
  328. if (option) {
  329. if (-1 == pSetupStringTableAddStringEx (
  330. g_OptionsTable,
  331. alias->Alias,
  332. STRTAB_CASE_INSENSITIVE,
  333. (PBYTE) &option,
  334. sizeof (POPTIONSTRUCT)
  335. )) {
  336. LOG ((LOG_ERROR, "User Options: Can't add alias %s to string table.", alias->Alias));
  337. break;
  338. }
  339. }
  340. ELSE_DEBUGMSG ((DBG_WARNING, "Could not find matching option for alias %s=%s.",alias->Alias,alias->Option));
  341. alias++;
  342. }
  343. }
  344. BOOL
  345. Cfg_InitializeUserOptions (
  346. VOID
  347. )
  348. /*++
  349. Routine Description:
  350. This routine is responsible for Initializing user configurable options for the win9xupg project.
  351. These options can come from either the command line or an unattend file. This routine also saves
  352. the user options into the Win9xUpg.UserOptions section of the answer file.
  353. The heirarchy of user options is:
  354. (1) Command line parameters.
  355. (2) Unattend file parameters.
  356. (3) Default parameters.
  357. In other words, command line parameters have precedence above unattend file parameters which in
  358. turn have precedence over the default parameters.
  359. Since this function relies on the winnt32 supplied Unattend File and Command Line parameters,
  360. it must not be called until after winnt32 has filled in the necessary variables. In practice,
  361. this means that this function cannot be called until after the first time one of win9xupg's
  362. wizard pages is activated.
  363. Arguments:
  364. None.
  365. Return Value:
  366. TRUE if user options were successfully configured, FALSE otherwise.
  367. --*/
  368. {
  369. BOOL rSuccess = TRUE;
  370. PTSTR user = NULL;
  371. PTSTR domain = NULL;
  372. PTSTR curPos = NULL;
  373. PTSTR password = NULL;
  374. TCHAR FileSystem[MAX_PATH] = TEXT("");
  375. g_OptionsTable = pSetupStringTableInitializeEx (sizeof (POPTIONSTRUCT), 0);
  376. if (!g_OptionsTable) {
  377. LOG ((LOG_ERROR, "User Options: Unable to initialize string table."));
  378. return FALSE;
  379. }
  380. //
  381. // Set default values for everything, fill in the options table.
  382. //
  383. if (!pInitUserOptions ()) {
  384. pSetupStringTableDestroy (g_OptionsTable);
  385. return FALSE;
  386. }
  387. //
  388. // Add any aliases to the table.
  389. //
  390. pInitAliases();
  391. //
  392. // Read values from the unattend file.
  393. //
  394. pReadUserOptionsFromUnattendFile ();
  395. //
  396. // Read values from the command line.
  397. //
  398. pReadUserOptionsFromCommandLine ();
  399. //
  400. // Do any post processing necessary.
  401. //
  402. //
  403. //If user wish to change filesystem type we have disable uninstall feature.
  404. //
  405. if(*g_UnattendScriptFile){
  406. GetPrivateProfileString(S_UNATTENDED,
  407. S_FILESYSTEM,
  408. FileSystem,
  409. FileSystem,
  410. sizeof(FileSystem),
  411. *g_UnattendScriptFile);
  412. if(FileSystem[0] && !StringIMatch(FileSystem, TEXT("LeaveAlone"))){
  413. LOG ((LOG_WARNING, "User Options: User require to change filesystem.Uninstall option will be disabled"));
  414. g_ConfigOptions.EnableBackup = TRISTATE_NO;
  415. }
  416. }
  417. //
  418. // Use migisol.exe only if testdlls is FALSE.
  419. //
  420. g_UseMigIsol = !g_ConfigOptions.TestDlls;
  421. #ifdef DEBUG
  422. //
  423. // if DoLog was specified, turn on the variable in debug.c.
  424. //
  425. if (g_ConfigOptions.DoLog) {
  426. SET_DOLOG();
  427. LogReInit (NULL, NULL);
  428. pCreateNetCfgIni();
  429. }
  430. #endif
  431. #ifdef PRERELEASE
  432. //
  433. // if stress was specified, turn on global.
  434. //
  435. if (g_ConfigOptions.Stress) {
  436. g_Stress = TRUE;
  437. g_ConfigOptions.AllLog = TRUE;
  438. }
  439. //
  440. // if fast was specified, turn on global.
  441. //
  442. if (g_ConfigOptions.Fast) {
  443. g_Stress = TRUE;
  444. }
  445. //
  446. // if autostress was specified, turn on stress.
  447. //
  448. if (g_ConfigOptions.AutoStress) {
  449. g_Stress = TRUE;
  450. g_ConfigOptions.AllLog = TRUE;
  451. g_ConfigOptions.Stress = TRUE;
  452. }
  453. //
  454. // If AllLog was specified, force all log output into files
  455. //
  456. if (g_ConfigOptions.AllLog) {
  457. SET_DOLOG();
  458. LogReInit (NULL, NULL);
  459. pCreateNetCfgIni();
  460. SuppressAllLogPopups (TRUE);
  461. }
  462. //
  463. // If help was specified, then dump the option list
  464. //
  465. if (g_ConfigOptions.Help) {
  466. POPTIONSTRUCT Option;
  467. PALIASSTRUCT Alias;
  468. GROWBUFFER GrowBuf = GROWBUF_INIT;
  469. TCHAR Buf[128];
  470. Option = g_OptionsList;
  471. while (Option->OptionName) {
  472. wsprintf (Buf, TEXT("/#U:%-20s"), Option->OptionName);
  473. GrowBufAppendString (&GrowBuf, Buf);
  474. Alias = g_AliasList;
  475. while (Alias->Alias) {
  476. if (StringIMatch (Option->OptionName, Alias->Option)) {
  477. wsprintf (Buf, TEXT("/#U:%-20s"), Alias->Alias);
  478. GrowBufAppendString (&GrowBuf, Buf);
  479. }
  480. Alias++;
  481. }
  482. wsprintf (Buf, TEXT("\n"));
  483. GrowBufAppendString (&GrowBuf, Buf);
  484. Option++;
  485. }
  486. MessageBox (NULL, (PCSTR) GrowBuf.Buf, TEXT("Help"), MB_OK);
  487. FreeGrowBuffer (&GrowBuf);
  488. return FALSE;
  489. }
  490. #endif
  491. //
  492. // Save user domain information into memdb.
  493. //
  494. if (g_ConfigOptions.UserDomain && *g_ConfigOptions.UserDomain) {
  495. curPos = g_ConfigOptions.UserDomain;
  496. while (curPos) {
  497. user = _tcschr(curPos,TEXT(','));
  498. if (user) {
  499. *user = 0;
  500. user = _tcsinc(user);
  501. domain = curPos;
  502. curPos = _tcschr(user,TEXT(','));
  503. if (curPos) {
  504. *curPos = 0;
  505. curPos = _tcsinc(curPos);
  506. }
  507. if (!MemDbSetValueEx(
  508. MEMDB_CATEGORY_KNOWNDOMAIN,
  509. domain,
  510. user,
  511. NULL,
  512. 0,
  513. NULL
  514. )) {
  515. ERROR_NONCRITICAL;
  516. LOG((LOG_ERROR,"Error saving domain information into memdb. Domain: %s User: %s",domain,user));
  517. }
  518. } else {
  519. ERROR_NONCRITICAL;
  520. LOG((LOG_ERROR,"Error in Unattend file for UserDomains. Domain specified but no User. Domain: %s",curPos));
  521. curPos = NULL;
  522. }
  523. }
  524. }
  525. //
  526. // If UserPassword was specified, then add the information into memdb.
  527. //
  528. if (g_ConfigOptions.UserPassword && *g_ConfigOptions.UserPassword) {
  529. curPos = g_ConfigOptions.UserPassword;
  530. while (curPos) {
  531. password = _tcschr(curPos,TEXT(','));
  532. if (password) {
  533. *password = 0;
  534. password = _tcsinc(password);
  535. user = curPos;
  536. curPos = _tcschr(password,TEXT(','));
  537. if (curPos) {
  538. *curPos = 0;
  539. curPos = _tcsinc(curPos);
  540. }
  541. if (!MemDbSetValueEx(
  542. MEMDB_CATEGORY_USERPASSWORD,
  543. user,
  544. password,
  545. NULL,
  546. g_ConfigOptions.EncryptedUserPasswords ? PASSWORD_ATTR_ENCRYPTED : 0,
  547. NULL
  548. )) {
  549. ERROR_NONCRITICAL;
  550. LOG((LOG_ERROR,"Error saving password information into memdb. Password: %s User: %s",password,user));
  551. }
  552. } else {
  553. ERROR_NONCRITICAL;
  554. LOG((LOG_ERROR,"Error in Unattend file for UserDomains. Password specified but no User. Password: %s",curPos));
  555. curPos = NULL;
  556. }
  557. }
  558. }
  559. //
  560. // If a default password was set, save that away now.
  561. //
  562. if (g_ConfigOptions.DefaultPassword && *g_ConfigOptions.DefaultPassword) {
  563. if (!MemDbSetValueEx (
  564. MEMDB_CATEGORY_USERPASSWORD,
  565. S_DEFAULTUSER,
  566. g_ConfigOptions.DefaultPassword,
  567. NULL,
  568. g_ConfigOptions.EncryptedUserPasswords ? PASSWORD_ATTR_ENCRYPTED : 0,
  569. NULL
  570. )) {
  571. ERROR_NONCRITICAL;
  572. LOG((LOG_ERROR, "Error saving password information into memdb. Password: %s (Default)", password));
  573. }
  574. }
  575. //
  576. // We're done with our string table.
  577. //
  578. pSetupStringTableDestroy (g_OptionsTable);
  579. return rSuccess;
  580. }
  581. //
  582. // Option Handling Functions.
  583. //
  584. BOOL
  585. pHandleBoolOption (
  586. IN PTSTR Name,
  587. IN PVOID * OptionVar,
  588. IN PTSTR Value
  589. )
  590. {
  591. BOOL rSuccess = TRUE;
  592. PBOOL option = (PBOOL) OptionVar;
  593. MYASSERT(Name && OptionVar);
  594. //
  595. // We treat a NULL value as equivelant to TRUE.
  596. // /#U:DOLOG on the command line is equivelant to
  597. // /#U:DOLOG=YES
  598. //
  599. if (!Value) {
  600. Value = S_YES;
  601. }
  602. if (StringIMatch (Value, S_YES) ||
  603. StringIMatch (Value, S_ONE) ||
  604. StringIMatch (Value, TEXT("TRUE"))) {
  605. *option = TRUE;
  606. }
  607. else {
  608. *option = FALSE;
  609. }
  610. //
  611. // Save the data away to buildinf.
  612. //
  613. WriteInfKey (S_WIN9XUPGUSEROPTIONS, Name, *option ? S_YES : S_NO);
  614. return rSuccess;
  615. }
  616. BOOL
  617. pHandleIntOption (
  618. IN PTSTR Name,
  619. IN PVOID * OptionVar,
  620. IN PTSTR Value
  621. )
  622. {
  623. BOOL rSuccess = TRUE;
  624. PINT option = (PINT) OptionVar;
  625. MYASSERT(Name && OptionVar);
  626. //
  627. // We treat a NULL value as equivelant to 0.
  628. // /#U:DOLOG on the command line is equivelant to
  629. // /#U:DOLOG=0
  630. //
  631. if (!Value) {
  632. Value = TEXT("0");
  633. }
  634. *option = _ttoi((PCTSTR)Value);
  635. //
  636. // Save the data away to buildinf.
  637. //
  638. WriteInfKey (S_WIN9XUPGUSEROPTIONS, Name, Value);
  639. return rSuccess;
  640. }
  641. BOOL
  642. pHandleTriStateOption (
  643. IN PTSTR Name,
  644. IN PVOID * OptionVar,
  645. IN PTSTR Value
  646. )
  647. {
  648. BOOL rSuccess = TRUE;
  649. PINT option = (PINT) OptionVar;
  650. MYASSERT(Name && OptionVar);
  651. //
  652. // We treat a NULL value as equivelant to AUTO.
  653. // /#U:DOLOG on the command line is equivelant to
  654. // /#U:DOLOG=AUTO
  655. //
  656. if (!Value) {
  657. Value = S_AUTO;
  658. }
  659. if (StringIMatch (Value, S_YES) ||
  660. StringIMatch (Value, S_ONE) ||
  661. StringIMatch (Value, S_TRUE) ||
  662. StringIMatch (Value, S_REQUIRED)) {
  663. *option = TRISTATE_YES;
  664. }
  665. else {
  666. if(StringIMatch (Value, S_NO) ||
  667. StringIMatch (Value, S_STR_FALSE) ||
  668. StringIMatch (Value, S_ZERO)) {
  669. *option = TRISTATE_NO;
  670. }
  671. else {
  672. *option = TRISTATE_AUTO;
  673. }
  674. }
  675. //
  676. // Save the data away to buildinf.
  677. //
  678. WriteInfKey (
  679. S_WIN9XUPGUSEROPTIONS,
  680. Name,
  681. (*option == TRISTATE_AUTO)? S_AUTO:
  682. (*option == TRISTATE_YES)? S_YES : S_NO);
  683. return rSuccess;
  684. }
  685. BOOL
  686. pHandleStringOption (
  687. IN PTSTR Name,
  688. IN PVOID * OptionVar,
  689. IN PTSTR Value OPTIONAL
  690. )
  691. {
  692. PTSTR * option = (PTSTR *) OptionVar;
  693. MYASSERT(Name && OptionVar);
  694. if (!Value) {
  695. if (!*option) {
  696. *option = S_EMPTY;
  697. }
  698. WriteInfKey (S_WIN9XUPGUSEROPTIONS, Name, NULL);
  699. return TRUE;
  700. }
  701. *option = PoolMemDuplicateString (g_UserOptionPool, Value);
  702. //
  703. // save the data into winnt.sif.
  704. //
  705. WriteInfKey (S_WIN9XUPGUSEROPTIONS, Name, *option);
  706. return TRUE;
  707. }
  708. BOOL
  709. pHandleMultiSzOption (
  710. IN PTSTR Name,
  711. IN PVOID * OptionVar,
  712. IN PTSTR Value
  713. )
  714. {
  715. BOOL rSuccess = TRUE;
  716. PTSTR * option = (PTSTR *) OptionVar;
  717. PTSTR end;
  718. PTSTR start;
  719. PTSTR temp;
  720. CHARTYPE ch;
  721. PTSTR p;
  722. GROWBUFFER growBuf = GROWBUF_INIT;
  723. UINT offset;
  724. MULTISZ_ENUM e;
  725. MYASSERT(Name && OptionVar);
  726. end = *option;
  727. if (end) {
  728. start = end;
  729. while (*end) {
  730. end = GetEndOfString (end) + 1;
  731. }
  732. end = _tcsinc (end);
  733. temp = (PTSTR) GrowBuffer (&growBuf, end - start);
  734. MYASSERT (temp);
  735. CopyMemory (temp, start, end - start);
  736. growBuf.End -= sizeof (TCHAR);
  737. }
  738. if (Value) {
  739. //
  740. // Parse Value into one or more strings, separated at the commas.
  741. //
  742. // NOTE: We do not support any escaping to get a real comma in one
  743. // of these strings
  744. //
  745. temp = AllocText (CharCount (Value) + 1);
  746. end = NULL;
  747. start = NULL;
  748. p = Value;
  749. do {
  750. ch = _tcsnextc (p);
  751. if (ch && _istspace (ch)) {
  752. if (!end) {
  753. end = p;
  754. }
  755. } else if (ch && ch != TEXT(',')) {
  756. if (!start) {
  757. start = p;
  758. }
  759. end = NULL;
  760. } else {
  761. if (!end) {
  762. end = p;
  763. }
  764. if (start) {
  765. StringCopyAB (temp, start, end);
  766. } else {
  767. *temp = 0;
  768. }
  769. MultiSzAppend (&growBuf, temp);
  770. FreeText (temp);
  771. end = NULL;
  772. start = NULL;
  773. }
  774. p = _tcsinc (p);
  775. } while (ch);
  776. }
  777. MultiSzAppend (&growBuf, S_EMPTY);
  778. *option = PoolMemDuplicateMultiSz (g_UserOptionPool, (PCTSTR) growBuf.Buf);
  779. FreeGrowBuffer (&growBuf);
  780. offset = 0;
  781. if (EnumFirstMultiSz (&e, *option)) {
  782. do {
  783. offset = WriteInfKeyEx (S_WIN9XUPGUSEROPTIONS, Name, e.CurrentString, offset, FALSE);
  784. } while (EnumNextMultiSz (&e));
  785. }
  786. return rSuccess;
  787. }
  788. BOOL
  789. pHandleSaveReportTo (
  790. IN PTSTR Name,
  791. IN PVOID * OptionVar,
  792. IN PTSTR Value
  793. )
  794. {
  795. BOOL rSuccess = TRUE;
  796. PTSTR * option = (PTSTR *) OptionVar;
  797. TCHAR computerName[MAX_COMPUTER_NAME];
  798. PTSTR newPath;
  799. PTSTR envVars[4]={NULL,NULL,NULL,NULL};
  800. UINT computerNameLength;
  801. MYASSERT (Name && OptionVar);
  802. rSuccess = pHandleStringOption (Name, OptionVar, Value);
  803. computerNameLength = MAX_COMPUTER_NAME;
  804. if (!GetComputerName (computerName, &computerNameLength)) {
  805. DEBUGMSG ((DBG_WARNING, "InitUserOptions: Could not retrieve computer name."));
  806. *computerName = 0;
  807. }
  808. if (*computerName) {
  809. envVars[0] = S_COMPUTERNAME;
  810. envVars[1] = computerName;
  811. }
  812. newPath = ExpandEnvironmentTextEx (*option, envVars);
  813. *option = PoolMemDuplicateString (g_UserOptionPool, newPath);
  814. FreeText (newPath);
  815. if (*option) {
  816. if (ERROR_SUCCESS != MakeSurePathExists (*option, FALSE)) {
  817. LOG ((LOG_ERROR, (PCSTR)MSG_ERROR_CREATING_SAVETO_DIRECTORY, g_ConfigOptions.SaveReportTo));
  818. *option = FALSE;
  819. }
  820. }
  821. return rSuccess;
  822. }
  823. BOOL
  824. pHandleBoot16 (
  825. IN PTSTR Name,
  826. IN PVOID * OptionVar,
  827. IN PTSTR Value
  828. )
  829. {
  830. BOOL rSuccess = TRUE;
  831. PTSTR * option = (PTSTR *) OptionVar;
  832. if (!Value ||
  833. StringIMatch (Value, S_NO) ||
  834. StringIMatch (Value, S_ZERO)) {
  835. *option = S_NO;
  836. *g_Boot16 = BOOT16_NO;
  837. }
  838. else if (Value &&
  839. (StringIMatch (Value, S_BOOT16_UNSPECIFIED) ||
  840. StringIMatch (Value, S_BOOT16_AUTOMATIC))) {
  841. *option = S_BOOT16_AUTOMATIC;
  842. *g_Boot16 = BOOT16_AUTOMATIC;
  843. }
  844. else {
  845. *g_Boot16 = BOOT16_YES;
  846. *option = S_YES;
  847. }
  848. WriteInfKey (S_WIN9XUPGUSEROPTIONS, Name, *option);
  849. return rSuccess;
  850. }
  851. BOOL
  852. pGetDefaultPassword (
  853. IN PTSTR Name,
  854. IN PVOID * OptionVar,
  855. IN PTSTR Value
  856. )
  857. {
  858. PTSTR * option = (PTSTR *) OptionVar;
  859. MYASSERT (Name && OptionVar);
  860. //
  861. // for Personal set an empty user password by default
  862. //
  863. if (g_PersonalSKU && !Value) {
  864. Value = TEXT("*");
  865. }
  866. return pHandleStringOption (Name, OptionVar, Value);
  867. }