windows-nt/Source/XPSP1/NT/windows/appcompat/shims/specific/aolfindbundledinstaller_shim.cpp
2020-09-26 16:20:57 +08:00

436 lines
11 KiB
C++

/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
AOLFindBundledInstaller_Shim.cpp
Abstract:
This shim is to provide a way to verify existance of
America Online bundled in OEM machines when user runs older
version of AOL/CS program (waol.exe or wcs2000.exe) or setup.
If it exists, it will provide Apphelp dialog to tell user that
there is newer America Online installer available.
If user chose "Run this program", shim will launch the bundled installer.
If user chose "Cancel", then shim will continue with current process.
Apphelp dialog only get displayed if LocateInstaller function says to do so.
History:
04/30/2001 markder Created
05/16/2001 andyseti Implemented LocateInstaller and ApphelpShowDialog.
--*/
#include "precomp.h"
#include "LegalStr.h"
#include <Softpub.h>
#include <WinCrypt.h>
#include <WinTrust.h>
#include "AOLFindBundledInstaller_AOLCode.h"
IMPLEMENT_SHIM_BEGIN(AOLFindBundledInstaller)
#include "ShimHookMacro.h"
#include "shimdb.h"
APIHOOK_ENUM_BEGIN
APIHOOK_ENUM_ENTRY(GetCommandLineA)
APIHOOK_ENUM_ENTRY(GetStartupInfoA)
APIHOOK_ENUM_ENTRY(GetModuleFileNameA)
APIHOOK_ENUM_ENTRY(CreateWindowExA)
APIHOOK_ENUM_END
#define MAX_PARAM 4
BOOL g_bDoneIt = FALSE;
CString g_csHTMLHelpID_BundledFound;
CString g_csHTMLHelpID_Incompatible;
DWORD g_dwHTMLHelpID_BundledFound = 0;
DWORD g_dwHTMLHelpID_Incompatible = 0;
CString g_csAppName;
CString g_csGUID;
//
// from apphelp\apphelp.h
//
#define APPTYPE_TYPE_MASK 0x000000FF
#define APPTYPE_INC_NOBLOCK 0x00000001
#define APPTYPE_INC_HARDBLOCK 0x00000002
#define APPTYPE_MINORPROBLEM 0x00000003
#define APPTYPE_REINSTALL 0x00000004
#define APPTYPE_VERSIONSUB 0x00000005
#define APPTYPE_SHIM 0x00000006
#define APPTYPE_NONE 0x00000000
enum ShimAppHelpSeverityType
{
APPHELP_MINORPROBLEM = APPTYPE_MINORPROBLEM,
APPHELP_HARDBLOCK = APPTYPE_INC_HARDBLOCK,
APPHELP_NOBLOCK = APPTYPE_INC_NOBLOCK,
APPHELP_VERSIONSUB = APPTYPE_VERSIONSUB,
APPHELP_SHIM = APPTYPE_SHIM,
APPHELP_REINSTALL = APPTYPE_REINSTALL,
APPHELP_NONE = APPTYPE_NONE
};
#define APPHELP_DIALOG_FAILED ((DWORD)-1)
// from sdbapi\shimdb.w
/*
typedef struct _APPHELP_INFO {
//
// html help id mode
//
DWORD dwHtmlHelpID; // html help id
DWORD dwSeverity; // must have
LPCTSTR lpszAppName;
GUID guidID; // entry guid
//
// Conventional mode
//
TAGID tiExe; // the TAGID of the exe entry within the DB
GUID guidDB; // the guid of the DB that has the EXE entry
BOOL bOfflineContent;
BOOL bUseHTMLHelp;
LPCTSTR lpszChmFile;
LPCTSTR lpszDetailsFile;
} APPHELP_INFO, *PAPPHELP_INFO;
*/
typedef BOOL (*_pfn_ApphelpShowDialog)(
IN PAPPHELP_INFO pAHInfo, // the info necessary to find the apphelp data
IN PHANDLE phProcess // [optional] returns the process handle of
// the process displaying the apphelp.
// When the process completes, the return value
// (from GetExitCodeProcess()) will be zero
// if the app should not run, or non-zero
// if it should run.
);
/*++
Parse the command line.
The format of the command line is:
MODE:AOL|CS;APPNAME:xxxxxx;HTMLHELPID:99999;GUID:xxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxx
--*/
BOOL
ParseCommandLine(
LPCSTR lpCommandLine
)
{
int iTotalParam = 0;
CSTRING_TRY
{
CStringToken csTok(lpCommandLine, L" ;");
CString token;
while (csTok.GetToken(token))
{
CStringToken csSingleTok(token, L":");
CString csParam;
CString csValue;
csSingleTok.GetToken(csParam);
csSingleTok.GetToken(csValue);
if (csParam.CompareNoCase(L"APPNAME") == 0)
{
g_csAppName = csValue;
++iTotalParam;
}
if (csParam.CompareNoCase(L"HTMLHELPID_BUNDLED") == 0)
{
g_csHTMLHelpID_BundledFound = csValue;
g_dwHTMLHelpID_BundledFound = _wtol(csValue.Get());
++iTotalParam;
}
if (csParam.CompareNoCase(L"HTMLHELPID_INCOMPAT") == 0)
{
g_csHTMLHelpID_Incompatible = csValue;
g_dwHTMLHelpID_Incompatible = _wtol(csValue.Get());
++iTotalParam;
}
if (csParam.CompareNoCase(L"GUID") == 0)
{
g_csGUID = csValue;
++iTotalParam;
}
}
}
CSTRING_CATCH
{
DPF("FindAOL", eDbgLevelInfo, "Error in CString.Exiting\n");
return FALSE;
}
if (iTotalParam < MAX_PARAM)
{
DPF("FindAOL", eDbgLevelInfo, "Total Parameter = %d is less than = %d\n",iTotalParam, MAX_PARAM);
return FALSE;
}
//
// Dump results of command line parse
//
DPF("FindAOL", eDbgLevelInfo, "===================================\n");
DPF("FindAOL", eDbgLevelInfo, " FindAOL \n");
DPF("FindAOL", eDbgLevelInfo, "===================================\n");
DPF("FindAOL", eDbgLevelInfo, "COMMAND_LINE(%s)", lpCommandLine);
DPF("FindAOL", eDbgLevelInfo, "-----------------------------------\n");
DPF("FindAOL", eDbgLevelInfo, "APPNAME = %S\n", g_csAppName);
DPF("FindAOL", eDbgLevelInfo, "HTMLHELPID_BUNDLED = %S\n", g_csHTMLHelpID_BundledFound);
DPF("FindAOL", eDbgLevelInfo, "HTMLHELPID_INCOMPAT = %S\n", g_csHTMLHelpID_Incompatible);
DPF("FindAOL", eDbgLevelInfo, "GUID = %S\n", g_csGUID);
DPF("FindAOL", eDbgLevelInfo, "-----------------------------------\n");
return TRUE;
}
BOOL InvokeApphelpShowDialog(DWORD dwHTMLHelpID)
{
_pfn_ApphelpShowDialog pfnApphelpShowDialog = NULL;
APPHELP_INFO AHInfo = { 0 };
HMODULE hAppHelpDLL = NULL;
hAppHelpDLL = LoadLibrary(L"APPHELP.DLL");
DPF("FindAOL", eDbgLevelWarning, "Apphelp:%d\n",hAppHelpDLL );
if (hAppHelpDLL)
{
pfnApphelpShowDialog = (_pfn_ApphelpShowDialog) GetProcAddress(hAppHelpDLL, "ApphelpShowDialog");
if (pfnApphelpShowDialog == NULL)
{
DPF("FindAOL", eDbgLevelInfo, "Unable to get APPHELP!ApphelpShowDialog procedure address.\n");
return FALSE;
}
AHInfo.dwHtmlHelpID = dwHTMLHelpID;
AHInfo.dwSeverity = APPHELP_NOBLOCK;
AHInfo.lpszAppName = g_csAppName.Get();
AHInfo.bPreserveChoice = TRUE;
HRESULT hr;
UNICODE_STRING ustrGuid;
NTSTATUS ntstatus;
RtlInitUnicodeString(&ustrGuid, g_csGUID.Get());
ntstatus = RtlGUIDFromString(&ustrGuid, &AHInfo.guidID);
if (NT_SUCCESS(ntstatus)==FALSE)
{
DPF("FindAOL", eDbgLevelInfo, "RtlGUIDFromString failed!\n");
return FALSE;
}
if (pfnApphelpShowDialog(&AHInfo,NULL))
{
DPF("FindAOL", eDbgLevelInfo, "!\n");
}
else
{
DPF("FindAOL", eDbgLevelInfo, "RtlGUIDFromString FAILED!\n");
return FALSE;
}
}
else
{
DPF("FindAOL", eDbgLevelInfo, "LoadLibrary FAILED!\n");
return FALSE;
}
return TRUE;
}
void DoIt()
{
char szModuleName[MAX_PATH];
DWORD dwLen = 0;
CHAR lpszInstaller[MAX_PATH];
BOOL bBundledInstallerFound = FALSE;
BOOL bDisplayAppHelpDialog = FALSE;
BOOL bKillCurrentProcess = FALSE;
BOOL bLaunchBundledInstaller = FALSE;
BOOL bReturnValue = FALSE;
UINT uiWinExecReturned = 0;
if (!g_bDoneIt) {
if (!ParseCommandLine(COMMAND_LINE)) {
goto eh;
}
bBundledInstallerFound = LocateInstaller(lpszInstaller, MAX_PATH, &bDisplayAppHelpDialog);
if (bBundledInstallerFound) {
DPF("FindAOL", eDbgLevelWarning, "Bundled installer found in %s.\n",lpszInstaller);
}
if (bBundledInstallerFound == FALSE && bDisplayAppHelpDialog == FALSE) {
DPF("FindAOL", eDbgLevelWarning, "Bundled installer not found. Let client run normally.\n");
goto eh;
}
if (bBundledInstallerFound == FALSE && bDisplayAppHelpDialog == TRUE) {
bReturnValue = InvokeApphelpShowDialog(g_dwHTMLHelpID_Incompatible);
// if user chose Cancel button, then just kill current process.
if (FALSE == bReturnValue) {
bKillCurrentProcess = TRUE;
}
}
if (bBundledInstallerFound == TRUE && bDisplayAppHelpDialog == TRUE) {
bReturnValue = InvokeApphelpShowDialog(g_dwHTMLHelpID_BundledFound);
// if user chose Continue button, then launch bundled installer.
if (TRUE == bReturnValue) {
bKillCurrentProcess = TRUE;
bLaunchBundledInstaller = TRUE;
}
}
if (bBundledInstallerFound == TRUE && bDisplayAppHelpDialog == FALSE) {
// Launch bundled installer.
bKillCurrentProcess = TRUE;
bLaunchBundledInstaller = TRUE;
}
if (bLaunchBundledInstaller) {
// launch bundled installer instead
uiWinExecReturned = WinExec(lpszInstaller, SW_SHOW);
if (uiWinExecReturned <= 31) {
DPF("FindAOL", eDbgLevelError, "Can not launch program. Error: %d\n",GetLastError());
goto eh;
}
}
if (bKillCurrentProcess) {
ExitProcess(0);
}
}
eh:
g_bDoneIt = TRUE;
}
LPSTR
APIHOOK(GetCommandLineA)()
{
DoIt();
return ORIGINAL_API(GetCommandLineA)();
}
VOID
APIHOOK(GetStartupInfoA)(
LPSTARTUPINFOA lpStartupInfo)
{
DoIt();
ORIGINAL_API(GetStartupInfoA)(lpStartupInfo);
}
DWORD
APIHOOK(GetModuleFileNameA)(
HMODULE hModule, // handle to module
LPSTR lpFilename, // file name of module
DWORD nSize // size of buffer
)
{
DoIt();
return ORIGINAL_API(GetModuleFileNameA)(hModule, lpFilename, nSize);
}
HWND
APIHOOK(CreateWindowExA)(
DWORD dwExStyle,
LPCSTR lpClassName,
LPCSTR lpWindowName,
DWORD dwStyle,
int x,
int y,
int nWidth,
int nHeight,
HWND hWndParent,
HMENU hMenu,
HINSTANCE hInstance,
LPVOID lpParam
)
{
DoIt();
return ORIGINAL_API(CreateWindowExA)(
dwExStyle,
lpClassName,
lpWindowName,
dwStyle,
x,
y,
nWidth,
nHeight,
hWndParent,
hMenu,
hInstance,
lpParam );
}
/*++
Register hooked functions
--*/
HOOK_BEGIN
APIHOOK_ENTRY(KERNEL32.DLL, GetCommandLineA)
APIHOOK_ENTRY(KERNEL32.DLL, GetStartupInfoA)
APIHOOK_ENTRY(KERNEL32.DLL, GetModuleFileNameA)
APIHOOK_ENTRY(USER32.DLL, CreateWindowExA)
HOOK_END
IMPLEMENT_SHIM_END