Leaked source code of windows server 2003
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.

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