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.

1767 lines
43 KiB

  1. #include "setupp.h"
  2. #pragma hdrstop
  3. #define INTL_ANSWER_FILE L"intl.txt"
  4. #define INTL_LANG_SECTION L"regionalsettings"
  5. #define INTL_LOCALE L"userlocale"
  6. #define INTL_KEYBOARD L"inputlocale"
  7. // This turns on some debug spew that lists all the available locales, geo
  8. // locations, and keyboards.
  9. #define INTL_LIST_OPTIONS 0
  10. #define LANG_LIST_INCREMENT 10
  11. POOBE_LOCALE_INFO LanguageList = NULL;
  12. DWORD LanguageListSize;
  13. DWORD LanguageIndex;
  14. DWORD DefaultID;
  15. DWORD DefaultIndex;
  16. typedef struct tagPHONEENTRY {
  17. LPWSTR Country;
  18. LPWSTR TollFreeNumber;
  19. LPWSTR TollNumber;
  20. } PHONEENTRY, *PPHONEENTRY;
  21. PWSTR PhoneList = NULL;
  22. DWORD PhoneListSize;
  23. DWORD PhoneListLength;
  24. //
  25. // Boolean value indicating whether we're doing a subset of gui-mode setup.
  26. //
  27. BOOL OobeSetup = FALSE;
  28. //
  29. // We need a global variable for OCM, coresponding to the local variable in
  30. // InstallWindowsNT().
  31. //
  32. #ifdef _OCM
  33. PVOID g_OcManagerContext;
  34. #endif
  35. BOOL
  36. WINAPI
  37. SetupGetProductType(
  38. PWSTR Product,
  39. PDWORD pSkuFlags
  40. )
  41. {
  42. Product[0] = 0;
  43. *pSkuFlags = 0;
  44. return TRUE;
  45. }
  46. PID3_RESULT
  47. WINAPI
  48. SetupPidGen3(
  49. PWSTR Pid3,
  50. DWORD SkuFlags,
  51. PWSTR OemId,
  52. BOOL Batch,
  53. PWSTR Pid2,
  54. LPBYTE lpPid3,
  55. LPBOOL Compliance
  56. )
  57. {
  58. if ( !InitializePidVariables() ) {
  59. SetupDebugPrint( L"SETUP: InitializePidVariables failed" );
  60. return PID_INVALID;
  61. }
  62. if ( !SetPid30Variables( Pid3 ) ) {
  63. SetupDebugPrint( L"SETUP: SetPid30Variables failed" );
  64. return PID_INVALID;
  65. }
  66. if ( !ValidateAndSetPid30() ) {
  67. SetupDebugPrint( L"SETUP: ValidateAndSetPid30 failed" );
  68. return PID_INVALID;
  69. }
  70. if(!SetProductIdInRegistry()) {
  71. SetupDebugPrint( L"SETUP: SetProductIdInRegistry failed" );
  72. return PID_INVALID;
  73. }
  74. return PID_VALID;
  75. }
  76. BOOL
  77. WINAPI
  78. SetupGetValidEula(
  79. PCWSTR Eula,
  80. PWSTR Path
  81. )
  82. {
  83. return TRUE;
  84. }
  85. BOOL
  86. CheckLangListSize(
  87. DWORD StructSize
  88. )
  89. {
  90. PVOID NewList;
  91. //
  92. // Check to make sure the LanguageList has at least 1 unused element.
  93. // If not, make it bigger.
  94. //
  95. if ( LanguageIndex == LanguageListSize ) {
  96. LanguageListSize *= 2;
  97. NewList = MyRealloc(
  98. LanguageList,
  99. LanguageListSize * StructSize
  100. );
  101. if ( NewList ) {
  102. LanguageList = NewList;
  103. } else {
  104. return FALSE;
  105. }
  106. }
  107. return TRUE;
  108. }
  109. VOID
  110. WINAPI
  111. SetupDestroyLanguageList(
  112. IN POOBE_LOCALE_INFO LanguageList,
  113. IN DWORD Count
  114. )
  115. {
  116. DWORD i;
  117. if ( LanguageList ) {
  118. for ( i=0; i < Count; i++ ) {
  119. if ( LanguageList + i ) {
  120. MyFree( LanguageList[i].Name );
  121. }
  122. }
  123. MyFree( LanguageList );
  124. }
  125. }
  126. BOOL
  127. CALLBACK
  128. EnumLocalesProc(
  129. PWSTR pszLocale
  130. )
  131. {
  132. BOOL b;
  133. LCID Locale;
  134. TCHAR LanguageName[128];
  135. POOBE_LOCALE_INFO pLocaleInfo;
  136. Locale = wcstoul (pszLocale, NULL, 16);
  137. b = GetLocaleInfo (
  138. Locale,
  139. LOCALE_SLANGUAGE | LOCALE_NOUSEROVERRIDE,
  140. LanguageName,
  141. sizeof(LanguageName) / sizeof(TCHAR)
  142. );
  143. MYASSERT(b);
  144. if ( !b ) {
  145. return FALSE;
  146. }
  147. //
  148. // Add it to our global array
  149. //
  150. if ( !CheckLangListSize( sizeof(OOBE_LOCALE_INFO) ) ) {
  151. SetupDestroyLanguageList( LanguageList, LanguageIndex );
  152. LanguageList = NULL;
  153. return FALSE;
  154. }
  155. pLocaleInfo = (POOBE_LOCALE_INFO)LanguageList + LanguageIndex;
  156. pLocaleInfo->Name = MyMalloc( (lstrlen(LanguageName) + 1) * sizeof(TCHAR) );
  157. if ( !pLocaleInfo->Name ) {
  158. SetupDestroyLanguageList( LanguageList, LanguageIndex );
  159. LanguageList = NULL;
  160. return FALSE;
  161. }
  162. lstrcpy( pLocaleInfo->Name, LanguageName );
  163. pLocaleInfo->Id = Locale;
  164. pLocaleInfo->Installed = IsValidLocale(
  165. Locale,
  166. LCID_INSTALLED
  167. );
  168. if ( Locale == DefaultID ) {
  169. DefaultIndex = LanguageIndex;
  170. }
  171. LanguageIndex++;
  172. return TRUE;
  173. }
  174. int
  175. __cdecl
  176. LocaleCompare(
  177. const void *arg1,
  178. const void *arg2
  179. )
  180. {
  181. return lstrcmp(
  182. ((POOBE_LOCALE_INFO)arg1)->Name,
  183. ((POOBE_LOCALE_INFO)arg2)->Name
  184. );
  185. }
  186. BOOL
  187. WINAPI
  188. SetupGetLocaleOptions(
  189. IN DWORD OptionalDefault,
  190. OUT POOBE_LOCALE_INFO *ReturnList,
  191. OUT PDWORD Items,
  192. OUT PDWORD Default
  193. )
  194. {
  195. BOOL bReturn = FALSE;
  196. DWORD i;
  197. //
  198. // Init our global variables
  199. //
  200. ASSERT_HEAP_IS_VALID();
  201. *ReturnList = NULL;
  202. MYASSERT( LanguageList == NULL );
  203. LanguageListSize = LANG_LIST_INCREMENT;
  204. LanguageList = MyMalloc( LanguageListSize * sizeof(OOBE_LOCALE_INFO));
  205. if ( !LanguageList ) {
  206. goto exit;
  207. }
  208. LanguageIndex = 0;
  209. DefaultID = OptionalDefault ? OptionalDefault : GetUserDefaultLCID();
  210. DefaultIndex = 0;
  211. EnumSystemLocales ( EnumLocalesProc , LCID_INSTALLED );
  212. if ( LanguageList ) {
  213. // Success
  214. qsort(
  215. LanguageList,
  216. LanguageIndex,
  217. sizeof( OOBE_LOCALE_INFO ),
  218. LocaleCompare
  219. );
  220. for (i=0; i<LanguageIndex; i++) {
  221. if (LanguageList[i].Id == DefaultID) {
  222. DefaultIndex = i;
  223. break;
  224. }
  225. }
  226. #if INTL_LIST_OPTIONS
  227. for (i=0; i<LanguageIndex; i++) {
  228. SetupDebugPrint2( L"Setup: SetupGetLocaleOptions|%x|%s",
  229. LanguageList[i].Id,
  230. LanguageList[i].Name );
  231. }
  232. #endif
  233. *ReturnList = LanguageList;
  234. LanguageList = NULL;
  235. *Items = LanguageIndex;
  236. *Default = DefaultIndex;
  237. bReturn = TRUE;
  238. }
  239. exit:
  240. ASSERT_HEAP_IS_VALID();
  241. return bReturn;
  242. }
  243. BOOL
  244. CALLBACK
  245. EnumGeoInfoProc(
  246. GEOID GeoID
  247. )
  248. {
  249. TCHAR pData[128];
  250. POOBE_LOCALE_INFO pGeoInfo;
  251. //
  252. // Add it to our global array
  253. //
  254. if ( !CheckLangListSize( sizeof(OOBE_LOCALE_INFO) ) ) {
  255. SetupDestroyLanguageList( LanguageList, LanguageIndex );
  256. LanguageList = NULL;
  257. return FALSE;
  258. }
  259. if( !GetGeoInfo(
  260. GeoID,
  261. GEO_FRIENDLYNAME,
  262. pData,
  263. sizeof(pData) / sizeof(TCHAR),
  264. 0
  265. )) {
  266. // Skip this one.
  267. MYASSERT(0);
  268. return TRUE;
  269. }
  270. pGeoInfo = (POOBE_LOCALE_INFO)LanguageList + LanguageIndex;
  271. pGeoInfo->Name = MyMalloc( (lstrlen(pData) + 1) * sizeof(TCHAR) );
  272. if ( !pGeoInfo->Name ) {
  273. SetupDestroyLanguageList( LanguageList, LanguageIndex );
  274. LanguageList = NULL;
  275. return FALSE;
  276. }
  277. lstrcpy( pGeoInfo->Name, pData );
  278. pGeoInfo->Id = GeoID;
  279. pGeoInfo->Installed = TRUE;
  280. if ( GeoID == (GEOID)DefaultID ) {
  281. DefaultIndex = LanguageIndex;
  282. }
  283. LanguageIndex++;
  284. return TRUE;
  285. }
  286. BOOL
  287. WINAPI
  288. SetupGetGeoOptions(
  289. IN DWORD OptionalDefault,
  290. OUT POOBE_LOCALE_INFO *ReturnList,
  291. OUT PDWORD Items,
  292. OUT PDWORD Default
  293. )
  294. {
  295. BOOL bReturn = FALSE;
  296. DWORD i;
  297. //
  298. // Init our global variables
  299. //
  300. ASSERT_HEAP_IS_VALID();
  301. *ReturnList = NULL;
  302. MYASSERT( LanguageList == NULL );
  303. LanguageListSize = LANG_LIST_INCREMENT;
  304. LanguageList = MyMalloc( LanguageListSize * sizeof(OOBE_LOCALE_INFO));
  305. if ( !LanguageList ) {
  306. goto exit;
  307. }
  308. LanguageIndex = 0;
  309. DefaultID = OptionalDefault ? OptionalDefault : GetUserGeoID( GEOCLASS_NATION );
  310. DefaultIndex = 0;
  311. bReturn = EnumSystemGeoID(
  312. GEOCLASS_NATION,
  313. 0,
  314. EnumGeoInfoProc
  315. );
  316. MYASSERT(bReturn);
  317. if ( bReturn && LanguageList ) {
  318. // Success
  319. qsort(
  320. LanguageList,
  321. LanguageIndex,
  322. sizeof( OOBE_LOCALE_INFO ),
  323. LocaleCompare
  324. );
  325. for (i=0; i<LanguageIndex; i++) {
  326. if (LanguageList[i].Id == DefaultID) {
  327. DefaultIndex = i;
  328. break;
  329. }
  330. }
  331. #if INTL_LIST_OPTIONS
  332. for (i=0; i<LanguageIndex; i++) {
  333. SetupDebugPrint2( L"Setup: SetupGetGeoOptions|%d|%s",
  334. LanguageList[i].Id,
  335. LanguageList[i].Name );
  336. }
  337. #endif
  338. bReturn = TRUE;
  339. *ReturnList = LanguageList;
  340. LanguageList = NULL;
  341. *Items = LanguageIndex;
  342. *Default = DefaultIndex;
  343. }
  344. exit:
  345. ASSERT_HEAP_IS_VALID();
  346. return bReturn;
  347. }
  348. BOOL
  349. WINAPI
  350. SetupGetKeyboardOptions(
  351. IN DWORD OptionalDefault,
  352. OUT POOBE_LOCALE_INFO *ReturnList,
  353. OUT PDWORD Items,
  354. OUT PDWORD Default
  355. )
  356. {
  357. DWORD DefaultKeyboard;
  358. DWORD i;
  359. BOOL bReturn = FALSE;
  360. TCHAR pData[128];
  361. TCHAR Substitute[9];
  362. POOBE_LOCALE_INFO pLocaleInfo;
  363. DWORD rc;
  364. HKEY hLangKey = NULL;
  365. HKEY hLangSubKey = NULL;
  366. DWORD Index;
  367. TCHAR SubKeyName[9];
  368. DWORD SubKeyNameLength;
  369. DWORD DataSize;
  370. DWORD Type;
  371. //
  372. // Initialize our variables
  373. //
  374. ASSERT_HEAP_IS_VALID();
  375. *ReturnList = NULL;
  376. MYASSERT( LanguageList == NULL );
  377. LanguageListSize = LANG_LIST_INCREMENT;
  378. LanguageList = MyMalloc( LanguageListSize * sizeof(OOBE_LOCALE_INFO));
  379. if ( !LanguageList ) {
  380. goto exit;
  381. }
  382. LanguageIndex = 0;
  383. // DefaultIndex = -1;
  384. *Default = 0;
  385. if (OptionalDefault) {
  386. DefaultKeyboard = OptionalDefault;
  387. } else {
  388. //
  389. // Lookup default keyboard in the registry
  390. //
  391. rc = RegOpenKeyEx( HKEY_USERS,
  392. L".DEFAULT\\Keyboard Layout\\Preload",
  393. 0,
  394. KEY_READ,
  395. &hLangKey );
  396. if( rc != NO_ERROR ) {
  397. SetupDebugPrint1( L"Setup: SetupGetKeyboardOptions - RegOpenKeyEx(.DEFAULT\\Keyboard Layout\\Preload) failed (%d)", rc );
  398. MYASSERT(0);
  399. goto exit;
  400. }
  401. DataSize = sizeof(pData);
  402. rc = RegQueryValueEx(
  403. hLangKey,
  404. L"1",
  405. NULL,
  406. &Type,
  407. (LPBYTE)pData,
  408. &DataSize
  409. );
  410. RegCloseKey( hLangKey );
  411. hLangKey = NULL;
  412. if( rc != NO_ERROR ) {
  413. SetupDebugPrint1( L"Setup: SetupGetKeyboardOptions - RegQueryValueEx(1) failed (%d)", rc );
  414. MYASSERT(0);
  415. goto exit;
  416. }
  417. DefaultKeyboard = wcstoul( pData, NULL, 16 );
  418. //
  419. // Now we look in the Substitutes key to see whether there is a
  420. // substitute there.
  421. //
  422. if( RegOpenKeyEx( HKEY_USERS,
  423. L".DEFAULT\\Keyboard Layout\\Substitutes",
  424. 0,
  425. KEY_READ,
  426. &hLangKey ) == NO_ERROR) {
  427. DataSize = sizeof(Substitute);
  428. if( (RegQueryValueEx( hLangKey,
  429. pData,
  430. NULL,
  431. &Type,
  432. (LPBYTE)Substitute,
  433. &DataSize ) == NO_ERROR) &&
  434. (Type == REG_SZ)
  435. ) {
  436. DefaultKeyboard = wcstoul( Substitute, NULL, 16 );
  437. }
  438. RegCloseKey(hLangKey);
  439. hLangKey = NULL;
  440. }
  441. }
  442. rc = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  443. L"System\\CurrentControlSet\\Control\\Keyboard Layouts",
  444. 0,
  445. KEY_ENUMERATE_SUB_KEYS | KEY_READ,
  446. &hLangKey );
  447. if( rc != NO_ERROR ) {
  448. SetupDebugPrint1( L"Setup: SetupGetKeyboardOptions - RegOpenKeyEx(System\\CurrentControlSet\\Control\\Keyboard Layouts) failed (%d)", rc );
  449. goto exit;
  450. }
  451. for( Index = 0; ; Index++ ) {
  452. SubKeyNameLength = sizeof(SubKeyName) / sizeof(TCHAR);
  453. rc = RegEnumKeyEx( hLangKey,
  454. Index,
  455. SubKeyName,
  456. &SubKeyNameLength,
  457. NULL,
  458. NULL,
  459. NULL,
  460. NULL );
  461. //
  462. // Did we error?
  463. //
  464. if( rc != ERROR_SUCCESS ) {
  465. //
  466. // Are we done?
  467. //
  468. if( rc != ERROR_NO_MORE_ITEMS ) {
  469. SetupDebugPrint2( L"Setup: SetupGetKeyboardOptions - RegEnumKeyEx failed (%d). Index = %d", rc, Index );
  470. MYASSERT(0);
  471. }
  472. break;
  473. }
  474. rc = RegOpenKeyEx( hLangKey,
  475. SubKeyName,
  476. 0,
  477. KEY_READ,
  478. &hLangSubKey );
  479. if( rc != NO_ERROR ) {
  480. SetupDebugPrint2( L"Setup: SetupGetKeyboardOptions - RegOpenKeyEx(%s) failed (%d)", SubKeyName, rc );
  481. MYASSERT(0);
  482. continue;
  483. }
  484. DataSize = sizeof(pData);
  485. rc = RegQueryValueEx(
  486. hLangSubKey,
  487. L"Layout Text",
  488. NULL,
  489. &Type,
  490. (LPBYTE)pData,
  491. &DataSize
  492. );
  493. RegCloseKey( hLangSubKey );
  494. hLangSubKey = NULL;
  495. if( rc != NO_ERROR ) {
  496. SetupDebugPrint2( L"Setup: SetupGetKeyboardOptions - RegQueryValueEx(Layout Text) for %s failed (%d)", SubKeyName, rc );
  497. continue;
  498. }
  499. //
  500. // Add it to our global array
  501. //
  502. if ( !CheckLangListSize( sizeof(OOBE_LOCALE_INFO) ) ) {
  503. SetupDestroyLanguageList( LanguageList, LanguageIndex );
  504. LanguageList = NULL;
  505. goto exit;
  506. }
  507. pLocaleInfo = (POOBE_LOCALE_INFO)LanguageList + LanguageIndex;
  508. pLocaleInfo->Name = MyMalloc( (lstrlen(pData) + 1) * sizeof(TCHAR) );
  509. if ( !pLocaleInfo->Name ) {
  510. SetupDestroyLanguageList( LanguageList, LanguageIndex );
  511. LanguageList = NULL;
  512. goto exit;
  513. }
  514. lstrcpy( pLocaleInfo->Name, pData );
  515. pLocaleInfo->Id = wcstoul( SubKeyName, NULL, 16 );
  516. pLocaleInfo->Installed = TRUE;
  517. LanguageIndex++;
  518. }
  519. RegCloseKey( hLangKey );
  520. hLangKey = NULL;
  521. qsort(
  522. LanguageList,
  523. LanguageIndex,
  524. sizeof( OOBE_LOCALE_INFO ),
  525. LocaleCompare
  526. );
  527. for (i=0; i<LanguageIndex; i++) {
  528. if (LanguageList[i].Id == DefaultKeyboard) {
  529. *Default = i;
  530. break;
  531. }
  532. }
  533. #if INTL_LIST_OPTIONS
  534. for (i=0; i<LanguageIndex; i++) {
  535. SetupDebugPrint2( L"Setup: SetupGetKeyboardOptions|%x|%s",
  536. LanguageList[i].Id,
  537. LanguageList[i].Name );
  538. }
  539. #endif
  540. bReturn = TRUE;
  541. *ReturnList = LanguageList;
  542. LanguageList = NULL;
  543. *Items = LanguageIndex;
  544. exit:
  545. if ( hLangKey ) {
  546. RegCloseKey( hLangKey );
  547. }
  548. if ( hLangSubKey ) {
  549. RegCloseKey( hLangSubKey );
  550. }
  551. ASSERT_HEAP_IS_VALID();
  552. return bReturn;
  553. }
  554. BOOL
  555. WINAPI
  556. SetupSetIntlOptions(
  557. DWORD LocationIndex,
  558. DWORD LanguageIndex,
  559. DWORD KeyboardIndex
  560. )
  561. {
  562. WCHAR PathBuffer[MAX_PATH];
  563. WCHAR KeyValue[128];
  564. WCHAR CmdLine[MAX_PATH];
  565. BOOL bResult;
  566. SetupDebugPrint3(
  567. L"SetupSetIntlOptions: Location = %d, Language = 0x%08x, Keyboard = 0x%08x",
  568. LocationIndex,
  569. LanguageIndex,
  570. KeyboardIndex );
  571. GetSystemDirectory( PathBuffer, MAX_PATH );
  572. pSetupConcatenatePaths( PathBuffer, INTL_ANSWER_FILE, MAX_PATH, NULL );
  573. DeleteFile( PathBuffer );
  574. //
  575. // Write language value
  576. //
  577. wsprintf(
  578. KeyValue,
  579. L"\"%08x\"",
  580. LanguageIndex
  581. );
  582. WritePrivateProfileString(
  583. INTL_LANG_SECTION,
  584. INTL_LOCALE,
  585. KeyValue,
  586. PathBuffer
  587. );
  588. //
  589. // Write keyboard value
  590. //
  591. wsprintf(
  592. KeyValue,
  593. L"\"%04x:%08x\"",
  594. KeyboardIndex & 0x0000ffff,
  595. KeyboardIndex
  596. );
  597. WritePrivateProfileString(
  598. INTL_LANG_SECTION,
  599. INTL_KEYBOARD,
  600. KeyValue,
  601. PathBuffer
  602. );
  603. //
  604. // Call intl.cpl to do the work
  605. //
  606. wsprintf(
  607. CmdLine,
  608. L"/f:\"%s\" /s:\"%s\"",
  609. PathBuffer,
  610. LegacySourcePath
  611. );
  612. InvokeControlPanelApplet(L"intl.cpl",L"",0,CmdLine);
  613. DeleteFile( PathBuffer );
  614. //
  615. // Set the GEO location
  616. //
  617. bResult = SetUserGeoID( LocationIndex );
  618. if ( !bResult ) {
  619. SetupDebugPrint1(
  620. L"SetupSetIntlOptions: SetUserGeoID failed. Status = %d.",
  621. GetLastError()
  622. );
  623. }
  624. MYASSERT( bResult );
  625. return bResult;
  626. }
  627. //+---------------------------------------------------------------------------
  628. //
  629. // Function: CompareCntryNameLookUpElements()
  630. //
  631. // Synopsis: Function to compare names used by sort
  632. //
  633. //+---------------------------------------------------------------------------
  634. int __cdecl ComparePhoneEntry(const void *e1, const void *e2)
  635. {
  636. PPHONEENTRY pPhone1 = (PPHONEENTRY)e1;
  637. PPHONEENTRY pPhone2 = (PPHONEENTRY)e2;
  638. return CompareStringW(LOCALE_USER_DEFAULT, 0,
  639. pPhone1->Country, -1,
  640. pPhone2->Country, -1
  641. ) - 2;
  642. }
  643. VOID
  644. WINAPI
  645. SetupDestroyPhoneList(
  646. )
  647. {
  648. if ( PhoneList ) {
  649. MyFree( PhoneList );
  650. }
  651. PhoneList = NULL;
  652. }
  653. VOID
  654. WINAPI
  655. SetupFreePhoneList(PPHONEENTRY PhoneList, DWORD cbEntries)
  656. {
  657. DWORD i;
  658. if ( PhoneList )
  659. {
  660. for( i=0; i < cbEntries; i++ )
  661. {
  662. if (PhoneList[i].Country) {
  663. GlobalFree(PhoneList[i].Country);
  664. }
  665. if (PhoneList[i].TollFreeNumber) {
  666. GlobalFree(PhoneList[i].TollFreeNumber);
  667. }
  668. if (PhoneList[i].TollNumber) {
  669. GlobalFree(PhoneList[i].TollNumber);
  670. }
  671. }
  672. GlobalFree(PhoneList);
  673. }
  674. PhoneList = NULL;
  675. }
  676. BOOL
  677. AddToPhoneList(
  678. LPCWSTR Item
  679. )
  680. {
  681. PVOID NewList;
  682. DWORD ItemLength = lstrlen(Item);
  683. if ( !PhoneList ) {
  684. PhoneListLength = 0;
  685. PhoneListSize = 1024;
  686. PhoneList = MyMalloc( PhoneListSize * sizeof(TCHAR) );
  687. if (!PhoneList) {
  688. return FALSE;
  689. }
  690. } else if ( PhoneListLength + ItemLength > PhoneListSize ) {
  691. PhoneListSize *= 2;
  692. NewList = MyRealloc(
  693. PhoneList,
  694. PhoneListSize * sizeof(TCHAR)
  695. );
  696. if ( NewList ) {
  697. PhoneList = NewList;
  698. } else {
  699. MyFree(PhoneList);
  700. return FALSE;
  701. }
  702. }
  703. memcpy( PhoneList + PhoneListLength,
  704. Item,
  705. ItemLength * sizeof(TCHAR)
  706. );
  707. PhoneListLength += ItemLength;
  708. return TRUE;
  709. }
  710. BOOL MakePhoneListForScript(PPHONEENTRY PhoneList, DWORD cbEntries)
  711. {
  712. BOOL bRet = FALSE;
  713. DWORD i;
  714. if ( PhoneList )
  715. {
  716. for( i=0; i < cbEntries; i++ )
  717. {
  718. if (!AddToPhoneList(PhoneList[i].Country) ||
  719. !AddToPhoneList( TEXT("\t") ) ||
  720. !AddToPhoneList(PhoneList[i].TollFreeNumber) ||
  721. !AddToPhoneList( TEXT("\t") ) ||
  722. !AddToPhoneList(PhoneList[i].TollNumber) ||
  723. !AddToPhoneList( TEXT("\t") ) )
  724. {
  725. goto ExitMakePhoneListForScript;
  726. }
  727. }
  728. bRet = TRUE;
  729. }
  730. ExitMakePhoneListForScript:
  731. return bRet;
  732. }
  733. BOOL AddItemToPhoneEntry(LPCWSTR Item,
  734. LPWSTR *pPointer)
  735. {
  736. BOOL bRet = FALSE;
  737. if ((Item) && (pPointer))
  738. {
  739. *pPointer = (LPWSTR)GlobalAlloc(GPTR, (lstrlen(Item) + 1)*sizeof(TCHAR));
  740. if (*pPointer)
  741. {
  742. lstrcpy(*pPointer, Item);
  743. bRet = TRUE;
  744. }
  745. }
  746. return bRet;
  747. }
  748. PTSTR
  749. WINAPI
  750. SetupReadPhoneList(
  751. PWSTR PhoneInfName
  752. )
  753. {
  754. HINF PhoneInf = NULL;
  755. DWORD LineCount;
  756. DWORD ItemNo;
  757. LPCTSTR SectionName;
  758. INFCONTEXT InfContext;
  759. BOOL bSucceeded = FALSE;
  760. PPHONEENTRY pPhoneList = NULL;
  761. SetupDebugPrint( L"START: SetupReadPhoneList");
  762. PhoneList = NULL;
  763. PhoneInf = SetupOpenInfFile( PhoneInfName, NULL, INF_STYLE_WIN4, NULL );
  764. if( PhoneInf == INVALID_HANDLE_VALUE ) {
  765. return NULL;
  766. }
  767. SectionName = TEXT("IsoCodes");
  768. LineCount = SetupGetLineCount( PhoneInf, SectionName );
  769. if ( !LineCount ) {
  770. goto ReadPhoneListCleanup;
  771. }
  772. pPhoneList = (PPHONEENTRY)GlobalAlloc(GPTR,
  773. (int)(sizeof(PHONEENTRY) * LineCount));
  774. if (!pPhoneList )
  775. {
  776. goto ReadPhoneListCleanup;
  777. }
  778. ZeroMemory( pPhoneList, sizeof(PHONEENTRY) * LineCount );
  779. for( ItemNo=0; ItemNo<LineCount; ItemNo++ ) {
  780. if( SetupGetLineByIndex( PhoneInf, SectionName, ItemNo, &InfContext )) {
  781. if ( !AddItemToPhoneEntry( pSetupGetField( &InfContext, 4 ), &pPhoneList[ItemNo].Country ) ) {
  782. goto ReadPhoneListCleanup;
  783. }
  784. if ( !AddItemToPhoneEntry( pSetupGetField( &InfContext, 5 ), &pPhoneList[ItemNo].TollFreeNumber ) ) {
  785. goto ReadPhoneListCleanup;
  786. }
  787. if ( !AddItemToPhoneEntry( pSetupGetField( &InfContext, 6 ), &pPhoneList[ItemNo].TollNumber ) ) {
  788. goto ReadPhoneListCleanup;
  789. }
  790. }
  791. }
  792. // sort the array
  793. qsort(pPhoneList, (int)LineCount,sizeof(PHONEENTRY),
  794. ComparePhoneEntry);
  795. // Convert the array into a TAB delimited list for script.
  796. if (MakePhoneListForScript(pPhoneList,LineCount))
  797. {
  798. //
  799. // Replace the final TAB with a NUL.
  800. //
  801. PhoneList[PhoneListLength-1] = '\0';
  802. bSucceeded = TRUE;
  803. }
  804. ReadPhoneListCleanup:
  805. if (pPhoneList)
  806. {
  807. SetupFreePhoneList(pPhoneList,LineCount);
  808. }
  809. SetupCloseInfFile( PhoneInf );
  810. SetupDebugPrint( L"END: SetupReadPhoneList");
  811. if ( bSucceeded ) {
  812. return PhoneList;
  813. } else {
  814. SetupDestroyPhoneList();
  815. return NULL;
  816. }
  817. }
  818. //
  819. // Read INF to map a TAPI country id to a 3 letter ISO code.
  820. //
  821. VOID
  822. SetupMapTapiToIso (
  823. IN PWSTR PhoneInfName,
  824. IN DWORD dwCountryID,
  825. OUT PWSTR szIsoCode
  826. )
  827. {
  828. HINF PhoneInf;
  829. WCHAR szCountryID[9];
  830. BOOL bResult;
  831. INFCONTEXT Context;
  832. szIsoCode[0] = L'\0';
  833. PhoneInf = SetupOpenInfFile( PhoneInfName, NULL, INF_STYLE_WIN4, NULL );
  834. if( PhoneInf == INVALID_HANDLE_VALUE ) {
  835. return;
  836. }
  837. wsprintf ( szCountryID, L"%d", dwCountryID);
  838. bResult = SetupFindFirstLine (
  839. PhoneInf,
  840. L"TapiCodes",
  841. szCountryID,
  842. &Context
  843. );
  844. if (bResult) {
  845. SetupGetStringField ( &Context, 1, szIsoCode, 4, NULL );
  846. SetupDebugPrint2 ( L"SetupMapTapiToIso: %d mapped to %s", dwCountryID, szIsoCode );
  847. }
  848. SetupCloseInfFile( PhoneInf );
  849. }
  850. BOOL
  851. WINAPI
  852. SetupGetSetupInfo(
  853. PWSTR Name, OPTIONAL
  854. DWORD cbName,
  855. PWSTR Org, OPTIONAL
  856. DWORD cbOrg,
  857. PWSTR OemId, OPTIONAL
  858. DWORD cbOemId,
  859. LPBOOL IntlSet OPTIONAL
  860. )
  861. {
  862. BOOL b = TRUE;
  863. HKEY hkey = NULL;
  864. DWORD Size;
  865. DWORD Type;
  866. //
  867. // Open the key if we need it
  868. //
  869. if( (Name || Org) &&
  870. RegOpenKeyEx(HKEY_LOCAL_MACHINE,WinntSoftwareKeyName,0,
  871. KEY_QUERY_VALUE,&hkey) != NO_ERROR) {
  872. return FALSE;
  873. }
  874. //
  875. // Get Name
  876. //
  877. if (Name) {
  878. Size = cbName;
  879. if((RegQueryValueEx(hkey,szRegisteredOwner,NULL,&Type,
  880. (LPBYTE)Name,&Size) != NO_ERROR)
  881. || (Type != REG_SZ)
  882. ) {
  883. b = FALSE;
  884. }
  885. }
  886. //
  887. // Get Org
  888. //
  889. if (Org) {
  890. Size = cbOrg;
  891. if((RegQueryValueEx(hkey,szRegisteredOrganization,NULL,&Type,
  892. (LPBYTE)Org,&Size) != NO_ERROR)
  893. || (Type != REG_SZ)
  894. ) {
  895. b = FALSE;
  896. }
  897. }
  898. // TBD: figure out what this is for
  899. if (OemId) {
  900. OemId[0] = 0;
  901. cbOemId = 0;
  902. }
  903. //
  904. // Note: IntlSet is not used currently
  905. //
  906. if (hkey) {
  907. RegCloseKey(hkey);
  908. }
  909. return b;
  910. }
  911. BOOL
  912. WINAPI
  913. SetupSetSetupInfo(
  914. PCWSTR Name,
  915. PCWSTR Org
  916. )
  917. {
  918. BOOL b;
  919. b = StoreNameOrgInRegistry( (PWSTR)Name, (PWSTR)Org );
  920. return b;
  921. }
  922. BOOL
  923. WINAPI
  924. SetupSetAdminPassword(
  925. PCWSTR OldPassword,
  926. PCWSTR NewPassword
  927. )
  928. {
  929. WCHAR AdminName[MAX_USERNAME+1];
  930. BOOL Status;
  931. GetAdminAccountName( AdminName );
  932. Status = SetLocalUserPassword( AdminName, OldPassword, NewPassword );
  933. if ( !Status ) {
  934. SetupDebugPrint( L"SetupSetAdminPassword: SetLocalUserPassword failed.");
  935. }
  936. return Status;
  937. }
  938. VOID
  939. WINAPI
  940. SetupOobeInitDebugLog(
  941. )
  942. {
  943. //
  944. // Do no UI. Note that we must set OobeSetup before our first call to
  945. // SetupDebugPrint.
  946. //
  947. OobeSetup = TRUE;
  948. SetupDebugPrint( L"SetupOobeInitDebugLog" );
  949. }
  950. // Run initialization that is known not to requires services to run.
  951. //
  952. VOID
  953. WINAPI
  954. SetupOobeInitPreServices(
  955. IN BOOL DoMiniSetupStuff
  956. )
  957. {
  958. //
  959. // Turn off logging.
  960. //
  961. // IsSetup = FALSE;
  962. SetupDebugPrint( L"SetupOobeInitPreServices" );
  963. if ( DoMiniSetupStuff ) {
  964. //
  965. // Act like the miniwizard (except with no UI)
  966. //
  967. MiniSetup = TRUE;
  968. Preinstall = TRUE;
  969. //
  970. // Tell SetupAPI not to bother backing up files and not to verify
  971. // that any INFs are digitally signed.
  972. //
  973. pSetupSetGlobalFlags(pSetupGetGlobalFlags()|PSPGF_NO_BACKUP|PSPGF_NO_VERIFY_INF);
  974. CommonInitialization();
  975. SetUpDataBlock();
  976. InternalSetupData.CallSpecificData1 = 0;
  977. #if 0
  978. //
  979. // We aren't going to do this for rev 1.
  980. //
  981. if( PnPReEnumeration ) {
  982. //
  983. // The user wants us to do PnP re-enumeration.
  984. // Go do it.
  985. //
  986. InstallPnpDevices( hdlg,
  987. SyssetupInf,
  988. GetDlgItem(hdlg,IDC_PROGRESS1),
  989. StartAtPercent,
  990. StopAtPercent );
  991. }
  992. #endif
  993. } else { // DoMiniSetupStuff
  994. //
  995. // Get handle to heap so we can periodically validate it.
  996. //
  997. #if DBG
  998. g_hSysSetupHeap = GetProcessHeap();
  999. #endif
  1000. }
  1001. }
  1002. // Run initialization that may or does require services.
  1003. //
  1004. VOID
  1005. WINAPI
  1006. SetupOobeInitPostServices(
  1007. IN BOOL DoMiniSetupStuff
  1008. )
  1009. {
  1010. InitializeExternalModules(
  1011. DoMiniSetupStuff,
  1012. &g_OcManagerContext
  1013. );
  1014. }
  1015. VOID
  1016. WINAPI
  1017. SetupOobeCleanup(
  1018. IN BOOL DoMiniSetupStuff
  1019. )
  1020. {
  1021. static FINISH_THREAD_PARAMS Context;
  1022. SetupDebugPrint( L"SetupOobeCleanup" );
  1023. if ( DoMiniSetupStuff ) {
  1024. RestoreBootTimeout();
  1025. Context.ThreadId = GetCurrentThreadId();
  1026. Context.OcManagerContext = g_OcManagerContext;
  1027. FinishThread( &Context );
  1028. }
  1029. }
  1030. // Resets the activation days (allowed 3 times only)
  1031. //
  1032. DWORD
  1033. SetupReArmWPA(
  1034. VOID
  1035. )
  1036. {
  1037. LPCSTR lpszReArmInterface = (LPCSTR)124;
  1038. typedef HRESULT (WINAPI* lpReArmEntryPoint) ();
  1039. HMODULE hRearmdll = NULL;
  1040. DWORD dwError = ERROR_SUCCESS;
  1041. hRearmdll = LoadLibraryA("licdll.dll");
  1042. if (hRearmdll)
  1043. {
  1044. lpReArmEntryPoint pReArmEntry =
  1045. (lpReArmEntryPoint) GetProcAddress(hRearmdll,lpszReArmInterface);
  1046. if (pReArmEntry)
  1047. {
  1048. //
  1049. // ValidateDigitalPid returns zero if success, otherwise its custom error code
  1050. //
  1051. HRESULT hr = (*pReArmEntry )();
  1052. if (FAILED(hr))
  1053. {
  1054. // If PID cannot be validated we should force activation/PID reentry.
  1055. SetupDebugPrint1(L"SETUP: Rollback WPA failed! HRESULT=%ld", hr);
  1056. dwError = (DWORD)hr;
  1057. }
  1058. else
  1059. SetupDebugPrint(L"SETUP: Rollback WPA succeeded.");
  1060. }
  1061. else {
  1062. SetupDebugPrint(L"SETUP: Failed to get WPA entry point!");
  1063. dwError = ERROR_INVALID_FUNCTION;
  1064. }
  1065. FreeLibrary (hRearmdll);
  1066. }
  1067. else {
  1068. SetupDebugPrint(L"SETUP: Failed to load WPA library!");
  1069. dwError = ERROR_FILE_NOT_FOUND;
  1070. }
  1071. // Return error code or success
  1072. //
  1073. return dwError;
  1074. }
  1075. // Once Windows is activated the Activate Windows shortcut is removed by msoobe.exe /a.
  1076. // If OEMs sysprep a machine they will need to re-activate Windows and the shortcut
  1077. // needs to be restored. Msoobe.exe cannot restore it because it does not
  1078. // run in server skus.
  1079. //
  1080. DWORD
  1081. SetupRestoreWPAShortcuts(
  1082. VOID
  1083. )
  1084. {
  1085. DWORD dwError = ERROR_SUCCESS;
  1086. HINF hinf;
  1087. hinf = SetupOpenInfFile(L"syssetup.inf",NULL,INF_STYLE_WIN4,NULL);
  1088. if(hinf != INVALID_HANDLE_VALUE)
  1089. {
  1090. if (SetupInstallFromInfSection(NULL,
  1091. hinf,
  1092. L"RESTORE_OOBE_ACTIVATE",
  1093. SPINST_PROFILEITEMS , //SPINST_ALL,
  1094. NULL,
  1095. NULL,
  1096. 0,
  1097. NULL,
  1098. NULL,
  1099. NULL,
  1100. NULL) != 0)
  1101. {
  1102. // Success
  1103. SetupDebugPrint(L"SETUP: Restore Activation shortcut succeeded");
  1104. }
  1105. else
  1106. {
  1107. // Failure
  1108. dwError = GetLastError();
  1109. SetupDebugPrint1(L"SETUP: Restore Activation shortcut failed. GetLastError=%ld",dwError);
  1110. }
  1111. SetupCloseInfFile(hinf);
  1112. }
  1113. else
  1114. {
  1115. dwError = GetLastError();
  1116. SetupDebugPrint1(L"SETUP: Restore Activation shortcut failed to open syssetup.inf. GetLastError=%ld",dwError);
  1117. }
  1118. return dwError;
  1119. }
  1120. BOOL Activationrequired(VOID);
  1121. // Rollback the activation days and put back the activate windows shortcut(s). X86 only.
  1122. //
  1123. DWORD
  1124. WINAPI
  1125. SetupOobeBnk(
  1126. LPBYTE pDummy
  1127. )
  1128. {
  1129. DWORD dwError = ERROR_SUCCESS;
  1130. // Return if we failed to rollback so we don'put the shortcut back
  1131. // On volume license skus this always returns successful
  1132. //
  1133. if (ERROR_SUCCESS != (dwError = SetupReArmWPA()))
  1134. return dwError;
  1135. // If not activated, restore the shortcuts, or if we don't
  1136. // require activation (for volume license skus)
  1137. //
  1138. if (Activationrequired())
  1139. {
  1140. // Restore the Activate Windows shortcut(s)
  1141. //
  1142. dwError = SetupRestoreWPAShortcuts();
  1143. }
  1144. return dwError;
  1145. }
  1146. static
  1147. LPTSTR
  1148. NextNumber(
  1149. LPTSTR lpString,
  1150. BOOL bSkipFirst
  1151. )
  1152. {
  1153. // The first time we just want to walk past any non-numbers,
  1154. // we don't want to skip any numbers if they are right at the
  1155. // begining of the string.
  1156. //
  1157. if ( bSkipFirst )
  1158. {
  1159. // Walk past the first number in the string.
  1160. //
  1161. while ( ( *lpString >= _T('0') ) &&
  1162. ( *lpString <= _T('9') ) )
  1163. {
  1164. lpString++;
  1165. }
  1166. }
  1167. // Now walk till we get to the next number or we reach the end.
  1168. //
  1169. while ( ( *lpString ) &&
  1170. ( ( *lpString < _T('0') ) ||
  1171. ( *lpString > _T('9') ) ) )
  1172. {
  1173. lpString++;
  1174. }
  1175. return lpString;
  1176. }
  1177. BOOL
  1178. WINAPI
  1179. SetupSetDisplay(
  1180. LPCTSTR lpszUnattend,
  1181. LPCTSTR lpszSection,
  1182. LPCTSTR lpszResolutionKey,
  1183. LPCTSTR lpszRefreshKey,
  1184. DWORD dwMinWidth,
  1185. DWORD dwMinHeight,
  1186. DWORD dwMinBits
  1187. )
  1188. {
  1189. DEVMODE devmode;
  1190. DWORD dwVal;
  1191. TCHAR szText[256];
  1192. LPTSTR lpDisplay;
  1193. BOOL bRet = TRUE;
  1194. ZeroMemory(&devmode, sizeof(DEVMODE));
  1195. devmode.dmSize = sizeof(DEVMODE);
  1196. // Check the current resolution, make sure it meets our mins.
  1197. //
  1198. if ( EnumDisplaySettings(NULL, ENUM_REGISTRY_SETTINGS, &devmode) )
  1199. {
  1200. if ( devmode.dmPelsWidth < dwMinWidth )
  1201. {
  1202. devmode.dmPelsWidth = dwMinWidth;
  1203. devmode.dmFields |= DM_PELSWIDTH;
  1204. }
  1205. if ( devmode.dmPelsHeight < dwMinHeight )
  1206. {
  1207. devmode.dmPelsHeight = dwMinHeight;
  1208. devmode.dmFields |= DM_PELSHEIGHT;
  1209. }
  1210. if ( devmode.dmBitsPerPel < dwMinBits )
  1211. {
  1212. devmode.dmBitsPerPel = dwMinBits;
  1213. devmode.dmFields |= DM_BITSPERPEL;
  1214. }
  1215. }
  1216. // Make sure they passed in an unattend and section to look in.
  1217. //
  1218. if ( lpszUnattend && *lpszUnattend && lpszSection && *lpszSection )
  1219. {
  1220. // Now check in the winbom to see if they want to change the current resolution.
  1221. //
  1222. szText[0] = _T('\0');
  1223. if ( ( lpszResolutionKey ) &&
  1224. ( *lpszResolutionKey ) &&
  1225. ( GetPrivateProfileString(lpszSection, lpszResolutionKey, _T(""), szText, sizeof(szText) / sizeof(szText[0]), lpszUnattend) ) &&
  1226. ( szText[0] ) )
  1227. {
  1228. bRet = FALSE;
  1229. lpDisplay = NextNumber(szText, FALSE);
  1230. if ( dwVal = (DWORD) _ttoi(lpDisplay) )
  1231. {
  1232. devmode.dmFields |= DM_PELSWIDTH;
  1233. devmode.dmPelsWidth = dwVal;
  1234. }
  1235. lpDisplay = NextNumber(lpDisplay, TRUE);
  1236. if ( dwVal = (DWORD) _ttoi(lpDisplay) )
  1237. {
  1238. devmode.dmFields |= DM_PELSHEIGHT;
  1239. devmode.dmPelsHeight = dwVal;
  1240. }
  1241. lpDisplay = NextNumber(lpDisplay, TRUE);
  1242. if ( dwVal = (DWORD) _ttoi(lpDisplay) )
  1243. {
  1244. devmode.dmFields |= DM_BITSPERPEL;
  1245. devmode.dmBitsPerPel = dwVal;
  1246. }
  1247. }
  1248. // Now check in the winbom to see if they want to change the default refresh rate.
  1249. //
  1250. szText[0] = _T('\0');
  1251. if ( ( lpszRefreshKey ) &&
  1252. ( *lpszRefreshKey ) &&
  1253. ( GetPrivateProfileString(lpszSection, lpszRefreshKey, _T(""), szText, sizeof(szText) / sizeof(szText[0]), lpszUnattend) ) &&
  1254. ( szText[0] ) )
  1255. {
  1256. bRet = FALSE;
  1257. if ( dwVal = (DWORD) _ttoi(szText) )
  1258. {
  1259. devmode.dmFields |= DM_DISPLAYFREQUENCY;
  1260. devmode.dmDisplayFrequency = dwVal;
  1261. }
  1262. }
  1263. }
  1264. // If we have anything to change, change it now.
  1265. //
  1266. if ( devmode.dmFields )
  1267. {
  1268. DWORD dwRet = ChangeDisplaySettings(&devmode, CDS_UPDATEREGISTRY | CDS_GLOBAL);
  1269. switch ( dwRet )
  1270. {
  1271. case DISP_CHANGE_SUCCESSFUL:
  1272. case DISP_CHANGE_RESTART:
  1273. bRet = TRUE;
  1274. break;
  1275. //case DISP_CHANGE_BADFLAGS:
  1276. //case DISP_CHANGE_BADPARAM:
  1277. //case DISP_CHANGE_FAILED:
  1278. //case DISP_CHANGE_BADMODE
  1279. //case DISP_CHANGE_NOTUPDATED:
  1280. //bRet = FALSE;
  1281. }
  1282. }
  1283. return bRet;
  1284. }
  1285. typedef struct _OEM_FINISH_APPS {
  1286. LPTSTR szApp;
  1287. LPTSTR szArgs;
  1288. } OEM_FINISH_APPS;
  1289. OEM_FINISH_APPS OEM_Finish_Apps[] = {
  1290. { L"Rundll32.exe", L"fldrclnr.dll,Wizard_RunDLL silent"},
  1291. { NULL, NULL} // End of list.
  1292. };
  1293. void RunOEMExtraTasks()
  1294. {
  1295. LPTSTR pApp = NULL;
  1296. LPTSTR pArgs = NULL;
  1297. DWORD dwSize;
  1298. DWORD dwCode;
  1299. int i;
  1300. BEGIN_SECTION(L"RunOEMExtraTasks");
  1301. i = 0;
  1302. while (OEM_Finish_Apps[i].szApp != NULL)
  1303. {
  1304. // Get the size we need to the expanded app
  1305. dwSize = ExpandEnvironmentStrings(
  1306. OEM_Finish_Apps[i].szApp ,
  1307. NULL,
  1308. 0);
  1309. if (dwSize)
  1310. {
  1311. pApp = (LPTSTR)GlobalAlloc(GPTR, sizeof(TCHAR) * dwSize);
  1312. if (pApp)
  1313. {
  1314. ExpandEnvironmentStrings(
  1315. OEM_Finish_Apps[i].szApp ,
  1316. pApp,
  1317. dwSize);
  1318. if (OEM_Finish_Apps[i].szArgs)
  1319. {
  1320. // Get the size we need to the expanded arguments
  1321. dwSize = ExpandEnvironmentStrings(
  1322. OEM_Finish_Apps[i].szArgs ,
  1323. NULL,
  1324. 0);
  1325. if (dwSize)
  1326. {
  1327. pArgs = (LPTSTR)GlobalAlloc(GPTR, sizeof(TCHAR) * dwSize);
  1328. if (pArgs)
  1329. {
  1330. ExpandEnvironmentStrings(
  1331. OEM_Finish_Apps[i].szArgs,
  1332. pArgs,
  1333. dwSize);
  1334. }
  1335. }
  1336. }
  1337. // Log what we will start
  1338. if (pArgs)
  1339. {
  1340. SetupDebugPrint2(L"Start command :%s: with arguments :%s:", pApp, pArgs);
  1341. }
  1342. else
  1343. {
  1344. SetupDebugPrint1(L"Start command :%s: with no arguments", pApp);
  1345. }
  1346. // Start the app.
  1347. dwCode = 0;
  1348. if (pArgs)
  1349. {
  1350. InvokeExternalApplicationEx(pApp, pArgs, &dwCode, INFINITE, TRUE);
  1351. }
  1352. else
  1353. {
  1354. // If we don't have args. the first parameter is NULL
  1355. InvokeExternalApplicationEx(NULL, pApp, &dwCode, INFINITE, TRUE);
  1356. }
  1357. }
  1358. }
  1359. if (pApp)
  1360. {
  1361. GlobalFree(pApp);
  1362. pApp = NULL;
  1363. }
  1364. if (pArgs)
  1365. {
  1366. GlobalFree(pArgs);
  1367. pArgs = NULL;
  1368. }
  1369. i++;
  1370. }
  1371. END_SECTION(L"RunOEMExtraTasks");
  1372. }
  1373. static
  1374. BOOL
  1375. SetupCheckRegValue(
  1376. IN HKEY hKey,
  1377. IN LPTSTR lpszValueName,
  1378. IN DWORD dwCompareValue
  1379. )
  1380. {
  1381. BOOL fRet = FALSE;
  1382. DWORD dwData = 0,
  1383. dwType,
  1384. cbSize = sizeof(dwData);
  1385. if ( ( ERROR_SUCCESS == RegQueryValueEx( hKey,
  1386. lpszValueName,
  1387. 0,
  1388. &dwType,
  1389. (LPBYTE) &dwData,
  1390. &cbSize ) ) &&
  1391. ( REG_DWORD == dwType) &&
  1392. ( dwData == dwCompareValue ) )
  1393. {
  1394. fRet = TRUE;
  1395. }
  1396. return fRet;
  1397. }
  1398. BOOL
  1399. SetupGetInstallMode(
  1400. OUT LPDWORD lpdwMode,
  1401. OUT LPDWORD lpdwFlags
  1402. )
  1403. {
  1404. BOOL fRet = FALSE;
  1405. HKEY hKeySetup;
  1406. //
  1407. // Make sure the caller is actually checking for something.
  1408. //
  1409. if ( lpdwMode || lpdwFlags )
  1410. {
  1411. //
  1412. // Also make sure we can open the "HKLM\System\Setup" key.
  1413. //
  1414. if ( ERROR_SUCCESS == RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  1415. TEXT("System\\Setup"),
  1416. 0,
  1417. KEY_READ,
  1418. &hKeySetup ) )
  1419. {
  1420. DWORD dwMode = SETUP_MODE_NONE,
  1421. dwFlags = 0;
  1422. BOOL fSetup,
  1423. fOobe,
  1424. fAudit,
  1425. fMini,
  1426. fFactory;
  1427. //
  1428. // Check all of the registry values we might care about...
  1429. //
  1430. fSetup = SetupCheckRegValue( hKeySetup, TEXT("SystemSetupInProgress"), 1 );
  1431. fOobe = SetupCheckRegValue( hKeySetup, TEXT("OobeInProgress"), 1 );
  1432. fAudit = SetupCheckRegValue( hKeySetup, TEXT("AuditInProgress"), 1 );
  1433. fMini = SetupCheckRegValue( hKeySetup, TEXT("MiniSetupInProgress"), 1 );
  1434. fFactory = SetupCheckRegValue( hKeySetup, TEXT("FactoryPreInstallInProgress"), 1 );
  1435. //
  1436. // We are in OOBE if the OobeInProgress value is non-zero...
  1437. //
  1438. if ( fOobe )
  1439. {
  1440. dwMode = SETUP_MODE_OOBE;
  1441. if ( fMini )
  1442. {
  1443. dwFlags |= SETUP_FLAG_OEM;
  1444. }
  1445. }
  1446. else
  1447. {
  1448. //
  1449. // We are in MiniSetup if the MiniSetupInProgress value is non-zero...
  1450. //
  1451. if ( fMini )
  1452. {
  1453. dwMode = SETUP_MODE_MINI;
  1454. dwFlags |= SETUP_FLAG_OEM;
  1455. }
  1456. else
  1457. {
  1458. //
  1459. // We are in Audit mode if the AuditInProgress value is non-zero...
  1460. //
  1461. if ( fAudit )
  1462. {
  1463. dwMode = SETUP_MODE_AUDIT;
  1464. dwFlags |= (SETUP_FLAG_OEM | SETUP_FLAG_UNATTENDED);
  1465. //
  1466. // If the FactoryPreInstallInProgress flag is non-zero, then we are delaying PNP...
  1467. //
  1468. if ( fFactory )
  1469. {
  1470. dwFlags |= SETUP_FLAG_DELAYPNP;
  1471. }
  1472. }
  1473. else
  1474. {
  1475. //
  1476. // We are in Setup if the SystemSetupInProgress and SetupType values are non-zero...
  1477. //
  1478. if ( fSetup )
  1479. {
  1480. dwMode = SETUP_MODE_SETUP;
  1481. }
  1482. }
  1483. }
  1484. }
  1485. //
  1486. // Now put our values into the caller's buffers...
  1487. //
  1488. if ( lpdwMode )
  1489. {
  1490. *lpdwMode = dwMode;
  1491. }
  1492. if ( lpdwFlags )
  1493. {
  1494. *lpdwFlags = dwFlags;
  1495. }
  1496. //
  1497. // We were able to open the Setup key... so return TRUE.
  1498. //
  1499. fRet = TRUE;
  1500. //
  1501. // We're done, so close the Setup key.
  1502. //
  1503. RegCloseKey( hKeySetup );
  1504. }
  1505. }
  1506. return fRet;
  1507. }