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.

2564 lines
79 KiB

  1. //--------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1999 - 2000.
  5. //
  6. //
  7. // File: loadsys
  8. //
  9. // Contents: Load system settings.
  10. //
  11. //---------------------------------------------------------------
  12. #include "loadhead.cxx"
  13. #pragma hdrstop
  14. #include <common.hxx>
  15. #include <stdlib.h>
  16. #include <objerror.h>
  17. #include <loadstate.hxx>
  18. #include <bothchar.hxx>
  19. #include <winnetwk.h>
  20. #include <lmshare.h>
  21. #include <lmaccess.h>
  22. #include <winspool.h>
  23. #include <winuserp.h> // in \nt\private\inc
  24. #include <wingdip.h> // in \nt\private\inc
  25. #include <ntlsa.h> // for domain/workgroup membership
  26. #include <ntexapi.h> // for NtSetDefaultLocale
  27. #include <devguid.h> // for modem device class
  28. #include <ras.h>
  29. #include <raserror.h>
  30. #include <loadras.hxx> // State Migration private RAS Phonebook APIs
  31. const TCHAR NETSHARES_SECTION[] = TEXT("NetShares");
  32. const TCHAR PRINTERS_SECTION[] = TEXT("Printers");
  33. const TCHAR PRINTER_DRIVER_MAP[] = TEXT("Printer Driver Mapping");
  34. const TCHAR RAS_SECTION[] = TEXT("RAS");
  35. const TCHAR ACCESS_SECTION[] = TEXT("Accessibility");
  36. const TCHAR DESKTOP_SECTION[] = TEXT("Desktop");
  37. const TCHAR KEYBOARDLAYOUT_MAP[] = TEXT("Keyboard.Layout.Mappings");
  38. const TCHAR REGKEY_PRELOAD[] = TEXT("Keyboard Layout\\Preload");
  39. const TCHAR REGKEY_SUBSTITUTES[] = TEXT("Keyboard Layout\\Substitutes");
  40. const TCHAR REGKEY_INTL[] = TEXT("Control Panel\\International");
  41. const TCHAR SCHED_PARAMS[] = TEXT(" /s /p");
  42. const DWORD INTL_NT4 = 0x200; // platform ID from intl.inf
  43. const DWORD INTL_95 = 0x001; // platform ID from intl.inf
  44. const DWORD INTL_98 = 0x002; // platform ID from intl.inf
  45. const int SIZE_128 = 128; // for user locale strings
  46. // Types and defines
  47. #define IS_IME_KBDLAYOUT(hkl) ((HIWORD((ULONG_PTR)(hkl)) & 0xf000) == 0xe000)
  48. #define ChkErr(s) if ((dwErr = (s)) != ERROR_SUCCESS) goto Err;
  49. #define ChkBoolErr(s) if ((success = (s)) == FALSE) { \
  50. dwErr = GetLastError(); \
  51. goto Err;\
  52. }
  53. #define PRIVATE_RAS // Define this to use our private
  54. // RasSetEntryProperties implementation.
  55. //
  56. // private structure needed by ConvertRecentDocsMRU
  57. //
  58. typedef struct {
  59. // Link structure
  60. WORD wSize;
  61. //ITEMIDLIST idl; // variable-length struct
  62. // String, plus three bytes appended to struct
  63. } LINKSTRUCT, *PLINKSTRUCT;
  64. //
  65. // Win95 uses a mix of LOGFONTA and a weird 16-bit LOGFONT
  66. // structure that uses SHORTs instead of LONGs.
  67. //
  68. typedef struct {
  69. SHORT lfHeight;
  70. SHORT lfWidth;
  71. SHORT lfEscapement;
  72. SHORT lfOrientation;
  73. SHORT lfWeight;
  74. BYTE lfItalic;
  75. BYTE lfUnderline;
  76. BYTE lfStrikeOut;
  77. BYTE lfCharSet;
  78. BYTE lfOutPrecision;
  79. BYTE lfClipPrecision;
  80. BYTE lfQuality;
  81. BYTE lfPitchAndFamily;
  82. char lfFaceName[LF_FACESIZE];
  83. } SHORT_LOGFONT, *PSHORT_LOGFONT;
  84. #define COLOR_MAX_V1 25
  85. #define COLOR_MAX_V3 25
  86. #define COLOR_MAX_V4 29
  87. #define COLOR_MAX_NT 29 // this is a modified version 2 format, similar to 4
  88. //
  89. // NT uses only UNICODE structures, and pads the members
  90. // to 32-bit boundaries.
  91. //
  92. typedef struct {
  93. SHORT version; // 2 for NT UNICODE
  94. WORD wDummy; // for alignment
  95. NONCLIENTMETRICSW ncm;
  96. LOGFONTW lfIconTitle;
  97. COLORREF rgb[COLOR_MAX_NT];
  98. } SCHEMEDATA_NT, *PSCHEMEDATA_NT;
  99. //
  100. // Win95 uses NONCLIENTMETRICSA which has LOGFONTA members,
  101. // but it uses a 16-bit LOGFONT as well.
  102. //
  103. #pragma pack(push)
  104. #pragma pack(1)
  105. typedef struct {
  106. SHORT version; // 1 for Win95 ANSI
  107. NONCLIENTMETRICSA ncm;
  108. SHORT_LOGFONT lfIconTitle;
  109. COLORREF rgb[COLOR_MAX_V1];
  110. } SCHEMEDATA_V1, *PSCHEMEDATA_V1;
  111. typedef struct {
  112. SHORT version; // 1 for Win95 ANSI
  113. NONCLIENTMETRICSA ncm;
  114. SHORT_LOGFONT lfIconTitle;
  115. COLORREF rgb[COLOR_MAX_V4];
  116. } SCHEMEDATA_V1A, *PSCHEMEDATA_V1A;
  117. typedef struct {
  118. SHORT version; // 3 for Win98 ANSI, 4 for portable format
  119. WORD Dummy;
  120. NONCLIENTMETRICSA ncm;
  121. LOGFONTA lfIconTitle;
  122. COLORREF rgb[COLOR_MAX_V3];
  123. } SCHEMEDATA_V3, *PSCHEMEDATA_V3;
  124. typedef struct {
  125. SHORT version; // 4 for Win32 format (whatever that means)
  126. WORD Dummy;
  127. NONCLIENTMETRICSA ncm;
  128. LOGFONTA lfIconTitle;
  129. COLORREF rgb[COLOR_MAX_V4];
  130. } SCHEMEDATA_V4, *PSCHEMEDATA_V4;
  131. #pragma pack(pop)
  132. typedef struct _APPLET_TIME_ZONE_INFORMATION
  133. {
  134. LONG Bias;
  135. LONG StandardBias;
  136. LONG DaylightBias;
  137. SYSTEMTIME StandardDate;
  138. SYSTEMTIME DaylightDate;
  139. } APPLET_TIME_ZONE_INFORMATION;
  140. // RAS api functions
  141. typedef DWORD
  142. (*MRasSetEntryDialParams)(
  143. IN LPCTSTR lpszPhonebook,
  144. IN LPRASDIALPARAMS lprasdialparams,
  145. IN BOOL fRemovePassword);
  146. typedef DWORD
  147. (*MRasGetEntryProperties)(
  148. IN LPCTSTR lpszPhonebook,
  149. IN LPCTSTR lpszEntry,
  150. OUT LPRASENTRYW lpRasEntry,
  151. OUT LPDWORD lpdwEntryInfoSize,
  152. OUT LPBYTE lpbDeviceInfo,
  153. OUT LPDWORD lpdwDeviceInfoSize);
  154. #ifdef PRIVATE_RAS
  155. typedef DWORD
  156. (*MWinState_RasSetEntryProperties)(
  157. IN LPCWSTR lpszPhonebook,
  158. IN LPCWSTR lpszEntry,
  159. IN LPRASENTRYW lpRasEntry,
  160. IN DWORD dwcbRasEntry,
  161. IN LPBYTE lpbDeviceConfig,
  162. IN DWORD dwcbDeviceConfig);
  163. #else
  164. typedef DWORD
  165. (*MRasSetEntryProperties)(
  166. IN LPCTSTR lpszPhonebook,
  167. IN LPCTSTR lpszEntry,
  168. IN LPRASENTRY lpRasEntry,
  169. IN DWORD dwEntryInfoSize,
  170. IN LPBYTE lpbDeviceInfo,
  171. IN DWORD dwDeviceInfoSize);
  172. #endif
  173. // Statics
  174. #ifdef PRIVATE_RAS
  175. static MWinState_RasSetEntryProperties GWinState_RasSetEntryProperties = NULL;
  176. #else
  177. static MRasSetEntryProperties GRasSetEntryProperties = NULL;
  178. #endif
  179. static MRasSetEntryDialParams GRasSetEntryDialParams = NULL;
  180. static MRasGetEntryProperties GRasGetEntryProperties = NULL;
  181. //+---------------------------------------------------------------------------
  182. //
  183. // Function: InitializeRasApi
  184. //
  185. // Synopsis: Loads rasapi32.dll, if it exists
  186. //
  187. // Arguments: none
  188. //
  189. // Returns: Appropriate status code
  190. //
  191. // History: 24-Feb-00 Jay Thaler Created
  192. //
  193. //----------------------------------------------------------------------------
  194. DWORD InitializeRasApi()
  195. {
  196. DWORD result = ERROR_SUCCESS;
  197. HINSTANCE rasdll;
  198. HINSTANCE loadrasdll; // State Mig. RAS Wrapper
  199. //
  200. // Load rasapi32.dll
  201. // If this fails, RAS isn't installed and we won't migrate RAS conectoids
  202. //
  203. rasdll = LoadLibraryA( "rasapi32.dll" );
  204. if (rasdll == NULL)
  205. {
  206. result = GetLastError();
  207. if (Verbose && DebugOutput)
  208. {
  209. Win32Printf(STDERR, "Warning: rasapi32.dll not loaded: %d\r\n", result);
  210. }
  211. goto cleanup;
  212. }
  213. GRasSetEntryDialParams = (MRasSetEntryDialParams)GetProcAddress(rasdll, "RasSetEntryDialParamsW");
  214. if (GRasSetEntryDialParams == NULL)
  215. {
  216. result = GetLastError();
  217. goto cleanup;
  218. }
  219. #ifndef PRIVATE_RAS
  220. GRasSetEntryProperties = (MRasSetEntryProperties)GetProcAddress(rasdll, "RasSetEntryPropertiesW");
  221. if (GRasSetEntryProperties == NULL)
  222. {
  223. result = GetLastError();
  224. goto cleanup;
  225. }
  226. #else
  227. //
  228. // Load the private wrapper for RAS APIs
  229. //
  230. loadrasdll = LoadLibraryA( "loadras.dll" );
  231. if (loadrasdll == NULL)
  232. {
  233. result = GetLastError();
  234. if (Verbose && DebugOutput)
  235. {
  236. Win32Printf(STDERR, "Warning: loadras.dll not loaded: %d\r\n", result);
  237. }
  238. goto cleanup;
  239. }
  240. GWinState_RasSetEntryProperties =
  241. (MWinState_RasSetEntryProperties)GetProcAddress(loadrasdll, "WinState_RasSetEntryPropertiesW");
  242. if (GWinState_RasSetEntryProperties == NULL)
  243. {
  244. result = GetLastError();
  245. goto cleanup;
  246. }
  247. #endif
  248. cleanup:
  249. if (result != ERROR_SUCCESS)
  250. {
  251. #ifdef PRIVATE_RAS
  252. GWinState_RasSetEntryProperties = NULL;
  253. #else
  254. GRasSetEntryProperties = NULL;
  255. #endif
  256. GRasSetEntryDialParams = NULL;
  257. }
  258. return result;
  259. }
  260. //+---------------------------------------------------------------------------
  261. //
  262. // Function: GetInfField
  263. //
  264. // Synopsis: returns an allocated string for current line field #N
  265. //
  266. // Arguments: [ppBuffer] -- output buffer
  267. // [pContext] -- INF file context
  268. // [nArg] -- argument field number
  269. //
  270. // Returns: Appropriate status code
  271. //
  272. // History: 20-Sep-99 HenryLee Created
  273. //
  274. //----------------------------------------------------------------------------
  275. DWORD GetInfField (TCHAR **ppBuffer, INFCONTEXT *pContext, DWORD nArg)
  276. {
  277. ULONG len = 0;
  278. DWORD dwErr = ERROR_SUCCESS;
  279. TCHAR *buffer;
  280. *ppBuffer = NULL;
  281. if (!SetupGetStringField ( pContext, nArg, NULL, 0, &len ))
  282. return ERROR_BAD_FORMAT;
  283. // Allocate a buffer. Some callers need an extra char for processing
  284. buffer = (TCHAR *) malloc( (len+1)*sizeof(TCHAR) );
  285. if (buffer == NULL)
  286. {
  287. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  288. }
  289. else
  290. {
  291. if (!SetupGetStringField( pContext, nArg, buffer, len, &len ))
  292. {
  293. free( buffer );
  294. dwErr = ERROR_BAD_FORMAT;
  295. }
  296. else *ppBuffer = buffer;
  297. }
  298. return dwErr;
  299. }
  300. //+---------------------------------------------------------------------------
  301. //
  302. // Function: LogFormatError
  303. //
  304. // Synopsis: logs error message in current locale
  305. //
  306. // Arguments:
  307. //
  308. // Returns: Appropriate status code
  309. //
  310. // History: 20-Sep-99 HenryLee Created
  311. //
  312. //----------------------------------------------------------------------------
  313. DWORD LogFormatError (DWORD dwErr)
  314. {
  315. DWORD dwRet = ERROR_SUCCESS;
  316. TCHAR *pcs = NULL;
  317. if (0 != FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
  318. FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL,
  319. dwErr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  320. (TCHAR*) &pcs, 0, NULL))
  321. {
  322. dwRet = Win32Printf (LogFile, "%ws\r\n", pcs);
  323. LocalFree (pcs);
  324. }
  325. else dwRet = GetLastError();
  326. return dwRet;
  327. }
  328. //+---------------------------------------------------------------------------
  329. //
  330. // Function: IsDefaultShare
  331. //
  332. // Synopsis: check if share name is a known system default share
  333. //
  334. // Arguments:
  335. //
  336. // Returns: Appropriate status code
  337. //
  338. // History: 20-Sep-99 HenryLee Created
  339. //
  340. //----------------------------------------------------------------------------
  341. BOOL IsDefaultShare (TCHAR *buffer)
  342. {
  343. ULONG ul = lstrlen(buffer);
  344. if (buffer[ul - 1] == '$')
  345. {
  346. if (lstrcmp (buffer, TEXT("IPC$")) == 0) return TRUE;
  347. if (lstrcmp (buffer, TEXT("ADMIN$")) == 0) return TRUE;
  348. if (ul == 2 && IsCharAlpha (buffer[0])) return TRUE;
  349. }
  350. return FALSE;
  351. }
  352. //+---------------------------------------------------------------------------
  353. //
  354. // Function: LoadNetShares
  355. //
  356. // Synopsis: loads network share settings
  357. //
  358. // Arguments:
  359. //
  360. // Returns: Appropriate status code
  361. //
  362. // History: 20-Sep-99 HenryLee Created
  363. //
  364. // NOTES: This code could be updated to do the following:
  365. // 1. Get the correct disk type from the field instead of
  366. // using STYPE_DISKTREE.
  367. // 2. Store (and retrieve) the correct max user count
  368. // 3. Handle custom access permissions
  369. //
  370. //----------------------------------------------------------------------------
  371. DWORD LoadNetShares ()
  372. {
  373. DWORD dwErr = ERROR_SUCCESS;
  374. INFCONTEXT context;
  375. NETRESOURCE nr;
  376. BOOL success;
  377. TCHAR * buffer = NULL;
  378. TCHAR * buffer2 = NULL;
  379. success = SetupFindFirstLine(InputInf, NETSHARES_SECTION, NULL, &context);
  380. if (!success)
  381. return ERROR_SUCCESS; // line not found
  382. do
  383. {
  384. BOOL fPersist = FALSE;
  385. BOOL bIgnore = FALSE;
  386. ZeroMemory (&nr, sizeof(nr));
  387. // loop through all the network shares and connect to them
  388. dwErr = GetInfField (&buffer, &context, 1);
  389. if (dwErr != ERROR_SUCCESS)
  390. {
  391. Win32Printf (LogFile, "Missing share name in [%ws]\r\n",
  392. NETSHARES_SECTION);
  393. break;
  394. }
  395. nr.dwType = RESOURCETYPE_DISK;
  396. nr.lpLocalName = buffer;
  397. dwErr = GetInfField (&buffer2, &context, 2);
  398. if (dwErr != ERROR_SUCCESS)
  399. {
  400. Win32Printf (LogFile, "Missing remote name in [%ws]\r\n",
  401. NETSHARES_SECTION);
  402. free (buffer);
  403. break;
  404. }
  405. nr.lpRemoteName = buffer2;
  406. if (buffer2[0] != L'\0' && buffer2[0] == L'\\' && buffer2[1] == L'\\')
  407. {
  408. TCHAR *buffer3 = NULL;
  409. if (ERROR_SUCCESS == GetInfField (&buffer3, &context, 3))
  410. {
  411. if (lstrcmp (buffer3, TEXT("persist")) == 0)
  412. fPersist = TRUE;
  413. free (buffer3);
  414. }
  415. dwErr = WNetAddConnection2 (&nr, NULL, NULL,
  416. fPersist ? CONNECT_UPDATE_PROFILE : 0);
  417. }
  418. else
  419. {
  420. TCHAR *buffer3 = NULL;
  421. TCHAR *buffer4 = NULL;
  422. SHARE_INFO_2 si2;
  423. DWORD dwPerm = ACCESS_READ; // default access
  424. if (!IsDefaultShare(buffer)) // ignore system shares
  425. {
  426. dwErr = GetInfField (&buffer3, &context, 3);
  427. if (dwErr == ERROR_SUCCESS)
  428. {
  429. dwPerm = _wtoi (buffer3); // share permission bits
  430. }
  431. dwErr = GetInfField (&buffer4, &context, 4);
  432. ZeroMemory (&si2, sizeof(si2));
  433. si2.shi2_netname = buffer;
  434. si2.shi2_type = STYPE_DISKTREE; // should get type from field
  435. si2.shi2_remark = buffer4;
  436. si2.shi2_permissions = dwPerm;
  437. if (lstrlen(buffer2) == 2 && buffer2[1] == ':')
  438. lstrcat ((TCHAR*)buffer2, TEXT("\\"));
  439. si2.shi2_path = buffer2;
  440. si2.shi2_max_uses = SHI_USES_UNLIMITED; // should get number
  441. // should handle custom access permissions here
  442. dwErr = NetShareAdd (NULL, 2, (BYTE *) &si2, NULL);
  443. if (buffer3 != NULL)
  444. free (buffer3);
  445. if (buffer4 != NULL)
  446. free (buffer4);
  447. }
  448. else bIgnore = TRUE;
  449. }
  450. if (dwErr != ERROR_SUCCESS)
  451. {
  452. LogFormatError (dwErr); // log error and keep on going
  453. dwErr = ERROR_SUCCESS;
  454. }
  455. else // log that the share was successfully added
  456. {
  457. Win32Printf (LogFile, "NetShare %ws %ws %ws\r\n", buffer, buffer2,
  458. bIgnore ? TEXT("not processed") : TEXT("added"));
  459. }
  460. free (buffer);
  461. free (buffer2);
  462. if (dwErr != ERROR_SUCCESS)
  463. break;
  464. // Advance to the next line.
  465. success = SetupFindNextLine( &context, &context );
  466. } while (success);
  467. return dwErr;
  468. }
  469. //+---------------------------------------------------------------------------
  470. //
  471. // Function: TranslatePrinterDriver
  472. //
  473. // Synopsis: converts Win9x printer driver names to NT driver names
  474. //
  475. // Arguments: [pcs9x] -- Win9x printer driver name
  476. // [pcsNT] -- NT printer driver name
  477. //
  478. // Returns: Appropriate status code
  479. //
  480. // History: 20-Sep-99 HenryLee Created
  481. //
  482. //----------------------------------------------------------------------------
  483. DWORD TranslatePrinterDriver (WCHAR *pcs9x, WCHAR **ppcsNT)
  484. {
  485. DWORD dwErr = ERROR_SUCCESS;
  486. HINF hInf;
  487. INFCONTEXT InfContext;
  488. *ppcsNT = NULL;
  489. //
  490. // See in prtupg9x.inf to see if the driver has a different name on NT
  491. //
  492. if ( SetupFindFirstLine(InputInf,
  493. PRINTER_DRIVER_MAP,
  494. pcs9x,
  495. &InfContext) )
  496. {
  497. dwErr = GetInfField (ppcsNT, &InfContext, 1);
  498. }
  499. return dwErr;
  500. }
  501. //+---------------------------------------------------------------------------
  502. //
  503. // Function: LoadPrinters
  504. //
  505. // Synopsis: loads printers settings
  506. //
  507. // Arguments:
  508. //
  509. // Returns: Appropriate status code
  510. //
  511. // History: 20-Sep-99 HenryLee Created
  512. //
  513. //----------------------------------------------------------------------------
  514. DWORD LoadPrinters ()
  515. {
  516. DWORD dwErr = ERROR_SUCCESS;
  517. INFCONTEXT context;
  518. BOOL success;
  519. TCHAR * buffer = NULL;
  520. DWORD dwReturnUp = ERROR_SUCCESS;
  521. success = SetupFindFirstLine(InputInf, PRINTERS_SECTION, NULL, &context);
  522. if (!success)
  523. return ERROR_SUCCESS; // line not found
  524. do
  525. {
  526. dwErr = GetInfField (&buffer, &context, 1);
  527. if (dwErr != ERROR_SUCCESS)
  528. {
  529. Win32PrintfResource (LogFile, IDS_PRINTER_MISSINGNAME,
  530. PRINTERS_SECTION);
  531. break;
  532. }
  533. if (!AddPrinterConnection (buffer))
  534. {
  535. dwErr = GetLastError();
  536. LogFormatError (dwErr); // log error and keep on going
  537. dwReturnUp = dwErr;
  538. dwErr = ERROR_SUCCESS;
  539. }
  540. else
  541. {
  542. Win32PrintfResource (LogFile, IDS_PRINTER_MIGRATED,
  543. buffer, buffer);
  544. }
  545. free (buffer); buffer = NULL;
  546. // Advance to the next line.
  547. success = SetupFindNextLine( &context, &context );
  548. }
  549. while (success);
  550. if (buffer) free (buffer);
  551. return dwReturnUp;
  552. }
  553. //+---------------------------------------------------------------------------
  554. //
  555. // Function: GetOSMajorID
  556. //
  557. // Synopsis: translate GetVersion IDs to INTL IDs
  558. //
  559. // Arguments:
  560. //
  561. // Returns: Appropriate status code
  562. //
  563. // History: 20-Sep-99 HenryLee Created
  564. //
  565. //----------------------------------------------------------------------------
  566. DWORD GetOSMajorID ()
  567. {
  568. if (SourceVersion & 0x80000000)
  569. {
  570. if ((SourceVersion & 0xFFFF) == 0x004)
  571. return INTL_NT4;
  572. }
  573. else if ((SourceVersion & 0xFFFF) == 0xA04)
  574. return INTL_98;
  575. else if ((SourceVersion & 0xFFFF) == 0x004)
  576. return INTL_95;
  577. return 0;
  578. }
  579. //+---------------------------------------------------------------------------
  580. //
  581. // Function: IsInExcludeList
  582. //
  583. // Synopsis: check if langid is in the exclude list to block migration
  584. //
  585. // Arguments:
  586. //
  587. // Returns: Appropriate status code
  588. //
  589. // History: 20-Sep-99 HenryLee Created
  590. //
  591. //----------------------------------------------------------------------------
  592. BOOL IsInExcludeList( HINF Inf, LANGID LangID)
  593. {
  594. TCHAR LangIDStr[9];
  595. TCHAR *Field;
  596. INFCONTEXT InfContext;
  597. int iOSID;
  598. int iLangID;
  599. wsprintf(LangIDStr,TEXT("0000%04X"),LangID);
  600. if (SetupFindFirstLine( Inf,
  601. TEXT("ExcludeSourceLocale"),
  602. LangIDStr,
  603. &InfContext ))
  604. {
  605. do {
  606. //
  607. // if in excluded field, this is not what we want
  608. //
  609. if (ERROR_SUCCESS == SetupGetIntField (&InfContext, 0, &iLangID) &&
  610. (iLangID == LangID))
  611. {
  612. //
  613. // if it is in major version list, we also got what we want
  614. //
  615. if (ERROR_SUCCESS == SetupGetIntField (&InfContext, 1, &iOSID))
  616. {
  617. if (iOSID & GetOSMajorID())
  618. {
  619. return TRUE;
  620. }
  621. }
  622. }
  623. } while ( SetupFindNextLine(&InfContext, &InfContext));
  624. }
  625. return FALSE;
  626. }
  627. //+---------------------------------------------------------------------------
  628. //
  629. // Function: CheckLanguageVersion
  630. //
  631. // Synopsis: verifies that source and target languages allow migration
  632. //
  633. // Arguments:
  634. //
  635. // Returns: Appropriate status code
  636. //
  637. // History: 20-Sep-99 HenryLee Created
  638. //
  639. //----------------------------------------------------------------------------
  640. BOOL CheckLanguageVersion (HINF Inf, LANGID SourceLangID, LANGID TargetLangID)
  641. {
  642. TCHAR SourceLangIDStr[9];
  643. LANGID SrcLANGID;
  644. TCHAR * Field;
  645. INFCONTEXT InfContext;
  646. int iOSID;
  647. int iLangID;
  648. if (SourceLangID == 0 || TargetLangID == 0)
  649. {
  650. return TRUE;
  651. }
  652. if (SourceLangID == TargetLangID)
  653. {
  654. //
  655. // special case, for Middle East version,
  656. // NT5 is localized build but NT4 is not
  657. //
  658. // they don't allow NT5 localized build to upgrade NT4,
  659. // although they are same language
  660. //
  661. // so we need to exclude these
  662. //
  663. return ((IsInExcludeList(Inf, SourceLangID) == FALSE));
  664. }
  665. //
  666. // if Src != Dst, then we need to look up inf file to see
  667. //
  668. // if we can open a backdoor for Target language
  669. //
  670. //
  671. // find alternative SourceLangID
  672. //
  673. wsprintf(SourceLangIDStr,TEXT("0000%04X"),SourceLangID);
  674. if (SetupFindFirstLine( Inf,
  675. TEXT("AlternativeSourceLocale"),
  676. SourceLangIDStr,
  677. &InfContext ))
  678. {
  679. do {
  680. //
  681. // Check if we found alternative locale
  682. //
  683. //
  684. if (ERROR_SUCCESS == SetupGetIntField (&InfContext, 0, &iLangID) &&
  685. (iLangID == SourceLangID))
  686. {
  687. if (ERROR_SUCCESS == GetInfField (&Field, &InfContext, 1))
  688. {
  689. LANGID AltTargetLangID = LANGIDFROMLCID(
  690. _tcstoul(Field,NULL,16));
  691. free (Field);
  692. if (TargetLangID != AltTargetLangID)
  693. {
  694. continue;
  695. }
  696. }
  697. //
  698. // We are here if we found alternative target lang,
  699. //
  700. // now check the version criteria
  701. //
  702. //
  703. // if it is in major version list, we also got what we want
  704. //
  705. if (ERROR_SUCCESS == SetupGetIntField (&InfContext, 2, &iOSID))
  706. {
  707. if (iOSID & GetOSMajorID())
  708. {
  709. return TRUE;
  710. }
  711. }
  712. }
  713. } while ( SetupFindNextLine(&InfContext,&InfContext));
  714. }
  715. return FALSE;
  716. }
  717. //+---------------------------------------------------------------------------
  718. //
  719. // Function: LoadVerifyOSLang
  720. //
  721. // Synopsis: verifies that source and target languages allow migration
  722. //
  723. // Arguments:
  724. //
  725. // Returns: Appropriate status code
  726. //
  727. // History: 20-Sep-99 HenryLee Created
  728. //
  729. //----------------------------------------------------------------------------
  730. DWORD LoadVerifyOSLang ()
  731. {
  732. DWORD dwErr = ERROR_SUCCESS;
  733. INFCONTEXT InfContext;
  734. LANGID langidLoad = 0;
  735. LANGID langidScan = 0;
  736. UINT errorline;
  737. TCHAR tcsInf [MAX_PATH+1];
  738. if (0 == GetWindowsDirectory ((TCHAR*)tcsInf, MAX_PATH))
  739. return GetLastError();
  740. // This inf file must exist for all Windows 2000 localized versions
  741. _tcsncat (tcsInf, TEXT("\\inf\\intl.inf"), MAX_PATH-_tcslen(tcsInf));
  742. HINF Inf = SetupOpenInfFile(tcsInf, NULL, INF_STYLE_WIN4, &errorline );
  743. if (INVALID_HANDLE_VALUE == Inf)
  744. {
  745. dwErr = GetLastError();
  746. Win32Printf (LogFile, "%systemroot%\\system\\inf\\intl.inf"
  747. "could not be opened Error=%d\r\n", dwErr);
  748. }
  749. else
  750. {
  751. if (SetupFindFirstLine( Inf,
  752. TEXT("DefaultValues"),
  753. TEXT("Locale"),
  754. &InfContext ))
  755. {
  756. TCHAR *pLoadLang = NULL;
  757. dwErr = GetInfField (&pLoadLang, &InfContext, 1);
  758. if (ERROR_SUCCESS == dwErr)
  759. {
  760. langidLoad = (LANGID)_tcstoul(pLoadLang,NULL,16);
  761. free (pLoadLang);
  762. if ( SetupFindFirstLine(InputInf,
  763. SOURCE_SECTION,
  764. LOCALE,
  765. &InfContext) )
  766. {
  767. TCHAR *pScanLang = NULL;
  768. dwErr = GetInfField (&pScanLang, &InfContext, 1);
  769. if (ERROR_SUCCESS == dwErr)
  770. {
  771. langidScan = (LANGID)_tcstoul(pScanLang,NULL,16);
  772. free (pScanLang);
  773. if (FALSE == CheckLanguageVersion(Inf,
  774. langidScan,langidLoad))
  775. {
  776. dwErr = ERROR_INSTALL_LANGUAGE_UNSUPPORTED;
  777. LogFormatError (dwErr);
  778. }
  779. }
  780. else
  781. {
  782. Win32Printf (LogFile, "locale missing in [%ws]\r\n",
  783. SOURCE_SECTION);
  784. LogFormatError (dwErr);
  785. }
  786. }
  787. }
  788. }
  789. else
  790. {
  791. dwErr = GetLastError();
  792. Win32Printf (LogFile, "intl.inf: default locale missing\r\n");
  793. LogFormatError (dwErr);
  794. }
  795. SetupCloseInfFile (Inf);
  796. }
  797. return dwErr;
  798. }
  799. //+---------------------------------------------------------------------------
  800. //
  801. // Function: MigrateKeyboardSubstitutes
  802. //
  803. // Synopsis: changes the user keyboard layouts
  804. //
  805. // Arguments:
  806. //
  807. // Returns: Appropriate status code
  808. //
  809. // History: 20-Sep-99 HenryLee Created
  810. //
  811. //----------------------------------------------------------------------------
  812. DWORD MigrateKeyboardSubstitutes (TCHAR *tcsName)
  813. {
  814. DWORD dwErr = ERROR_SUCCESS;
  815. ULONG ulOrig = _tcstoul(tcsName, NULL, 16);
  816. ULONG ulLang = LOWORD(ulOrig);
  817. HKEY hKey = NULL;
  818. BOOL fFound = FALSE;
  819. if (IS_IME_KBDLAYOUT(ulOrig) || ulLang == ulOrig)
  820. return ERROR_SUCCESS;
  821. if (ERROR_SUCCESS == RegOpenKeyEx (
  822. CurrentUser ? CurrentUser : HKEY_CURRENT_USER,
  823. REGKEY_SUBSTITUTES,
  824. NULL,
  825. KEY_READ | KEY_WRITE,
  826. &hKey))
  827. {
  828. DWORD dwIndex = 0;
  829. ULONG ulIndex;
  830. ULONG ulValue;
  831. TCHAR tcsIndex[KL_NAMELENGTH];
  832. TCHAR tcsValue[KL_NAMELENGTH];
  833. while (dwErr == ERROR_SUCCESS)
  834. {
  835. DWORD cbIndex = sizeof (tcsIndex);
  836. DWORD cbValue = sizeof(tcsValue);
  837. dwErr = RegEnumValue (hKey, dwIndex, tcsIndex, &cbIndex,
  838. NULL, NULL, (BYTE*) tcsValue, &cbValue);
  839. if (ERROR_SUCCESS == dwErr)
  840. {
  841. ulIndex = _tcstoul(tcsIndex, NULL, 16);
  842. ulValue = _tcstoul(tcsValue, NULL, 16);
  843. if (ulIndex == ulLang && ulValue == ulOrig)
  844. {
  845. fFound = TRUE;
  846. break;
  847. }
  848. }
  849. dwIndex++;
  850. }
  851. if (dwErr == ERROR_NO_MORE_ITEMS)
  852. dwErr = ERROR_SUCCESS;
  853. if (!fFound) // add a new value
  854. {
  855. wsprintf (tcsIndex, TEXT("%08x"), ulLang);
  856. dwErr = RegSetValueEx (hKey, tcsIndex, 0, REG_SZ, (BYTE*)tcsName,
  857. (_tcslen(tcsName)+1)*sizeof(TCHAR));
  858. }
  859. RegCloseKey (hKey);
  860. }
  861. return dwErr;
  862. }
  863. //+---------------------------------------------------------------------------
  864. //
  865. // Function: MigrateKeyboardPreloads
  866. //
  867. // Synopsis: changes the user keyboard layouts
  868. //
  869. // Arguments:
  870. //
  871. // Returns: Appropriate status code
  872. //
  873. // History: 20-Sep-99 HenryLee Created
  874. //
  875. //----------------------------------------------------------------------------
  876. DWORD MigrateKeyboardPreloads (TCHAR *tcsName)
  877. {
  878. DWORD dwErr = ERROR_SUCCESS;
  879. ULONG ul = _tcstoul(tcsName, NULL, 16);
  880. HKEY hKey = NULL;
  881. BOOL fFound = FALSE;
  882. // look for a preload with this locale
  883. if (!IS_IME_KBDLAYOUT(ul))
  884. ul = LOWORD(ul);
  885. if (ERROR_SUCCESS == RegOpenKeyEx (
  886. CurrentUser ? CurrentUser : HKEY_CURRENT_USER,
  887. REGKEY_PRELOAD,
  888. NULL,
  889. KEY_READ | KEY_WRITE,
  890. &hKey))
  891. {
  892. DWORD dwIndex = 0;
  893. ULONG ulIndexMax = 0;
  894. ULONG ulIndex;
  895. ULONG ulValue;
  896. TCHAR tcsIndex[KL_NAMELENGTH];
  897. TCHAR tcsValue[KL_NAMELENGTH];
  898. while (dwErr == ERROR_SUCCESS)
  899. {
  900. DWORD cbIndex = sizeof (tcsIndex);
  901. DWORD cbValue = sizeof(tcsValue);
  902. dwErr = RegEnumValue (hKey, dwIndex, tcsIndex, &cbIndex,
  903. NULL, NULL, (BYTE*)tcsValue, &cbValue);
  904. if (ERROR_SUCCESS == dwErr)
  905. {
  906. ulIndex = _tcstoul(tcsIndex, NULL, 10);
  907. if (ulIndex > ulIndexMax)
  908. ulIndexMax = ulIndex;
  909. ulValue = _tcstoul(tcsValue, NULL, 16);
  910. if (ulValue == ul)
  911. {
  912. fFound = TRUE;
  913. break;
  914. }
  915. }
  916. dwIndex++;
  917. }
  918. if (dwErr == ERROR_NO_MORE_ITEMS)
  919. dwErr = ERROR_SUCCESS;
  920. if (!fFound) // add a new value
  921. {
  922. wsprintf (tcsIndex, TEXT("%d"), ulIndexMax+1);
  923. wsprintf (tcsValue, TEXT("%08x"), ul);
  924. dwErr = RegSetValueEx (hKey, tcsIndex, 0, REG_SZ, (BYTE*)tcsValue,
  925. (_tcslen(tcsValue)+1)*sizeof(TCHAR));
  926. }
  927. RegCloseKey (hKey);
  928. }
  929. return dwErr;
  930. }
  931. //+---------------------------------------------------------------------------
  932. //
  933. // Function: LoadKeyboardLayouts
  934. //
  935. // Synopsis: changes the user keyboard layouts
  936. //
  937. // Arguments:
  938. //
  939. // Returns: Appropriate status code
  940. //
  941. // History: 20-Sep-99 HenryLee Created
  942. //
  943. //----------------------------------------------------------------------------
  944. DWORD LoadKeyboardLayouts ()
  945. {
  946. DWORD dwErr = ERROR_SUCCESS;
  947. INFCONTEXT InfContext;
  948. BOOL fFound;
  949. // translate input locales if source is Win9x
  950. if (!(SourceVersion & 0x80000000))
  951. return ERROR_SUCCESS;
  952. if (SetupFindFirstLine(InputInf, SOURCE_SECTION, INPUTLOCALE, &InfContext))
  953. {
  954. TCHAR *pLayout = NULL;
  955. UINT iLayouts = SetupGetFieldCount(&InfContext);
  956. for (UINT i = 1; i <= iLayouts; i++)
  957. {
  958. dwErr = GetInfField (&pLayout, &InfContext, i);
  959. if (ERROR_SUCCESS == dwErr)
  960. {
  961. INFCONTEXT InfContext2;
  962. //
  963. // See in usermig.inf to see if different ID exists
  964. //
  965. if ( SetupFindFirstLine(InputInf,
  966. KEYBOARDLAYOUT_MAP,
  967. pLayout,
  968. &InfContext2) )
  969. {
  970. TCHAR *pMap = NULL;
  971. if (ERROR_SUCCESS == GetInfField (&pMap, &InfContext2, 1))
  972. {
  973. free (pLayout);
  974. pLayout = pMap;
  975. }
  976. }
  977. dwErr = MigrateKeyboardPreloads (pLayout);
  978. if (ERROR_SUCCESS == dwErr)
  979. dwErr = MigrateKeyboardSubstitutes (pLayout);
  980. if (CurrentUser == HKEY_CURRENT_USER)
  981. {
  982. TCHAR kbname[KL_NAMELENGTH];
  983. GetKeyboardLayoutName (kbname);
  984. if (i == 1 && lstrcmp(kbname, pLayout) != 0) // load default
  985. {
  986. ULONG ulLayout = _tcstoul(pLayout, NULL, 16);
  987. HKL hklCurrent = GetKeyboardLayout(0);
  988. if (Verbose)
  989. printf ("Loading keyboard layout %ws \n", pLayout);
  990. HKL hkl = LoadKeyboardLayoutEx (hklCurrent, pLayout,
  991. KLF_REORDER | KLF_ACTIVATE | KLF_SETFORPROCESS |
  992. KLF_SUBSTITUTE_OK);
  993. if (hkl != NULL)
  994. {
  995. SystemParametersInfo (SPI_SETDEFAULTINPUTLANG, 0,
  996. (VOID *) &hkl, 0);
  997. if (Verbose)
  998. {
  999. #ifdef _WIN64
  1000. printf ("Activated keyboard layout %08I64x\n",hkl);
  1001. #else
  1002. printf ("Activated keyboard layout %08x\n",hkl);
  1003. #endif
  1004. }
  1005. }
  1006. }
  1007. else if (i > 1) // load the alternates
  1008. {
  1009. LoadKeyboardLayout (pLayout, KLF_SUBSTITUTE_OK);
  1010. }
  1011. }
  1012. free (pLayout);
  1013. if (dwErr != ERROR_SUCCESS)
  1014. break;
  1015. }
  1016. else
  1017. {
  1018. Win32Printf (LogFile,"Could not read keyboard layout %d\r\n",i);
  1019. }
  1020. }
  1021. }
  1022. if (dwErr != ERROR_SUCCESS)
  1023. Win32Printf (LogFile, "Could not load all keyboard layouts\r\n");
  1024. return dwErr;
  1025. }
  1026. //+---------------------------------------------------------------------------
  1027. //
  1028. // Function: EnumerateModems
  1029. //
  1030. // Synopsis: enumerates the modem devices on the system
  1031. //
  1032. // Arguments:
  1033. //
  1034. // Returns: Appropriate status code
  1035. //
  1036. // History: 20-Sep-99 HenryLee Created
  1037. //
  1038. //----------------------------------------------------------------------------
  1039. DWORD EnumerateModems (TCHAR *ptsPort, ULONG ulLen)
  1040. {
  1041. DWORD dwErr = ERROR_SUCCESS;
  1042. UINT i = 0;
  1043. BOOL fDetected = FALSE;
  1044. SP_DEVINFO_DATA sdd;
  1045. HDEVINFO hdi = SetupDiGetClassDevs (&GUID_DEVCLASS_MODEM,
  1046. NULL,
  1047. NULL,
  1048. DIGCF_PRESENT );
  1049. if (hdi != INVALID_HANDLE_VALUE)
  1050. {
  1051. ZeroMemory (&sdd, sizeof(sdd));
  1052. sdd.cbSize = sizeof(sdd);
  1053. sdd.ClassGuid = GUID_DEVCLASS_MODEM;
  1054. while (SetupDiEnumDeviceInfo (hdi, i++, &sdd))
  1055. {
  1056. HKEY hKey = SetupDiOpenDevRegKey (hdi,
  1057. &sdd,
  1058. DICS_FLAG_GLOBAL,
  1059. 0,
  1060. DIREG_DRV,
  1061. KEY_READ);
  1062. if (hKey != INVALID_HANDLE_VALUE)
  1063. {
  1064. ULONG ulLenQuery = ulLen;
  1065. dwErr = RegQueryValueEx(hKey,
  1066. TEXT("AttachedTo"),
  1067. NULL,
  1068. NULL,
  1069. (BYTE *)ptsPort,
  1070. &ulLenQuery);
  1071. RegCloseKey (hKey);
  1072. if (dwErr == ERROR_SUCCESS) // found a modem
  1073. {
  1074. fDetected = TRUE;
  1075. break;
  1076. }
  1077. }
  1078. else dwErr = GetLastError();
  1079. }
  1080. if (!fDetected)
  1081. dwErr = ERROR_NO_MORE_DEVICES; // no modem detected
  1082. }
  1083. else dwErr = GetLastError();
  1084. return dwErr;
  1085. }
  1086. //+---------------------------------------------------------------------------
  1087. //
  1088. // Function: RasGetPhoneBookFile
  1089. //
  1090. // Synopsis: determines location of RAS settings in phonebook file
  1091. //
  1092. // Arguments:
  1093. //
  1094. // Returns: Appropriate status code
  1095. //
  1096. // History: 20-Sep-99 HenryLee Created
  1097. //
  1098. //----------------------------------------------------------------------------
  1099. DWORD RasGetPhoneBookFile(TCHAR *strPhoneBook)
  1100. {
  1101. const TCHAR RASPHONE_SUBPATH[] = TEXT("\\ras\\rasphone.pbk");
  1102. if (0 == GetSystemDirectory ((TCHAR*)strPhoneBook, MAX_PATH))
  1103. return GetLastError();
  1104. _tcsncat(strPhoneBook, (TCHAR *) RASPHONE_SUBPATH,
  1105. MAX_PATH-_tcslen(strPhoneBook));
  1106. return ERROR_SUCCESS;
  1107. }
  1108. //+---------------------------------------------------------------------------
  1109. //
  1110. // Function: LoadRas
  1111. //
  1112. // Synopsis: create the phonebook file for RAS settings
  1113. //
  1114. // Arguments:
  1115. //
  1116. // Returns: Appropriate status code
  1117. //
  1118. // History: 20-Sep-99 HenryLee Created
  1119. //
  1120. //----------------------------------------------------------------------------
  1121. DWORD LoadRas()
  1122. {
  1123. DWORD dwErr = ERROR_SUCCESS;
  1124. BOOL success;
  1125. INFCONTEXT context;
  1126. RASENTRY RasEntry;
  1127. RASDIALPARAMS RasDialParams;
  1128. success = SetupFindFirstLine(InputInf, RAS_SECTION, NULL, &context);
  1129. if (!success)
  1130. return ERROR_SUCCESS; // line not found
  1131. do {
  1132. ZeroMemory( &RasEntry, sizeof(RASENTRY) );
  1133. ZeroMemory( &RasDialParams, sizeof(RASDIALPARAMS) );
  1134. RasDialParams.dwSize = sizeof(RASDIALPARAMS);
  1135. RasEntry.dwSize = sizeof(RASENTRY);
  1136. ChkBoolErr( SetupGetStringField( &context, 1, RasDialParams.szEntryName,
  1137. RAS_MaxEntryName + 1, NULL) );
  1138. // load RasEntry structure
  1139. ChkBoolErr( SetupGetIntField( &context, 2, (int*)&RasEntry.dwfOptions) );
  1140. ChkBoolErr( SetupGetIntField( &context, 3, (int*)&RasEntry.dwCountryID) );
  1141. ChkBoolErr( SetupGetIntField( &context, 4, (int*)&RasEntry.dwCountryCode) );
  1142. ChkBoolErr( SetupGetStringField( &context, 5, RasEntry.szAreaCode,
  1143. RAS_MaxAreaCode + 1, NULL) );
  1144. ChkBoolErr( SetupGetStringField( &context, 6, RasEntry.szLocalPhoneNumber,
  1145. RAS_MaxPhoneNumber + 1, NULL) );
  1146. ChkBoolErr( SetupGetIntField( &context, 7, (int*)&RasEntry.dwAlternateOffset) );
  1147. ChkBoolErr( SetupGetIntField( &context, 8, (int*)&RasEntry.ipaddr) );
  1148. ChkBoolErr( SetupGetIntField( &context, 9, (int*)&RasEntry.ipaddrDns) );
  1149. ChkBoolErr( SetupGetIntField( &context, 10, (int*)&RasEntry.ipaddrDnsAlt) );
  1150. ChkBoolErr( SetupGetIntField( &context, 11, (int*)&RasEntry.ipaddrWins) );
  1151. ChkBoolErr( SetupGetIntField( &context, 12, (int*)&RasEntry.ipaddrWinsAlt) );
  1152. ChkBoolErr( SetupGetIntField( &context, 13, (int*)&RasEntry.dwFrameSize) );
  1153. ChkBoolErr( SetupGetIntField( &context, 14, (int*)&RasEntry.dwfNetProtocols) );
  1154. ChkBoolErr( SetupGetIntField( &context, 15, (int*)&RasEntry.dwFramingProtocol) );
  1155. ChkBoolErr( SetupGetStringField( &context, 16, RasEntry.szScript, MAX_PATH, NULL) );
  1156. ChkBoolErr( SetupGetStringField( &context, 17, RasEntry.szAutodialDll, MAX_PATH, NULL) );
  1157. ChkBoolErr( SetupGetStringField( &context, 18, RasEntry.szAutodialFunc, MAX_PATH, NULL) );
  1158. ChkBoolErr( SetupGetStringField( &context, 19, RasEntry.szDeviceType,
  1159. RAS_MaxDeviceType + 1, NULL) );
  1160. ChkBoolErr( SetupGetStringField( &context, 20, RasEntry.szDeviceName,
  1161. RAS_MaxDeviceName + 1, NULL) );
  1162. ChkBoolErr( SetupGetStringField( &context, 21, RasEntry.szX25PadType,
  1163. RAS_MaxPadType + 1, NULL) );
  1164. ChkBoolErr( SetupGetStringField( &context, 22, RasEntry.szX25Address,
  1165. RAS_MaxX25Address + 1, NULL) );
  1166. ChkBoolErr( SetupGetStringField( &context, 23, RasEntry.szX25Facilities,
  1167. RAS_MaxFacilities + 1, NULL) );
  1168. ChkBoolErr( SetupGetStringField( &context, 24, RasEntry.szX25UserData,
  1169. RAS_MaxUserData + 1, NULL) );
  1170. ChkBoolErr( SetupGetIntField( &context, 25, (int*)&RasEntry.dwChannels) );
  1171. // load RasDialParams structure
  1172. ChkBoolErr( SetupGetStringField( &context, 26, RasDialParams.szPhoneNumber,
  1173. RAS_MaxPhoneNumber + 1, NULL) );
  1174. ChkBoolErr( SetupGetStringField( &context, 27, RasDialParams.szCallbackNumber,
  1175. RAS_MaxCallbackNumber+1, NULL) );
  1176. ChkBoolErr( SetupGetStringField( &context, 28, RasDialParams.szUserName, UNLEN+1, NULL) );
  1177. ChkBoolErr( SetupGetStringField( &context, 29, RasDialParams.szPassword, PWLEN+1, NULL) );
  1178. ChkBoolErr( SetupGetStringField( &context, 30, RasDialParams.szDomain, DNLEN+1, NULL) );
  1179. // Set default options that do not exist on pre-Win2000 OS, but are
  1180. // set by default when you create a connection via the Win2000 GUI.
  1181. RasEntry.dwfOptions |= RASEO_PreviewUserPw;
  1182. RasEntry.dwfOptions |= RASEO_ShowDialingProgress;
  1183. RasEntry.dwfOptions |= RASEO_ModemLights;
  1184. // New Win2k encryption field
  1185. if( RasEntry.dwfOptions & RASEO_RequireDataEncryption )
  1186. {
  1187. RasEntry.dwEncryptionType = ET_Require;
  1188. }
  1189. else
  1190. {
  1191. RasEntry.dwEncryptionType = ET_Optional;
  1192. }
  1193. #ifdef PRIVATE_RAS
  1194. dwErr = GWinState_RasSetEntryProperties(NULL, // Current user default phonebook
  1195. RasDialParams.szEntryName,
  1196. &RasEntry,
  1197. sizeof(RASENTRY),
  1198. NULL,
  1199. NULL);
  1200. #else
  1201. dwErr = GRasSetEntryProperties(NULL, // Current user default phonebook
  1202. RasDialParams.szEntryName,
  1203. &RasEntry,
  1204. sizeof(RASENTRY),
  1205. NULL,
  1206. NULL);
  1207. #endif
  1208. if ( dwErr != ERROR_SUCCESS)
  1209. {
  1210. Win32PrintfResource (LogFile, IDS_RAS_ENTRY_NOT_MIGRATED, RasDialParams.szEntryName);
  1211. if (DebugOutput)
  1212. Win32Printf(LogFile, "RasSetEntryProperties failed: Error %d\r\n", dwErr);
  1213. }
  1214. dwErr = GRasSetEntryDialParams(NULL,
  1215. &RasDialParams,
  1216. TRUE); // Never put password in
  1217. if ( dwErr != ERROR_SUCCESS)
  1218. {
  1219. Win32PrintfResource (LogFile, IDS_RAS_ENTRY_NOT_MIGRATED, RasDialParams.szEntryName);
  1220. if (DebugOutput)
  1221. Win32Printf(LogFile, "RasSetEntryDialParams failed: Error %d\r\n", dwErr);
  1222. }
  1223. // Advance to the next line.
  1224. success = SetupFindNextLine( &context, &context );
  1225. } while (success);
  1226. Err:
  1227. return dwErr;
  1228. }
  1229. //+---------------------------------------------------------------------------
  1230. //
  1231. // Function: ConvertLFShort
  1232. //
  1233. // Synopsis: convert Win9x 16-bit LOGFONTs to NT formats
  1234. //
  1235. // Arguments:
  1236. //
  1237. // Returns: Appropriate status code
  1238. //
  1239. // History: 20-Sep-99 HenryLee Created
  1240. //
  1241. //----------------------------------------------------------------------------
  1242. DWORD ConvertLFShort (LOGFONTW *plfDest, const SHORT_LOGFONT *plfSrc)
  1243. {
  1244. plfDest->lfHeight = plfSrc->lfHeight;
  1245. plfDest->lfWidth = plfSrc->lfWidth;
  1246. plfDest->lfEscapement = plfSrc->lfEscapement;
  1247. plfDest->lfOrientation = plfSrc->lfOrientation;
  1248. plfDest->lfWeight = plfSrc->lfWeight;
  1249. plfDest->lfItalic = plfSrc->lfItalic;
  1250. plfDest->lfUnderline = plfSrc->lfUnderline;
  1251. plfDest->lfStrikeOut = plfSrc->lfStrikeOut;
  1252. plfDest->lfCharSet = plfSrc->lfCharSet;
  1253. plfDest->lfOutPrecision = plfSrc->lfOutPrecision;
  1254. plfDest->lfClipPrecision = plfSrc->lfClipPrecision;
  1255. plfDest->lfQuality = plfSrc->lfQuality;
  1256. plfDest->lfPitchAndFamily = plfSrc->lfPitchAndFamily;
  1257. ZeroMemory (plfDest->lfFaceName, sizeof(plfDest->lfFaceName));
  1258. if (0 == MultiByteToWideChar (GetACP(),
  1259. 0,
  1260. plfSrc->lfFaceName,
  1261. -1,
  1262. plfDest->lfFaceName,
  1263. sizeof (plfDest->lfFaceName) / sizeof (WCHAR)))
  1264. return GetLastError();
  1265. return ERROR_SUCCESS;
  1266. }
  1267. //+---------------------------------------------------------------------------
  1268. //
  1269. // Function: ConvertLF
  1270. //
  1271. // Synopsis: convert Win9x LOGFONTs to NT formats
  1272. //
  1273. // Arguments:
  1274. //
  1275. // Returns: Appropriate status code
  1276. //
  1277. // History: 20-Sep-99 HenryLee Created
  1278. //
  1279. //----------------------------------------------------------------------------
  1280. DWORD ConvertLF (LOGFONTW *plfDest, const LOGFONTA *plfSrc)
  1281. {
  1282. plfDest->lfHeight = plfSrc->lfHeight;
  1283. plfDest->lfWidth = plfSrc->lfWidth;
  1284. plfDest->lfEscapement = plfSrc->lfEscapement;
  1285. plfDest->lfOrientation = plfSrc->lfOrientation;
  1286. plfDest->lfWeight = plfSrc->lfWeight;
  1287. plfDest->lfItalic = plfSrc->lfItalic;
  1288. plfDest->lfUnderline = plfSrc->lfUnderline;
  1289. plfDest->lfStrikeOut = plfSrc->lfStrikeOut;
  1290. plfDest->lfCharSet = plfSrc->lfCharSet;
  1291. plfDest->lfOutPrecision = plfSrc->lfOutPrecision;
  1292. plfDest->lfClipPrecision = plfSrc->lfClipPrecision;
  1293. plfDest->lfQuality = plfSrc->lfQuality;
  1294. plfDest->lfPitchAndFamily = plfSrc->lfPitchAndFamily;
  1295. ZeroMemory (plfDest->lfFaceName, sizeof(plfDest->lfFaceName));
  1296. if (0 == MultiByteToWideChar (GetACP(),
  1297. 0,
  1298. plfSrc->lfFaceName,
  1299. -1,
  1300. plfDest->lfFaceName,
  1301. sizeof (plfDest->lfFaceName) / sizeof (WCHAR)))
  1302. return GetLastError();
  1303. return ERROR_SUCCESS;
  1304. }
  1305. //+---------------------------------------------------------------------------
  1306. //
  1307. // Function: ConvertNonClientMetrics
  1308. //
  1309. // Synopsis: convert Win9x client metrics to NT formats
  1310. //
  1311. // Arguments:
  1312. //
  1313. // Returns: Appropriate status code
  1314. //
  1315. // History: 20-Sep-99 HenryLee Created
  1316. //
  1317. //----------------------------------------------------------------------------
  1318. void ConvertNonClientMetrics (NONCLIENTMETRICSW *Dest, NONCLIENTMETRICSA *Src)
  1319. {
  1320. Dest->cbSize = sizeof (NONCLIENTMETRICSW);
  1321. Dest->iBorderWidth = Src->iBorderWidth;
  1322. Dest->iScrollWidth = Src->iScrollWidth;
  1323. Dest->iScrollHeight = Src->iScrollHeight;
  1324. Dest->iCaptionWidth = Src->iCaptionWidth;
  1325. Dest->iCaptionHeight = Src->iCaptionHeight;
  1326. Dest->iSmCaptionWidth = Src->iSmCaptionWidth;
  1327. Dest->iSmCaptionHeight = Src->iSmCaptionHeight;
  1328. Dest->iMenuWidth = Src->iMenuWidth;
  1329. Dest->iMenuHeight = Src->iMenuHeight;
  1330. ConvertLF (&Dest->lfCaptionFont, &Src->lfCaptionFont);
  1331. ConvertLF (&Dest->lfSmCaptionFont, &Src->lfSmCaptionFont);
  1332. ConvertLF (&Dest->lfMenuFont, &Src->lfMenuFont);
  1333. ConvertLF (&Dest->lfStatusFont, &Src->lfStatusFont);
  1334. ConvertLF (&Dest->lfMessageFont, &Src->lfMessageFont);
  1335. }
  1336. //+---------------------------------------------------------------------------
  1337. //
  1338. // Function: ConvertAppearanceScheme
  1339. //
  1340. // Synopsis: convert Win9x schemes to NT formats
  1341. //
  1342. // Arguments:
  1343. //
  1344. // Returns: Appropriate status code
  1345. //
  1346. // History: 20-Sep-99 HenryLee Created
  1347. //
  1348. //----------------------------------------------------------------------------
  1349. DWORD ConvertAppearanceScheme (DWORD *ptype, BYTE **pdata, DWORD *pdata_len)
  1350. {
  1351. DWORD dwErr = ERROR_SUCCESS;
  1352. DWORD dwSize = *pdata_len;
  1353. if (*ptype == REG_BINARY &&
  1354. (dwSize == sizeof(SCHEMEDATA_V1) ||
  1355. dwSize == sizeof(SCHEMEDATA_V3) ||
  1356. dwSize == sizeof(SCHEMEDATA_V4) ||
  1357. dwSize == sizeof(SCHEMEDATA_V1A)))
  1358. {
  1359. SCHEMEDATA_NT sd_nt;
  1360. SCHEMEDATA_V1 * psd_v1;
  1361. SCHEMEDATA_V3 * psd_v3;
  1362. SCHEMEDATA_V4 * psd_v4;
  1363. SCHEMEDATA_V1A * psd_v1a;
  1364. BOOL Copy3dValues = FALSE;
  1365. BOOL shouldChange = TRUE;
  1366. psd_v1 = (SCHEMEDATA_V1 *) *pdata;
  1367. if (psd_v1->version == 1)
  1368. {
  1369. sd_nt.version = 2;
  1370. ConvertNonClientMetrics (&sd_nt.ncm, &psd_v1->ncm);
  1371. ConvertLFShort (&sd_nt.lfIconTitle, &psd_v1->lfIconTitle);
  1372. ZeroMemory (sd_nt.rgb, sizeof (sd_nt.rgb));
  1373. CopyMemory ( &sd_nt.rgb, &psd_v1->rgb,
  1374. min (sizeof (psd_v1->rgb), sizeof (sd_nt.rgb)));
  1375. Copy3dValues = TRUE;
  1376. }
  1377. else if (psd_v1->version == 3 && dwSize==sizeof(SCHEMEDATA_V1A))
  1378. {
  1379. psd_v1a = (PSCHEMEDATA_V1A) psd_v1;
  1380. sd_nt.version = 2;
  1381. ConvertNonClientMetrics (&sd_nt.ncm, &psd_v1a->ncm);
  1382. ConvertLFShort (&sd_nt.lfIconTitle, &psd_v1a->lfIconTitle);
  1383. ZeroMemory (sd_nt.rgb, sizeof (sd_nt.rgb));
  1384. CopyMemory ( &sd_nt.rgb, &psd_v1a->rgb,
  1385. min (sizeof (psd_v1a->rgb), sizeof (sd_nt.rgb)) );
  1386. Copy3dValues = TRUE;
  1387. }
  1388. else if (psd_v1->version == 3 && dwSize==sizeof(SCHEMEDATA_V3))
  1389. {
  1390. psd_v3 = (PSCHEMEDATA_V3) psd_v1;
  1391. sd_nt.version = 2;
  1392. ConvertNonClientMetrics (&sd_nt.ncm, &psd_v3->ncm);
  1393. ConvertLF (&sd_nt.lfIconTitle, &psd_v3->lfIconTitle);
  1394. ZeroMemory (sd_nt.rgb, sizeof (sd_nt.rgb));
  1395. CopyMemory ( &sd_nt.rgb, &psd_v3->rgb,
  1396. min (sizeof (psd_v3->rgb), sizeof (sd_nt.rgb)) );
  1397. Copy3dValues = TRUE;
  1398. }
  1399. else if (psd_v1->version == 4)
  1400. {
  1401. psd_v4 = (PSCHEMEDATA_V4) psd_v1;
  1402. sd_nt.version = 2;
  1403. ConvertNonClientMetrics (&sd_nt.ncm, &psd_v4->ncm);
  1404. ConvertLF (&sd_nt.lfIconTitle, &psd_v4->lfIconTitle);
  1405. ZeroMemory (sd_nt.rgb, sizeof (sd_nt.rgb));
  1406. CopyMemory ( &sd_nt.rgb, &psd_v4->rgb,
  1407. min (sizeof (psd_v4->rgb), sizeof (sd_nt.rgb)) );
  1408. }
  1409. else shouldChange = FALSE;
  1410. if (Copy3dValues)
  1411. {
  1412. //
  1413. // Make sure the NT structure has values for 3D colors
  1414. //
  1415. sd_nt.rgb[COLOR_HOTLIGHT] = sd_nt.rgb[COLOR_ACTIVECAPTION];
  1416. sd_nt.rgb[COLOR_GRADIENTACTIVECAPTION] =
  1417. sd_nt.rgb[COLOR_ACTIVECAPTION];
  1418. sd_nt.rgb[COLOR_GRADIENTINACTIVECAPTION] =
  1419. sd_nt.rgb[COLOR_INACTIVECAPTION];
  1420. }
  1421. if (shouldChange)
  1422. {
  1423. BYTE *pnew_data;
  1424. if (NULL == (pnew_data = (BYTE *)malloc (sizeof(sd_nt))))
  1425. return ERROR_NOT_ENOUGH_MEMORY;
  1426. CopyMemory (pnew_data, &sd_nt, sizeof(sd_nt));
  1427. free (*pdata);
  1428. *pdata = pnew_data;
  1429. *pdata_len = sizeof(sd_nt);
  1430. }
  1431. }
  1432. else if (Verbose)
  1433. printf ("ConvertAppearanceScheme type=%d, size=%d\n",*ptype,*pdata_len);
  1434. return dwErr;
  1435. }
  1436. //+---------------------------------------------------------------------------
  1437. //
  1438. // Function: ConvertRecentDocsMRU
  1439. //
  1440. // Synopsis: convert Win9x "Start Menu" "Documents" settings
  1441. //
  1442. // Arguments:
  1443. //
  1444. // Returns: Appropriate status code
  1445. //
  1446. // History: 20-Sep-99 HenryLee Created
  1447. //
  1448. //----------------------------------------------------------------------------
  1449. DWORD ConvertRecentDocsMRU (DWORD *ptype, BYTE **pdata, DWORD *pdata_len)
  1450. {
  1451. DWORD dwErr = ERROR_SUCCESS;
  1452. if (*ptype == REG_BINARY)
  1453. {
  1454. LINKSTRUCT *pls95, *plsNT;
  1455. CHAR *str, *strEnd;
  1456. WCHAR *wstr, *wstrEnd;
  1457. DWORD dwLinkSize, dwNewSize;
  1458. DWORD dwRenewSize;
  1459. str = (CHAR *) *pdata;
  1460. dwNewSize = strlen(str);
  1461. strEnd = str + dwNewSize;
  1462. pls95 = (LINKSTRUCT *) strEnd;
  1463. dwLinkSize = dwNewSize + 1 + pls95->wSize + sizeof (WORD);
  1464. if (dwLinkSize != *pdata_len)
  1465. {
  1466. return ERROR_SUCCESS; // length mismatch, do not transform
  1467. }
  1468. dwNewSize = MultiByteToWideChar (GetACP(),0,str,-1, NULL, 0);
  1469. if (dwNewSize == 0)
  1470. return GetLastError();
  1471. if (NULL == (wstr = (WCHAR *) malloc (
  1472. (dwNewSize + 1)*sizeof(WCHAR) + dwLinkSize)))
  1473. return ERROR_NOT_ENOUGH_MEMORY;
  1474. if (0 == MultiByteToWideChar (GetACP(),0,str,-1,wstr,dwNewSize))
  1475. dwErr = GetLastError();
  1476. if (ERROR_SUCCESS == dwErr)
  1477. {
  1478. wstrEnd = wstr + wcslen(wstr);
  1479. plsNT = (PLINKSTRUCT) ((LPBYTE) wstr + ((DWORD)(wstrEnd-wstr)));
  1480. CopyMemory (plsNT, pls95, dwLinkSize);
  1481. free (*pdata);
  1482. *pdata = (BYTE *) wstr;
  1483. *pdata_len = dwNewSize;
  1484. }
  1485. else free (wstr);
  1486. }
  1487. return dwErr;
  1488. }
  1489. //+---------------------------------------------------------------------------
  1490. //
  1491. // Function: ConvertLogFont
  1492. //
  1493. // Synopsis: convert Win9x font binary data
  1494. //
  1495. // Arguments:
  1496. //
  1497. // Returns: Appropriate status code
  1498. //
  1499. // History: 20-Sep-99 HenryLee Created
  1500. //
  1501. //----------------------------------------------------------------------------
  1502. DWORD ConvertLogFont (DWORD *ptype, BYTE **pdata, DWORD *pdata_len)
  1503. {
  1504. if (*ptype == REG_BINARY && *pdata_len == sizeof(SHORT_LOGFONT))
  1505. {
  1506. BYTE *pnew_data;
  1507. LOGFONTW lfNT;
  1508. ConvertLFShort (&lfNT, (SHORT_LOGFONT *) *pdata);
  1509. if (NULL == (pnew_data = (BYTE *)malloc (sizeof(lfNT))))
  1510. return ERROR_NOT_ENOUGH_MEMORY;
  1511. CopyMemory (pnew_data, &lfNT, sizeof(lfNT));
  1512. free (*pdata);
  1513. *pdata = pnew_data;
  1514. *pdata_len = sizeof(lfNT);
  1515. }
  1516. return ERROR_SUCCESS;
  1517. }
  1518. //+---------------------------------------------------------------------------
  1519. //
  1520. // Function: ConvertToDword
  1521. //
  1522. // Synopsis: convert string data to DWORD
  1523. //
  1524. // Arguments:
  1525. //
  1526. // Returns: Appropriate status code
  1527. //
  1528. // History: 20-Sep-99 HenryLee Created
  1529. //
  1530. //----------------------------------------------------------------------------
  1531. DWORD ConvertToDword (DWORD *ptype, BYTE **pdata, DWORD *pdata_len)
  1532. {
  1533. if (*ptype == REG_SZ || *ptype == REG_EXPAND_SZ)
  1534. {
  1535. BYTE *pnew_data;
  1536. DWORD dwValue = _tcstoul ((PCTSTR) *pdata, NULL, 10);
  1537. if (NULL == (pnew_data = (BYTE *)malloc (sizeof(dwValue))))
  1538. return ERROR_NOT_ENOUGH_MEMORY;
  1539. CopyMemory (pnew_data, &dwValue, sizeof(dwValue));
  1540. free (*pdata);
  1541. *pdata = pnew_data;
  1542. *pdata_len = sizeof(dwValue);
  1543. *ptype = REG_DWORD;
  1544. }
  1545. return ERROR_SUCCESS;
  1546. }
  1547. //+---------------------------------------------------------------------------
  1548. //
  1549. // Function: ConvertToString
  1550. //
  1551. // Synopsis: convert DWORD to a string
  1552. //
  1553. // Arguments:
  1554. //
  1555. // Returns: Appropriate status code
  1556. //
  1557. // History: 20-Sep-99 HenryLee Created
  1558. //
  1559. //----------------------------------------------------------------------------
  1560. DWORD ConvertToString (DWORD *ptype, BYTE **pdata, DWORD *pdata_len)
  1561. {
  1562. if (*ptype == REG_DWORD)
  1563. {
  1564. BYTE *pnew_data;
  1565. DWORD dwSize;
  1566. TCHAR tcsValue[16];
  1567. wsprintf (tcsValue, TEXT("%lu"), * ((DWORD *) *pdata));
  1568. dwSize = (_tcslen (tcsValue) + 1) * sizeof(TCHAR);
  1569. if (NULL == (pnew_data = (BYTE *)malloc (dwSize)))
  1570. return ERROR_NOT_ENOUGH_MEMORY;
  1571. CopyMemory (pnew_data, tcsValue, dwSize);
  1572. free (*pdata);
  1573. *pdata = pnew_data;
  1574. *pdata_len = dwSize;
  1575. *ptype = REG_SZ;
  1576. }
  1577. return ERROR_SUCCESS;
  1578. }
  1579. //+---------------------------------------------------------------------------
  1580. //
  1581. // Function: AntiAlias
  1582. //
  1583. // Synopsis: convert FontSmoothing from "1" to "2"
  1584. //
  1585. // Arguments:
  1586. //
  1587. // Returns: Appropriate status code
  1588. //
  1589. // History: 20-Sep-99 HenryLee Created
  1590. //
  1591. //----------------------------------------------------------------------------
  1592. DWORD AntiAlias (DWORD *ptype, BYTE **pdata, DWORD *pdata_len)
  1593. {
  1594. if (*ptype == REG_SZ)
  1595. {
  1596. DWORD dwValue = _tcstoul ((TCHAR *) *pdata, NULL, 10);
  1597. if (dwValue > 0)
  1598. wsprintf ((TCHAR *) *pdata, TEXT("%d"), FE_AA_ON);
  1599. }
  1600. return ERROR_SUCCESS;
  1601. }
  1602. //+--------------------------------------------------------------------------
  1603. //
  1604. // Function: FixActiveDesktop
  1605. //
  1606. // Synopsis: convert active desktop blob
  1607. //
  1608. // Arguments:
  1609. //
  1610. // Returns: Appropriate status code
  1611. //
  1612. // History: 20-Sep-99 HenryLee Created
  1613. //
  1614. //---------------------------------------------------------------------------
  1615. DWORD FixActiveDesktop (DWORD *ptype, BYTE **pdata, DWORD *pdata_len)
  1616. {
  1617. const USHORT BadBufferSize = 16;
  1618. const USHORT GoodBufferSize = 28;
  1619. BYTE BadBuffer[BadBufferSize] =
  1620. {0x10, 0x00, 0x00, 0x00,
  1621. 0x01, 0x00, 0x00, 0x00,
  1622. 0x00, 0x00, 0x00, 0x00,
  1623. 0x00, 0x00, 0x00, 0x00};
  1624. BYTE GoodBuffer[GoodBufferSize] =
  1625. {0x1C, 0x00, 0x00, 0x00,
  1626. 0x20, 0x08, 0x00, 0x00,
  1627. 0x00, 0x00, 0x00, 0x00,
  1628. 0x00, 0x00, 0x00, 0x00,
  1629. 0x00, 0x00, 0x00, 0x00,
  1630. 0x00, 0x00, 0x00, 0x00,
  1631. 0x0A, 0x00, 0x00, 0x00};
  1632. if (*ptype == REG_BINARY && *pdata_len == BadBufferSize)
  1633. {
  1634. BOOL shouldChange = TRUE;
  1635. for (USHORT i = 0; i < BadBufferSize; i++)
  1636. {
  1637. if ((*pdata)[i] != BadBuffer[i])
  1638. {
  1639. shouldChange = FALSE;
  1640. break;
  1641. }
  1642. }
  1643. if (shouldChange)
  1644. {
  1645. BYTE *pnew_data;
  1646. if (NULL == (pnew_data = (BYTE *)malloc (sizeof(GoodBuffer))))
  1647. return ERROR_NOT_ENOUGH_MEMORY;
  1648. CopyMemory (pnew_data, GoodBuffer, sizeof(GoodBuffer));
  1649. free (*pdata);
  1650. *pdata = pnew_data;
  1651. *pdata_len = sizeof(GoodBuffer);
  1652. }
  1653. }
  1654. return ERROR_SUCCESS;
  1655. }
  1656. //+--------------------------------------------------------------------------
  1657. //
  1658. // Function: LoadTimeZone
  1659. //
  1660. // Synopsis: set the current timezone
  1661. //
  1662. // Arguments:
  1663. //
  1664. // Returns: Appropriate status code
  1665. //
  1666. // History: 20-Sep-99 HenryLee Created
  1667. //
  1668. //---------------------------------------------------------------------------
  1669. DWORD LoadTimeZone ()
  1670. {
  1671. const int TZNAME_SIZE = 32;
  1672. const TCHAR REGKEY_TIMEZONES[] =
  1673. _T("Software\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones");
  1674. const TCHAR REGVAL_TZI[] = _T("TZI");
  1675. const TCHAR REGVAL_DLT[] = _T("Dlt");
  1676. DWORD dwErr = ERROR_SUCCESS;
  1677. const int LINEBUFSIZE = 1024;
  1678. HKEY hKey = NULL;
  1679. INFCONTEXT InfContext;
  1680. TCHAR tcsTimeZone[LINEBUFSIZE];
  1681. TIME_ZONE_INFORMATION tzi;
  1682. APPLET_TIME_ZONE_INFORMATION atzi;
  1683. if (TIME_ZONE_ID_INVALID == GetTimeZoneInformation (&tzi))
  1684. {
  1685. Win32Printf (LogFile, "Could not get time zone information\r\n");
  1686. ChkErr (GetLastError());
  1687. }
  1688. if (SetupFindFirstLine(InputInf, SOURCE_SECTION, TIMEZONE, &InfContext))
  1689. {
  1690. TCHAR *buffer = NULL;
  1691. TCHAR *buffer2 = NULL;
  1692. ChkErr (GetInfField (&buffer, &InfContext, 1));
  1693. if (lstrcmp (tzi.StandardName, buffer) != 0)
  1694. {
  1695. _tcsncpy (tcsTimeZone, (TCHAR*) REGKEY_TIMEZONES, LINEBUFSIZE);
  1696. _tcsncat (tcsTimeZone, TEXT("\\"),
  1697. LINEBUFSIZE - _tcslen(tcsTimeZone) - 1);
  1698. _tcsncat (tcsTimeZone, buffer,
  1699. LINEBUFSIZE - _tcslen(tcsTimeZone) - 1);
  1700. if (RegOpenKey (HKEY_LOCAL_MACHINE, tcsTimeZone, &hKey) ==
  1701. ERROR_SUCCESS)
  1702. {
  1703. ULONG ulLen = sizeof(atzi);
  1704. if (ERROR_SUCCESS == RegQueryValueEx(hKey,
  1705. REGVAL_TZI, 0, NULL, (LPBYTE)&atzi, &ulLen))
  1706. {
  1707. tzi.Bias = atzi.Bias;
  1708. tzi.StandardBias = atzi.StandardBias;
  1709. tzi.DaylightBias = atzi.DaylightBias;
  1710. tzi.StandardDate = atzi.StandardDate;
  1711. tzi.DaylightDate = atzi.DaylightDate;
  1712. _tcsncpy (tzi.StandardName, buffer, TZNAME_SIZE);
  1713. ULONG ulLen = TZNAME_SIZE;
  1714. if (ERROR_SUCCESS != RegQueryValueEx(hKey, REGVAL_DLT,
  1715. 0, NULL, (LPBYTE) &tzi.DaylightName, &ulLen))
  1716. _tcscpy (tzi.DaylightName, TEXT(""));
  1717. // SetTimeZoneInformation will update local time
  1718. // since the UTC time has not changed
  1719. if (FALSE == SetTimeZoneInformation (&tzi))
  1720. dwErr = GetLastError();
  1721. if (Verbose)
  1722. printf ("TimeZone = %ws\n", tzi.StandardName);
  1723. }
  1724. }
  1725. }
  1726. free (buffer);
  1727. }
  1728. Err:
  1729. if (hKey != NULL)
  1730. RegCloseKey (hKey);
  1731. return dwErr;
  1732. }
  1733. //+--------------------------------------------------------------------------
  1734. //
  1735. // Function: SaveLocaleInfo
  1736. //
  1737. // Synopsis: formats a locale setting for registry update
  1738. //
  1739. // Arguments:
  1740. //
  1741. // Returns: Appropriate status code
  1742. //
  1743. // History: 20-Sep-99 HenryLee Created
  1744. //
  1745. //---------------------------------------------------------------------------
  1746. DWORD SaveLocaleInfo(HKEY hKey, LCID lcid, LCTYPE LCType, TCHAR *pIniString)
  1747. {
  1748. DWORD dwErr = ERROR_SUCCESS;
  1749. TCHAR ptcsBuffer[SIZE_128];
  1750. if (GetLocaleInfo( lcid,
  1751. LCType | LOCALE_NOUSEROVERRIDE,
  1752. ptcsBuffer,
  1753. SIZE_128 ))
  1754. {
  1755. dwErr = RegSetValueEx( hKey,
  1756. pIniString,
  1757. 0L,
  1758. REG_SZ,
  1759. (BYTE *)ptcsBuffer,
  1760. (lstrlen(ptcsBuffer)+1) * sizeof(TCHAR));
  1761. }
  1762. return dwErr;
  1763. }
  1764. //+--------------------------------------------------------------------------
  1765. //
  1766. // Function: LoadInstallUserLocale
  1767. //
  1768. // Synopsis: sets the current user locale
  1769. //
  1770. // Arguments:
  1771. //
  1772. // Returns: Appropriate status code
  1773. //
  1774. // History: 20-Sep-99 HenryLee Created
  1775. //
  1776. //---------------------------------------------------------------------------
  1777. DWORD LoadInstallUserLocale ()
  1778. {
  1779. HKEY hKey = NULL;
  1780. DWORD dwErr = ERROR_SUCCESS;
  1781. LCID lcid = 0;
  1782. TCHAR *ptcsUserLocale = NULL;
  1783. TCHAR ptcsOldLocale[25];
  1784. INFCONTEXT infcontext;
  1785. ULONG ulLen = 0;
  1786. if (SetupFindFirstLine(InputInf, SOURCE_SECTION, USERLOCALE, &infcontext))
  1787. {
  1788. dwErr = GetInfField (&ptcsUserLocale, &infcontext, 1);
  1789. if (ERROR_SUCCESS == dwErr)
  1790. {
  1791. lcid = (LCID)_tcstoul(ptcsUserLocale,NULL,16);
  1792. }
  1793. }
  1794. //
  1795. // Revert to current user locale if missing from INF
  1796. //
  1797. if (lcid == 0)
  1798. {
  1799. free (ptcsUserLocale);
  1800. return ERROR_SUCCESS;
  1801. }
  1802. //
  1803. // Make sure the locale is valid.
  1804. //
  1805. if (!IsValidLocale(lcid, LCID_INSTALLED))
  1806. {
  1807. ChkErr (ERROR_INSTALL_LANGUAGE_UNSUPPORTED);
  1808. }
  1809. //
  1810. // Set the locale value in the user's control panel international
  1811. // section of the registry.
  1812. //
  1813. ChkErr(RegOpenKeyEx(CurrentUser ? CurrentUser : HKEY_CURRENT_USER,
  1814. REGKEY_INTL,
  1815. 0L,
  1816. KEY_READ | KEY_WRITE,
  1817. &hKey ));
  1818. //
  1819. // Update user locale only if it's different
  1820. //
  1821. ulLen = sizeof (ptcsOldLocale);
  1822. if (ERROR_SUCCESS == RegQueryValueEx(hKey,
  1823. TEXT("Locale"),
  1824. NULL,NULL,
  1825. (BYTE*)ptcsOldLocale, &ulLen) &&
  1826. lstrcmp (ptcsUserLocale, ptcsOldLocale) == 0)
  1827. {
  1828. free (ptcsUserLocale);
  1829. RegCloseKey (hKey);
  1830. return ERROR_SUCCESS;
  1831. }
  1832. ChkErr (RegSetValueEx( hKey,
  1833. TEXT("Locale"),
  1834. 0L,
  1835. REG_SZ,
  1836. (LPBYTE)ptcsUserLocale,
  1837. (lstrlen(ptcsUserLocale)+1) * sizeof(TCHAR)));
  1838. //
  1839. // When the locale changes, update ALL registry information.
  1840. //
  1841. ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_ICALENDARTYPE, TEXT("iCalendarType")));
  1842. ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_ICOUNTRY, TEXT("iCountry")));
  1843. ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_ICURRDIGITS, TEXT("iCurrDigits")));
  1844. ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_ICURRENCY, TEXT("iCurrency")));
  1845. ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_IDATE, TEXT("iDate")));
  1846. ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_IDIGITS, TEXT("iDigits")));
  1847. ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_IFIRSTDAYOFWEEK, TEXT("iFirstDayOfWeek" )));
  1848. ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_IFIRSTWEEKOFYEAR, TEXT("iFirstWeekOfYear")));
  1849. ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_ILZERO, TEXT("iLzero")));
  1850. ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_IMEASURE, TEXT("iMeasure")));
  1851. ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_INEGCURR, TEXT("iNegCurr")));
  1852. ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_INEGNUMBER, TEXT("iNegNumber")));
  1853. ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_ITIME, TEXT("iTime")));
  1854. ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_ITIMEMARKPOSN, TEXT("iTimePrefix")));
  1855. ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_ITLZERO, TEXT("iTLZero")));
  1856. ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_IDIGITSUBSTITUTION,TEXT("NumShape")));
  1857. ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_S1159, TEXT("s1159")));
  1858. ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_S2359, TEXT("s2359")));
  1859. ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_SCOUNTRY, TEXT("sCountry")));
  1860. ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_SCURRENCY, TEXT("sCurrency")));
  1861. ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_SDATE, TEXT("sDate")));
  1862. ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_SDECIMAL, TEXT("sDecimal")));
  1863. ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_SGROUPING, TEXT("sGrouping")));
  1864. ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_SABBREVLANGNAME, TEXT("sLanguage")));
  1865. ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_SLIST, TEXT("sList")));
  1866. ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_SLONGDATE, TEXT("sLongDate")));
  1867. ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_SMONDECIMALSEP, TEXT("sMonDecimalSep")));
  1868. ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_SMONGROUPING, TEXT("sMonGrouping")));
  1869. ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_SMONTHOUSANDSEP, TEXT("sMonThousandSep")));
  1870. ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_SNATIVEDIGITS, TEXT("sNativeDigits")));
  1871. ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_SNEGATIVESIGN, TEXT("sNegativeSign")));
  1872. ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_SPOSITIVESIGN, TEXT("sPositiveSign")));
  1873. ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_SSHORTDATE, TEXT("sShortDate")));
  1874. ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_STHOUSAND, TEXT("sThousand")));
  1875. ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_STIME, TEXT("sTime")));
  1876. ChkErr(SaveLocaleInfo(hKey, lcid, LOCALE_STIMEFORMAT, TEXT("sTimeFormat")));
  1877. //
  1878. // Set the user's default locale in the system so that any new
  1879. // process will use the new locale.
  1880. //
  1881. if (CurrentUser == HKEY_CURRENT_USER)
  1882. NtSetDefaultLocale(TRUE, lcid);
  1883. Err:
  1884. //
  1885. // Flush the International key.
  1886. //
  1887. if (hKey != NULL)
  1888. {
  1889. RegFlushKey(hKey);
  1890. RegCloseKey(hKey);
  1891. }
  1892. if (ptcsUserLocale != NULL)
  1893. free (ptcsUserLocale);
  1894. //
  1895. // Return success.
  1896. //
  1897. return (dwErr);
  1898. }
  1899. #if 0
  1900. //+--------------------------------------------------------------------------
  1901. //
  1902. // Function: ReadVersionKey
  1903. //
  1904. // Synopsis: helper function that reads a value in CurrentVersion key
  1905. //
  1906. // Arguments:
  1907. //
  1908. // Returns: Appropriate status code
  1909. //
  1910. // History: 20-Sep-99 HenryLee Created
  1911. //
  1912. //---------------------------------------------------------------------------
  1913. DWORD ReadVersionKey (TCHAR *pValueName, TCHAR *pValue, ULONG ulLen)
  1914. {
  1915. HKEY hKey = NULL;
  1916. DWORD dwErr = ERROR_SUCCESS;
  1917. static const TCHAR REGKEY_VERSION[] =
  1918. TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion");
  1919. ChkErr (RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGKEY_VERSION,
  1920. NULL, KEY_READ, &hKey));
  1921. ChkErr (RegQueryValueEx(hKey,pValueName,NULL,NULL,(BYTE*)pValue, &ulLen));
  1922. Err:
  1923. if (hKey != NULL)
  1924. RegCloseKey (hKey);
  1925. return dwErr;
  1926. }
  1927. #endif
  1928. #if 0
  1929. //+--------------------------------------------------------------------------
  1930. //
  1931. // Function: GetDomainMembershipInfo
  1932. //
  1933. // Synopsis: return domain or workgroup name
  1934. //
  1935. // Arguments: [szname] -- output string for sysprep
  1936. //
  1937. // Returns: Appropriate status code
  1938. //
  1939. // History: 20-Sep-99 HenryLee Created
  1940. //
  1941. //---------------------------------------------------------------------------
  1942. NTSTATUS GetDomainMembershipInfo (TCHAR *szName)
  1943. {
  1944. NTSTATUS ntstatus;
  1945. POLICY_PRIMARY_DOMAIN_INFO* ppdi;
  1946. LSA_OBJECT_ATTRIBUTES loa;
  1947. LSA_HANDLE hLsa = 0;
  1948. loa.Length = sizeof(LSA_OBJECT_ATTRIBUTES);
  1949. loa.RootDirectory = NULL;
  1950. loa.ObjectName = NULL;
  1951. loa.Attributes = 0;
  1952. loa.SecurityDescriptor = NULL;
  1953. loa.SecurityQualityOfService = NULL;
  1954. ntstatus = LsaOpenPolicy(NULL, &loa, POLICY_VIEW_LOCAL_INFORMATION, &hLsa);
  1955. if (LSA_SUCCESS(ntstatus))
  1956. {
  1957. ntstatus = LsaQueryInformationPolicy( hLsa,
  1958. PolicyPrimaryDomainInformation,
  1959. (VOID **) &ppdi );
  1960. if( LSA_SUCCESS( ntstatus ) )
  1961. {
  1962. lstrcpy (szName, (ppdi->Sid > 0 ) ? TEXT("JoinDomain=") :
  1963. TEXT("JoinWorkgroup="));
  1964. lstrcat( szName, ppdi->Name.Buffer );
  1965. }
  1966. LsaClose (hLsa);
  1967. }
  1968. return (ntstatus);
  1969. }
  1970. #endif
  1971. #if 0
  1972. //+--------------------------------------------------------------------------
  1973. //
  1974. // Function: SysprepFile
  1975. //
  1976. // Synopsis: generates the sysprep unattended file
  1977. //
  1978. // Arguments: [dwLangGroup] -- language group to install
  1979. //
  1980. // Returns: Appropriate status code
  1981. //
  1982. // History: 20-Sep-99 HenryLee Created
  1983. //
  1984. //---------------------------------------------------------------------------
  1985. DWORD SysprepFile (DWORD dwLangGroup)
  1986. {
  1987. HANDLE hFile = INVALID_HANDLE_VALUE;
  1988. DWORD dwErr = ERROR_SUCCESS;
  1989. DWORD dwTimeZone = 0;
  1990. INFCONTEXT InfContext;
  1991. TCHAR * pFullName = NULL;
  1992. TCHAR * pOrgName = NULL;
  1993. const int MAX_WORKGROUP_LENGTH = 15;
  1994. const int NAME_LENGTH = 128;
  1995. const TCHAR REGVAL_FULLNAME[] = TEXT("RegisteredOwner");
  1996. const TCHAR REGVAL_ORGNAME[] = TEXT("RegisteredOrganization");
  1997. const TCHAR REGVAL_INSTALLPATH[] = TEXT("SourcePath");
  1998. TCHAR szFullName[NAME_LENGTH] = TEXT("");
  1999. TCHAR szOrgName[NAME_LENGTH] = TEXT("");
  2000. TCHAR szInstall[MAX_PATH];
  2001. TCHAR szTargetPath[MAX_PATH];
  2002. TCHAR szComputerName[NAME_LENGTH];
  2003. TCHAR *pTargetPath;
  2004. CHAR *pFile = NULL;
  2005. ULONG ulLen;
  2006. TCHAR szJoin [MAX_WORKGROUP_LENGTH + 1 + NAME_LENGTH];
  2007. CHAR szSysprep[] = "[Unattended]\r\n"
  2008. "OemSkipEula=Yes\r\n"
  2009. "InstallFilesPath=%ws\r\n"
  2010. "TargetPath=%ws\r\n"
  2011. "\r\n"
  2012. "[GuiUnattended]\r\n"
  2013. "AdminPassword=*\r\n"
  2014. "OEMSkipRegional=1\r\n"
  2015. "TimeZone=%x\r\n"
  2016. "OemSkipWelcome=1\r\n"
  2017. "\r\n"
  2018. "[UserData]\r\n"
  2019. "FullName=\"%ws\"\r\n"
  2020. "OrgName=\"%ws\"\r\n"
  2021. "ComputerName=%ws\r\n"
  2022. "\r\n"
  2023. "[Identification]\r\n"
  2024. "%ws\r\n"
  2025. "\r\n"
  2026. "[RegionalSettings]\r\n"
  2027. "LanguageGroup=%d\r\n"
  2028. "\r\n"
  2029. "[Networking]\r\n"
  2030. "InstallDefaultComponents=Yes\r\n";
  2031. if (FALSE == GetWindowsDirectory ((TCHAR*) szTargetPath, MAX_PATH))
  2032. ChkErr (GetLastError());
  2033. if (szTargetPath[1] == ':' && szTargetPath[2] == '\\')
  2034. pTargetPath = &szTargetPath[2];
  2035. else
  2036. pTargetPath = &szTargetPath[0];
  2037. ulLen = NAME_LENGTH;
  2038. if (FALSE == GetComputerName ((TCHAR*) szComputerName, &ulLen))
  2039. ChkErr (GetLastError());
  2040. if (SetupFindFirstLine(InputInf, SOURCE_SECTION, FULLNAME, &InfContext))
  2041. {
  2042. ChkErr (GetInfField (&pFullName, &InfContext, 1));
  2043. }
  2044. else // use the current fullname
  2045. {
  2046. ChkErr(ReadVersionKey((TCHAR*)REGVAL_FULLNAME,
  2047. szFullName, sizeof(szFullName)));
  2048. pFullName = szFullName;
  2049. }
  2050. if (SetupFindFirstLine(InputInf, SOURCE_SECTION, ORGNAME, &InfContext))
  2051. {
  2052. ChkErr (GetInfField (&pOrgName, &InfContext, 1));
  2053. }
  2054. else // use the current org name
  2055. {
  2056. ChkErr(ReadVersionKey((TCHAR*)REGVAL_ORGNAME,
  2057. szFullName, sizeof(szFullName)));
  2058. pFullName = szOrgName;
  2059. }
  2060. if (ERROR_SUCCESS != ReadVersionKey((TCHAR*)REGVAL_INSTALLPATH,
  2061. szInstall, sizeof(szInstall)))
  2062. {
  2063. lstrcpy ((TCHAR *)szInstall, TEXT("")); // prompt for media?
  2064. }
  2065. if(!LSA_SUCCESS(GetDomainMembershipInfo(szJoin)))
  2066. lstrcpy (szJoin, TEXT(""));
  2067. if ((pFile = (CHAR *) malloc (4096)) == NULL)
  2068. ChkErr (ERROR_NOT_ENOUGH_MEMORY);
  2069. wsprintfA (pFile, szSysprep, szInstall, pTargetPath, dwTimeZone,
  2070. pFullName, pOrgName, szComputerName, szJoin, dwLangGroup);
  2071. hFile = CreateFile (
  2072. TEXT("sysprep.inf"),
  2073. GENERIC_READ | GENERIC_WRITE,
  2074. 0, // No sharing.
  2075. NULL, // No inheritance
  2076. CREATE_ALWAYS,
  2077. FILE_ATTRIBUTE_NORMAL,
  2078. NULL // No template file.
  2079. );
  2080. if (INVALID_HANDLE_VALUE == hFile)
  2081. ChkErr (GetLastError());
  2082. if (FALSE == WriteFile (hFile, pFile, lstrlenA(pFile), &ulLen, NULL))
  2083. ChkErr (GetLastError());
  2084. Err:
  2085. if (pFullName != NULL)
  2086. free (pFullName);
  2087. if (pOrgName != NULL)
  2088. free (pOrgName);
  2089. if (pFile != NULL)
  2090. free (pFile);
  2091. if (hFile != INVALID_HANDLE_VALUE)
  2092. CloseHandle (hFile);
  2093. return dwErr;
  2094. }
  2095. #endif
  2096. //+---------------------------------------------------------------------------
  2097. //
  2098. // Function: LoadSystem
  2099. //
  2100. // Synopsis: load system settings
  2101. //
  2102. // Arguments:
  2103. //
  2104. // Returns: Appropriate status code
  2105. //
  2106. // History: 20-Sep-99 HenryLee Created
  2107. //
  2108. //----------------------------------------------------------------------------
  2109. DWORD LoadSystem(int argc, char *argv[])
  2110. {
  2111. DWORD dwErr = ERROR_SUCCESS;
  2112. DWORD ccLen;
  2113. WCHAR *pBuf = NULL;
  2114. HKEY hKey;
  2115. WCHAR *pwMigrationPath = NULL;
  2116. int i;
  2117. DWORD dwInfCount = 0;
  2118. if ((dwErr = LoadVerifyOSLang()) != ERROR_SUCCESS)
  2119. return dwErr;
  2120. // If the schedule flag is set, write a run once to schedule
  2121. // applying the system settings.
  2122. if (SchedSystem)
  2123. {
  2124. WCHAR wcsModule[MAX_PATH];
  2125. DWORD ccModule = MAX_PATH;
  2126. if (0 == GetModuleFileName (NULL, wcsModule, ccModule))
  2127. {
  2128. dwErr = GetLastError();
  2129. goto cleanup;
  2130. }
  2131. // Convert the migration path to unicode.
  2132. dwErr = MakeUnicode( MigrationPath, &pwMigrationPath );
  2133. if (dwErr != ERROR_SUCCESS)
  2134. goto cleanup;
  2135. // Build a command line containing:
  2136. // /p parameter, to indicate running the user portion
  2137. // /s parameter, to indicate migrating system settings
  2138. // path to migration.inf
  2139. ccLen = wcslen(wcsModule) + wcslen(SCHED_PARAMS) + 1;
  2140. pBuf = (WCHAR *) malloc( ccLen * sizeof(WCHAR) );
  2141. if (pBuf == NULL)
  2142. {
  2143. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  2144. goto cleanup;
  2145. }
  2146. wcscpy( pBuf, wcsModule );
  2147. wcscat( pBuf, SCHED_PARAMS);
  2148. // Open the run once key.
  2149. dwErr = RegOpenKeyEx(CurrentUser ? CurrentUser : HKEY_CURRENT_USER,
  2150. L"Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce",
  2151. 0, KEY_WRITE, &hKey );
  2152. if (dwErr != ERROR_SUCCESS)
  2153. goto cleanup;
  2154. // Write the command to the registry.
  2155. dwErr = RegSetValueEx( hKey, TEXT("loadstate"), 0, REG_SZ,
  2156. (UCHAR *) pBuf, ccLen*sizeof(WCHAR) );
  2157. if (dwErr != ERROR_SUCCESS)
  2158. goto cleanup;
  2159. RegCloseKey( hKey );
  2160. dwErr = RegCreateKeyEx(CurrentUser ? CurrentUser : HKEY_CURRENT_USER,
  2161. L"Software\\Microsoft\\Windows\\CurrentVersion\\Loadstate",
  2162. 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL );
  2163. if (dwErr != ERROR_SUCCESS)
  2164. goto cleanup;
  2165. // Write LogFile path to registry
  2166. dwErr = RegSetValueEx( hKey, TEXT("Logfile"), 0, REG_SZ,
  2167. (UCHAR *)szLogFile, (_tcslen(szLogFile) * sizeof(TCHAR)) );
  2168. if (dwErr != ERROR_SUCCESS)
  2169. goto cleanup;
  2170. // Write Migration path to registry
  2171. dwErr = RegSetValueEx( hKey, TEXT("Store"), 0, REG_SZ,
  2172. (UCHAR *)pwMigrationPath, (_tcslen(pwMigrationPath) * sizeof(TCHAR)) );
  2173. if (dwErr != ERROR_SUCCESS)
  2174. goto cleanup;
  2175. TCHAR szInfFile[MAX_PATH + 1];
  2176. TCHAR szFullInfFile[MAX_PATH + 1];
  2177. TCHAR szKeyName[6];
  2178. TCHAR *ptsFileNamePart;
  2179. // Prevent KeyName buffer overflow
  2180. if ( argc > 99)
  2181. {
  2182. if (Verbose)
  2183. {
  2184. Win32Printf(LogFile, "ERROR: Too many command line arguments [%d]\r\n", argc);
  2185. }
  2186. dwErr = ERROR_INVALID_PARAMETER;
  2187. goto cleanup;
  2188. }
  2189. // Write InfFile paths to registry
  2190. for (i = 1; i < argc; i++)
  2191. {
  2192. if ((argv[i][0] == '/' || argv[i][0] == '-') &&
  2193. (tolower(argv[i][1]) == 'i'))
  2194. {
  2195. i++;
  2196. _stprintf(szKeyName, TEXT("Inf%d"), ++dwInfCount);
  2197. if (0 == MultiByteToWideChar (GetACP(), 0, argv[i], -1, szInfFile, MAX_PATH))
  2198. {
  2199. dwErr = GetLastError();
  2200. goto cleanup;
  2201. }
  2202. dwErr = GetFullPathName( szInfFile,
  2203. MAX_PATH,
  2204. szFullInfFile,
  2205. &ptsFileNamePart);
  2206. if (0 == dwErr)
  2207. {
  2208. dwErr = GetLastError();
  2209. goto cleanup;
  2210. }
  2211. dwErr = RegSetValueEx( hKey, szKeyName, 0, REG_SZ,
  2212. (UCHAR *)szFullInfFile, (_tcslen(szFullInfFile) * sizeof(TCHAR)) );
  2213. if (dwErr != ERROR_SUCCESS)
  2214. goto cleanup;
  2215. }
  2216. }
  2217. RegCloseKey( hKey );
  2218. cleanup:
  2219. if (dwErr != ERROR_SUCCESS)
  2220. LogFormatError (dwErr);
  2221. free( pBuf );
  2222. free( pwMigrationPath );
  2223. }
  2224. else
  2225. {
  2226. if (!CopySystem)
  2227. return ERROR_SUCCESS;
  2228. ChkErr (LoadNetShares());
  2229. ChkErr (LoadPrinters());
  2230. dwErr = InitializeRasApi();
  2231. if ( dwErr == ERROR_SUCCESS )
  2232. {
  2233. ChkErr (LoadRas());
  2234. }
  2235. else
  2236. {
  2237. // No problem, just skip Ras processing
  2238. dwErr = ERROR_SUCCESS;
  2239. }
  2240. if (CopyUser == FALSE)
  2241. {
  2242. if (CurrentUser == NULL)
  2243. CurrentUser = HKEY_CURRENT_USER;
  2244. ChkErr(InitializeHash());
  2245. }
  2246. ChkErr(CopyInf (ACCESS_SECTION));
  2247. ChkErr(CopyInf (DESKTOP_SECTION));
  2248. ChkErr(LoadKeyboardLayouts());
  2249. ChkErr (LoadTimeZone());
  2250. ChkErr (LoadInstallUserLocale());
  2251. }
  2252. Err:
  2253. return dwErr;
  2254. }