windows-nt/Source/XPSP1/NT/shell/ext/loadwc/loadwc.cpp

911 lines
29 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
//----------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1996 - 1997.
//
// File: LoadWC.cpp
//
// Contents: exe to load webcheck
//
// Classes:
//
// Functions:
//
// History: 12-12/96 rayen (Raymond Endres) Created
//
//----------------------------------------------------------------------------
#define _SHELL32_
#include <windows.h>
#include <ccstock.h>
#include <debug.h>
#include <docobj.h>
#include <webcheck.h>
#include <shlguid.h>
#include <shlobj.h>
#include <shellp.h>
// need to do this so we can #include <runonce.c>
BOOL g_fCleanBoot = FALSE;
BOOL g_fEndSession = FALSE;
//
// Channels are enabled for the IE4 upgrades.
//
#define ENABLE_CHANNELS
#define MLUI_INIT
#include <mluisupp.h>
//
// NOTE: ActiveSetup relies on our window name and class name
// to shut us down properly in softboot. Do not change it.
//
const TCHAR c_szClassName[] = TEXT("LoadWC");
const TCHAR c_szWebCheckWindow[] = TEXT("MS_WebcheckMonitor");
const TCHAR c_szWebcheckKey[] = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Webcheck");
// message send to dynamically start sens/lce (must not conflict with dialmon)
#define WM_START_SENSLCE (WM_USER+200)
// only used in debug code to grovel with shell service object
#ifdef DEBUG
const TCHAR c_szWebCheck[] = TEXT("WebCheck");
const TCHAR c_szShellReg[] = TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\ShellServiceObjectDelayLoad");
#endif
typedef struct {
HINSTANCE hInstance; // handle to current instance
HWND hwnd; // main window handle
int nCmdShow; // hidden or not?
HINSTANCE hWebcheck; // handle to webcheck dll
BOOL fUninstallOnly; // TRUE -> run uninstall stubs only, then quit
BOOL fIntShellMode; // TRUE -> integrated shell mode, else browser-only
BOOL fStartSensLce;
} GLOBALS;
GLOBALS g;
// webcheck function we dynaload
typedef HRESULT (WINAPI *PFNSTART)(BOOL fForceExternals);
typedef HRESULT (WINAPI *PFNSTOP)(void);
// Code to run install/uninstall stubs, from shell\inc.
#define HINST_THISDLL g.hInstance
#include "resource.h"
//#include <stubsup.h>
#include <inststub.h>
int WINAPI WinMainT(HINSTANCE, HINSTANCE, LPSTR, int);
LRESULT APIENTRY WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
void vLoadWebCheck(void);
void vUnloadWebCheck(void);
BOOL bParseCommandLine(LPSTR lpCmdLine, int nCmdShow);
//----------------------------------------------------------------------------
// ModuleEntry
//----------------------------------------------------------------------------
extern "C" int _stdcall ModuleEntry(void)
{
int i;
STARTUPINFOA si;
LPTSTR pszCmdLine;
pszCmdLine = GetCommandLine();
// g_hProcessHeap = GetProcessHeap();
//
// We don't want the "No disk in drive X:" requesters, so we set
// the critical error mask such that calls will just silently fail
//
SetErrorMode(SEM_FAILCRITICALERRORS);
if ( *pszCmdLine == TEXT('\"') ) {
/*
* Scan, and skip over, subsequent characters until
* another double-quote or a null is encountered.
*/
while ( *++pszCmdLine && (*pszCmdLine
!= TEXT('\"')) );
/*
* If we stopped on a double-quote (usual case), skip
* over it.
*/
if ( *pszCmdLine == TEXT('\"') )
pszCmdLine++;
}
else {
while (*pszCmdLine > TEXT(' '))
pszCmdLine++;
}
/*
* Skip past any white space preceeding the second token.
*/
while (*pszCmdLine && (*pszCmdLine <= TEXT(' '))) {
pszCmdLine++;
}
si.dwFlags = 0;
GetStartupInfoA(&si);
i = WinMainT(GetModuleHandle(NULL), NULL, pszCmdLine,
si.dwFlags & STARTF_USESHOWWINDOW ? si.wShowWindow : SW_SHOWDEFAULT);
// Since we now have a way for an extension to tell us when it is finished,
// we will terminate all processes when the main thread goes away.
ExitProcess(i);
// DebugMsg(DM_TRACE, TEXT("c.me: Cabinet main thread exiting without ExitProcess."));
return i;
}
//----------------------------------------------------------------------------
// Registry helper function
//----------------------------------------------------------------------------
BOOL ReadRegValue(HKEY hkeyRoot, const TCHAR *pszKey, const TCHAR *pszValue,
void *pData, DWORD dwBytes)
{
long lResult;
HKEY hkey;
DWORD dwType;
lResult = RegOpenKey(hkeyRoot, pszKey, &hkey);
if (lResult != ERROR_SUCCESS) {
return FALSE;
}
lResult = RegQueryValueEx(hkey, pszValue, NULL, &dwType, (BYTE *)pData,
&dwBytes);
RegCloseKey(hkey);
if (lResult != ERROR_SUCCESS)
return FALSE;
return TRUE;
}
BOOL WriteRegValue(HKEY hkeyRoot, const TCHAR *pszKey, const TCHAR *pszValue,
DWORD dwType, void *pData, DWORD dwBytes)
{
HKEY hkey;
long lResult = RegOpenKey(hkeyRoot, pszKey, &hkey);
if (ERROR_SUCCESS == lResult)
{
lResult = RegSetValueEx(hkey, pszValue, 0, dwType, (BYTE *)pData, dwBytes);
RegCloseKey(hkey);
}
return ERROR_SUCCESS == lResult;
}
void MakeWindowsRootPath(LPSTR pszBuffer)
{
LPSTR pszEnd = NULL;
if (*pszBuffer == '\\' && *(pszBuffer+1) == '\\') {
pszEnd = pszBuffer + 2;
while (*pszEnd && (*pszEnd != '\\'))
pszEnd++;
if (*pszEnd) {
pszEnd++;
while (*pszEnd && (*pszEnd != '\\'))
pszEnd++;
if (*pszEnd)
pszEnd++;
}
}
else {
LPSTR pszNext = CharNext(pszBuffer);
if (*pszNext == ':' && *(pszNext+1) == '\\')
pszEnd = pszNext + 2;
}
if (pszEnd != NULL)
*pszEnd = '\0';
else {
/* ??? Windows dir is neither UNC nor a root path?
* Just make sure it ends in a backslash.
*/
LPSTR pszLast = pszBuffer;
if (*pszBuffer) {
pszLast = CharPrev(pszBuffer, pszBuffer + lstrlen(pszBuffer));
}
if (*pszLast != '\\')
lstrcat(pszLast, "\\");
}
}
//----------------------------------------------------------------------------
// InitShellFolders
//
// More of making loadwc.exe a browser-only mode catch-all. This code makes
// sure that the Shell Folders key in the per-user registry is fully populated
// with the absolute paths to all the special folders for IE, even if
// shell32.dll doesn't understand all of them.
//
// As the shell would do in SHGetSpecialFolderLocation, we check the
// User Shell Folders key for a path, and if that's present we copy it to the
// Shell Folders key, expanding %USERPROFILE% if necessary. If the value is
// not present under User Shell Folders, we generate the default location
// (usually under the Windows directory) and store that location under
// Shell Folders.
//----------------------------------------------------------------------------
struct FolderDescriptor {
UINT idsDirName; /* Resource ID for directory name */
LPCTSTR pszRegValue; /* Name of reg value to set path in */
BOOL fDefaultInRoot : 1; /* TRUE if default location is root directory */
BOOL fWriteToUSF : 1; /* TRUE if we should write to User Shell Folders to work around Win95 bug */
} aFolders[] = {
{ IDS_CSIDL_PERSONAL_L, TEXT("Personal"), TRUE, TRUE } ,
{ IDS_CSIDL_FAVORITES_L, TEXT("Favorites"), FALSE, TRUE },
{ IDS_CSIDL_APPDATA_L, TEXT("AppData"), FALSE, FALSE },
{ IDS_CSIDL_CACHE_L, TEXT("Cache"), FALSE, FALSE },
{ IDS_CSIDL_COOKIES_L, TEXT("Cookies"), FALSE, FALSE },
{ IDS_CSIDL_HISTORY_L, TEXT("History"), FALSE, FALSE },
};
void InitShellFolders(void)
{
LONG err;
HKEY hkeySF = NULL;
HKEY hkeyUSF = NULL;
TCHAR szDefaultDir[MAX_PATH];
TCHAR szRootDir[MAX_PATH+1]; // possible extra '\'
LPSTR pszPathEnd;
LPSTR pszRootEnd;
/* Get the windows directory and simulate PathAddBackslash (which we
* can't get out of shlwapi, because loadwc.exe also needs to be able
* to load after IE has been uninstalled and shlwapi deleted).
*
* Also build the root directory of the drive that the Windows directory
* is on, so we can put My Documents there if necessary.
*/
*szDefaultDir = TEXT('\0');
GetWindowsDirectory(szDefaultDir, ARRAYSIZE(szDefaultDir));
lstrcpy(szRootDir, szDefaultDir);
MakeWindowsRootPath(szRootDir);
pszRootEnd = szRootDir + lstrlen(szRootDir);
pszPathEnd = CharPrev(szDefaultDir, szDefaultDir + lstrlen(szDefaultDir));
if (*pszPathEnd != '\\') {
pszPathEnd = CharNext(pszPathEnd);
*(pszPathEnd++) = '\\';
}
// pszPathEnd now points to where we can append the relative path
UINT cchPathSpace = ARRAYSIZE(szDefaultDir) - (UINT)(pszPathEnd - szDefaultDir);
UINT cchRootSpace = ARRAYSIZE(szRootDir) - (UINT)(pszRootEnd - szRootDir);
err = RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders",
0, KEY_QUERY_VALUE | KEY_SET_VALUE, &hkeySF);
if (err == ERROR_SUCCESS) {
err = RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders",
0, KEY_QUERY_VALUE, &hkeyUSF);
if (err == ERROR_SUCCESS) {
for (UINT i=0; i<ARRAYSIZE(aFolders); i++) {
TCHAR szRawFolderName[MAX_PATH];
TCHAR szExpandedFolderName[MAX_PATH];
DWORD dwType;
DWORD cbData = sizeof(szRawFolderName);
LPSTR pszPath;
err = RegQueryValueEx(hkeyUSF, aFolders[i].pszRegValue,
NULL, &dwType, (LPBYTE)szRawFolderName,
&cbData);
if (err == ERROR_SUCCESS) {
if ((dwType != REG_EXPAND_SZ && dwType != REG_SZ) ||
!ExpandEnvironmentStrings(szRawFolderName,
szExpandedFolderName,
ARRAYSIZE(szExpandedFolderName)))
{
continue;
}
pszPath = szExpandedFolderName;
}
else {
if (!MLLoadString(aFolders[i].idsDirName,
aFolders[i].fDefaultInRoot ? pszRootEnd : pszPathEnd,
aFolders[i].fDefaultInRoot ? cchRootSpace : cchPathSpace)) {
continue;
}
if (aFolders[i].fDefaultInRoot)
pszPath = szRootDir;
else
pszPath = szDefaultDir;
if (GetFileAttributes(pszPath) == 0xffffffff)
CreateDirectory(pszPath, NULL);
/* The Win95 shell has a bug where for some shell folders,
* if there isn't a path recorded under User Shell Folders,
* the shell folder is assumed not to exist. So, for those
* folders only, we also write the default path to USF.
* We do not do this generically because no value under
* USF is supposed to mean "use the one in the Windows
* directory", whereas an absolute path means "use that
* path"; if there's a path under USF, it will be used
* literally, which is a problem if the folder is set up
* to use the shared folder location but roams to a machine
* with Windows installed in a different directory.
*/
if (aFolders[i].fWriteToUSF) {
RegSetValueEx(hkeyUSF, aFolders[i].pszRegValue, 0, REG_SZ,
(LPBYTE)pszPath, lstrlen(pszPath)+1);
}
}
RegSetValueEx(hkeySF, aFolders[i].pszRegValue, 0, REG_SZ,
(LPBYTE)pszPath, lstrlen(pszPath)+1);
}
RegCloseKey(hkeyUSF);
}
RegCloseKey(hkeySF);
}
}
/* Function to determine whether we're in integrated-shell mode or browser-only
* mode. The method for doing this (looking for DllGetVersion exported from
* shell32.dll) is taken from shdocvw. We don't actually call that entrypoint,
* we just look for it.
*/
BOOL IsIntegratedShellMode()
{
FARPROC pfnDllGetVersion = NULL;
HMODULE hmodShell = LoadLibrary("shell32.dll");
if (hmodShell != NULL) {
pfnDllGetVersion = GetProcAddress(hmodShell, "DllGetVersion");
FreeLibrary(hmodShell);
}
return (pfnDllGetVersion != NULL);
}
//
// Convert the string to a DWORD.
//
DWORD StringToDW(LPCTSTR psz)
{
DWORD dwRet = 0;
while (*psz >= TEXT('0') && *psz <= TEXT('9'))
{
dwRet = dwRet * 10 + *psz - TEXT('0');
*psz++;
}
return dwRet;
}
//
// Is the version string from IE4
//
BOOL IsVersionIE4(LPCTSTR pszVersion)
{
BOOL fRet = FALSE;
//
// IE3.0 is 4.70 and Ie4.0x is >= 4.71.1218.xxxx
//
if (pszVersion[0] == TEXT('4') && pszVersion[1] == TEXT('.'))
{
DWORD dw = StringToDW(pszVersion+2);
if (dw > 71 || (dw == 71 && pszVersion[4] == TEXT('.') &&
StringToDW(pszVersion+5) >= 1218))
{
fRet = TRUE;
}
}
return fRet;
}
//
// Determine if this is an IE4 upgrade.
//
BOOL IsIE4Upgrade()
{
BOOL fRet = FALSE;
TCHAR szVersion[MAX_PATH];
if (ReadRegValue(HKEY_LOCAL_MACHINE,
TEXT("Software\\Microsoft\\IE Setup\\Setup"),
TEXT("PreviousIESysFile"), (void *)szVersion,
sizeof(szVersion)))
{
fRet = IsVersionIE4(szVersion);
}
return fRet;
}
//
// This is an IE5 or later function. If the user's machine is running IE4 they
// have uninstalled back to IE4.
//
BOOL IsUninstallToIE4()
{
BOOL fRet = FALSE;
TCHAR szVersion[MAX_PATH];
if (ReadRegValue(HKEY_LOCAL_MACHINE,
TEXT("Software\\Microsoft\\Internet Explorer"),
TEXT("Version"), (void *)szVersion,
sizeof(szVersion)))
{
fRet = IsVersionIE4(szVersion);
}
return fRet;
}
/* Function to launch miscellaneous applications for browser only mode.
* We run IEXPLORE.EXE -channelband, looking in the registry for the path
* to IEXPLORE, and WELCOME.EXE /f, located in the same directory.
*/
#ifdef ENABLE_CHANNELS
const TCHAR c_szChanBarRegPath[] = TEXT("Software\\Microsoft\\Internet Explorer\\Main");
const TCHAR c_szChanBarKey[] = TEXT("Show_ChannelBand");
#endif
void LaunchBrowserOnlyApps()
{
TCHAR szPath[MAX_PATH];
/* Don't launch any of these guys if this is a "redist mode" install,
* i.e. if a game or something installed browser components silently
* without the user really realizing it's there.
*/
if (ReadRegValue(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\IE Setup\\Setup",
"InstallMode", (void *)szPath, sizeof(szPath))
&& !lstrcmp(szPath, "R")) {
return;
}
LPTSTR pszPathEnd;
LONG cbPath = sizeof(szPath);
/* Get the default value from the App Paths\IEXPLORE.EXE reg key, which
* is the absolute path to the EXE.
*/
if (RegQueryValue(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\IEXPLORE.EXE",
szPath, &cbPath) != ERROR_SUCCESS) {
pszPathEnd = szPath;
lstrcpy(szPath, "IEXPLORE.EXE"); /* can't get from reg, hope it's on the path */
}
else {
/* Find the last backslash in the path. This is a manual
* version of strrchr(szPath, '\\').
*/
LPTSTR pszLastBackslash = NULL;
for (pszPathEnd = szPath; *pszPathEnd; pszPathEnd = CharNext(pszPathEnd)) {
if (*pszPathEnd == '\\')
pszLastBackslash = pszPathEnd;
}
if (pszLastBackslash == NULL)
pszPathEnd = szPath;
else
pszPathEnd = pszLastBackslash + 1; /* point after last backslash */
}
#ifdef ENABLE_CHANNELS
/* Don't launch the channel band app if the user doesn't want it.
* They want it if the reg value is missing, or if it's "yes".
* On WinNT, we default to "no" for browser-only installs.
*/
TCHAR szValue[20];
BOOL fShowChannelBand=FALSE;
if (ReadRegValue(HKEY_CURRENT_USER, c_szChanBarRegPath,
c_szChanBarKey, (void *)szValue, sizeof(szValue)))
{
if (!lstrcmpi(szValue, "yes"))
{
fShowChannelBand=TRUE;
}
}
//
// In general, don't auto launch the channel bar post IE4.
//
// Exception: Show the channelband if there is no Show_ChannelBand key and
// the user upgraded over IE4 and this is W95 or W98. This is required
// because IE4 would launch a channel bar in this scenario w/o writting the
// Show_ChannelBand key. We don't want to turn of the channel bar for these
// users.
//
// Another exception: Loadwc doesn't get uninstalled when IE is
// uninstalled. If the user uninstalls IE5+ and goes back to IE4 we want
// this version of loadwc to revert to IE4 loadwc behavior.
//
else
{
OSVERSIONINFO vi;
vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&vi);
if (vi.dwPlatformId != VER_PLATFORM_WIN32_NT &&
(IsIE4Upgrade() || IsUninstallToIE4()))
{
fShowChannelBand=TRUE;
//
// Set the registry key so this code only runs once and upgrades to
// IE5 don't have to worry about this scenario.
//
WriteRegValue(HKEY_CURRENT_USER, c_szChanBarRegPath, c_szChanBarKey,
REG_SZ, TEXT("yes"), sizeof(TEXT("yes")));
}
else
{
WriteRegValue(HKEY_CURRENT_USER, c_szChanBarRegPath, c_szChanBarKey,
REG_SZ, TEXT("no"), sizeof(TEXT("no")));
}
}
if (fShowChannelBand)
{
int cLen = lstrlen(szPath);
lstrcpyn(szPath + cLen, " -channelband", ARRAYSIZE(szPath) - cLen);
WinExec(szPath, SW_SHOWNORMAL);
}
#endif
/* Check the registry to see if the welcome app should be launched. Again,
* only launch if value is missing or positive (non-zero dword, this time).
*/
DWORD dwShow = 0;
if (!ReadRegValue(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Tips",
"ShowIE4", (void *)&dwShow, sizeof(dwShow))
|| dwShow) {
lstrcpyn(pszPathEnd, "WELCOME.EXE /f", ARRAYSIZE(szPath) - (UINT)(pszPathEnd - szPath));
WinExec(szPath, SW_SHOWNORMAL);
}
}
//----------------------------------------------------------------------------
// WinMain
//----------------------------------------------------------------------------
int WINAPI WinMainT(
HINSTANCE hInstance, // handle to current instance
HINSTANCE hPrevInstance, // handle to previous instance
LPSTR lpCmdLine, // pointer to command line
int nCmdShow // show state of window
)
{
HWND hwndOtherInstance;
// Save the globals
g.hInstance = hInstance;
g.nCmdShow = SW_HIDE;
g.fUninstallOnly = FALSE;
g.fStartSensLce = FALSE;
g.fIntShellMode = IsIntegratedShellMode();
g.hWebcheck = NULL;
MLLoadResources(g.hInstance, TEXT("loadwclc.dll"));
// Parse the command line, for DEBUG options and for uninstall-only switch.
// Now also sets fStartSensLce
if (!bParseCommandLine(lpCmdLine, nCmdShow))
return 0;
// look for webcheck window. This is ultimately the guy we need to
// find to load sens/lce late in the game.
hwndOtherInstance = FindWindow(c_szWebCheckWindow, c_szWebCheckWindow);
if(NULL == hwndOtherInstance)
{
// can't find webcheck, look for loadwc. If we find him but not
// webcheck, we either don't have the MOP or we're still in the 15
// second delay. Send the messages to loadwc and he'll take care
// of it.
hwndOtherInstance = FindWindow(c_szClassName, c_szClassName);
}
if(hwndOtherInstance)
{
// an instance is already running. Tell it about Sens/LCE loading
// requirements and bail out
if(g.fStartSensLce)
{
PostMessage(hwndOtherInstance, WM_START_SENSLCE, 0, 0);
}
return 0;
}
// Set up the absolute paths for all the shell folders we care about,
// in case we're in browser-only mode and the shell doesn't support
// the new ones.
if (!g.fUninstallOnly)
InitShellFolders();
// Run all install/uninstall stubs for browser-only mode.
// If IE4 has been uninstalled, we'll be run with the -u switch; this
// means to run install/uninstall stubs only, no webcheck stuff.
if (!g.fIntShellMode) {
RunInstallUninstallStubs2(NULL);
}
if (g.fUninstallOnly)
return 0;
// Launch the channel bar and welcome apps in browser-only mode.
if (!g.fIntShellMode) {
LaunchBrowserOnlyApps();
}
// Register the window class for the main window.
WNDCLASS wc;
if (!hPrevInstance)
{
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = NULL;
wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = c_szClassName;
if (!RegisterClass(&wc))
return 0;
}
// Create the main window.
g.hwnd = CreateWindow(c_szClassName,
c_szClassName,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
(HWND) NULL,
(HMENU) NULL,
hInstance,
(LPVOID) NULL);
if (!g.hwnd)
return 0;
// Show the window and paint its contents.
ShowWindow(g.hwnd, g.nCmdShow);
// Start the message loop
MSG msg;
while (GetMessage(&msg, (HWND) NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
MLFreeResources(g.hInstance);
// Return the exit code to Windows
return (int)msg.wParam;
}
//----------------------------------------------------------------------------
// WndProc
//----------------------------------------------------------------------------
LRESULT APIENTRY WndProc(
HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
)
{
switch (uMsg) {
case WM_CREATE:
DWORD dwTime;
if(!ReadRegValue(HKEY_CURRENT_USER, c_szWebcheckKey, "DelayLoad", &dwTime, sizeof(DWORD)))
dwTime = 15;
SetTimer(hwnd, 1, 1000 * dwTime, NULL);
break;
case WM_START_SENSLCE:
g.fStartSensLce = TRUE;
break;
case WM_TIMER:
KillTimer(hwnd, 1);
vLoadWebCheck();
return 0;
case WM_ENDSESSION:
if (!wParam) // if not fEndSession, bail
break;
// else fall through to WM_DESTROY
case WM_DESTROY:
vUnloadWebCheck();
PostQuitMessage(0);
return 0;
default:
break;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
//----------------------------------------------------------------------------
// vLoadWebCheck
//----------------------------------------------------------------------------
void vLoadWebCheck(void)
{
if(g.hWebcheck)
return;
g.hWebcheck = LoadLibrary(TEXT("webcheck.dll"));
if(g.hWebcheck)
{
PFNSTART pfn = (PFNSTART)GetProcAddress(g.hWebcheck, (LPCSTR)7);
if(pfn)
{
pfn(g.fStartSensLce);
}
else
{
// clean up dll
FreeLibrary(g.hWebcheck);
g.hWebcheck = NULL;
}
}
}
//----------------------------------------------------------------------------
// vUnloadWebCheck
//----------------------------------------------------------------------------
void vUnloadWebCheck(void)
{
if (!g.hWebcheck)
return;
PFNSTOP pfn = (PFNSTOP)GetProcAddress(g.hWebcheck, (LPCSTR)8);
if(pfn)
{
pfn();
}
// [darrenmi] don't bother unloading webcheck. We only do this in
// response to a shut down so it's not a big deal. On NT screen saver
// proxy has a thread that wakes up after the call to StopService - if
// we've unloaded the dll before then, we're toast.
// clean up dll
//FreeLibrary(g.hWebcheck);
//g.hWebcheck = NULL;
}
//=--------------------------------------------------------------------------=
// StringFromGuid
// returns an ANSI string from a CLSID or GUID
//
// Parameters:
// REFIID - [in] clsid to make string out of.
// LPSTR - [in] buffer in which to place resultant GUID.
//
// Output:
// int - number of chars written out.
//=--------------------------------------------------------------------------=
#ifdef DEBUG
int StringFromGuid(
const CLSID* piid,
LPTSTR pszBuf
)
{
return wsprintf(pszBuf, TEXT("{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}"), piid->Data1,
piid->Data2, piid->Data3, piid->Data4[0], piid->Data4[1], piid->Data4[2],
piid->Data4[3], piid->Data4[4], piid->Data4[5], piid->Data4[6], piid->Data4[7]);
}
#endif // DEBUG
//----------------------------------------------------------------------------
// bParseCmdLine
//
// Parse the command line
// -u run install/uninstall stubs only, then quit
// DEBUG options:
// -v visible window (easy to shutdown)
// -a add webcheck to shell service object
// -r remove webcheck from shell service object
// -s fix shell folders only
// -? these options
//----------------------------------------------------------------------------
BOOL bParseCommandLine(LPSTR lpCmdLine, int nCmdShow)
{
if (!lpCmdLine)
return TRUE;
CharUpper(lpCmdLine); /* easier to parse */
while (*lpCmdLine) {
if (*lpCmdLine != '-' && *lpCmdLine != '/')
break;
lpCmdLine++;
switch (*(lpCmdLine++)) {
case 'E':
// ignore 'embedding' command line
break;
case 'L':
case 'M':
g.fStartSensLce = TRUE;
break;
case 'U':
g.fUninstallOnly = TRUE;
break;
#ifdef DEBUG
case 'V':
g.nCmdShow = nCmdShow;
break;
case 'A':
{
HKEY hkey;
DWORD dwRet;
if (ERROR_SUCCESS == RegCreateKeyEx(HKEY_LOCAL_MACHINE, c_szShellReg, 0, 0, 0, KEY_READ | KEY_WRITE, NULL, &hkey, &dwRet))
{
// NOTE: Does it matter if we set this as ANSI or Unicode? No, stored in Unicode.
// NOTE: Does sizeof include the terminating null? Yes.
int iRet;
TCHAR szCLSID[GUIDSTR_MAX];
iRet = StringFromGuid(&CLSID_WebCheck, szCLSID);
ASSERT(GUIDSTR_MAX == (iRet + 1));
if (ERROR_SUCCESS == RegSetValueEx(hkey, c_szWebCheck, 0, REG_SZ, (CONST BYTE*)szCLSID, sizeof(szCLSID)))
{
MessageBox(NULL, "Webcheck was added to the shell service object list", "LoadWC", MB_OK);
}
RegCloseKey(hkey);
}
return FALSE;
}
break;
case 'R':
{
HKEY hkey;
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szShellReg, 0, KEY_READ | KEY_WRITE, &hkey))
{
if (ERROR_SUCCESS == RegDeleteValue(hkey, c_szWebCheck))
MessageBox(NULL, "Webcheck was removed from the shell service object list", "LoadWC", MB_OK);
RegCloseKey(hkey);
}
return FALSE;
}
break;
case 'S':
InitShellFolders();
return FALSE;
case '?':
default:
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);
return FALSE;
#endif
}
while (*lpCmdLine == ' ' || *lpCmdLine == '\t') {
lpCmdLine++;
}
}
return TRUE;
}