Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

910 lines
29 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. long lResult;
  128. HKEY hkey;
  129. DWORD dwType;
  130. lResult = RegOpenKey(hkeyRoot, pszKey, &hkey);
  131. if (lResult != ERROR_SUCCESS) {
  132. return FALSE;
  133. }
  134. lResult = RegQueryValueEx(hkey, pszValue, NULL, &dwType, (BYTE *)pData,
  135. &dwBytes);
  136. RegCloseKey(hkey);
  137. if (lResult != ERROR_SUCCESS)
  138. return FALSE;
  139. return TRUE;
  140. }
  141. BOOL WriteRegValue(HKEY hkeyRoot, const TCHAR *pszKey, const TCHAR *pszValue,
  142. DWORD dwType, void *pData, DWORD dwBytes)
  143. {
  144. HKEY hkey;
  145. long lResult = RegOpenKey(hkeyRoot, pszKey, &hkey);
  146. if (ERROR_SUCCESS == lResult)
  147. {
  148. lResult = RegSetValueEx(hkey, pszValue, 0, dwType, (BYTE *)pData, dwBytes);
  149. RegCloseKey(hkey);
  150. }
  151. return ERROR_SUCCESS == lResult;
  152. }
  153. void MakeWindowsRootPath(LPSTR pszBuffer)
  154. {
  155. LPSTR pszEnd = NULL;
  156. if (*pszBuffer == '\\' && *(pszBuffer+1) == '\\') {
  157. pszEnd = pszBuffer + 2;
  158. while (*pszEnd && (*pszEnd != '\\'))
  159. pszEnd++;
  160. if (*pszEnd) {
  161. pszEnd++;
  162. while (*pszEnd && (*pszEnd != '\\'))
  163. pszEnd++;
  164. if (*pszEnd)
  165. pszEnd++;
  166. }
  167. }
  168. else {
  169. LPSTR pszNext = CharNext(pszBuffer);
  170. if (*pszNext == ':' && *(pszNext+1) == '\\')
  171. pszEnd = pszNext + 2;
  172. }
  173. if (pszEnd != NULL)
  174. *pszEnd = '\0';
  175. else {
  176. /* ??? Windows dir is neither UNC nor a root path?
  177. * Just make sure it ends in a backslash.
  178. */
  179. LPSTR pszLast = pszBuffer;
  180. if (*pszBuffer) {
  181. pszLast = CharPrev(pszBuffer, pszBuffer + lstrlen(pszBuffer));
  182. }
  183. if (*pszLast != '\\')
  184. lstrcat(pszLast, "\\");
  185. }
  186. }
  187. //----------------------------------------------------------------------------
  188. // InitShellFolders
  189. //
  190. // More of making loadwc.exe a browser-only mode catch-all. This code makes
  191. // sure that the Shell Folders key in the per-user registry is fully populated
  192. // with the absolute paths to all the special folders for IE, even if
  193. // shell32.dll doesn't understand all of them.
  194. //
  195. // As the shell would do in SHGetSpecialFolderLocation, we check the
  196. // User Shell Folders key for a path, and if that's present we copy it to the
  197. // Shell Folders key, expanding %USERPROFILE% if necessary. If the value is
  198. // not present under User Shell Folders, we generate the default location
  199. // (usually under the Windows directory) and store that location under
  200. // Shell Folders.
  201. //----------------------------------------------------------------------------
  202. struct FolderDescriptor {
  203. UINT idsDirName; /* Resource ID for directory name */
  204. LPCTSTR pszRegValue; /* Name of reg value to set path in */
  205. BOOL fDefaultInRoot : 1; /* TRUE if default location is root directory */
  206. BOOL fWriteToUSF : 1; /* TRUE if we should write to User Shell Folders to work around Win95 bug */
  207. } aFolders[] = {
  208. { IDS_CSIDL_PERSONAL_L, TEXT("Personal"), TRUE, TRUE } ,
  209. { IDS_CSIDL_FAVORITES_L, TEXT("Favorites"), FALSE, TRUE },
  210. { IDS_CSIDL_APPDATA_L, TEXT("AppData"), FALSE, FALSE },
  211. { IDS_CSIDL_CACHE_L, TEXT("Cache"), FALSE, FALSE },
  212. { IDS_CSIDL_COOKIES_L, TEXT("Cookies"), FALSE, FALSE },
  213. { IDS_CSIDL_HISTORY_L, TEXT("History"), FALSE, FALSE },
  214. };
  215. void InitShellFolders(void)
  216. {
  217. LONG err;
  218. HKEY hkeySF = NULL;
  219. HKEY hkeyUSF = NULL;
  220. TCHAR szDefaultDir[MAX_PATH];
  221. TCHAR szRootDir[MAX_PATH+1]; // possible extra '\'
  222. LPSTR pszPathEnd;
  223. LPSTR pszRootEnd;
  224. /* Get the windows directory and simulate PathAddBackslash (which we
  225. * can't get out of shlwapi, because loadwc.exe also needs to be able
  226. * to load after IE has been uninstalled and shlwapi deleted).
  227. *
  228. * Also build the root directory of the drive that the Windows directory
  229. * is on, so we can put My Documents there if necessary.
  230. */
  231. *szDefaultDir = TEXT('\0');
  232. GetWindowsDirectory(szDefaultDir, ARRAYSIZE(szDefaultDir));
  233. lstrcpy(szRootDir, szDefaultDir);
  234. MakeWindowsRootPath(szRootDir);
  235. pszRootEnd = szRootDir + lstrlen(szRootDir);
  236. pszPathEnd = CharPrev(szDefaultDir, szDefaultDir + lstrlen(szDefaultDir));
  237. if (*pszPathEnd != '\\') {
  238. pszPathEnd = CharNext(pszPathEnd);
  239. *(pszPathEnd++) = '\\';
  240. }
  241. // pszPathEnd now points to where we can append the relative path
  242. UINT cchPathSpace = ARRAYSIZE(szDefaultDir) - (UINT)(pszPathEnd - szDefaultDir);
  243. UINT cchRootSpace = ARRAYSIZE(szRootDir) - (UINT)(pszRootEnd - szRootDir);
  244. err = RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders",
  245. 0, KEY_QUERY_VALUE | KEY_SET_VALUE, &hkeySF);
  246. if (err == ERROR_SUCCESS) {
  247. err = RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders",
  248. 0, KEY_QUERY_VALUE, &hkeyUSF);
  249. if (err == ERROR_SUCCESS) {
  250. for (UINT i=0; i<ARRAYSIZE(aFolders); i++) {
  251. TCHAR szRawFolderName[MAX_PATH];
  252. TCHAR szExpandedFolderName[MAX_PATH];
  253. DWORD dwType;
  254. DWORD cbData = sizeof(szRawFolderName);
  255. LPSTR pszPath;
  256. err = RegQueryValueEx(hkeyUSF, aFolders[i].pszRegValue,
  257. NULL, &dwType, (LPBYTE)szRawFolderName,
  258. &cbData);
  259. if (err == ERROR_SUCCESS) {
  260. if ((dwType != REG_EXPAND_SZ && dwType != REG_SZ) ||
  261. !ExpandEnvironmentStrings(szRawFolderName,
  262. szExpandedFolderName,
  263. ARRAYSIZE(szExpandedFolderName)))
  264. {
  265. continue;
  266. }
  267. pszPath = szExpandedFolderName;
  268. }
  269. else {
  270. if (!MLLoadString(aFolders[i].idsDirName,
  271. aFolders[i].fDefaultInRoot ? pszRootEnd : pszPathEnd,
  272. aFolders[i].fDefaultInRoot ? cchRootSpace : cchPathSpace)) {
  273. continue;
  274. }
  275. if (aFolders[i].fDefaultInRoot)
  276. pszPath = szRootDir;
  277. else
  278. pszPath = szDefaultDir;
  279. if (GetFileAttributes(pszPath) == 0xffffffff)
  280. CreateDirectory(pszPath, NULL);
  281. /* The Win95 shell has a bug where for some shell folders,
  282. * if there isn't a path recorded under User Shell Folders,
  283. * the shell folder is assumed not to exist. So, for those
  284. * folders only, we also write the default path to USF.
  285. * We do not do this generically because no value under
  286. * USF is supposed to mean "use the one in the Windows
  287. * directory", whereas an absolute path means "use that
  288. * path"; if there's a path under USF, it will be used
  289. * literally, which is a problem if the folder is set up
  290. * to use the shared folder location but roams to a machine
  291. * with Windows installed in a different directory.
  292. */
  293. if (aFolders[i].fWriteToUSF) {
  294. RegSetValueEx(hkeyUSF, aFolders[i].pszRegValue, 0, REG_SZ,
  295. (LPBYTE)pszPath, lstrlen(pszPath)+1);
  296. }
  297. }
  298. RegSetValueEx(hkeySF, aFolders[i].pszRegValue, 0, REG_SZ,
  299. (LPBYTE)pszPath, lstrlen(pszPath)+1);
  300. }
  301. RegCloseKey(hkeyUSF);
  302. }
  303. RegCloseKey(hkeySF);
  304. }
  305. }
  306. /* Function to determine whether we're in integrated-shell mode or browser-only
  307. * mode. The method for doing this (looking for DllGetVersion exported from
  308. * shell32.dll) is taken from shdocvw. We don't actually call that entrypoint,
  309. * we just look for it.
  310. */
  311. BOOL IsIntegratedShellMode()
  312. {
  313. FARPROC pfnDllGetVersion = NULL;
  314. HMODULE hmodShell = LoadLibrary("shell32.dll");
  315. if (hmodShell != NULL) {
  316. pfnDllGetVersion = GetProcAddress(hmodShell, "DllGetVersion");
  317. FreeLibrary(hmodShell);
  318. }
  319. return (pfnDllGetVersion != NULL);
  320. }
  321. //
  322. // Convert the string to a DWORD.
  323. //
  324. DWORD StringToDW(LPCTSTR psz)
  325. {
  326. DWORD dwRet = 0;
  327. while (*psz >= TEXT('0') && *psz <= TEXT('9'))
  328. {
  329. dwRet = dwRet * 10 + *psz - TEXT('0');
  330. *psz++;
  331. }
  332. return dwRet;
  333. }
  334. //
  335. // Is the version string from IE4
  336. //
  337. BOOL IsVersionIE4(LPCTSTR pszVersion)
  338. {
  339. BOOL fRet = FALSE;
  340. //
  341. // IE3.0 is 4.70 and Ie4.0x is >= 4.71.1218.xxxx
  342. //
  343. if (pszVersion[0] == TEXT('4') && pszVersion[1] == TEXT('.'))
  344. {
  345. DWORD dw = StringToDW(pszVersion+2);
  346. if (dw > 71 || (dw == 71 && pszVersion[4] == TEXT('.') &&
  347. StringToDW(pszVersion+5) >= 1218))
  348. {
  349. fRet = TRUE;
  350. }
  351. }
  352. return fRet;
  353. }
  354. //
  355. // Determine if this is an IE4 upgrade.
  356. //
  357. BOOL IsIE4Upgrade()
  358. {
  359. BOOL fRet = FALSE;
  360. TCHAR szVersion[MAX_PATH];
  361. if (ReadRegValue(HKEY_LOCAL_MACHINE,
  362. TEXT("Software\\Microsoft\\IE Setup\\Setup"),
  363. TEXT("PreviousIESysFile"), (void *)szVersion,
  364. sizeof(szVersion)))
  365. {
  366. fRet = IsVersionIE4(szVersion);
  367. }
  368. return fRet;
  369. }
  370. //
  371. // This is an IE5 or later function. If the user's machine is running IE4 they
  372. // have uninstalled back to IE4.
  373. //
  374. BOOL IsUninstallToIE4()
  375. {
  376. BOOL fRet = FALSE;
  377. TCHAR szVersion[MAX_PATH];
  378. if (ReadRegValue(HKEY_LOCAL_MACHINE,
  379. TEXT("Software\\Microsoft\\Internet Explorer"),
  380. TEXT("Version"), (void *)szVersion,
  381. sizeof(szVersion)))
  382. {
  383. fRet = IsVersionIE4(szVersion);
  384. }
  385. return fRet;
  386. }
  387. /* Function to launch miscellaneous applications for browser only mode.
  388. * We run IEXPLORE.EXE -channelband, looking in the registry for the path
  389. * to IEXPLORE, and WELCOME.EXE /f, located in the same directory.
  390. */
  391. #ifdef ENABLE_CHANNELS
  392. const TCHAR c_szChanBarRegPath[] = TEXT("Software\\Microsoft\\Internet Explorer\\Main");
  393. const TCHAR c_szChanBarKey[] = TEXT("Show_ChannelBand");
  394. #endif
  395. void LaunchBrowserOnlyApps()
  396. {
  397. TCHAR szPath[MAX_PATH];
  398. /* Don't launch any of these guys if this is a "redist mode" install,
  399. * i.e. if a game or something installed browser components silently
  400. * without the user really realizing it's there.
  401. */
  402. if (ReadRegValue(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\IE Setup\\Setup",
  403. "InstallMode", (void *)szPath, sizeof(szPath))
  404. && !lstrcmp(szPath, "R")) {
  405. return;
  406. }
  407. LPTSTR pszPathEnd;
  408. LONG cbPath = sizeof(szPath);
  409. /* Get the default value from the App Paths\IEXPLORE.EXE reg key, which
  410. * is the absolute path to the EXE.
  411. */
  412. if (RegQueryValue(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\IEXPLORE.EXE",
  413. szPath, &cbPath) != ERROR_SUCCESS) {
  414. pszPathEnd = szPath;
  415. lstrcpy(szPath, "IEXPLORE.EXE"); /* can't get from reg, hope it's on the path */
  416. }
  417. else {
  418. /* Find the last backslash in the path. This is a manual
  419. * version of strrchr(szPath, '\\').
  420. */
  421. LPTSTR pszLastBackslash = NULL;
  422. for (pszPathEnd = szPath; *pszPathEnd; pszPathEnd = CharNext(pszPathEnd)) {
  423. if (*pszPathEnd == '\\')
  424. pszLastBackslash = pszPathEnd;
  425. }
  426. if (pszLastBackslash == NULL)
  427. pszPathEnd = szPath;
  428. else
  429. pszPathEnd = pszLastBackslash + 1; /* point after last backslash */
  430. }
  431. #ifdef ENABLE_CHANNELS
  432. /* Don't launch the channel band app if the user doesn't want it.
  433. * They want it if the reg value is missing, or if it's "yes".
  434. * On WinNT, we default to "no" for browser-only installs.
  435. */
  436. TCHAR szValue[20];
  437. BOOL fShowChannelBand=FALSE;
  438. if (ReadRegValue(HKEY_CURRENT_USER, c_szChanBarRegPath,
  439. c_szChanBarKey, (void *)szValue, sizeof(szValue)))
  440. {
  441. if (!lstrcmpi(szValue, "yes"))
  442. {
  443. fShowChannelBand=TRUE;
  444. }
  445. }
  446. //
  447. // In general, don't auto launch the channel bar post IE4.
  448. //
  449. // Exception: Show the channelband if there is no Show_ChannelBand key and
  450. // the user upgraded over IE4 and this is W95 or W98. This is required
  451. // because IE4 would launch a channel bar in this scenario w/o writting the
  452. // Show_ChannelBand key. We don't want to turn of the channel bar for these
  453. // users.
  454. //
  455. // Another exception: Loadwc doesn't get uninstalled when IE is
  456. // uninstalled. If the user uninstalls IE5+ and goes back to IE4 we want
  457. // this version of loadwc to revert to IE4 loadwc behavior.
  458. //
  459. else
  460. {
  461. OSVERSIONINFO vi;
  462. vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  463. GetVersionEx(&vi);
  464. if (vi.dwPlatformId != VER_PLATFORM_WIN32_NT &&
  465. (IsIE4Upgrade() || IsUninstallToIE4()))
  466. {
  467. fShowChannelBand=TRUE;
  468. //
  469. // Set the registry key so this code only runs once and upgrades to
  470. // IE5 don't have to worry about this scenario.
  471. //
  472. WriteRegValue(HKEY_CURRENT_USER, c_szChanBarRegPath, c_szChanBarKey,
  473. REG_SZ, TEXT("yes"), sizeof(TEXT("yes")));
  474. }
  475. else
  476. {
  477. WriteRegValue(HKEY_CURRENT_USER, c_szChanBarRegPath, c_szChanBarKey,
  478. REG_SZ, TEXT("no"), sizeof(TEXT("no")));
  479. }
  480. }
  481. if (fShowChannelBand)
  482. {
  483. int cLen = lstrlen(szPath);
  484. lstrcpyn(szPath + cLen, " -channelband", ARRAYSIZE(szPath) - cLen);
  485. WinExec(szPath, SW_SHOWNORMAL);
  486. }
  487. #endif
  488. /* Check the registry to see if the welcome app should be launched. Again,
  489. * only launch if value is missing or positive (non-zero dword, this time).
  490. */
  491. DWORD dwShow = 0;
  492. if (!ReadRegValue(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Tips",
  493. "ShowIE4", (void *)&dwShow, sizeof(dwShow))
  494. || dwShow) {
  495. lstrcpyn(pszPathEnd, "WELCOME.EXE /f", ARRAYSIZE(szPath) - (UINT)(pszPathEnd - szPath));
  496. WinExec(szPath, SW_SHOWNORMAL);
  497. }
  498. }
  499. //----------------------------------------------------------------------------
  500. // WinMain
  501. //----------------------------------------------------------------------------
  502. int WINAPI WinMainT(
  503. HINSTANCE hInstance, // handle to current instance
  504. HINSTANCE hPrevInstance, // handle to previous instance
  505. LPSTR lpCmdLine, // pointer to command line
  506. int nCmdShow // show state of window
  507. )
  508. {
  509. HWND hwndOtherInstance;
  510. // Save the globals
  511. g.hInstance = hInstance;
  512. g.nCmdShow = SW_HIDE;
  513. g.fUninstallOnly = FALSE;
  514. g.fStartSensLce = FALSE;
  515. g.fIntShellMode = IsIntegratedShellMode();
  516. g.hWebcheck = NULL;
  517. MLLoadResources(g.hInstance, TEXT("loadwclc.dll"));
  518. // Parse the command line, for DEBUG options and for uninstall-only switch.
  519. // Now also sets fStartSensLce
  520. if (!bParseCommandLine(lpCmdLine, nCmdShow))
  521. return 0;
  522. // look for webcheck window. This is ultimately the guy we need to
  523. // find to load sens/lce late in the game.
  524. hwndOtherInstance = FindWindow(c_szWebCheckWindow, c_szWebCheckWindow);
  525. if(NULL == hwndOtherInstance)
  526. {
  527. // can't find webcheck, look for loadwc. If we find him but not
  528. // webcheck, we either don't have the MOP or we're still in the 15
  529. // second delay. Send the messages to loadwc and he'll take care
  530. // of it.
  531. hwndOtherInstance = FindWindow(c_szClassName, c_szClassName);
  532. }
  533. if(hwndOtherInstance)
  534. {
  535. // an instance is already running. Tell it about Sens/LCE loading
  536. // requirements and bail out
  537. if(g.fStartSensLce)
  538. {
  539. PostMessage(hwndOtherInstance, WM_START_SENSLCE, 0, 0);
  540. }
  541. return 0;
  542. }
  543. // Set up the absolute paths for all the shell folders we care about,
  544. // in case we're in browser-only mode and the shell doesn't support
  545. // the new ones.
  546. if (!g.fUninstallOnly)
  547. InitShellFolders();
  548. // Run all install/uninstall stubs for browser-only mode.
  549. // If IE4 has been uninstalled, we'll be run with the -u switch; this
  550. // means to run install/uninstall stubs only, no webcheck stuff.
  551. if (!g.fIntShellMode) {
  552. RunInstallUninstallStubs2(NULL);
  553. }
  554. if (g.fUninstallOnly)
  555. return 0;
  556. // Launch the channel bar and welcome apps in browser-only mode.
  557. if (!g.fIntShellMode) {
  558. LaunchBrowserOnlyApps();
  559. }
  560. // Register the window class for the main window.
  561. WNDCLASS wc;
  562. if (!hPrevInstance)
  563. {
  564. wc.style = 0;
  565. wc.lpfnWndProc = WndProc;
  566. wc.cbClsExtra = 0;
  567. wc.cbWndExtra = 0;
  568. wc.hInstance = hInstance;
  569. wc.hIcon = NULL;
  570. wc.hCursor = NULL;
  571. wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
  572. wc.lpszMenuName = NULL;
  573. wc.lpszClassName = c_szClassName;
  574. if (!RegisterClass(&wc))
  575. return 0;
  576. }
  577. // Create the main window.
  578. g.hwnd = CreateWindow(c_szClassName,
  579. c_szClassName,
  580. WS_OVERLAPPEDWINDOW,
  581. CW_USEDEFAULT,
  582. CW_USEDEFAULT,
  583. CW_USEDEFAULT,
  584. CW_USEDEFAULT,
  585. (HWND) NULL,
  586. (HMENU) NULL,
  587. hInstance,
  588. (LPVOID) NULL);
  589. if (!g.hwnd)
  590. return 0;
  591. // Show the window and paint its contents.
  592. ShowWindow(g.hwnd, g.nCmdShow);
  593. // Start the message loop
  594. MSG msg;
  595. while (GetMessage(&msg, (HWND) NULL, 0, 0)) {
  596. TranslateMessage(&msg);
  597. DispatchMessage(&msg);
  598. }
  599. MLFreeResources(g.hInstance);
  600. // Return the exit code to Windows
  601. return (int)msg.wParam;
  602. }
  603. //----------------------------------------------------------------------------
  604. // WndProc
  605. //----------------------------------------------------------------------------
  606. LRESULT APIENTRY WndProc(
  607. HWND hwnd,
  608. UINT uMsg,
  609. WPARAM wParam,
  610. LPARAM lParam
  611. )
  612. {
  613. switch (uMsg) {
  614. case WM_CREATE:
  615. DWORD dwTime;
  616. if(!ReadRegValue(HKEY_CURRENT_USER, c_szWebcheckKey, "DelayLoad", &dwTime, sizeof(DWORD)))
  617. dwTime = 15;
  618. SetTimer(hwnd, 1, 1000 * dwTime, NULL);
  619. break;
  620. case WM_START_SENSLCE:
  621. g.fStartSensLce = TRUE;
  622. break;
  623. case WM_TIMER:
  624. KillTimer(hwnd, 1);
  625. vLoadWebCheck();
  626. return 0;
  627. case WM_ENDSESSION:
  628. if (!wParam) // if not fEndSession, bail
  629. break;
  630. // else fall through to WM_DESTROY
  631. case WM_DESTROY:
  632. vUnloadWebCheck();
  633. PostQuitMessage(0);
  634. return 0;
  635. default:
  636. break;
  637. }
  638. return DefWindowProc(hwnd, uMsg, wParam, lParam);
  639. }
  640. //----------------------------------------------------------------------------
  641. // vLoadWebCheck
  642. //----------------------------------------------------------------------------
  643. void vLoadWebCheck(void)
  644. {
  645. if(g.hWebcheck)
  646. return;
  647. g.hWebcheck = LoadLibrary(TEXT("webcheck.dll"));
  648. if(g.hWebcheck)
  649. {
  650. PFNSTART pfn = (PFNSTART)GetProcAddress(g.hWebcheck, (LPCSTR)7);
  651. if(pfn)
  652. {
  653. pfn(g.fStartSensLce);
  654. }
  655. else
  656. {
  657. // clean up dll
  658. FreeLibrary(g.hWebcheck);
  659. g.hWebcheck = NULL;
  660. }
  661. }
  662. }
  663. //----------------------------------------------------------------------------
  664. // vUnloadWebCheck
  665. //----------------------------------------------------------------------------
  666. void vUnloadWebCheck(void)
  667. {
  668. if (!g.hWebcheck)
  669. return;
  670. PFNSTOP pfn = (PFNSTOP)GetProcAddress(g.hWebcheck, (LPCSTR)8);
  671. if(pfn)
  672. {
  673. pfn();
  674. }
  675. // [darrenmi] don't bother unloading webcheck. We only do this in
  676. // response to a shut down so it's not a big deal. On NT screen saver
  677. // proxy has a thread that wakes up after the call to StopService - if
  678. // we've unloaded the dll before then, we're toast.
  679. // clean up dll
  680. //FreeLibrary(g.hWebcheck);
  681. //g.hWebcheck = NULL;
  682. }
  683. //=--------------------------------------------------------------------------=
  684. // StringFromGuid
  685. // returns an ANSI string from a CLSID or GUID
  686. //
  687. // Parameters:
  688. // REFIID - [in] clsid to make string out of.
  689. // LPSTR - [in] buffer in which to place resultant GUID.
  690. //
  691. // Output:
  692. // int - number of chars written out.
  693. //=--------------------------------------------------------------------------=
  694. #ifdef DEBUG
  695. int StringFromGuid(
  696. const CLSID* piid,
  697. LPTSTR pszBuf
  698. )
  699. {
  700. return wsprintf(pszBuf, TEXT("{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}"), piid->Data1,
  701. piid->Data2, piid->Data3, piid->Data4[0], piid->Data4[1], piid->Data4[2],
  702. piid->Data4[3], piid->Data4[4], piid->Data4[5], piid->Data4[6], piid->Data4[7]);
  703. }
  704. #endif // DEBUG
  705. //----------------------------------------------------------------------------
  706. // bParseCmdLine
  707. //
  708. // Parse the command line
  709. // -u run install/uninstall stubs only, then quit
  710. // DEBUG options:
  711. // -v visible window (easy to shutdown)
  712. // -a add webcheck to shell service object
  713. // -r remove webcheck from shell service object
  714. // -s fix shell folders only
  715. // -? these options
  716. //----------------------------------------------------------------------------
  717. BOOL bParseCommandLine(LPSTR lpCmdLine, int nCmdShow)
  718. {
  719. if (!lpCmdLine)
  720. return TRUE;
  721. CharUpper(lpCmdLine); /* easier to parse */
  722. while (*lpCmdLine) {
  723. if (*lpCmdLine != '-' && *lpCmdLine != '/')
  724. break;
  725. lpCmdLine++;
  726. switch (*(lpCmdLine++)) {
  727. case 'E':
  728. // ignore 'embedding' command line
  729. break;
  730. case 'L':
  731. case 'M':
  732. g.fStartSensLce = TRUE;
  733. break;
  734. case 'U':
  735. g.fUninstallOnly = TRUE;
  736. break;
  737. #ifdef DEBUG
  738. case 'V':
  739. g.nCmdShow = nCmdShow;
  740. break;
  741. case 'A':
  742. {
  743. HKEY hkey;
  744. DWORD dwRet;
  745. if (ERROR_SUCCESS == RegCreateKeyEx(HKEY_LOCAL_MACHINE, c_szShellReg, 0, 0, 0, KEY_READ | KEY_WRITE, NULL, &hkey, &dwRet))
  746. {
  747. // NOTE: Does it matter if we set this as ANSI or Unicode? No, stored in Unicode.
  748. // NOTE: Does sizeof include the terminating null? Yes.
  749. int iRet;
  750. TCHAR szCLSID[GUIDSTR_MAX];
  751. iRet = StringFromGuid(&CLSID_WebCheck, szCLSID);
  752. ASSERT(GUIDSTR_MAX == (iRet + 1));
  753. if (ERROR_SUCCESS == RegSetValueEx(hkey, c_szWebCheck, 0, REG_SZ, (CONST BYTE*)szCLSID, sizeof(szCLSID)))
  754. {
  755. MessageBox(NULL, "Webcheck was added to the shell service object list", "LoadWC", MB_OK);
  756. }
  757. RegCloseKey(hkey);
  758. }
  759. return FALSE;
  760. }
  761. break;
  762. case 'R':
  763. {
  764. HKEY hkey;
  765. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szShellReg, 0, KEY_READ | KEY_WRITE, &hkey))
  766. {
  767. if (ERROR_SUCCESS == RegDeleteValue(hkey, c_szWebCheck))
  768. MessageBox(NULL, "Webcheck was removed from the shell service object list", "LoadWC", MB_OK);
  769. RegCloseKey(hkey);
  770. }
  771. return FALSE;
  772. }
  773. break;
  774. case 'S':
  775. InitShellFolders();
  776. return FALSE;
  777. case '?':
  778. default:
  779. MessageBox(NULL, "Command line options:\n-v\tvisible window\n-a\tadd webcheck as shell service\n-r\tremove webcheck as shell service\n-s\tfixup shell folders only", "LoadWC", MB_OK);
  780. return FALSE;
  781. #endif
  782. }
  783. while (*lpCmdLine == ' ' || *lpCmdLine == '\t') {
  784. lpCmdLine++;
  785. }
  786. }
  787. return TRUE;
  788. }