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.

924 lines
31 KiB

  1. /*****************************************************************************\
  2. MAIN.CPP
  3. Microsoft Confidential
  4. Copyright (c) Microsoft Corporation 1998
  5. All rights reserved
  6. Contains...
  7. 1/99 - JCOHEN
  8. Created main program file.
  9. \*****************************************************************************/
  10. #include "precomp.h"
  11. #include "msobmain.h"
  12. #include "setupkey.h"
  13. #include "resource.h"
  14. #define ICWDESKTOPCHANGED L"DesktopChanged"
  15. #define MAX_MESSAGE_LEN 256
  16. #define ICWSETTINGSPATH L"Software\\Microsoft\\Internet Connection Wizard"
  17. #define ICW_REGKEYCOMPLETED L"Completed"
  18. #define REGSTR_PATH_SETUPKEY REGSTR_PATH_SETUP REGSTR_KEY_SETUP
  19. #define REGSTR_PATH_SYSTEMSETUPKEY L"System\\Setup"
  20. #define REGSTR_VALUE_CMDLINE L"CmdLine"
  21. #define REGSTR_VALUE_SETUPTYPE L"SetupType"
  22. #define REGSTR_VALUE_MINISETUPINPROGRESS L"MiniSetupInProgress"
  23. #define REGSTR_PATH_IEONDESKTOP REGSTR_PATH_IEXPLORER L"\\AdvancedOptions\\BROWSE\\IEONDESKTOP"
  24. static const WCHAR g_szRegPathWelcomeICW[] = L"Welcome\\ICW";
  25. static const WCHAR g_szAllUsers[] = L"All Users";
  26. static const WCHAR g_szConnectApp[] = L"ICWCONN1.EXE";
  27. static const WCHAR g_szConnectLink[] = L"Connect to the Internet";
  28. static const WCHAR g_szOEApp[] = L"MSINM.EXE";
  29. static const WCHAR g_szOELink[] = L"Outlook Express";
  30. static const WCHAR g_szRegPathICWSettings[] = L"Software\\Microsoft\\Internet Connection Wizard";
  31. static const WCHAR g_szRegValICWCompleted[] = L"Completed";
  32. WCHAR g_szShellNext [MAX_PATH+1] = L"\0nogood";
  33. WCHAR g_szShellNextParams [MAX_PATH+1] = L"\0nogood";
  34. HINSTANCE g_hInstance = NULL;
  35. /*******************************************************************
  36. NAME: RegisterComObjects
  37. SYNOPSIS: App entry point
  38. ********************************************************************/
  39. BOOL SelfRegisterComObject(LPWSTR szDll, BOOL fRegister)
  40. {
  41. HINSTANCE hModule = LoadLibrary(szDll);
  42. BOOL bRet = FALSE;
  43. if (hModule)
  44. {
  45. HRESULT (STDAPICALLTYPE *pfn)(void);
  46. if (fRegister)
  47. (FARPROC&)pfn = GetProcAddress(hModule, REG_SERVER);
  48. else
  49. (FARPROC&)pfn = GetProcAddress(hModule, UNREG_SERVER);
  50. if (pfn && SUCCEEDED((*pfn)()))
  51. bRet = TRUE;
  52. FreeLibrary(hModule);
  53. }
  54. return bRet;
  55. }
  56. // This undoes what DoDesktopChanges did
  57. void UndoDesktopChanges()
  58. {
  59. WCHAR szConnectTotheInternetTitle[MAX_PATH];
  60. HKEY hkey;
  61. // Verify that we really changed the desktop
  62. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER,
  63. ICWSETTINGSPATH,
  64. 0,
  65. KEY_ALL_ACCESS,
  66. &hkey))
  67. {
  68. DWORD dwDesktopChanged = 0;
  69. DWORD dwTmp = sizeof(DWORD);
  70. DWORD dwType = 0;
  71. if (ERROR_SUCCESS == RegQueryValueEx(hkey,
  72. ICWDESKTOPCHANGED,
  73. NULL,
  74. &dwType,
  75. (LPBYTE)&dwDesktopChanged,
  76. &dwTmp))
  77. {
  78. }
  79. RegCloseKey(hkey);
  80. // Bail if the desktop was not changed by us
  81. if(!dwDesktopChanged)
  82. {
  83. return;
  84. }
  85. }
  86. // Always nuke the Connect to the internet icon
  87. HINSTANCE hInst = LoadLibrary(OOBE_MAIN_DLL);
  88. if (!LoadString(hInst,
  89. IDS_CONNECT_DESKTOP_TITLE,
  90. szConnectTotheInternetTitle,
  91. MAX_CHARS_IN_BUFFER(szConnectTotheInternetTitle)))
  92. {
  93. lstrcpy(szConnectTotheInternetTitle, g_szConnectLink);
  94. }
  95. RemoveDesktopShortCut(szConnectTotheInternetTitle);
  96. }
  97. void StartIE
  98. (
  99. LPWSTR lpszURL
  100. )
  101. {
  102. WCHAR szIEPath[MAX_PATH];
  103. HKEY hkey;
  104. // first get the app path
  105. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  106. REGSTR_PATH_APPPATHS,
  107. 0,
  108. KEY_READ,
  109. &hkey) == ERROR_SUCCESS)
  110. {
  111. DWORD dwTmp = sizeof(szIEPath);
  112. if(RegQueryValue(hkey, L"iexplore.exe", szIEPath, (PLONG)&dwTmp) != ERROR_SUCCESS)
  113. {
  114. ShellExecute(NULL, L"open",szIEPath,lpszURL,NULL,SW_NORMAL);
  115. }
  116. else
  117. {
  118. ShellExecute(NULL, L"open",L"iexplore.exe",lpszURL,NULL,SW_NORMAL);
  119. }
  120. RegCloseKey(hkey);
  121. }
  122. else
  123. {
  124. ShellExecute(NULL, L"open",L"iexplore.exe",lpszURL,NULL,SW_NORMAL);
  125. }
  126. }
  127. void HandleShellNext()
  128. {
  129. DWORD dwVal = 0;
  130. DWORD dwSize = sizeof(dwVal);
  131. HKEY hKey = NULL;
  132. if(RegOpenKeyEx(HKEY_CURRENT_USER,
  133. ICWSETTINGSPATH,
  134. 0,
  135. KEY_ALL_ACCESS,
  136. &hKey) == ERROR_SUCCESS)
  137. {
  138. RegQueryValueEx(hKey,
  139. ICW_REGKEYCOMPLETED,
  140. 0,
  141. NULL,
  142. (LPBYTE)&dwVal,
  143. &dwSize);
  144. RegCloseKey(hKey);
  145. }
  146. if (dwVal)
  147. {
  148. TRACE3(L"Starting IE because HKCU\\%s\\%s = %d", ICWSETTINGSPATH, ICW_REGKEYCOMPLETED, dwVal);
  149. UndoDesktopChanges();
  150. if (PathIsURL(g_szShellNext))
  151. {
  152. TRACE1(L"Navigating to %s", g_szShellNext);
  153. StartIE(g_szShellNext);
  154. }
  155. else if(g_szShellNext[0] != L'\0')
  156. {
  157. // Let the shell deal with it
  158. TRACE1(L"ShellExecuting %s", g_szShellNext);
  159. ShellExecute(NULL, L"open",g_szShellNext,g_szShellNextParams,NULL,SW_NORMAL);
  160. }
  161. }
  162. }
  163. //+----------------------------------------------------------------------------
  164. //
  165. // Function: GetShellNextFromReg
  166. //
  167. // Synopsis: Reads the ShellNext key from the registry, and then parses it
  168. // into a command and parameter. This key is set by
  169. // SetShellNext in inetcfg.dll in conjunction with
  170. // CheckConnectionWizard.
  171. //
  172. // Arguments: none
  173. //
  174. // Returns: none
  175. //
  176. // History: jmazner 7/9/97 Olympus #9170
  177. //
  178. //-----------------------------------------------------------------------------
  179. BOOL GetShellNextFromReg
  180. (
  181. LPWSTR lpszCommand,
  182. LPWSTR lpszParams
  183. )
  184. {
  185. BOOL fRet = TRUE;
  186. WCHAR szShellNextCmd [MAX_PATH] = L"\0";
  187. DWORD dwShellNextSize = sizeof(szShellNextCmd);
  188. LPWSTR lpszTemp = NULL;
  189. HKEY hkey = NULL;
  190. if( !lpszCommand || !lpszParams )
  191. {
  192. return FALSE;
  193. }
  194. if ((RegOpenKey(HKEY_CURRENT_USER, ICWSETTINGSPATH, &hkey)) == ERROR_SUCCESS)
  195. {
  196. if (RegQueryValueEx(hkey,
  197. L"ShellNext",
  198. NULL,
  199. NULL,
  200. (BYTE *)szShellNextCmd,
  201. (DWORD *)&dwShellNextSize) != ERROR_SUCCESS)
  202. {
  203. fRet = FALSE;
  204. goto GetShellNextFromRegExit;
  205. }
  206. }
  207. else
  208. {
  209. fRet = FALSE;
  210. goto GetShellNextFromRegExit;
  211. }
  212. //
  213. // This call will parse the first token into lpszCommand, and set szShellNextCmd
  214. // to point to the remaining tokens (these will be the parameters). Need to use
  215. // the pszTemp var because GetCmdLineToken changes the pointer's value, and we
  216. // need to preserve lpszShellNextCmd's value so that we can GlobalFree it later.
  217. //
  218. lpszTemp = szShellNextCmd;
  219. GetCmdLineToken( &lpszTemp, lpszCommand );
  220. lstrcpy( lpszParams, lpszTemp );
  221. //
  222. // it's possible that the shellNext command was wrapped in quotes for
  223. // parsing purposes. But since ShellExec doesn't understand quotes,
  224. // we now need to remove them.
  225. //
  226. if( L'"' == lpszCommand[0] )
  227. {
  228. //
  229. // get rid of the first quote
  230. // note that we're shifting the entire string beyond the first quote
  231. // plus the terminating NULL down by one byte.
  232. //
  233. memmove( lpszCommand, &(lpszCommand[1]), BYTES_REQUIRED_BY_SZ(lpszCommand) );
  234. //
  235. // now get rid of the last quote
  236. //
  237. lpszCommand[lstrlen(lpszCommand) - 1] = L'\0';
  238. }
  239. GetShellNextFromRegExit:
  240. if (hkey)
  241. RegCloseKey(hkey);
  242. return fRet;
  243. }
  244. //+----------------------------------------------------------------------------
  245. //
  246. // Function: RemoveShellNextFromReg
  247. //
  248. // Synopsis: deletes the ShellNext reg key if present. This key is set by
  249. // SetShellNext in inetcfg.dll in conjunction with
  250. // CheckConnectionWizard.
  251. //
  252. // Arguments: none
  253. //
  254. // Returns: none
  255. //
  256. // History: jmazner 7/9/97 Olympus #9170
  257. //
  258. //-----------------------------------------------------------------------------
  259. void RemoveShellNextFromReg( void )
  260. {
  261. HKEY hkey;
  262. if ((RegOpenKey(HKEY_CURRENT_USER, ICWSETTINGSPATH, &hkey)) == ERROR_SUCCESS)
  263. {
  264. RegDeleteValue(hkey, L"ShellNext");
  265. RegCloseKey(hkey);
  266. }
  267. }
  268. //GetShellNext
  269. //
  270. // 5/21/97 jmazner Olympus #4157
  271. // usage: /shellnext c:\path\executeable [parameters]
  272. // the token following nextapp will be shellExec'd at the
  273. // end of the "current" path. It can be anything that the shell
  274. // knows how to handle -- an .exe, a URL, etc.. If executable
  275. // name contains white space (eg: c:\program files\foo.exe), it
  276. // should be wrapped in double quotes, "c:\program files\foo.exe"
  277. // This will cause us to treat it as a single token.
  278. //
  279. // all consecutive subsequent tokens will
  280. // be passed to ShellExec as the parameters until a token is
  281. // encountered of the form /<non-slash character>. That is to say,
  282. // the character combination // will be treated as an escape character
  283. //
  284. // this is easiest to explain by way of examples.
  285. //
  286. // examples of usage:
  287. //
  288. // icwconn1.exe /shellnext "C:\prog files\wordpad.exe" file.txt
  289. // icwconn1.exe /prod IE /shellnext msimn.exe /promo MCI
  290. // icwconn1.exe /shellnext msimn.exe //START_MAIL /promo MCI
  291. //
  292. // the executeable string and parameter string are limited to
  293. // a length of MAX_PATH
  294. //
  295. BOOL GetShellNextToken(LPWSTR szCmdLine, LPWSTR szOut)
  296. {
  297. if (lstrcmpi(szOut, CMD_SHELLNEXT)==0)
  298. {
  299. // next token is expected to be white space
  300. GetCmdLineToken(&szCmdLine, szOut);
  301. if (szOut[0])
  302. {
  303. ZeroMemory(g_szShellNext, sizeof(g_szShellNext));
  304. ZeroMemory(g_szShellNextParams, sizeof(g_szShellNextParams));
  305. // Read white space
  306. GetCmdLineToken(&szCmdLine, szOut);
  307. //this should be the thing to ShellExec
  308. if(*szCmdLine != L'/')
  309. {
  310. // watch closely, this gets a bit tricky
  311. //
  312. // if this command begins with a double quote, assume it ends
  313. // in a matching quote. We do _not_ want to store the
  314. // quotes, however, since ShellExec doesn't parse them out.
  315. if( L'"' != szOut[0] )
  316. {
  317. // no need to worry about any of this quote business
  318. lstrcpy( g_szShellNext, szOut );
  319. }
  320. else
  321. {
  322. lstrcpy( g_szShellNext, &szOut[1] );
  323. g_szShellNext[lstrlen(g_szShellNext) - 1] = L'\0';
  324. }
  325. TRACE1(L"g_szShellNext = %s", g_szShellNext);
  326. // now read in everything up to the next command line switch
  327. // and consider it to be the parameter. Treat the sequence
  328. // "//" as an escape sequence, and allow it through.
  329. // Example:
  330. // the token /whatever is considered to be a switch to
  331. // icwconn1, and thus will break us out of the whle loop.
  332. //
  333. // the token //something is should be interpreted as a
  334. // command line /something to the the ShellNext app, and
  335. // should not break us out of the while loop.
  336. GetCmdLineToken(&szCmdLine, szOut);
  337. while( szOut[0] )
  338. {
  339. if( L'/' == szOut[0] )
  340. {
  341. if( L'/' != szOut[1] )
  342. {
  343. // it's not an escape sequence, so we're done
  344. break;
  345. }
  346. else
  347. {
  348. // it is an escape sequence, so store it in
  349. // the parameter list, but remove the first /
  350. lstrcat( g_szShellNextParams, &szOut[1] );
  351. }
  352. }
  353. else
  354. {
  355. lstrcat( g_szShellNextParams, szOut );
  356. }
  357. GetCmdLineToken(&szCmdLine, szOut);
  358. }
  359. TRACE1(L"g_szShellNextParams = %s", g_szShellNextParams);
  360. return TRUE;
  361. }
  362. }
  363. }
  364. return FALSE;
  365. }
  366. void ParseCommandLine(LPTSTR lpszCmdParam, APMD *pApmd, DWORD *pProp, int *pRmdIndx)
  367. {
  368. if(lpszCmdParam && pApmd && pProp && pRmdIndx)
  369. {
  370. WCHAR szOut[MAX_PATH];
  371. GetCmdLineToken(&lpszCmdParam, szOut);
  372. while (szOut[0])
  373. {
  374. if (0 == lstrcmpi(szOut, CMD_FULLSCREENMODE))
  375. { // For now, full screen => OEM OOBE mode
  376. *pProp |= (PROP_FULLSCREEN | PROP_OOBE_OEM);
  377. *pApmd = APMD_OOBE;
  378. }
  379. else if (0 == lstrcmpi(szOut, CMD_RETAIL))
  380. { // retail => full screen => OOBE mode
  381. *pProp |= PROP_FULLSCREEN;
  382. *pProp &= ~PROP_OOBE_OEM;
  383. *pApmd = APMD_OOBE;
  384. }
  385. else if (0 == lstrcmpi(szOut, CMD_PRECONFIG))
  386. {
  387. *pApmd = APMD_MSN;
  388. }
  389. else if (0 == lstrcmpi(szOut, CMD_OFFLINE))
  390. {
  391. *pApmd = APMD_MSN;
  392. }
  393. else if (0 == lstrcmpi(szOut, CMD_SETPWD))
  394. {
  395. *pProp |= PROP_SETCONNECTIOD;
  396. }
  397. else if (0 == lstrcmpi(szOut, CMD_OOBE))
  398. {
  399. *pApmd = APMD_OOBE;
  400. }
  401. else if (0 == lstrcmpi(szOut, CMD_REG))
  402. {
  403. *pApmd = APMD_REG;
  404. }
  405. else if (0 == lstrcmpi(szOut, CMD_ISP))
  406. {
  407. *pApmd = APMD_ISP;
  408. }
  409. else if (0 == lstrcmpi(szOut, CMD_ACTIVATE))
  410. {
  411. *pApmd = APMD_ACT;
  412. }
  413. else if (0 == lstrcmpi(szOut, CMD_1))
  414. {
  415. *pRmdIndx = 1;
  416. }
  417. else if (0 == lstrcmpi(szOut, CMD_2))
  418. {
  419. *pRmdIndx = 2;
  420. }
  421. else if (0 == lstrcmpi(szOut, CMD_3))
  422. {
  423. *pRmdIndx = 3;
  424. }
  425. else if (0 == lstrcmpi(szOut, CMD_MSNMODE))
  426. {
  427. *pApmd = APMD_MSN;
  428. *pProp |= PROP_CALLFROM_MSN;
  429. }
  430. else if (0 == lstrcmpi(szOut, CMD_ICWMODE))
  431. {
  432. *pApmd = APMD_MSN;
  433. }
  434. else if (GetShellNextToken(lpszCmdParam, szOut))
  435. {
  436. //*pApmd = APMD_DEFAULT;
  437. }
  438. else if (0 == lstrcmpi(szOut, CMD_2NDINSTANCE))
  439. {
  440. *pProp |= PROP_2NDINSTANCE;
  441. }
  442. GetCmdLineToken(&lpszCmdParam, szOut);
  443. }
  444. }
  445. }
  446. void AutoActivation()
  447. {
  448. // See if we are in an unattend case
  449. WCHAR File [MAX_PATH*2] = L"\0";
  450. DWORD dwExit;
  451. BOOL AutoActivate = FALSE;
  452. TRACE( L"Starting AutoActivation");
  453. if (GetCanonicalizedPath(File, INI_SETTINGS_FILENAME))
  454. {
  455. TRACE1( L"GetCanonicalizedPath: %s",File);
  456. if (GetPrivateProfileInt(OPTIONS_SECTION,
  457. L"IntroOnly",
  458. 0,
  459. File) > 0)
  460. {
  461. TRACE( L"Found intro Only");
  462. AutoActivate = TRUE;
  463. }
  464. }
  465. if (AutoActivate)
  466. {
  467. // Since we did intro only call autoactivation. it checks
  468. // if it should run.
  469. ExpandEnvironmentStrings(
  470. TEXT("%SystemRoot%\\System32\\oobe\\oobebaln.exe /S"),
  471. File,
  472. sizeof(File)/sizeof(WCHAR));
  473. TRACE1( L"Launching:%s", File);
  474. // Launch and wait.
  475. // I tried without wait and the activation did not succeed.
  476. InvokeExternalApplicationEx(NULL, File, &dwExit, INFINITE, TRUE);
  477. }
  478. TRACE( L"AutoActivation done");
  479. }
  480. VOID
  481. RunFactory(
  482. )
  483. {
  484. TCHAR szFileName[MAX_PATH + 32] = TEXT("");
  485. DWORD dwExit;
  486. if ( ( ExpandEnvironmentStrings(
  487. TEXT("%SystemDrive%\\sysprep\\factory.exe"),
  488. szFileName,
  489. sizeof(szFileName) / sizeof(TCHAR)) == 0 ) ||
  490. ( szFileName[0] == TEXT('\0') ) ||
  491. ( GetFileAttributes(szFileName) == 0xFFFFFFFF ) )
  492. {
  493. // If this fails, there is nothing we can really do.
  494. //
  495. TRACE( L"Factory.exe not found");
  496. } else {
  497. InvokeExternalApplicationEx(
  498. szFileName,
  499. L"-oobe",
  500. &dwExit,
  501. INFINITE,
  502. TRUE
  503. );
  504. }
  505. }
  506. void RemoveIntroOnly()
  507. {
  508. WCHAR File [MAX_PATH*2] = L"\0";
  509. if (GetCanonicalizedPath(File, INI_SETTINGS_FILENAME))
  510. {
  511. WritePrivateProfileString(OPTIONS_SECTION,
  512. L"IntroOnly",
  513. L"0",
  514. File);
  515. }
  516. }
  517. INT WINAPI LaunchMSOOBE(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpszCmdParam, INT nCmdShow)
  518. {
  519. HANDLE Mutex;
  520. BOOL bRegisteredDlls = FALSE;
  521. BOOL bUseOleUninitialize = FALSE;
  522. int iReturn=1;
  523. APMD Apmd = APMD_DEFAULT;
  524. DWORD Prop = 0;
  525. int RmdIndx = 0;
  526. //
  527. // We can't use TRACE() until this is called, so don't put anything before it.
  528. //
  529. SetupOobeInitDebugLog();
  530. TRACE1( L"OOBE run with the following parameters: %s", lpszCmdParam );
  531. OOBE_SHUTDOWN_ACTION osa = SHUTDOWN_NOACTION;
  532. g_hInstance = hInstance;
  533. // Parse the command line early. The out params are passed to CObMain to
  534. // set the private members.
  535. ParseCommandLine(lpszCmdParam, &Apmd, &Prop, &RmdIndx);
  536. // If we are not the 2nd instance
  537. if (!(Prop & PROP_2NDINSTANCE))
  538. {
  539. CheckDigitalID();
  540. if (Apmd == APMD_OOBE) {
  541. CSetupKey setupkey;
  542. MYASSERT(setupkey.IsValid());
  543. if ( Prop & PROP_OOBE_OEM ) {
  544. // Remove IntroOnly, just in case it is still set from the original install.
  545. RemoveIntroOnly();
  546. // reset the SetupType so that OOBe can be restarted (OEM case)
  547. if (ERROR_SUCCESS != setupkey.set_SetupType(SETUPTYPE_NOREBOOT)) {
  548. return FALSE;
  549. }
  550. } else {
  551. //
  552. // In the retail OOBE case, clean up the registry early, in case we
  553. // fail to run to completion for some reason. We need to make sure
  554. // we get rid of the OobeInProgress key.
  555. //
  556. CleanupForLogon(setupkey);
  557. }
  558. }
  559. // If we are the first instance, do the checking and register the DLLs
  560. // If we are the 2nd instance this is not needed.
  561. //Exit if MSN app window is aready running and push that window to front
  562. HWND hWnd = FindWindow(OOBE_MAIN_CLASSNAME, NULL);
  563. if(hWnd != NULL)
  564. {
  565. SetForegroundWindow(hWnd);
  566. if (IsIconic(hWnd))
  567. SendMessage(hWnd, WM_SYSCOMMAND, SC_RESTORE, NULL);
  568. TRACE(L"OOBE is already running in this session.");
  569. return 0;
  570. }
  571. // It's possible that OOBE is running in another session. If so, we need
  572. // to bail out.
  573. Mutex = CreateMutex( NULL, TRUE, TEXT("Global\\OOBE is running") );
  574. if ( !Mutex || GetLastError() == ERROR_ALREADY_EXISTS ) {
  575. WCHAR szTitle [MAX_PATH] = L"\0";
  576. WCHAR szMsg [MAX_PATH] = L"\0";
  577. HINSTANCE hInst = GetModuleHandle(OOBE_MAIN_DLL);
  578. TRACE(L"OOBE is already running in another session.");
  579. if(hInst) {
  580. LoadString(hInst, IDS_APPNAME, szTitle, MAX_CHARS_IN_BUFFER(szTitle));
  581. LoadString(hInst, IDS_ALREADY_RUNNING, szMsg, MAX_CHARS_IN_BUFFER(szMsg));
  582. MessageBox( NULL, szMsg, szTitle, MB_OK | MB_ICONEXCLAMATION | MB_APPLMODAL );
  583. }
  584. if ( Mutex ) {
  585. CloseHandle( Mutex );
  586. }
  587. return 0;
  588. }
  589. if(!SelfRegisterComObject(OOBE_WEB_DLL, TRUE)) {
  590. TRACE(L"SelfRegisterComObject() failed.");
  591. return 1;
  592. }
  593. if(!SelfRegisterComObject(OOBE_SHELL_DLL, TRUE)) {
  594. TRACE(L"SelfRegisterComObject() failed.");
  595. return 1;
  596. }
  597. if(!SelfRegisterComObject(OOBE_COMM_DLL, TRUE)) {
  598. TRACE(L"SelfRegisterComObject() failed.");
  599. return 1;
  600. }
  601. bRegisteredDlls = TRUE;
  602. }
  603. //If CoInit fails something is seriously messed up, run away
  604. if (!(Prop & PROP_FULLSCREEN))
  605. {
  606. bUseOleUninitialize = TRUE;
  607. // Need to use OleInitialize to get Clipboard support or Ctrl+C (Copy) does not work
  608. // in the edit controls on the OOBE pages.
  609. if(FAILED(OleInitialize(NULL))) {
  610. TRACE(L"OleInitialize() failed.");
  611. return 1;
  612. }
  613. }
  614. else
  615. {
  616. // Don't have the support in fullscreen OOBE.
  617. if(FAILED(CoInitialize(NULL))) {
  618. TRACE(L"CoInitialize() failed.");
  619. return 1;
  620. }
  621. }
  622. {
  623. // DO NOT REMOVE THIS SCOPE BLOCK. It controls the scope of ObMain.
  624. // ObMain must be initialized after CoInitialize is called and
  625. // destroyed prior to calling CoUninitialize.
  626. //
  627. CObMain ObMain(Apmd, Prop, RmdIndx);
  628. // If we are the 1st instance or
  629. // if we are the second instance and we are in OOBE mode and in fullscreen mode
  630. if (!ObMain.Is2ndInstance() ||
  631. (ObMain.Is2ndInstance() && ObMain.FHasProperty(PROP_OOBE_OEM)))
  632. {
  633. // If not in safe mode proceed.
  634. //
  635. if (!InSafeMode() || InDsRestoreMode() )
  636. {
  637. BOOL fOemOobeMode = ObMain.InOobeMode() && ObMain.FHasProperty(PROP_OOBE_OEM);
  638. // Start the fullscreen background
  639. //
  640. if (!ObMain.Is2ndInstance() && ObMain.FFullScreen())
  641. {
  642. ObMain.CreateBackground();
  643. }
  644. // Run factory.exe if we're in OEM mode.
  645. //
  646. if (fOemOobeMode && !ObMain.Is2ndInstance()) {
  647. RunFactory();
  648. }
  649. // CObMain::Init contains critical initialization. DO NOT call any other
  650. // CObMain methods prior to it.
  651. //
  652. if (ObMain.Init())
  653. {
  654. if (Prop & PROP_SETCONNECTIOD)
  655. {
  656. ObMain.SetConnectoidInfo();
  657. }
  658. else if ((osa = ObMain.DisplayReboot()) != SHUTDOWN_NOACTION)
  659. {
  660. // Either we ran minisetup or we're done.
  661. //
  662. if (osa == SHUTDOWN_REBOOT)
  663. {
  664. ObMain.PowerDown(TRUE);
  665. }
  666. }
  667. else
  668. {
  669. if (!ObMain.Is2ndInstance())
  670. {
  671. // If we are the 1st instance, call syssetup
  672. // and start the magnifier if needed.
  673. // The 2nd instance does not need this.
  674. SetupOobeInitPreServices( fOemOobeMode );
  675. if (ObMain.FFullScreen())
  676. {
  677. WCHAR WinntPath[MAX_PATH];
  678. WCHAR Answer[MAX_PATH];
  679. // Check if we should run Magnifier
  680. if(GetCanonicalizedPath(WinntPath, WINNT_INF_FILENAME))
  681. {
  682. if(GetPrivateProfileString( L"Accessibility",
  683. L"AccMagnifier",
  684. L"",
  685. Answer,
  686. sizeof(Answer)/sizeof(WCHAR),
  687. WinntPath
  688. ))
  689. {
  690. if ( lstrcmpi( Answer, L"1") == 0)
  691. {
  692. InvokeExternalApplication(L"magnify.exe", L"", NULL);
  693. }
  694. }
  695. }
  696. }
  697. }
  698. else
  699. {
  700. //
  701. // The first instance did the minisetup stuff, so
  702. // we don't need to do it again.
  703. //
  704. SetupOobeInitPreServices(FALSE);
  705. }
  706. if(0 != ObMain.InitApplicationWindow())
  707. {
  708. // BUGBUG: Is the following true for NT?
  709. // If we finish OOBE, we return 0 to let the machine boot,
  710. // otherwise we return 1 and the machine shutsdown because
  711. // the user canceled or there was a fatal error.
  712. //
  713. iReturn = ObMain.RunOOBE() ? 0 : 1;
  714. }
  715. if (!ObMain.InAuditMode())
  716. {
  717. // We need to remove this entry now, so ICWMAN (INETWIZ) does not
  718. // pick it up later
  719. RemoveShellNextFromReg();
  720. HandleShellNext();
  721. if (!ObMain.Is2ndInstance() && ObMain.FFullScreen())
  722. {
  723. // Only the 1st instance can do this.
  724. // it called SetupOobeInitPreServices
  725. CSetupKey setupkey;
  726. OOBE_SHUTDOWN_ACTION action;
  727. // We want to clear the restart stuff before
  728. // calling SetupOobeCleanup. SetupOobeCleanup
  729. // enables System Restore, which creates a restore
  730. // point immediately and the restore point would
  731. // cause Winlogon to start OOBE.
  732. ObMain.RemoveRestartStuff(setupkey);
  733. // SHUTDOWN_POWERDOWN happens only if bad pid
  734. // is entered or eula is declined. We don't want to call
  735. // SetupOobeCleanup and enable system restore
  736. // at this point. This has to be called after
  737. // RemoveRestartStuff.
  738. if ((setupkey.get_ShutdownAction(&action) != ERROR_SUCCESS) ||
  739. (action != SHUTDOWN_POWERDOWN))
  740. {
  741. if (fOemOobeMode)
  742. {
  743. ObMain.CreateBackground();
  744. SetupOobeCleanup( fOemOobeMode );
  745. ObMain.StopBackgroundWindow();
  746. }
  747. else
  748. {
  749. SetupOobeCleanup( fOemOobeMode );
  750. }
  751. }
  752. }
  753. }
  754. }
  755. }
  756. if (!ObMain.InAuditMode() && ObMain.FFullScreen())
  757. {
  758. // OOBE is done, let see if we should launch AutoActivation?
  759. AutoActivation();
  760. }
  761. ObMain.Cleanup();
  762. } else if (ObMain.InMode(APMD_ACT)) {
  763. WCHAR szTitle [MAX_PATH] = L"\0";
  764. WCHAR szMsg [MAX_PATH] = L"\0";
  765. HINSTANCE hInst = GetModuleHandle(OOBE_MAIN_DLL);
  766. TRACE(L"Desktop activation cannot be run in safe mode.");
  767. if(hInst) {
  768. LoadString(hInst, IDS_APPNAME, szTitle, MAX_CHARS_IN_BUFFER(szTitle));
  769. LoadString(hInst, IDS_SAFEMODE, szMsg, MAX_CHARS_IN_BUFFER(szMsg));
  770. MessageBox( NULL, szMsg, szTitle, MB_OK | MB_ICONEXCLAMATION | MB_APPLMODAL );
  771. }
  772. } else {
  773. // we are in safemode and not running Activation.
  774. // At least start the services.
  775. SignalComputerNameChangeComplete();
  776. }
  777. }
  778. // DO NOT REMOVE THIS SCOPE BLOCK. It controls the scope of ObMain.
  779. // ObMain must be initialized after CoInitialize is called and
  780. // destroyed prior to calling CoUninitialize.
  781. //
  782. }
  783. if (bUseOleUninitialize)
  784. {
  785. OleUninitialize();
  786. }
  787. else
  788. {
  789. CoUninitialize();
  790. }
  791. if (bRegisteredDlls)
  792. {
  793. SelfRegisterComObject(OOBE_WEB_DLL, FALSE);
  794. SelfRegisterComObject(OOBE_SHELL_DLL, FALSE);
  795. SelfRegisterComObject(OOBE_COMM_DLL, FALSE);
  796. CloseHandle( Mutex );
  797. }
  798. TRACE( L"OOBE has finished." );
  799. return iReturn;
  800. }