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.

835 lines
27 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996 - 1997.
  5. //
  6. // File: LoadWC.cpp
  7. //
  8. // Contents: exe to load webcheck
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 12-12/96 rayen (Raymond Endres) Created
  15. //
  16. //----------------------------------------------------------------------------
  17. #define _SHELL32_
  18. #include <windows.h>
  19. #include <ccstock.h>
  20. #include <debug.h>
  21. #include <docobj.h>
  22. #include <webcheck.h>
  23. #include <shlguid.h>
  24. #include <shlobj.h>
  25. #include <shellp.h>
  26. // need to do this so we can #include <runonce.c>
  27. BOOL g_fCleanBoot = FALSE;
  28. BOOL g_fEndSession = FALSE;
  29. //
  30. // Channels are enabled for the IE4 upgrades.
  31. //
  32. #define ENABLE_CHANNELS
  33. #define MLUI_INIT
  34. #include <mluisupp.h>
  35. //
  36. // NOTE: ActiveSetup relies on our window name and class name
  37. // to shut us down properly in softboot. Do not change it.
  38. //
  39. const TCHAR c_szClassName[] = TEXT("LoadWC");
  40. const TCHAR c_szWebCheckWindow[] = TEXT("MS_WebcheckMonitor");
  41. const TCHAR c_szWebcheckKey[] = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Webcheck");
  42. // message send to dynamically start sens/lce (must not conflict with dialmon)
  43. #define WM_START_SENSLCE (WM_USER+200)
  44. // only used in debug code to grovel with shell service object
  45. #ifdef DEBUG
  46. const TCHAR c_szWebCheck[] = TEXT("WebCheck");
  47. const TCHAR c_szShellReg[] = TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\ShellServiceObjectDelayLoad");
  48. #endif
  49. typedef struct {
  50. HINSTANCE hInstance; // handle to current instance
  51. HWND hwnd; // main window handle
  52. int nCmdShow; // hidden or not?
  53. HINSTANCE hWebcheck; // handle to webcheck dll
  54. BOOL fUninstallOnly; // TRUE -> run uninstall stubs only, then quit
  55. BOOL fIntShellMode; // TRUE -> integrated shell mode, else browser-only
  56. BOOL fStartSensLce;
  57. } GLOBALS;
  58. GLOBALS g;
  59. // webcheck function we dynaload
  60. typedef HRESULT (WINAPI *PFNSTART)(BOOL fForceExternals);
  61. typedef HRESULT (WINAPI *PFNSTOP)(void);
  62. // Code to run install/uninstall stubs, from shell\inc.
  63. #define HINST_THISDLL g.hInstance
  64. #include "resource.h"
  65. //#include <stubsup.h>
  66. #include <inststub.h>
  67. int WINAPI WinMainT(HINSTANCE, HINSTANCE, LPSTR, int);
  68. LRESULT APIENTRY WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  69. void vLoadWebCheck(void);
  70. void vUnloadWebCheck(void);
  71. BOOL bParseCommandLine(LPSTR lpCmdLine, int nCmdShow);
  72. //----------------------------------------------------------------------------
  73. // ModuleEntry
  74. //----------------------------------------------------------------------------
  75. extern "C" int _stdcall ModuleEntry(void)
  76. {
  77. int i;
  78. STARTUPINFOA si;
  79. LPTSTR pszCmdLine;
  80. pszCmdLine = GetCommandLine();
  81. // g_hProcessHeap = GetProcessHeap();
  82. //
  83. // We don't want the "No disk in drive X:" requesters, so we set
  84. // the critical error mask such that calls will just silently fail
  85. //
  86. SetErrorMode(SEM_FAILCRITICALERRORS);
  87. if ( *pszCmdLine == TEXT('\"') ) {
  88. /*
  89. * Scan, and skip over, subsequent characters until
  90. * another double-quote or a null is encountered.
  91. */
  92. while ( *++pszCmdLine && (*pszCmdLine
  93. != TEXT('\"')) );
  94. /*
  95. * If we stopped on a double-quote (usual case), skip
  96. * over it.
  97. */
  98. if ( *pszCmdLine == TEXT('\"') )
  99. pszCmdLine++;
  100. }
  101. else {
  102. while (*pszCmdLine > TEXT(' '))
  103. pszCmdLine++;
  104. }
  105. /*
  106. * Skip past any white space preceeding the second token.
  107. */
  108. while (*pszCmdLine && (*pszCmdLine <= TEXT(' '))) {
  109. pszCmdLine++;
  110. }
  111. si.dwFlags = 0;
  112. GetStartupInfoA(&si);
  113. i = WinMainT(GetModuleHandle(NULL), NULL, pszCmdLine,
  114. si.dwFlags & STARTF_USESHOWWINDOW ? si.wShowWindow : SW_SHOWDEFAULT);
  115. // Since we now have a way for an extension to tell us when it is finished,
  116. // we will terminate all processes when the main thread goes away.
  117. ExitProcess(i);
  118. // DebugMsg(DM_TRACE, TEXT("c.me: Cabinet main thread exiting without ExitProcess."));
  119. return i;
  120. }
  121. //----------------------------------------------------------------------------
  122. // Registry helper function
  123. //----------------------------------------------------------------------------
  124. BOOL ReadRegValue(HKEY hkeyRoot, const TCHAR *pszKey, const TCHAR *pszValue,
  125. void *pData, DWORD dwBytes)
  126. {
  127. return ERROR_SUCCESS == SHRegGetValue(hkeyRoot, pszKey, pszValue, SRRF_RT_ANY | SRRF_NOEXPAND, NULL, pData, &dwBytes);
  128. }
  129. BOOL WriteRegValue(HKEY hkeyRoot, const TCHAR *pszKey, const TCHAR *pszValue,
  130. DWORD dwType, void *pData, DWORD dwBytes)
  131. {
  132. HKEY hkey;
  133. long lResult = RegOpenKeyEx(hkeyRoot, pszKey, 0, KEY_WRITE, &hkey);
  134. if (ERROR_SUCCESS == lResult)
  135. {
  136. lResult = RegSetValueEx(hkey, pszValue, 0, dwType, (BYTE *)pData, dwBytes);
  137. RegCloseKey(hkey);
  138. }
  139. return ERROR_SUCCESS == lResult;
  140. }
  141. void MakeWindowsRootPath(LPSTR pszBuffer, UINT cchBuffer)
  142. {
  143. LPSTR pszEnd = NULL;
  144. if (*pszBuffer == '\\' && *(pszBuffer+1) == '\\') {
  145. pszEnd = pszBuffer + 2;
  146. while (*pszEnd && (*pszEnd != '\\'))
  147. pszEnd++;
  148. if (*pszEnd) {
  149. pszEnd++;
  150. while (*pszEnd && (*pszEnd != '\\'))
  151. pszEnd++;
  152. if (*pszEnd)
  153. pszEnd++;
  154. }
  155. }
  156. else {
  157. LPSTR pszNext = CharNext(pszBuffer);
  158. if (*pszNext == ':' && *(pszNext+1) == '\\')
  159. pszEnd = pszNext + 2;
  160. }
  161. if (pszEnd != NULL)
  162. *pszEnd = '\0';
  163. else {
  164. /* ??? Windows dir is neither UNC nor a root path?
  165. * Just make sure it ends in a backslash.
  166. */
  167. LPSTR pszLast = pszBuffer;
  168. if (*pszBuffer) {
  169. pszLast = CharPrev(pszBuffer, pszBuffer + lstrlen(pszBuffer));
  170. }
  171. if (*pszLast != '\\')
  172. StrCatBuff(pszLast, "\\", cchBuffer);
  173. }
  174. }
  175. //----------------------------------------------------------------------------
  176. // InitShellFolders
  177. //
  178. // More of making loadwc.exe a browser-only mode catch-all. This code makes
  179. // sure that the Shell Folders key in the per-user registry is fully populated
  180. // with the absolute paths to all the special folders for IE, even if
  181. // shell32.dll doesn't understand all of them.
  182. //
  183. // As the shell would do in SHGetSpecialFolderLocation, we check the
  184. // User Shell Folders key for a path, and if that's present we copy it to the
  185. // Shell Folders key, expanding %USERPROFILE% if necessary. If the value is
  186. // not present under User Shell Folders, we generate the default location
  187. // (usually under the Windows directory) and store that location under
  188. // Shell Folders.
  189. //----------------------------------------------------------------------------
  190. struct FolderDescriptor {
  191. UINT idsDirName; /* Resource ID for directory name */
  192. LPCTSTR pszRegValue; /* Name of reg value to set path in */
  193. BOOL fDefaultInRoot : 1; /* TRUE if default location is root directory */
  194. BOOL fWriteToUSF : 1; /* TRUE if we should write to User Shell Folders to work around Win95 bug */
  195. } aFolders[] = {
  196. { IDS_CSIDL_PERSONAL_L, TEXT("Personal"), TRUE, TRUE } ,
  197. { IDS_CSIDL_FAVORITES_L, TEXT("Favorites"), FALSE, TRUE },
  198. { IDS_CSIDL_APPDATA_L, TEXT("AppData"), FALSE, FALSE },
  199. { IDS_CSIDL_CACHE_L, TEXT("Cache"), FALSE, FALSE },
  200. { IDS_CSIDL_COOKIES_L, TEXT("Cookies"), FALSE, FALSE },
  201. { IDS_CSIDL_HISTORY_L, TEXT("History"), FALSE, FALSE },
  202. };
  203. void InitShellFolders(void)
  204. {
  205. LONG err;
  206. HKEY hkeySF = NULL;
  207. HKEY hkeyUSF = NULL;
  208. TCHAR szDefaultDir[MAX_PATH];
  209. TCHAR szRootDir[MAX_PATH+1]; // possible extra '\'
  210. LPSTR pszPathEnd;
  211. LPSTR pszRootEnd;
  212. /* Get the windows directory and simulate PathAddBackslash (which we
  213. * can't get out of shlwapi, because loadwc.exe also needs to be able
  214. * to load after IE has been uninstalled and shlwapi deleted).
  215. *
  216. * Also build the root directory of the drive that the Windows directory
  217. * is on, so we can put My Documents there if necessary.
  218. */
  219. *szDefaultDir = TEXT('\0');
  220. GetWindowsDirectory(szDefaultDir, ARRAYSIZE(szDefaultDir));
  221. StrCpyN(szRootDir, szDefaultDir, ARRAYSIZE(szRootDir));
  222. MakeWindowsRootPath(szRootDir, ARRAYSIZE(szRootDir));
  223. pszRootEnd = szRootDir + lstrlen(szRootDir);
  224. pszPathEnd = CharPrev(szDefaultDir, szDefaultDir + lstrlen(szDefaultDir));
  225. if (*pszPathEnd != '\\') {
  226. pszPathEnd = CharNext(pszPathEnd);
  227. *(pszPathEnd++) = '\\';
  228. }
  229. // pszPathEnd now points to where we can append the relative path
  230. UINT cchPathSpace = ARRAYSIZE(szDefaultDir) - (UINT)(pszPathEnd - szDefaultDir);
  231. UINT cchRootSpace = ARRAYSIZE(szRootDir) - (UINT)(pszRootEnd - szRootDir);
  232. err = RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders",
  233. 0, KEY_QUERY_VALUE | KEY_SET_VALUE, &hkeySF);
  234. if (err == ERROR_SUCCESS) {
  235. err = RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders",
  236. 0, KEY_QUERY_VALUE, &hkeyUSF);
  237. if (err == ERROR_SUCCESS) {
  238. for (UINT i=0; i<ARRAYSIZE(aFolders); i++) {
  239. TCHAR szRawFolderName[MAX_PATH];
  240. TCHAR szExpandedFolderName[MAX_PATH];
  241. DWORD dwType;
  242. DWORD cbData = sizeof(szRawFolderName);
  243. LPSTR pszPath;
  244. err = SHRegGetValue(hkeyUSF, NULL, aFolders[i].pszRegValue, SRRF_RT_ANY | SRRF_NOEXPAND, &dwType, szRawFolderName, &cbData);
  245. if (err == ERROR_SUCCESS) {
  246. switch (dwType)
  247. {
  248. case REG_SZ:
  249. pszPath = szRawFolderName;
  250. break;
  251. case REG_EXPAND_SZ:
  252. {
  253. DWORD cchExpanded = ExpandEnvironmentStrings(szRawFolderName, szExpandedFolderName, ARRAYSIZE(szExpandedFolderName));
  254. if (cchExpanded <= 0 || cchExpanded > ARRAYSIZE(szExpandedFolderName))
  255. {
  256. continue;
  257. }
  258. pszPath = szExpandedFolderName;
  259. break;
  260. }
  261. default:
  262. continue;
  263. }
  264. }
  265. else {
  266. if (!MLLoadString(aFolders[i].idsDirName,
  267. aFolders[i].fDefaultInRoot ? pszRootEnd : pszPathEnd,
  268. aFolders[i].fDefaultInRoot ? cchRootSpace : cchPathSpace)) {
  269. continue;
  270. }
  271. if (aFolders[i].fDefaultInRoot)
  272. pszPath = szRootDir;
  273. else
  274. pszPath = szDefaultDir;
  275. if (GetFileAttributes(pszPath) == 0xffffffff)
  276. CreateDirectory(pszPath, NULL);
  277. /* The Win95 shell has a bug where for some shell folders,
  278. * if there isn't a path recorded under User Shell Folders,
  279. * the shell folder is assumed not to exist. So, for those
  280. * folders only, we also write the default path to USF.
  281. * We do not do this generically because no value under
  282. * USF is supposed to mean "use the one in the Windows
  283. * directory", whereas an absolute path means "use that
  284. * path"; if there's a path under USF, it will be used
  285. * literally, which is a problem if the folder is set up
  286. * to use the shared folder location but roams to a machine
  287. * with Windows installed in a different directory.
  288. */
  289. if (aFolders[i].fWriteToUSF) {
  290. RegSetValueEx(hkeyUSF, aFolders[i].pszRegValue, 0, REG_SZ,
  291. (LPBYTE)pszPath, lstrlen(pszPath)+1);
  292. }
  293. }
  294. RegSetValueEx(hkeySF, aFolders[i].pszRegValue, 0, REG_SZ,
  295. (LPBYTE)pszPath, lstrlen(pszPath)+1);
  296. }
  297. RegCloseKey(hkeyUSF);
  298. }
  299. RegCloseKey(hkeySF);
  300. }
  301. }
  302. /* Function to determine whether we're in integrated-shell mode or browser-only
  303. * mode. The method for doing this (looking for DllGetVersion exported from
  304. * shell32.dll) is taken from shdocvw. We don't actually call that entrypoint,
  305. * we just look for it.
  306. */
  307. BOOL IsIntegratedShellMode()
  308. {
  309. FARPROC pfnDllGetVersion = NULL;
  310. HMODULE hmodShell = LoadLibrary("shell32.dll");
  311. if (hmodShell != NULL) {
  312. pfnDllGetVersion = GetProcAddress(hmodShell, "DllGetVersion");
  313. FreeLibrary(hmodShell);
  314. }
  315. return (pfnDllGetVersion != NULL);
  316. }
  317. //
  318. // Convert the string to a DWORD.
  319. //
  320. DWORD StringToDW(LPCTSTR psz)
  321. {
  322. DWORD dwRet = 0;
  323. while (*psz >= TEXT('0') && *psz <= TEXT('9'))
  324. {
  325. dwRet = dwRet * 10 + *psz - TEXT('0');
  326. *psz++;
  327. }
  328. return dwRet;
  329. }
  330. //
  331. // Is the version string from IE4
  332. //
  333. BOOL IsVersionIE4(LPCTSTR pszVersion)
  334. {
  335. BOOL fRet = FALSE;
  336. //
  337. // IE3.0 is 4.70 and Ie4.0x is >= 4.71.1218.xxxx
  338. //
  339. if (pszVersion[0] == TEXT('4') && pszVersion[1] == TEXT('.'))
  340. {
  341. DWORD dw = StringToDW(pszVersion+2);
  342. if (dw > 71 || (dw == 71 && pszVersion[4] == TEXT('.') &&
  343. StringToDW(pszVersion+5) >= 1218))
  344. {
  345. fRet = TRUE;
  346. }
  347. }
  348. return fRet;
  349. }
  350. //
  351. // Determine if this is an IE4 upgrade.
  352. //
  353. BOOL IsIE4Upgrade()
  354. {
  355. BOOL fRet = FALSE;
  356. TCHAR szVersion[MAX_PATH];
  357. if (ReadRegValue(HKEY_LOCAL_MACHINE,
  358. TEXT("Software\\Microsoft\\IE Setup\\Setup"),
  359. TEXT("PreviousIESysFile"), (void *)szVersion,
  360. sizeof(szVersion)))
  361. {
  362. fRet = IsVersionIE4(szVersion);
  363. }
  364. return fRet;
  365. }
  366. //
  367. // This is an IE5 or later function. If the user's machine is running IE4 they
  368. // have uninstalled back to IE4.
  369. //
  370. BOOL IsUninstallToIE4()
  371. {
  372. BOOL fRet = FALSE;
  373. TCHAR szVersion[MAX_PATH];
  374. if (ReadRegValue(HKEY_LOCAL_MACHINE,
  375. TEXT("Software\\Microsoft\\Internet Explorer"),
  376. TEXT("Version"), (void *)szVersion,
  377. sizeof(szVersion)))
  378. {
  379. fRet = IsVersionIE4(szVersion);
  380. }
  381. return fRet;
  382. }
  383. /* Function to launch miscellaneous applications for browser only mode.
  384. * We run IEXPLORE.EXE -channelband, looking in the registry for the path
  385. * to IEXPLORE, and WELCOME.EXE /f, located in the same directory.
  386. */
  387. #ifdef ENABLE_CHANNELS
  388. const TCHAR c_szChanBarRegPath[] = TEXT("Software\\Microsoft\\Internet Explorer\\Main");
  389. const TCHAR c_szChanBarKey[] = TEXT("Show_ChannelBand");
  390. #endif
  391. void LaunchBrowserOnlyApps()
  392. {
  393. TCHAR szPath[MAX_PATH];
  394. /* Don't launch any of these guys if this is a "redist mode" install,
  395. * i.e. if a game or something installed browser components silently
  396. * without the user really realizing it's there.
  397. */
  398. if (ReadRegValue(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\IE Setup\\Setup",
  399. "InstallMode", (void *)szPath, sizeof(szPath))
  400. && !lstrcmp(szPath, "R")) {
  401. return;
  402. }
  403. LPTSTR pszPathEnd;
  404. LONG cbPath = sizeof(szPath);
  405. /* Get the default value from the App Paths\IEXPLORE.EXE reg key, which
  406. * is the absolute path to the EXE.
  407. */
  408. if (RegQueryValue(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\IEXPLORE.EXE",
  409. szPath, &cbPath) != ERROR_SUCCESS) {
  410. pszPathEnd = szPath;
  411. StrCpyN(szPath, "IEXPLORE.EXE", ARRAYSIZE(szPath)); /* can't get from reg, hope it's on the path */
  412. }
  413. else {
  414. /* Find the last backslash in the path. This is a manual
  415. * version of strrchr(szPath, '\\').
  416. */
  417. LPTSTR pszLastBackslash = NULL;
  418. for (pszPathEnd = szPath; *pszPathEnd; pszPathEnd = CharNext(pszPathEnd)) {
  419. if (*pszPathEnd == '\\')
  420. pszLastBackslash = pszPathEnd;
  421. }
  422. if (pszLastBackslash == NULL)
  423. pszPathEnd = szPath;
  424. else
  425. pszPathEnd = pszLastBackslash + 1; /* point after last backslash */
  426. }
  427. #ifdef ENABLE_CHANNELS
  428. /* Don't launch the channel band app if the user doesn't want it.
  429. * They want it if the reg value is missing, or if it's "yes".
  430. * On WinNT, we default to "no" for browser-only installs.
  431. */
  432. TCHAR szValue[20];
  433. BOOL fShowChannelBand=FALSE;
  434. if (ReadRegValue(HKEY_CURRENT_USER, c_szChanBarRegPath,
  435. c_szChanBarKey, (void *)szValue, sizeof(szValue)))
  436. {
  437. if (!lstrcmpi(szValue, "yes"))
  438. {
  439. fShowChannelBand=TRUE;
  440. }
  441. }
  442. //
  443. // In general, don't auto launch the channel bar post IE4.
  444. //
  445. // Exception: Show the channelband if there is no Show_ChannelBand key and
  446. // the user upgraded over IE4 and this is W95 or W98. This is required
  447. // because IE4 would launch a channel bar in this scenario w/o writting the
  448. // Show_ChannelBand key. We don't want to turn of the channel bar for these
  449. // users.
  450. //
  451. // Another exception: Loadwc doesn't get uninstalled when IE is
  452. // uninstalled. If the user uninstalls IE5+ and goes back to IE4 we want
  453. // this version of loadwc to revert to IE4 loadwc behavior.
  454. //
  455. else
  456. {
  457. OSVERSIONINFO vi;
  458. vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  459. GetVersionEx(&vi);
  460. if (vi.dwPlatformId != VER_PLATFORM_WIN32_NT &&
  461. (IsIE4Upgrade() || IsUninstallToIE4()))
  462. {
  463. fShowChannelBand=TRUE;
  464. //
  465. // Set the registry key so this code only runs once and upgrades to
  466. // IE5 don't have to worry about this scenario.
  467. //
  468. WriteRegValue(HKEY_CURRENT_USER, c_szChanBarRegPath, c_szChanBarKey,
  469. REG_SZ, TEXT("yes"), sizeof(TEXT("yes")));
  470. }
  471. else
  472. {
  473. WriteRegValue(HKEY_CURRENT_USER, c_szChanBarRegPath, c_szChanBarKey,
  474. REG_SZ, TEXT("no"), sizeof(TEXT("no")));
  475. }
  476. }
  477. if (fShowChannelBand)
  478. {
  479. int cLen = lstrlen(szPath);
  480. StrCpyN(szPath + cLen, " -channelband", ARRAYSIZE(szPath) - cLen);
  481. WinExec(szPath, SW_SHOWNORMAL);
  482. }
  483. #endif
  484. /* Check the registry to see if the welcome app should be launched. Again,
  485. * only launch if value is missing or positive (non-zero dword, this time).
  486. */
  487. DWORD dwShow = 0;
  488. if (!ReadRegValue(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Tips",
  489. "ShowIE4", (void *)&dwShow, sizeof(dwShow))
  490. || dwShow) {
  491. StrCpyN(pszPathEnd, "WELCOME.EXE /f", ARRAYSIZE(szPath) - (UINT)(pszPathEnd - szPath));
  492. WinExec(szPath, SW_SHOWNORMAL);
  493. }
  494. }
  495. //----------------------------------------------------------------------------
  496. // WinMain
  497. //----------------------------------------------------------------------------
  498. int WINAPI WinMainT(
  499. HINSTANCE hInstance, // handle to current instance
  500. HINSTANCE hPrevInstance, // handle to previous instance
  501. LPSTR lpCmdLine, // pointer to command line
  502. int nCmdShow // show state of window
  503. )
  504. {
  505. HWND hwndOtherInstance;
  506. // Save the globals
  507. g.hInstance = hInstance;
  508. g.nCmdShow = SW_HIDE;
  509. g.fUninstallOnly = FALSE;
  510. g.fStartSensLce = FALSE;
  511. g.fIntShellMode = IsIntegratedShellMode();
  512. g.hWebcheck = NULL;
  513. MLLoadResources(g.hInstance, TEXT("loadwclc.dll"));
  514. // Parse the command line, for DEBUG options and for uninstall-only switch.
  515. // Now also sets fStartSensLce
  516. if (!bParseCommandLine(lpCmdLine, nCmdShow))
  517. return 0;
  518. // look for webcheck window. This is ultimately the guy we need to
  519. // find to load sens/lce late in the game.
  520. hwndOtherInstance = FindWindow(c_szWebCheckWindow, c_szWebCheckWindow);
  521. if(NULL == hwndOtherInstance)
  522. {
  523. // can't find webcheck, look for loadwc. If we find him but not
  524. // webcheck, we either don't have the MOP or we're still in the 15
  525. // second delay. Send the messages to loadwc and he'll take care
  526. // of it.
  527. hwndOtherInstance = FindWindow(c_szClassName, c_szClassName);
  528. }
  529. if(hwndOtherInstance)
  530. {
  531. // an instance is already running. Tell it about Sens/LCE loading
  532. // requirements and bail out
  533. if(g.fStartSensLce)
  534. {
  535. PostMessage(hwndOtherInstance, WM_START_SENSLCE, 0, 0);
  536. }
  537. return 0;
  538. }
  539. // Set up the absolute paths for all the shell folders we care about,
  540. // in case we're in browser-only mode and the shell doesn't support
  541. // the new ones.
  542. if (!g.fUninstallOnly)
  543. InitShellFolders();
  544. // Run all install/uninstall stubs for browser-only mode.
  545. // If IE4 has been uninstalled, we'll be run with the -u switch; this
  546. // means to run install/uninstall stubs only, no webcheck stuff.
  547. if (!g.fIntShellMode) {
  548. RunInstallUninstallStubs2(NULL);
  549. }
  550. if (g.fUninstallOnly)
  551. return 0;
  552. // Launch the channel bar and welcome apps in browser-only mode.
  553. if (!g.fIntShellMode) {
  554. LaunchBrowserOnlyApps();
  555. }
  556. // Register the window class for the main window.
  557. WNDCLASS wc;
  558. if (!hPrevInstance)
  559. {
  560. wc.style = 0;
  561. wc.lpfnWndProc = WndProc;
  562. wc.cbClsExtra = 0;
  563. wc.cbWndExtra = 0;
  564. wc.hInstance = hInstance;
  565. wc.hIcon = NULL;
  566. wc.hCursor = NULL;
  567. wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
  568. wc.lpszMenuName = NULL;
  569. wc.lpszClassName = c_szClassName;
  570. if (!RegisterClass(&wc))
  571. return 0;
  572. }
  573. // Create the main window.
  574. g.hwnd = CreateWindow(c_szClassName,
  575. c_szClassName,
  576. WS_OVERLAPPEDWINDOW,
  577. CW_USEDEFAULT,
  578. CW_USEDEFAULT,
  579. CW_USEDEFAULT,
  580. CW_USEDEFAULT,
  581. (HWND) NULL,
  582. (HMENU) NULL,
  583. hInstance,
  584. (LPVOID) NULL);
  585. if (!g.hwnd)
  586. return 0;
  587. // Show the window and paint its contents.
  588. ShowWindow(g.hwnd, g.nCmdShow);
  589. // Start the message loop
  590. MSG msg;
  591. while (GetMessage(&msg, (HWND) NULL, 0, 0)) {
  592. TranslateMessage(&msg);
  593. DispatchMessage(&msg);
  594. }
  595. MLFreeResources(g.hInstance);
  596. // Return the exit code to Windows
  597. return (int)msg.wParam;
  598. }
  599. //----------------------------------------------------------------------------
  600. // WndProc
  601. //----------------------------------------------------------------------------
  602. LRESULT APIENTRY WndProc(
  603. HWND hwnd,
  604. UINT uMsg,
  605. WPARAM wParam,
  606. LPARAM lParam
  607. )
  608. {
  609. switch (uMsg) {
  610. case WM_CREATE:
  611. DWORD dwTime;
  612. if(!ReadRegValue(HKEY_CURRENT_USER, c_szWebcheckKey, "DelayLoad", &dwTime, sizeof(dwTime)))
  613. dwTime = 15;
  614. SetTimer(hwnd, 1, 1000 * dwTime, NULL);
  615. break;
  616. case WM_START_SENSLCE:
  617. g.fStartSensLce = TRUE;
  618. break;
  619. case WM_TIMER:
  620. KillTimer(hwnd, 1);
  621. vLoadWebCheck();
  622. return 0;
  623. case WM_ENDSESSION:
  624. if (!wParam) // if not fEndSession, bail
  625. break;
  626. // else fall through to WM_DESTROY
  627. case WM_DESTROY:
  628. vUnloadWebCheck();
  629. PostQuitMessage(0);
  630. return 0;
  631. default:
  632. break;
  633. }
  634. return DefWindowProc(hwnd, uMsg, wParam, lParam);
  635. }
  636. //----------------------------------------------------------------------------
  637. // vLoadWebCheck
  638. //----------------------------------------------------------------------------
  639. void vLoadWebCheck(void)
  640. {
  641. if(g.hWebcheck)
  642. return;
  643. g.hWebcheck = LoadLibrary(TEXT("webcheck.dll"));
  644. if(g.hWebcheck)
  645. {
  646. PFNSTART pfn = (PFNSTART)GetProcAddress(g.hWebcheck, (LPCSTR)7);
  647. if(pfn)
  648. {
  649. pfn(g.fStartSensLce);
  650. }
  651. else
  652. {
  653. // clean up dll
  654. FreeLibrary(g.hWebcheck);
  655. g.hWebcheck = NULL;
  656. }
  657. }
  658. }
  659. //----------------------------------------------------------------------------
  660. // vUnloadWebCheck
  661. //----------------------------------------------------------------------------
  662. void vUnloadWebCheck(void)
  663. {
  664. if (!g.hWebcheck)
  665. return;
  666. PFNSTOP pfn = (PFNSTOP)GetProcAddress(g.hWebcheck, (LPCSTR)8);
  667. if(pfn)
  668. {
  669. pfn();
  670. }
  671. // [darrenmi] don't bother unloading webcheck. We only do this in
  672. // response to a shut down so it's not a big deal. On NT screen saver
  673. // proxy has a thread that wakes up after the call to StopService - if
  674. // we've unloaded the dll before then, we're toast.
  675. // clean up dll
  676. //FreeLibrary(g.hWebcheck);
  677. //g.hWebcheck = NULL;
  678. }
  679. //----------------------------------------------------------------------------
  680. // bParseCmdLine
  681. //
  682. // Parse the command line
  683. // -u run install/uninstall stubs only, then quit
  684. // DEBUG options:
  685. // -v visible window (easy to shutdown)
  686. // -a add webcheck to shell service object
  687. // -r remove webcheck from shell service object
  688. // -s fix shell folders only
  689. // -? these options
  690. //----------------------------------------------------------------------------
  691. BOOL bParseCommandLine(LPSTR lpCmdLine, int nCmdShow)
  692. {
  693. if (!lpCmdLine)
  694. return TRUE;
  695. CharUpper(lpCmdLine); /* easier to parse */
  696. while (*lpCmdLine) {
  697. if (*lpCmdLine != '-' && *lpCmdLine != '/')
  698. break;
  699. lpCmdLine++;
  700. switch (*(lpCmdLine++)) {
  701. case 'E':
  702. // ignore 'embedding' command line
  703. break;
  704. case 'L':
  705. case 'M':
  706. g.fStartSensLce = TRUE;
  707. break;
  708. case 'U':
  709. g.fUninstallOnly = TRUE;
  710. break;
  711. }
  712. while (*lpCmdLine == ' ' || *lpCmdLine == '\t') {
  713. lpCmdLine++;
  714. }
  715. }
  716. return TRUE;
  717. }