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.
1659 lines
57 KiB
1659 lines
57 KiB
#include <windows.h>
|
|
#include <objbase.h>
|
|
#include <shlobj.h>
|
|
#include <fusenetincludes.h>
|
|
#include <activator.h>
|
|
#include <versionmanagement.h>
|
|
#include <shellapi.h> // for shellexecuteex
|
|
|
|
#include <shellres.h>
|
|
|
|
#define INITGUID
|
|
#include <guiddef.h>
|
|
|
|
// used in OnProgress(), copied from guids.c
|
|
DEFINE_GUID( IID_IAssemblyManifestImport,
|
|
0x696fb37f,0xda64,0x4175,0x94,0xe7,0xfd,0xc8,0x23,0x45,0x39,0xc4);
|
|
|
|
// Update services
|
|
#include "server.h"
|
|
DEFINE_GUID(IID_IAssemblyUpdate,
|
|
0x301b3415,0xf52d,0x4d40,0xbd,0xf7,0x31,0xd8,0x27,0x12,0xc2,0xdc);
|
|
|
|
DEFINE_GUID(CLSID_CAssemblyUpdate,
|
|
0x37b088b8,0x70ef,0x4ecf,0xb1,0x1e,0x1f,0x3f,0x4d,0x10,0x5f,0xdd);
|
|
|
|
extern HRESULT GetLastWin32Error();
|
|
|
|
#define WZ_TYPE_DOTNET L".NetAssembly"
|
|
#define WZ_TYPE_WIN32 L"win32Executable"
|
|
#define WZ_TYPE_AVALON L"avalon"
|
|
#define WZ_TYPE_CONSOLE L"win32Console"
|
|
#define TYPE_DOTNET 1
|
|
#define TYPE_WIN32 2
|
|
#define TYPE_AVALON 3
|
|
#define TYPE_CONSOLE 4
|
|
|
|
#if 1
|
|
#include "ndphostthunk.cpp"
|
|
#else // old code
|
|
// CLR Hosting
|
|
#import "..\..\clrhost\asmexec.tlb" raw_interfaces_only
|
|
using namespace asmexec;
|
|
#endif
|
|
|
|
|
|
// debug msg stuff
|
|
void Msg(LPCWSTR pwz);
|
|
|
|
void ShowError(LPCWSTR pwz);
|
|
|
|
void ShowError(HRESULT hr, LPCWSTR pwz=NULL);
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
typedef struct
|
|
{
|
|
LPCWSTR pwzTitle;
|
|
LPCWSTR pwzText;
|
|
} SHOWDIALOG_MSG;
|
|
|
|
#define DIALOG_OK 1
|
|
#define DIALOG_CANCEL 2
|
|
#define DIALOG_CLOSE 3
|
|
//IDC_TEXT
|
|
INT_PTR CALLBACK DialogBoxProc(
|
|
HWND hwndDlg, // handle to dialog box
|
|
UINT uMsg, // message
|
|
WPARAM wParam, // first message parameter
|
|
LPARAM lParam // second message parameter
|
|
)
|
|
{
|
|
//
|
|
// Dialog proc for dialog window
|
|
//
|
|
switch( uMsg )
|
|
{
|
|
case WM_INITDIALOG:
|
|
{
|
|
SHOWDIALOG_MSG* pMsg = (SHOWDIALOG_MSG*) lParam;
|
|
if (pMsg->pwzTitle)
|
|
SetWindowText( hwndDlg, (LPWSTR) pMsg->pwzTitle);
|
|
if (pMsg->pwzText)
|
|
{
|
|
HWND hwndText = GetDlgItem( hwndDlg, IDC_TEXT );
|
|
if (hwndText)
|
|
SetWindowText( hwndText, (LPWSTR) pMsg->pwzText);
|
|
}
|
|
}
|
|
return TRUE;
|
|
|
|
case WM_COMMAND:
|
|
switch( LOWORD( wParam ) )
|
|
{
|
|
#ifdef IDC_OK
|
|
case IDC_OK:
|
|
EndDialog( hwndDlg, DIALOG_OK );
|
|
return TRUE;
|
|
#endif
|
|
|
|
#ifdef IDC_CANCEL
|
|
case IDC_CANCEL:
|
|
EndDialog( hwndDlg, DIALOG_CANCEL );
|
|
return TRUE;
|
|
#endif
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
|
|
case WM_NOTIFY:
|
|
if ((IDC_TEXT == LOWORD(wParam) ) &&
|
|
((NM_CLICK == ((LPNMHDR)lParam)->code) ||
|
|
(NM_RETURN == ((LPNMHDR)lParam)->code)))
|
|
{
|
|
PNMLINK pNMLink = (PNMLINK) lParam;
|
|
|
|
// check szURL empty
|
|
if (pNMLink->item.szUrl[0] == L'\0')
|
|
return FALSE;
|
|
|
|
SHELLEXECUTEINFO sei = { 0 };
|
|
sei.cbSize = sizeof(SHELLEXECUTEINFO);
|
|
sei.fMask = SEE_MASK_DOENVSUBST | SEE_MASK_NO_CONSOLE; //SEE_MASK_FLAG_NO_UI |
|
|
sei.nShow = SW_SHOWNORMAL;
|
|
// ISSUE-06/14/02-felixybc shellexecute should work as such
|
|
// for some unknown reason it is failing with module not found
|
|
//sei.lpFile = pNMLink->item.szUrl;
|
|
sei.lpParameters=pNMLink->item.szUrl;
|
|
sei.lpFile=L"iexplore.exe";
|
|
//
|
|
sei.lpVerb = L"open";
|
|
|
|
// ISSUE: check return with IF_WIN32_FALSE_EXIT(), check hInstApp for detail error
|
|
ShellExecuteEx(&sei);
|
|
return TRUE;
|
|
}
|
|
else
|
|
// WM_NOTIFY not handled.
|
|
return FALSE;
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
extern HINSTANCE g_DllInstance;
|
|
|
|
HRESULT ShowDialog(HWND hWndParent, WORD wDlgId, LPCWSTR pwzText, LPCWSTR pwzTitle, DWORD& dwReturnValue)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
MAKE_ERROR_MACROS_STATIC(hr);
|
|
INT_PTR iptrReturn = 0;
|
|
SHOWDIALOG_MSG msg = {0};
|
|
|
|
/* INITCOMMONCONTROLSEX iccex;
|
|
iccex.dwSize = sizeof(INITCOMMONCONTROLSEX);
|
|
iccex.dwICC = ICC_LINK_CLASS | ICC_WIN95_CLASSES | ICC_STANDARD_CLASSES;
|
|
IF_FALSE_EXIT(InitCommonControlsEx(&iccex), E_FAIL);*/
|
|
|
|
msg.pwzTitle = pwzTitle;
|
|
msg.pwzText = pwzText;
|
|
|
|
IF_WIN32_FALSE_EXIT((iptrReturn = DialogBoxParam(g_DllInstance, MAKEINTRESOURCE(wDlgId), hWndParent, DialogBoxProc, (LPARAM) &msg) > 0));
|
|
dwReturnValue = PtrToLong((VOID *)iptrReturn);
|
|
|
|
exit:
|
|
return hr;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
RunCommand(LPCWSTR wzAppFileName, LPWSTR pwzCommandline, LPCWSTR wzCurrentDir, BOOL fWait)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
MAKE_ERROR_MACROS_STATIC(hr);
|
|
STARTUPINFO si;
|
|
PROCESS_INFORMATION pi;
|
|
|
|
ZeroMemory(&si, sizeof(si));
|
|
ZeroMemory(&pi, sizeof(pi));
|
|
|
|
si.cb = sizeof(si);
|
|
|
|
// wzCurrentDir: The string must be a full path and file name that includes a drive letter; or NULL
|
|
// note: pwzCommandline is LPWSTR, NOT LPCWSTR
|
|
IF_WIN32_FALSE_EXIT(CreateProcess(wzAppFileName, pwzCommandline, NULL, NULL, FALSE, 0, NULL, wzCurrentDir, &si, &pi));
|
|
|
|
if (fWait)
|
|
{
|
|
IF_FALSE_EXIT(!(WaitForSingleObject(pi.hProcess, 180000L) == WAIT_TIMEOUT), HRESULT_FROM_WIN32(ERROR_TIMEOUT));
|
|
}
|
|
|
|
exit:
|
|
if(pi.hProcess)
|
|
{
|
|
BOOL bReturn = CloseHandle(pi.hProcess);
|
|
if (SUCCEEDED(hr) && !bReturn)
|
|
hr = GetLastWin32Error();
|
|
}
|
|
if(pi.hThread)
|
|
{
|
|
BOOL bReturn = CloseHandle(pi.hThread);
|
|
if (SUCCEEDED(hr) && !bReturn)
|
|
hr = GetLastWin32Error();
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
RunCommandConsole(LPCWSTR wzAppFileName, LPCWSTR wzCurrentDir, BOOL fWait)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
MAKE_ERROR_MACROS_STATIC(hr);
|
|
LPWSTR pwzPath = NULL;
|
|
LPWSTR pwzBuffer = NULL;
|
|
DWORD ccPath = 0;
|
|
|
|
CString sAppdir;
|
|
CString sSystemDir;
|
|
CString sCurrentDir;
|
|
CString sCmdExe;
|
|
CString sCommandLine;
|
|
CString sPath;
|
|
|
|
// App dir
|
|
IF_FAILED_EXIT(sAppdir.Assign(wzCurrentDir));
|
|
|
|
// System directory.
|
|
// bugbug - platforms; use GetRealWindowsDirectory instead?
|
|
IF_WIN32_FALSE_EXIT((ccPath = GetSystemDirectory(NULL, 0)));
|
|
IF_FALSE_EXIT(ccPath+1 > ccPath, HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW)); // check overflow
|
|
ccPath+=1;
|
|
IF_ALLOC_FAILED_EXIT(pwzBuffer = new WCHAR[ccPath]);
|
|
IF_WIN32_FALSE_EXIT(GetSystemDirectory(pwzBuffer, ccPath));
|
|
IF_FAILED_EXIT(sSystemDir.Assign(pwzBuffer));
|
|
|
|
// Current dir = root dir
|
|
*(pwzBuffer+ sizeof("c:\\")-1) = L'\0';
|
|
IF_FAILED_EXIT(sCurrentDir.Assign(pwzBuffer));
|
|
|
|
// Path to cmd.exe
|
|
IF_FAILED_EXIT(sCmdExe.Assign(sSystemDir));
|
|
IF_FAILED_EXIT(sCmdExe.Append(L"\\cmd.exe"));
|
|
|
|
// command line
|
|
IF_FAILED_EXIT(sCommandLine.Assign(L"/k \""));
|
|
IF_FAILED_EXIT(sCommandLine.Append(wzAppFileName));
|
|
IF_FAILED_EXIT(sCommandLine.Append(L"\""));
|
|
|
|
// Get current path.
|
|
IF_WIN32_FALSE_EXIT((ccPath = GetEnvironmentVariable(L"PATH", NULL, 0)));
|
|
IF_ALLOC_FAILED_EXIT(pwzPath = new WCHAR[ccPath]);
|
|
IF_WIN32_FALSE_EXIT(GetEnvironmentVariable(L"PATH", pwzPath, ccPath));
|
|
IF_FAILED_EXIT(sPath.TakeOwnership(pwzPath, ccPath));
|
|
pwzPath = NULL;
|
|
|
|
// Append app path to current path.
|
|
IF_FAILED_EXIT(sPath.Append(sAppdir));
|
|
|
|
// set new path env variable.
|
|
IF_WIN32_FALSE_EXIT(SetEnvironmentVariable(L"PATH", sPath._pwz));
|
|
|
|
IF_FAILED_EXIT(RunCommand(sCmdExe._pwz, sCommandLine._pwz, sCurrentDir._pwz,fWait));
|
|
|
|
exit:
|
|
SAFEDELETEARRAY(pwzPath);
|
|
SAFEDELETEARRAY(pwzBuffer);
|
|
|
|
return hr;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// note: this append a '.manifest' file extension to the given pwzRealName
|
|
HRESULT
|
|
CopyToUSStartMenu(LPCWSTR pwzFilePath, LPCWSTR pwzRealName, BOOL bOverwrite, LPWSTR* ppwzResultFilePath)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
MAKE_ERROR_MACROS_STATIC(hr);
|
|
LPWSTR pwz = NULL;
|
|
CString sPath;
|
|
|
|
IF_ALLOC_FAILED_EXIT(pwz = new WCHAR[MAX_PATH]);
|
|
pwz[0] = L'\0';
|
|
|
|
// should it create the folder? C:\Documents and Settings\username\Start Menu\Programs
|
|
// "Start Menu\Programs" is localized in non-english windows
|
|
IF_FAILED_EXIT(SHGetFolderPath(NULL, CSIDL_PROGRAMS | CSIDL_FLAG_CREATE, NULL, SHGFP_TYPE_CURRENT, pwz));
|
|
|
|
IF_FAILED_EXIT(sPath.TakeOwnership(pwz, 0));
|
|
pwz = NULL;
|
|
|
|
// ISSUE-2002/03/27-felixybc Check returned path from SHGetFolderPath has no trailing '\'
|
|
IF_FAILED_EXIT(sPath.Append(L"\\"));
|
|
IF_FAILED_EXIT(sPath.Append(pwzRealName));
|
|
IF_FAILED_EXIT(sPath.Append(L".manifest"));
|
|
|
|
if (!CopyFile(pwzFilePath, sPath._pwz, !bOverwrite))
|
|
{
|
|
hr = GetLastWin32Error();
|
|
ASSERT(hr == HRESULT_FROM_WIN32(ERROR_FILE_EXISTS)); // do not assert if file already exists
|
|
goto exit;
|
|
}
|
|
|
|
// return the file path
|
|
IF_FAILED_EXIT(sPath.ReleaseOwnership(ppwzResultFilePath));
|
|
|
|
exit:
|
|
SAFEDELETEARRAY(pwz);
|
|
return hr;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// ISSUE-2002/03/30-felixybc Temp wrapper code
|
|
// wrapper for CAssemblyUpdate::RegisterAssemblySubscriptionEx
|
|
HRESULT
|
|
RegisterAssemblySubscriptionEx(IAssemblyUpdate *pAssemblyUpdate,
|
|
LPWSTR pwzDisplayName, LPWSTR pwzUrl, IManifestInfo *pSubscriptionInfo)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
MAKE_ERROR_MACROS_STATIC(hr);
|
|
DWORD *pdw = NULL;
|
|
BOOL *pb = NULL;
|
|
DWORD dwInterval = 0, dwUnit = 0, dwEvent = 0;
|
|
BOOL bDemandConnection = FALSE;
|
|
DWORD dwCB = 0, dwFlag = 0;
|
|
|
|
IF_FAILED_EXIT(pSubscriptionInfo->Get(MAN_INFO_SUBSCRIPTION_SYNCHRONIZE_INTERVAL, (LPVOID *)&pdw, &dwCB, &dwFlag));
|
|
IF_FALSE_EXIT(pdw != NULL, E_UNEXPECTED);
|
|
dwInterval = *pdw;
|
|
SAFEDELETEARRAY(pdw);
|
|
|
|
IF_FAILED_EXIT(pSubscriptionInfo->Get(MAN_INFO_SUBSCRIPTION_INTERVAL_UNIT, (LPVOID *)&pdw, &dwCB, &dwFlag));
|
|
IF_FALSE_EXIT(pdw != NULL, E_UNEXPECTED);
|
|
dwUnit = *pdw;
|
|
SAFEDELETEARRAY(pdw);
|
|
|
|
IF_FAILED_EXIT(pSubscriptionInfo->Get(MAN_INFO_SUBSCRIPTION_SYNCHRONIZE_EVENT, (LPVOID *)&pdw, &dwCB, &dwFlag));
|
|
IF_FALSE_EXIT(pdw != NULL, E_UNEXPECTED);
|
|
dwEvent = *pdw;
|
|
SAFEDELETEARRAY(pdw);
|
|
|
|
IF_FAILED_EXIT(pSubscriptionInfo->Get(MAN_INFO_SUBSCRIPTION_EVENT_DEMAND_CONNECTION, (LPVOID *)&pb, &dwCB, &dwFlag));
|
|
IF_FALSE_EXIT(pb != NULL, E_UNEXPECTED);
|
|
bDemandConnection = *pb;
|
|
SAFEDELETEARRAY(pb);
|
|
|
|
IF_FAILED_EXIT(pAssemblyUpdate->RegisterAssemblySubscriptionEx(pwzDisplayName,
|
|
pwzUrl, dwInterval, dwUnit, dwEvent, bDemandConnection));
|
|
|
|
exit:
|
|
return hr;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
|
// BUGBUG hacky should move this from extricon.cpp to util.cpp and declare in project.hpp
|
|
extern LONG GetRegKeyValue(HKEY hkeyParent, PCWSTR pcwzSubKey,
|
|
PCWSTR pcwzValue, PDWORD pdwValueType,
|
|
PBYTE pbyteBuf, PDWORD pdwcbBufLen);
|
|
|
|
// ISSUE-2002/03/30-felixybc Temp read subscription info code
|
|
// note: replace this with generic subscription info stored -> IManifestInfo type == MAN_INFO_SUBSCRIPTION
|
|
// return: S_OK - success
|
|
// error - error or missing reg key or reg value type not DWORD
|
|
HRESULT
|
|
CheckSubscribedWithEventSync(LPASSEMBLY_IDENTITY pAsmId, DWORD* pdwEvent)
|
|
{
|
|
// copied from service\server\update.cpp
|
|
#define WZ_SYNC_EVENT L"SyncEvent"
|
|
#define REG_KEY_FUSION_SUBS L"Software\\Microsoft\\Fusion\\Installer\\1.0.0.0\\Subscription"
|
|
|
|
HRESULT hr = S_OK;
|
|
MAKE_ERROR_MACROS_STATIC(hr);
|
|
DWORD dwType = 0;
|
|
DWORD dwValue = -1;
|
|
DWORD dwSize = 0;
|
|
|
|
CString sSubsKey;
|
|
LPWSTR pwzName = NULL;
|
|
|
|
IF_FAILED_EXIT(pAsmId->GetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_NAME, &pwzName, &dwSize));
|
|
IF_FALSE_EXIT(hr == S_OK, E_FAIL);
|
|
|
|
IF_FAILED_EXIT(sSubsKey.Assign(REG_KEY_FUSION_SUBS));
|
|
IF_FAILED_EXIT(sSubsKey.Append(L"\\"));
|
|
IF_FAILED_EXIT(sSubsKey.Append(pwzName));
|
|
|
|
dwSize = sizeof(dwValue);
|
|
|
|
if (GetRegKeyValue(HKEY_CURRENT_USER,
|
|
sSubsKey._pwz, WZ_SYNC_EVENT,
|
|
&dwType, (PBYTE) &dwValue, &dwSize)
|
|
== ERROR_SUCCESS)
|
|
{
|
|
*pdwEvent = dwValue;
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
hr = GetLastWin32Error();
|
|
}
|
|
|
|
exit:
|
|
SAFEDELETEARRAY(pwzName);
|
|
return hr;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// CreateActivator
|
|
// ---------------------------------------------------------------------------
|
|
STDAPI
|
|
CreateActivator(
|
|
LPACTIVATOR *ppActivator,
|
|
CDebugLog * pDbgLog,
|
|
DWORD dwFlags)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
MAKE_ERROR_MACROS_STATIC(hr);
|
|
|
|
CActivator *pAct = NULL;
|
|
|
|
pAct = new(CActivator) (pDbgLog);
|
|
IF_ALLOC_FAILED_EXIT(pAct);
|
|
|
|
exit:
|
|
|
|
*ppActivator = pAct;//static_cast<IActivator*> (pAct);
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// ctor
|
|
// ---------------------------------------------------------------------------
|
|
CActivator::CActivator(CDebugLog * pDbgLog)
|
|
: _dwSig('vtca'), _cRef(1), _hr(S_OK),
|
|
_pManImport(NULL), _pAsmId(NULL), _pAppInfo(NULL),
|
|
_pManEmit(NULL), _pwzAppRootDir(NULL), _pwzAppManifestPath(NULL),
|
|
_pwzCodebase(NULL), _dwManifestType(MANIFEST_TYPE_UNKNOWN),
|
|
_bIs1stTimeInstall(FALSE), _bIsCheckingRequiredUpdate(FALSE),
|
|
#ifdef DEVMODE
|
|
_bIsDevMode(FALSE),
|
|
#endif
|
|
_pSecurityMgr(NULL), _hrManEmit(S_OK), _ptPlatform(NULL),
|
|
_dwMissingPlatform(0)
|
|
{
|
|
|
|
_pDbgLog = pDbgLog;
|
|
|
|
if(_pDbgLog)
|
|
_pDbgLog->AddRef();
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// dtor
|
|
// ---------------------------------------------------------------------------
|
|
CActivator::~CActivator()
|
|
{
|
|
if (_ptPlatform)
|
|
{
|
|
for (DWORD dw = 0; dw < _dwMissingPlatform; dw++)
|
|
{
|
|
SAFEDELETEARRAY((_ptPlatform[dw]).pwzName);
|
|
SAFEDELETEARRAY((_ptPlatform[dw]).pwzURL);
|
|
}
|
|
SAFEDELETEARRAY(_ptPlatform);
|
|
}
|
|
|
|
SAFERELEASE(_pSecurityMgr);
|
|
SAFERELEASE(_pManEmit);
|
|
SAFERELEASE(_pAsmId);
|
|
SAFERELEASE(_pAppInfo);
|
|
SAFERELEASE(_pManImport);
|
|
SAFERELEASE(_pDbgLog);
|
|
|
|
SAFEDELETEARRAY(_pwzAppManifestPath);
|
|
SAFEDELETEARRAY(_pwzAppRootDir);
|
|
SAFEDELETEARRAY(_pwzCodebase);
|
|
}
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// CActivator::Initialize
|
|
//
|
|
// pwzFileURL can be NULL
|
|
// ---------------------------------------------------------------------------
|
|
HRESULT CActivator::Initialize(LPCWSTR pwzFilePath, LPCWSTR pwzFileURL)
|
|
{
|
|
IManifestInfo *pDependAsmInfo = NULL;
|
|
DWORD dwCount, dwFlag = 0;
|
|
|
|
IF_NULL_EXIT(pwzFilePath, E_INVALIDARG);
|
|
|
|
if (pwzFileURL != NULL)
|
|
IF_FAILED_EXIT(_sWebManifestURL.Assign((LPWSTR)pwzFileURL));
|
|
|
|
// valid start conditions to invoke this function, passing
|
|
// 1. path to desktop manifest (install redirect to subscription manifest on server)
|
|
// 2. path to desktop manifest (install redirect to applicaion manifest on server)
|
|
// 3. path to application manifest (no install, run from source)
|
|
// 4. URL to subscription manifest on server
|
|
// 5. URL to application manifest on server
|
|
|
|
if (FAILED(_hr=CreateAssemblyManifestImport(&_pManImport, pwzFilePath, _pDbgLog, 0)))
|
|
{
|
|
Msg(L"Error in loading and parsing the manifest file.");
|
|
goto exit;
|
|
}
|
|
|
|
IF_FAILED_EXIT(_pManImport->ReportManifestType(&_dwManifestType));
|
|
if (_dwManifestType == MANIFEST_TYPE_UNKNOWN)
|
|
{
|
|
Msg(L"This manifest does not have a known format type.");
|
|
_hr = E_ABORT;
|
|
goto exit;
|
|
}
|
|
|
|
// allow only valid start conditions
|
|
|
|
if (_sWebManifestURL._cc != 0 &&
|
|
_dwManifestType != MANIFEST_TYPE_SUBSCRIPTION &&
|
|
_dwManifestType != MANIFEST_TYPE_APPLICATION)
|
|
{
|
|
Msg(L"Not supported: URL pointing to a desktop manifest.");
|
|
_hr = E_ABORT;
|
|
goto exit;
|
|
}
|
|
|
|
if (_sWebManifestURL._cc == 0 &&
|
|
_dwManifestType != MANIFEST_TYPE_DESKTOP &&
|
|
_dwManifestType != MANIFEST_TYPE_APPLICATION)
|
|
{
|
|
Msg(L"This manifest does not have the proper format and cannot be used to start an application.");
|
|
_hr = E_ABORT;
|
|
goto exit;
|
|
}
|
|
|
|
// get data from the manifest file
|
|
|
|
if (_dwManifestType != MANIFEST_TYPE_SUBSCRIPTION)
|
|
{
|
|
if (FAILED(_hr=_pManImport->GetAssemblyIdentity(&_pAsmId)))
|
|
{
|
|
Msg(L"This manifest does not have the proper format and contains no assembly identity.");
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
if (_dwManifestType != MANIFEST_TYPE_APPLICATION)
|
|
{
|
|
// BUGBUG: hardcoded index '0'
|
|
IF_FAILED_EXIT(_pManImport->GetNextAssembly(0, &pDependAsmInfo));
|
|
if (pDependAsmInfo)
|
|
{
|
|
if (_dwManifestType == MANIFEST_TYPE_SUBSCRIPTION)
|
|
#ifdef DEVMODE
|
|
{
|
|
#endif
|
|
pDependAsmInfo->Get(MAN_INFO_DEPENDENT_ASM_ID, (LPVOID *)&_pAsmId, &dwCount, &dwFlag);
|
|
#ifdef DEVMODE
|
|
|
|
DWORD *pdw = NULL;
|
|
|
|
// is it devMode?
|
|
IF_FAILED_EXIT(pDependAsmInfo->Get(MAN_INFO_DEPENDENT_ASM_TYPE, (LPVOID *)&pdw, &dwCount, &dwFlag));
|
|
IF_FALSE_EXIT(pdw != NULL, E_UNEXPECTED);
|
|
|
|
if (*pdw == DEPENDENT_ASM_INSTALL_TYPE_DEVSYNC)
|
|
_bIsDevMode = TRUE;
|
|
SAFEDELETEARRAY(pdw);
|
|
}
|
|
#endif
|
|
|
|
pDependAsmInfo->Get(MAN_INFO_DEPENDENT_ASM_CODEBASE, (LPVOID *)&_pwzCodebase, &dwCount, &dwFlag);
|
|
}
|
|
|
|
if (!_pAsmId || !_pwzCodebase)
|
|
{
|
|
Msg(L"This subscription manifest contains no dependent assembly identity or a subscription codebase.");
|
|
_hr = E_FAIL;
|
|
goto exit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (_sWebManifestURL._cc != 0)
|
|
{
|
|
// if URL->app manifest (case 5), codebase is that URL
|
|
// note: if path->app manifest (case 3), this does NOT apply
|
|
|
|
// BUGBUG: HACK: this implies re-download of the app manifest. pref?
|
|
|
|
size_t ccCodebase = wcslen(pwzFileURL)+1;
|
|
_pwzCodebase = new WCHAR[ccCodebase];
|
|
IF_ALLOC_FAILED_EXIT(_pwzCodebase);
|
|
|
|
memcpy(_pwzCodebase, pwzFileURL, ccCodebase * sizeof(WCHAR));
|
|
}
|
|
}
|
|
|
|
if (_sWebManifestURL._cc == 0 &&
|
|
_dwManifestType == MANIFEST_TYPE_APPLICATION)
|
|
{
|
|
// run from source
|
|
// set _pwzAppRootDir, _pwzAppManifestPath
|
|
CString sManifestFilePath;
|
|
CString sManifestFileDir;
|
|
|
|
IF_FAILED_EXIT(sManifestFilePath.Assign(pwzFilePath));
|
|
|
|
IF_FAILED_EXIT(sManifestFileDir.Assign(sManifestFilePath));
|
|
IF_FAILED_EXIT(sManifestFileDir.RemoveLastElement());
|
|
IF_FAILED_EXIT(sManifestFileDir.Append(L"\\"));
|
|
IF_FAILED_EXIT(sManifestFileDir.ReleaseOwnership(&_pwzAppRootDir));
|
|
|
|
IF_FAILED_EXIT(sManifestFilePath.ReleaseOwnership(&_pwzAppManifestPath));
|
|
}
|
|
|
|
exit:
|
|
SAFERELEASE(pDependAsmInfo)
|
|
return _hr;
|
|
}
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// CActivator::Process
|
|
// ---------------------------------------------------------------------------
|
|
HRESULT CActivator::Process()
|
|
{
|
|
LPWSTR pwzDesktopManifestTempPath = NULL;
|
|
DWORD dwCount = 0, dwFlag = 0;
|
|
|
|
IF_NULL_EXIT(_pAsmId, E_UNEXPECTED); // not initialized
|
|
|
|
if (_sWebManifestURL._cc == 0 &&
|
|
_dwManifestType == MANIFEST_TYPE_APPLICATION)
|
|
{
|
|
// run from source
|
|
|
|
if (FAILED(_hr=_pManImport->GetManifestApplicationInfo(&_pAppInfo)) || _hr==S_FALSE)
|
|
{
|
|
// can't continue without this...
|
|
_hr = E_ABORT;
|
|
Msg(L"The application manifest does not have the shell information and cannot be used to start an application.");
|
|
goto exit;
|
|
}
|
|
|
|
// bypass other processing
|
|
// _pwzAppRootDir, _pwzAppManifestPath are already set in Initialize
|
|
_hr = S_FALSE;
|
|
goto exit;
|
|
}
|
|
|
|
// search cache, download/install if necessary
|
|
|
|
// BUGBUG: UGLY - pManImport & pwzFileURL are needed only for desktop manifest stuff.
|
|
// This and below subscription registration should be cleaned up once assemblydownload is restructured.
|
|
/// (see checks for "_sWebManifestURL._cc != 0 && dwManifestType == MANIFEST_TYPE_SUBSCRIPTION")
|
|
|
|
IF_FAILED_EXIT(ResolveAndInstall(&pwzDesktopManifestTempPath));
|
|
|
|
// register for updates
|
|
|
|
if (_bIs1stTimeInstall && _sWebManifestURL._cc != 0 && _dwManifestType == MANIFEST_TYPE_SUBSCRIPTION)
|
|
{
|
|
// note: this code must be identical to what assemblydownload.cpp DoCacheUpdate() does!
|
|
LPWSTR pwzName = NULL;
|
|
|
|
if ((_hr = _pAsmId->GetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_NAME, &pwzName, &dwCount)) != S_OK)
|
|
{
|
|
ShowError(_hr, L"Error in retrieving assembly name. Cannot register subscription for updates.");
|
|
// note: This- no asm name- should not be allowed!
|
|
}
|
|
else
|
|
{
|
|
IAssemblyUpdate *pAssemblyUpdate = NULL;
|
|
|
|
// register for updates
|
|
_hr = CoCreateInstance(CLSID_CAssemblyUpdate, NULL, CLSCTX_LOCAL_SERVER,
|
|
IID_IAssemblyUpdate, (void**)&pAssemblyUpdate);
|
|
if (SUCCEEDED(_hr))
|
|
{
|
|
IManifestInfo* pSubsInfo = NULL;
|
|
if (SUCCEEDED(_hr = _pManImport->GetSubscriptionInfo(&pSubsInfo)))
|
|
{
|
|
_hr = RegisterAssemblySubscriptionEx(pAssemblyUpdate, pwzName,
|
|
_sWebManifestURL._pwz, pSubsInfo);
|
|
pSubsInfo->Release();
|
|
}
|
|
|
|
pAssemblyUpdate->Release();
|
|
}
|
|
|
|
if (FAILED(_hr))
|
|
{
|
|
ShowError(_hr, L"Error in update services. Cannot register subscription for updates.");
|
|
//goto exit; do not terminate!fail gracefully
|
|
}
|
|
|
|
// BUGBUG: need a way to recover from this and register later
|
|
|
|
delete[] pwzName;
|
|
}
|
|
}
|
|
|
|
// CVersionManagement's RegisterInstall() below requires a manifest import to an application manifest
|
|
if (_sWebManifestURL._cc != 0 || pwzDesktopManifestTempPath)
|
|
{
|
|
// if URL, crack the app manifest to get shell state info
|
|
|
|
// BUGBUG: if URL->app manifest (case 5), pwzFilePath is a copy and is already cracked-so no need in that case?
|
|
|
|
_pManImport->Release();
|
|
if (FAILED(_hr=CreateAssemblyManifestImport(&_pManImport, _pwzAppManifestPath, _pDbgLog, 0)))
|
|
{
|
|
Msg(L"Error in loading and parsing the application manifest file.");
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
if (FAILED(_hr=_pManImport->GetManifestApplicationInfo(&_pAppInfo)) || _hr==S_FALSE)
|
|
{
|
|
// can't continue without this...
|
|
_hr = E_ABORT;
|
|
Msg(L"This manifest does not have the shell information and cannot be used to start an application.");
|
|
goto exit;
|
|
}
|
|
|
|
// copy desktop manifest, if present
|
|
// even if the app deployment can possibly be broken and will not execute
|
|
if (pwzDesktopManifestTempPath)
|
|
{
|
|
LPWSTR pwzFriendlyName = NULL;
|
|
|
|
// BUGBUG: should get status on the desktop manifest generated, not copy in some cases, eg. file size == 0 or XMLDOM errors
|
|
// use _hrManEmit to check
|
|
|
|
if (FAILED(_hr = _pAppInfo->Get(MAN_INFO_APPLICATION_FRIENDLYNAME, (LPVOID *)&pwzFriendlyName, &dwCount, &dwFlag)))
|
|
{
|
|
Msg(L"This application does not have a friendly name specified, no desktop manifest is generated and the installation is not registered.");
|
|
}
|
|
else
|
|
{
|
|
// BUGBUG: should somehow continue even w/o a friendly name? name conflict?
|
|
|
|
IF_FALSE_EXIT(pwzFriendlyName != NULL, E_UNEXPECTED);
|
|
|
|
LPWSTR pwzDesktopManifestPath = NULL;
|
|
|
|
_hr = CopyToUSStartMenu(pwzDesktopManifestTempPath, pwzFriendlyName, FALSE, &pwzDesktopManifestPath);
|
|
|
|
delete[] pwzFriendlyName;
|
|
|
|
// note: if a file with the same name already exists, the desktop manifest is not copied over
|
|
// and so, this existing file will not be deleted when this app is uninstalled.
|
|
|
|
// ISSUE-2002/03/27-felixybc finalize on what to do if file already exists - this could be a name squatting attack
|
|
|
|
IF_FALSE_EXIT(!(FAILED(_hr) && _hr != HRESULT_FROM_WIN32(ERROR_FILE_EXISTS)), _hr); // _hr from CopyToUSStartMenu() above...
|
|
|
|
LPVERSION_MANAGEMENT pVerMan = NULL;
|
|
|
|
if (SUCCEEDED(_hr = CreateVersionManagement(&pVerMan, 0)))
|
|
{
|
|
HRESULT hrVerMan = S_OK;
|
|
if (FAILED(hrVerMan = pVerMan->RegisterInstall(_pManImport, pwzDesktopManifestPath)))
|
|
{
|
|
ShowError(hrVerMan, L"Error registering installation. Uninstall of this application cannot be done in Add/Remove Programs.");
|
|
//goto exit; did not change _hr
|
|
}
|
|
}
|
|
|
|
delete [] pwzDesktopManifestPath;
|
|
if (pVerMan)
|
|
pVerMan->Release();
|
|
|
|
// _hr from CreateVersionManagement() above...
|
|
IF_FAILED_EXIT(_hr);
|
|
}
|
|
}
|
|
|
|
|
|
exit:
|
|
if (pwzDesktopManifestTempPath)
|
|
{
|
|
// delete the temp file for desktop manifest
|
|
BOOL bReturn = DeleteFile(pwzDesktopManifestTempPath);
|
|
if (SUCCEEDED(_hr) && !bReturn)
|
|
_hr = GetLastWin32Error(); // else ignore return value
|
|
|
|
delete[] pwzDesktopManifestTempPath;
|
|
}
|
|
|
|
return _hr;
|
|
}
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// CActivator::Execute
|
|
// ---------------------------------------------------------------------------
|
|
HRESULT CActivator::Execute()
|
|
{
|
|
LPWSTR pwzEntrypoint = NULL;
|
|
LPWSTR pwzType = NULL;
|
|
LPWSTR pwzAssemblyName = NULL;
|
|
LPWSTR pwzAssemblyClass = NULL;
|
|
LPWSTR pwzAssemblyMethod = NULL;
|
|
LPWSTR pwzAssemblyArgs = NULL;
|
|
|
|
LPWSTR pwzCmdLine = NULL;
|
|
int iAppType = 0;
|
|
DWORD dwCount, dwFlag = 0;
|
|
|
|
IF_NULL_EXIT(_pAppInfo, E_UNEXPECTED); // not processed
|
|
|
|
// execute the app
|
|
|
|
IF_FAILED_EXIT(_pAppInfo->Get(MAN_INFO_APPLICATION_ENTRYPOINT, (LPVOID *)&pwzEntrypoint, &dwCount, &dwFlag));
|
|
if(pwzEntrypoint && *pwzEntrypoint == L'\0')
|
|
SAFEDELETEARRAY(pwzEntrypoint);
|
|
|
|
if (FAILED(_hr = _pAppInfo->Get(MAN_INFO_APPLICATION_ENTRYIMAGETYPE, (LPVOID *)&pwzType, &dwCount, &dwFlag)))
|
|
{
|
|
Msg(L"Error in retrieving application type. Cannot continue.");
|
|
goto exit;
|
|
}
|
|
IF_FALSE_EXIT(pwzType != NULL, E_UNEXPECTED);
|
|
|
|
IF_FAILED_EXIT(FusionCompareString(pwzType, WZ_TYPE_DOTNET, 0));
|
|
if (_hr == S_OK)
|
|
iAppType = TYPE_DOTNET;
|
|
else
|
|
{
|
|
IF_FAILED_EXIT(FusionCompareString(pwzType, WZ_TYPE_WIN32, 0));
|
|
if (_hr == S_OK)
|
|
iAppType = TYPE_WIN32;
|
|
else
|
|
{
|
|
IF_FAILED_EXIT(FusionCompareString(pwzType, WZ_TYPE_AVALON, 0));
|
|
if (_hr == S_OK)
|
|
iAppType = TYPE_AVALON;
|
|
else
|
|
{
|
|
IF_FAILED_EXIT(FusionCompareString(pwzType, WZ_TYPE_CONSOLE, 0));
|
|
if (_hr == S_OK)
|
|
iAppType = TYPE_CONSOLE;
|
|
else
|
|
{
|
|
// unknown type
|
|
Msg(L"Unsupported application type. Cannot continue.");
|
|
_hr = E_ABORT;
|
|
goto exit;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if( (iAppType == TYPE_CONSOLE) || (iAppType == TYPE_WIN32) )
|
|
{
|
|
if(!pwzEntrypoint)
|
|
{
|
|
Msg(L"Entry point not specified. Could not run this application.");
|
|
goto exit;
|
|
}
|
|
|
|
size_t ccWorkingDir = wcslen(_pwzAppRootDir);
|
|
size_t ccEntryPoint = wcslen(pwzEntrypoint)+1;
|
|
pwzCmdLine = new WCHAR[ccWorkingDir+ccEntryPoint]; // 2 strings + '\0'
|
|
IF_ALLOC_FAILED_EXIT(pwzCmdLine);
|
|
|
|
memcpy(pwzCmdLine, _pwzAppRootDir, ccWorkingDir * sizeof(WCHAR));
|
|
memcpy(pwzCmdLine+ccWorkingDir, pwzEntrypoint, ccEntryPoint * sizeof(WCHAR));
|
|
|
|
// check if the entry point is in cache or not
|
|
BOOL bExists = FALSE;
|
|
IF_FAILED_EXIT(CheckFileExistence(pwzCmdLine, &bExists));
|
|
if (!bExists)
|
|
{
|
|
Msg(L"Entry point does not exist. Cannot continue.");
|
|
_hr = E_ABORT;
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
|
|
if (iAppType == TYPE_DOTNET || iAppType == TYPE_AVALON)
|
|
{
|
|
#if 0
|
|
DWORD dwZone;
|
|
#endif
|
|
|
|
// ISSUE - note: ndphost should do the checking below instead
|
|
IF_FAILED_EXIT(_pAppInfo->Get(MAN_INFO_APPLICATION_ASSEMBLYNAME,
|
|
(LPVOID *)&pwzAssemblyName, &dwCount, &dwFlag));
|
|
if(pwzAssemblyName && *pwzAssemblyName == L'\0')
|
|
SAFEDELETEARRAY(pwzAssemblyName);
|
|
|
|
IF_FAILED_EXIT(_pAppInfo->Get(MAN_INFO_APPLICATION_ASSEMBLYCLASS,
|
|
(LPVOID *)&pwzAssemblyClass, &dwCount, &dwFlag));
|
|
if(pwzAssemblyClass && *pwzAssemblyClass == L'\0')
|
|
SAFEDELETEARRAY(pwzAssemblyClass);
|
|
|
|
IF_FAILED_EXIT(_pAppInfo->Get(MAN_INFO_APPLICATION_ASSEMBLYMETHOD,
|
|
(LPVOID *)&pwzAssemblyMethod, &dwCount, &dwFlag));
|
|
if(pwzAssemblyMethod && *pwzAssemblyMethod == L'\0')
|
|
SAFEDELETEARRAY(pwzAssemblyMethod);
|
|
|
|
IF_FAILED_EXIT(_pAppInfo->Get(MAN_INFO_APPLICATION_ASSEMBLYARGS,
|
|
(LPVOID *)&pwzAssemblyArgs, &dwCount, &dwFlag));
|
|
if(pwzAssemblyArgs && *pwzAssemblyArgs == L'\0')
|
|
SAFEDELETEARRAY(pwzAssemblyArgs);
|
|
|
|
if(!pwzAssemblyName)
|
|
{
|
|
Msg(L"The application manifest does not have an activation assembly.");
|
|
_hr = E_ABORT;
|
|
goto exit;
|
|
}
|
|
|
|
if(pwzEntrypoint)
|
|
{
|
|
Msg(L"Entrypoint cannot be specified for managed code application types.");
|
|
_hr = E_ABORT;
|
|
goto exit;
|
|
}
|
|
|
|
if((pwzAssemblyClass && !pwzAssemblyMethod)
|
|
|| (!pwzAssemblyClass && pwzAssemblyMethod)
|
|
|| (pwzAssemblyArgs && !pwzAssemblyClass))
|
|
{
|
|
Msg(L"Both AssemblyClass and AssemblyMethod must be specified.");
|
|
_hr = E_ABORT;
|
|
goto exit;
|
|
}
|
|
|
|
// note: at this point the codebase can be: URL to app manifest _or_ URL to subscription manifest
|
|
// (depends on how 1st time install is started with)
|
|
if ((_sWebManifestURL._cc != 0 ||
|
|
_dwManifestType != MANIFEST_TYPE_APPLICATION) && // run from source
|
|
_pwzCodebase == NULL)
|
|
{
|
|
Msg(L"This application does not have a codebase specified. Cannot continue to execute .NetAssembly.");
|
|
_hr = E_ABORT;
|
|
goto exit;
|
|
}
|
|
|
|
#if 0
|
|
if (_pSecurityMgr == NULL)
|
|
{
|
|
// lazy init.
|
|
_hr = CoCreateInstance(CLSID_InternetSecurityManager, NULL, CLSCTX_INPROC_SERVER,
|
|
IID_IInternetSecurityManager, (void**)&_pSecurityMgr);
|
|
if (FAILED(_hr))
|
|
_pSecurityMgr = NULL;
|
|
IF_FAILED_EXIT(_hr);
|
|
}
|
|
|
|
// BUGBUG?: shouldn't use codebase from ref manifest to set zone?
|
|
IF_FAILED_EXIT(_pSecurityMgr->MapUrlToZone(_pwzCodebase, &dwZone, 0));
|
|
#endif
|
|
|
|
#if 0 // old code
|
|
// BUGBUG: hack for avalon (bug # 875)
|
|
SetCurrentDirectory(_pwzAppRootDir);
|
|
|
|
try
|
|
{
|
|
IAsmExecutePtr pIAsmExecute(__uuidof(AsmExecute));
|
|
long lRetVal = -1;
|
|
long lFlag = 0x3;
|
|
LPWSTR pwzArg = NULL;
|
|
|
|
// BUGBUG: change AsmExec if it's no longer needed to send commandline argument
|
|
// clean up interface
|
|
|
|
if (iAppType == TYPE_AVALON)
|
|
{
|
|
// call with manifest file path as a parameter
|
|
//pwzArg = pwzAppManifestPath; avalon arg hack
|
|
|
|
// pass Avalon flag
|
|
lFlag = 0x1003;
|
|
|
|
// BUGBUG: a hack to show debug msg
|
|
AllocConsole();
|
|
}
|
|
|
|
//parameters: Codebase/filepath Flag Zone Url Arg
|
|
// BUGBUG: DWORD is unsigned and long is signed
|
|
|
|
_hr = pIAsmExecute->Execute(_bstr_t(pwzCmdLine), lFlag, dwZone, _bstr_t(_pwzCodebase), _bstr_t(pwzArg), &lRetVal);
|
|
|
|
// BUGBUG: do something about lRetVal
|
|
}
|
|
catch (_com_error &e)
|
|
{
|
|
_hr = e.Error();
|
|
Msg((LPWSTR)e.ErrorMessage());
|
|
}
|
|
|
|
// BUGBUG: get/display the actual error message
|
|
// _hr from Execute() or inside catch(){} above
|
|
if (FAILED(_hr))
|
|
goto exit;
|
|
#else
|
|
CString sHostPath;
|
|
CString sCommandLine;
|
|
// IF_FAILED_EXIT(MakeCommandLine(_pwzAppRootDir, pwzAssemblyName, pwzAssemblyClass, pwzAssemblyMethod, pwzAssemblyArgs, _pwzCodebase, dwZone, sHostPath, sCommandLine));
|
|
IF_FAILED_EXIT(MakeCommandLine(_pwzAppManifestPath, _pwzCodebase, sHostPath, sCommandLine));
|
|
IF_FAILED_EXIT(RunCommand(sHostPath._pwz, sCommandLine._pwz, _pwzAppRootDir, FALSE));
|
|
#endif
|
|
}
|
|
else if (iAppType == TYPE_WIN32)
|
|
{
|
|
// BUGBUG: Win32 app has no sandboxing... use SAFER?
|
|
|
|
// BUGBUG: start directory: what if the exe is in a subdir of pwzAppRootDir?
|
|
|
|
// CreateProcess dislike having the filename in the path for the start directory
|
|
if (FAILED(_hr=RunCommand(pwzCmdLine, NULL, _pwzAppRootDir, FALSE)))
|
|
{
|
|
ShowError(_hr, L"Win32Executable: Create process error.");
|
|
_hr = E_ABORT;
|
|
goto exit;
|
|
}
|
|
}
|
|
else if (iAppType == TYPE_CONSOLE)
|
|
{
|
|
// BUGBUG: Win32 app has no sandboxing... use SAFER?
|
|
|
|
// BUGBUG: start directory: what if the exe is in a subdir of pwzAppRootDir?
|
|
|
|
// CreateProcess dislike having the filename in the path for the start directory
|
|
if (FAILED(_hr=RunCommandConsole(pwzCmdLine, _pwzAppRootDir, FALSE)))
|
|
{
|
|
ShowError(_hr, L"Win32Console: Create process error.");
|
|
_hr = E_ABORT;
|
|
goto exit;
|
|
}
|
|
}
|
|
//else
|
|
// unknown type....
|
|
|
|
exit:
|
|
SAFEDELETEARRAY(pwzEntrypoint);
|
|
SAFEDELETEARRAY(pwzType);
|
|
SAFEDELETEARRAY(pwzCmdLine);
|
|
|
|
SAFEDELETEARRAY(pwzAssemblyName);
|
|
SAFEDELETEARRAY(pwzAssemblyClass);
|
|
SAFEDELETEARRAY(pwzAssemblyMethod);
|
|
SAFEDELETEARRAY(pwzAssemblyArgs);
|
|
|
|
return _hr;
|
|
}
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// CActivator::OnProgress
|
|
// ---------------------------------------------------------------------------
|
|
HRESULT CActivator::OnProgress(DWORD dwNotification, HRESULT hrNotification,
|
|
LPCWSTR szNotification, DWORD dwProgress,
|
|
DWORD dwProgressMax, IUnknown *pUnk)
|
|
{
|
|
LPASSEMBLY_MANIFEST_IMPORT pManifestImport = NULL;
|
|
LPASSEMBLY_IDENTITY pAsmId = NULL;
|
|
IManifestInfo *pDependAsmInfo = NULL;
|
|
|
|
// only handles notification it cares
|
|
if (dwNotification == ASM_NOTIFICATION_SUBSCRIPTION_MANIFEST ||
|
|
dwNotification == ASM_NOTIFICATION_APPLICATION_MANIFEST)
|
|
{
|
|
// szNotification == URL to manifest
|
|
IF_NULL_EXIT(szNotification, E_INVALIDARG);
|
|
|
|
// pUnk == manifest import of manifest
|
|
IF_FAILED_EXIT(pUnk->QueryInterface(IID_IAssemblyManifestImport, (LPVOID*) &pManifestImport));
|
|
|
|
if (dwNotification == ASM_NOTIFICATION_SUBSCRIPTION_MANIFEST)
|
|
{
|
|
LPWSTR pwzName = NULL;
|
|
DWORD dwCount = 0;
|
|
|
|
IF_FAILED_EXIT(_pAsmId->GetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_NAME, &pwzName, &dwCount));
|
|
|
|
{
|
|
IAssemblyUpdate *pAssemblyUpdate = NULL;
|
|
|
|
// register for updates
|
|
_hr = CoCreateInstance(CLSID_CAssemblyUpdate, NULL, CLSCTX_LOCAL_SERVER,
|
|
IID_IAssemblyUpdate, (void**)&pAssemblyUpdate);
|
|
if (SUCCEEDED(_hr))
|
|
{
|
|
IManifestInfo* pSubsInfo = NULL;
|
|
if (SUCCEEDED(_hr = pManifestImport->GetSubscriptionInfo(&pSubsInfo)))
|
|
{
|
|
_hr = RegisterAssemblySubscriptionEx(pAssemblyUpdate, pwzName,
|
|
(LPWSTR) szNotification, pSubsInfo);
|
|
pSubsInfo->Release();
|
|
}
|
|
|
|
pAssemblyUpdate->Release();
|
|
}
|
|
|
|
delete[] pwzName;
|
|
|
|
// do not fail... should show UI?
|
|
if (FAILED(_hr))
|
|
_hr = S_OK;
|
|
// goto exit;
|
|
|
|
// BUGBUG: need a way to recover from this and register later
|
|
}
|
|
|
|
// export dependency/dependentassembly/assemblyIdentity & subscription
|
|
if (_pManEmit)
|
|
_hrManEmit = _pManEmit->SetDependencySubscription(pManifestImport, (LPWSTR)szNotification);
|
|
else if (_bIsCheckingRequiredUpdate)
|
|
{
|
|
// if _bIsCheckingRequiredUpdate, _pManEmit == NULL,
|
|
// and must be downloading subscription manifest
|
|
|
|
// check if required update
|
|
|
|
BOOL bIsToDownload = FALSE; // default is normal
|
|
|
|
// BUGBUG: hardcoded index '0'
|
|
IF_FAILED_EXIT(pManifestImport->GetNextAssembly(0, &pDependAsmInfo));
|
|
IF_FALSE_EXIT(_hr == S_OK, E_FAIL);
|
|
if (pDependAsmInfo)
|
|
{
|
|
LPASSEMBLY_CACHE_IMPORT pCacheImport = NULL;
|
|
DWORD dwFlag= 0;
|
|
|
|
//already has it?
|
|
IF_FAILED_EXIT(pDependAsmInfo->Get(MAN_INFO_DEPENDENT_ASM_ID, (LPVOID *)&pAsmId, &dwCount, &dwFlag));
|
|
IF_FALSE_EXIT(pAsmId != NULL, E_UNEXPECTED);
|
|
|
|
IF_FAILED_EXIT(CreateAssemblyCacheImport(&pCacheImport, pAsmId, CACHEIMP_CREATE_RETRIEVE));
|
|
if (_hr == S_FALSE)
|
|
{
|
|
// no, does not have it
|
|
|
|
DWORD *pdw = NULL;
|
|
|
|
// is it required?
|
|
IF_FAILED_EXIT(pDependAsmInfo->Get(MAN_INFO_DEPENDENT_ASM_TYPE, (LPVOID *)&pdw, &dwCount, &dwFlag));
|
|
IF_FALSE_EXIT(pdw != NULL, E_UNEXPECTED);
|
|
|
|
if (*pdw == DEPENDENT_ASM_INSTALL_TYPE_REQUIRED)
|
|
bIsToDownload = TRUE; // yes, it is required
|
|
#ifdef DEVMODE
|
|
else if (*pdw == DEPENDENT_ASM_INSTALL_TYPE_DEVSYNC)
|
|
bIsToDownload = TRUE; // yes, it is devsync, assume required
|
|
#endif
|
|
SAFEDELETEARRAY(pdw);
|
|
}
|
|
|
|
SAFERELEASE(pCacheImport);
|
|
}
|
|
|
|
if (!bIsToDownload)
|
|
_hr = E_ABORT; // signal abort the download
|
|
}
|
|
}
|
|
else if (dwNotification == ASM_NOTIFICATION_APPLICATION_MANIFEST)
|
|
{
|
|
// check for dependent platforms
|
|
IF_FAILED_EXIT(CheckPlatformRequirementsEx(pManifestImport, _pDbgLog, &_dwMissingPlatform, &_ptPlatform));
|
|
IF_TRUE_EXIT((_dwMissingPlatform > 0), E_ABORT);
|
|
|
|
if (_pManEmit)
|
|
{
|
|
// export assemblyIdentity & application
|
|
|
|
// ignore failure
|
|
_hrManEmit = _pManEmit->ImportManifestInfo(pManifestImport);
|
|
|
|
// export dependency/dependentassembly/assemblyIdentity & subscription
|
|
// ignore failure, if already called once this is ignored
|
|
_hrManEmit = _pManEmit->SetDependencySubscription(pManifestImport, (LPWSTR)szNotification);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
_hr = S_OK;
|
|
|
|
exit:
|
|
SAFERELEASE(pAsmId);
|
|
SAFERELEASE(pDependAsmInfo);
|
|
|
|
SAFERELEASE(pManifestImport);
|
|
return _hr;
|
|
}
|
|
|
|
// IUnknown methods
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// CActivator::QI
|
|
// ---------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CActivator::QueryInterface(REFIID riid, void** ppvObj)
|
|
{
|
|
if ( IsEqualIID(riid, IID_IUnknown)
|
|
// || IsEqualIID(riid, IID_IActivator)
|
|
)
|
|
{
|
|
*ppvObj = this; //static_cast<IActivator*> (this);
|
|
AddRef();
|
|
return S_OK;
|
|
}
|
|
else
|
|
{
|
|
*ppvObj = NULL;
|
|
return E_NOINTERFACE;
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// CActivator::AddRef
|
|
// ---------------------------------------------------------------------------
|
|
STDMETHODIMP_(ULONG)
|
|
CActivator::AddRef()
|
|
{
|
|
return InterlockedIncrement ((LONG*) &_cRef);
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// CActivator::Release
|
|
// ---------------------------------------------------------------------------
|
|
STDMETHODIMP_(ULONG)
|
|
CActivator::Release()
|
|
{
|
|
ULONG lRet = InterlockedDecrement ((LONG*) &_cRef);
|
|
if (!lRet)
|
|
delete this;
|
|
return lRet;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
HRESULT CreateTempFile(LPCWSTR pcwzPrefix, LPWSTR *ppwzFilePath)
|
|
{
|
|
#define DEFAULT_PATH_LEN MAX_PATH
|
|
#define TEMP_FILE_NAME_LEN sizeof("preuuuu.TMP") // from msdn
|
|
HRESULT hr = S_OK;
|
|
MAKE_ERROR_MACROS_STATIC(hr);
|
|
LPWSTR pwzTempPath = NULL;
|
|
LPWSTR pwzTempFilePath = NULL;
|
|
|
|
IF_NULL_EXIT(pcwzPrefix, E_INVALIDARG);
|
|
IF_NULL_EXIT(ppwzFilePath, E_INVALIDARG);
|
|
*ppwzFilePath = NULL;
|
|
|
|
IF_FALSE_EXIT(lstrlen(pcwzPrefix) == 3, E_INVALIDARG);
|
|
|
|
// assemble temp file path
|
|
IF_ALLOC_FAILED_EXIT(pwzTempPath = new WCHAR[DEFAULT_PATH_LEN]);
|
|
|
|
// ISSUE-2002/03/31-felixybc GetTempPath can overrun the buffer?
|
|
DWORD dwLen = GetTempPath(DEFAULT_PATH_LEN, pwzTempPath);
|
|
IF_WIN32_FALSE_EXIT(dwLen);
|
|
|
|
if (dwLen >= DEFAULT_PATH_LEN)
|
|
{
|
|
// resize, add 1 for terminating null
|
|
IF_FALSE_EXIT(dwLen+1 > dwLen, HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW)); // check overflow
|
|
SAFEDELETEARRAY(pwzTempPath);
|
|
IF_ALLOC_FAILED_EXIT(pwzTempPath = new WCHAR[dwLen+1]);
|
|
|
|
DWORD dwLenNew = GetTempPath(dwLen+1, pwzTempPath);
|
|
IF_WIN32_FALSE_EXIT(dwLenNew);
|
|
|
|
IF_FALSE_EXIT(dwLenNew < dwLen+1, E_FAIL); // why is it still not enough?
|
|
}
|
|
|
|
DWORD dwBufLen = lstrlen(pwzTempPath)+1;
|
|
// note: can do a better check here
|
|
IF_FALSE_EXIT(dwBufLen > 1, E_FAIL);
|
|
|
|
// allocate buffer large enough for temp path and temp file name
|
|
DWORD dwLenNew = (dwBufLen > DEFAULT_PATH_LEN)? dwBufLen : DEFAULT_PATH_LEN;
|
|
dwLenNew += TEMP_FILE_NAME_LEN;
|
|
|
|
// check for overflow
|
|
IF_FALSE_EXIT(dwLenNew > dwBufLen, E_FAIL);
|
|
|
|
IF_ALLOC_FAILED_EXIT(pwzTempFilePath = new WCHAR[dwLenNew]);
|
|
// *pwzTempFilePath = L'\0';
|
|
|
|
// note: temp file to be deleted by the caller
|
|
IF_WIN32_FALSE_EXIT(GetTempFileName(pwzTempPath, pcwzPrefix, 0, pwzTempFilePath));
|
|
|
|
*ppwzFilePath = pwzTempFilePath;
|
|
pwzTempFilePath = NULL;
|
|
|
|
exit:
|
|
/* if (FAILED(hr) && pwzTempFilePath != NULL)
|
|
{
|
|
if (*pwzTempFilePath != L'\0')
|
|
{
|
|
// ignore if error deleting the file
|
|
DeleteFile(pwzTempFilePath);
|
|
}
|
|
}*/
|
|
|
|
SAFEDELETEARRAY(pwzTempFilePath);
|
|
SAFEDELETEARRAY(pwzTempPath);
|
|
|
|
return hr;
|
|
}
|
|
// ---------------------------------------------------------------------------
|
|
// CActivator::ResolveAndInstall
|
|
// note: parameter _pwzCodebase can be NULL
|
|
// must delete if *ppwzDesktopManifestPathName != NULL
|
|
// ---------------------------------------------------------------------------
|
|
HRESULT CActivator::ResolveAndInstall(LPWSTR *ppwzDesktopManifestPathName)
|
|
{
|
|
LPASSEMBLY_CACHE_IMPORT pCacheImport = NULL;
|
|
DWORD dwCC = 0;
|
|
|
|
_bIs1stTimeInstall = FALSE;
|
|
|
|
// look into the cache
|
|
|
|
IF_FAILED_EXIT(CreateAssemblyCacheImport(&pCacheImport, _pAsmId, CACHEIMP_CREATE_RESOLVE_REF));
|
|
|
|
// hr from CreateAssemblyCacheImport() above
|
|
|
|
// Case 1, cached copy exist
|
|
// _hr == S_OK
|
|
|
|
if (_hr == S_OK && _dwManifestType == MANIFEST_TYPE_DESKTOP)
|
|
{
|
|
// BUGBUG: broken if subscribed then run with a desktop manifest generated with URL to app manifest
|
|
// should check and ignore if desktop manifest redirect to applicaion manifest on server
|
|
// as there is no way to check for update/changes in subscription manifest, even if subscribed so
|
|
// correct fix is to use subscription manifest's URL stored
|
|
|
|
// check if subscribed with event sync
|
|
|
|
DWORD dwSyncEvent = MAN_INFO_SUBSCRIPTION_MAX;
|
|
_hr = CheckSubscribedWithEventSync(_pAsmId, &dwSyncEvent);
|
|
// ISSUE-2002/04/12-felixybc If the value is absent, ERROR_NO_MORE_FILES is returned.
|
|
// Note that dwSyncEvent is unmodified.
|
|
if (_hr != HRESULT_FROM_WIN32(ERROR_NO_MORE_FILES))
|
|
IF_FAILED_EXIT(_hr);
|
|
|
|
if (dwSyncEvent == SUBSCRIPTION_SYNC_EVENT_ON_APP_STARTUP)
|
|
{
|
|
LPASSEMBLY_DOWNLOAD pAsmDownload = NULL;
|
|
|
|
// event sync onApplicationStartup == required update
|
|
|
|
// _pwzCodebase != NULL
|
|
|
|
// check policy before download
|
|
IF_FAILED_EXIT(CheckZonePolicy(_pwzCodebase));
|
|
|
|
IF_FAILED_EXIT(CreateAssemblyDownload(&pAsmDownload, _pDbgLog, 0));
|
|
|
|
_bIsCheckingRequiredUpdate = TRUE;
|
|
|
|
// (synchronous & ui & bindsink) download from codebase
|
|
_hr=pAsmDownload->DownloadManifestAndDependencies(_pwzCodebase, this, DOWNLOAD_FLAGS_PROGRESS_UI | DOWNLOAD_FLAGS_NOTIFY_BINDSINK);
|
|
pAsmDownload->Release();
|
|
_bIsCheckingRequiredUpdate = FALSE;
|
|
|
|
// hr from DownloadManifestAndDependencies() above
|
|
if (FAILED(_hr))
|
|
{
|
|
if (_hr != E_ABORT)
|
|
{
|
|
HRESULT hrTemp;
|
|
CString sErrMsg;
|
|
if(SUCCEEDED(hrTemp = _pDbgLog->GetLoggedMsgs(0, sErrMsg)))
|
|
{
|
|
hrTemp = sErrMsg.Append(L"Error in file download while checking for required update. Cannot continue.");
|
|
if(SUCCEEDED(hrTemp))
|
|
{
|
|
ShowError(sErrMsg._pwz);
|
|
_hr = E_ABORT;
|
|
}
|
|
}
|
|
}
|
|
goto exit;
|
|
}
|
|
|
|
IF_FAILED_EXIT(HandlePlatformCheckResult());
|
|
|
|
SAFERELEASE(pCacheImport);
|
|
// either no required update needed, or another version have been completely downloaded at this time...
|
|
// BUGBUG: Determine if abort done by our bindsink when no required update - thus no need to re-create cache import.
|
|
// get cache dir again to ensure running the highest version
|
|
IF_FAILED_EXIT(CreateAssemblyCacheImport(&pCacheImport, _pAsmId, CACHEIMP_CREATE_RESOLVE_REF));
|
|
|
|
if (_hr == S_FALSE)
|
|
{
|
|
// should never happen, at least 1 was found before
|
|
Msg(L"No completed cached version found. Possible cache corruption. Cannot continue.");
|
|
_hr = E_ABORT;
|
|
goto exit;
|
|
}
|
|
}
|
|
else
|
|
// if _hr == error, ignore
|
|
_hr = S_OK;
|
|
}
|
|
|
|
// Case 2, cached copy (of the referenced version) not exist
|
|
else if (_hr == S_FALSE)
|
|
{
|
|
LPASSEMBLY_DOWNLOAD pAsmDownload = NULL;
|
|
|
|
// BUGBUG?: what if it is not a partial ref but there's actually another version installed?
|
|
|
|
if (_pwzCodebase == NULL)
|
|
{
|
|
Msg(L"No completed cached version of this application found and this manifest cannot be used to initiate an install. Cannot continue.");
|
|
_hr = E_FAIL;
|
|
goto exit;
|
|
}
|
|
|
|
// create temp file name
|
|
IF_FAILED_EXIT(CreateTempFile(L"DMA", ppwzDesktopManifestPathName)); // desktop manifest file
|
|
|
|
_bIs1stTimeInstall = TRUE;
|
|
|
|
// check policy before download
|
|
IF_FAILED_EXIT(CheckZonePolicy(_pwzCodebase));
|
|
|
|
#ifdef DEVMODE
|
|
IF_FAILED_EXIT(CreateAssemblyDownload(&pAsmDownload, _pDbgLog, (_bIsDevMode ? DOWNLOAD_DEVMODE : 0)));
|
|
#else
|
|
IF_FAILED_EXIT(CreateAssemblyDownload(&pAsmDownload, _pDbgLog, 0));
|
|
#endif
|
|
|
|
// should generate the desktop manifest file if 1st time install (from mimehandler or not)
|
|
// or even if it subsequently fails
|
|
// ignore error
|
|
_hrManEmit=CreateAssemblyManifestEmit(&_pManEmit, *ppwzDesktopManifestPathName, MANIFEST_TYPE_DESKTOP);
|
|
|
|
// BUGBUG: UGLY - _pManImport & _sWebManifestURL._pwz are needed only for desktop manifest stuff.
|
|
// ???
|
|
// This should be cleaned up once assemblydownload is restructured.
|
|
// (see checks for "_sWebManifestURL._cc != 0 && dwManifestType == MANIFEST_TYPE_SUBSCRIPTION")
|
|
if (_sWebManifestURL._cc != 0 && _dwManifestType == MANIFEST_TYPE_SUBSCRIPTION && _pManEmit)
|
|
{
|
|
// export dependency/dependentassembly/assemblyIdentity & subscription
|
|
|
|
// ignore failure
|
|
_hrManEmit = _pManEmit->SetDependencySubscription(_pManImport, _sWebManifestURL._pwz);
|
|
}
|
|
|
|
//BUGBUG: need ref def matching checks for desktop->subscription->app manifests' ids
|
|
|
|
// (synchronous & ui & bindsink) download from codebase
|
|
_hr=pAsmDownload->DownloadManifestAndDependencies(_pwzCodebase, this, DOWNLOAD_FLAGS_PROGRESS_UI | DOWNLOAD_FLAGS_NOTIFY_BINDSINK);
|
|
pAsmDownload->Release();
|
|
if (_pManEmit)
|
|
{
|
|
// write out desktop manifest
|
|
_hrManEmit = _pManEmit->Commit();
|
|
SAFERELEASE(_pManEmit);
|
|
}
|
|
|
|
// hr from DownloadManifestAndDependencies() above
|
|
if (FAILED(_hr))
|
|
{
|
|
if (_hr == E_ABORT)
|
|
{
|
|
// Msg(L"File download canceled.");
|
|
}
|
|
else
|
|
{
|
|
HRESULT hrTemp;
|
|
CString sErrMsg;
|
|
if(SUCCEEDED(hrTemp = _pDbgLog->GetLoggedMsgs(0, sErrMsg)))
|
|
{
|
|
hrTemp = sErrMsg.Append(L"Error in file download. Cannot continue.");
|
|
if(SUCCEEDED(hrTemp))
|
|
{
|
|
ShowError(sErrMsg._pwz);
|
|
_hr = E_ABORT;
|
|
}
|
|
}
|
|
}
|
|
goto exit;
|
|
}
|
|
|
|
IF_FAILED_EXIT(HandlePlatformCheckResult());
|
|
|
|
// another version might have been completed at this time...
|
|
// get cache dir again to ensure running the highest version
|
|
IF_FAILED_EXIT(CreateAssemblyCacheImport(&pCacheImport, _pAsmId, CACHEIMP_CREATE_RESOLVE_REF));
|
|
|
|
if (_hr == S_FALSE)
|
|
{
|
|
Msg(L"No completed cached version found. Possible error in download cache commit. Cannot continue.");
|
|
_hr = E_ABORT;
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
IF_FAILED_EXIT(pCacheImport->GetManifestFileDir(&_pwzAppRootDir, &dwCC));
|
|
IF_FALSE_EXIT(dwCC >= sizeof("c:\\"), E_FAIL); // this should never happen
|
|
|
|
IF_FAILED_EXIT(pCacheImport->GetManifestFilePath(&_pwzAppManifestPath, &dwCC));
|
|
|
|
exit:
|
|
SAFERELEASE(pCacheImport);
|
|
|
|
if (FAILED(_hr))
|
|
{
|
|
SAFEDELETEARRAY(_pwzAppRootDir);
|
|
SAFEDELETEARRAY(_pwzAppManifestPath);
|
|
}
|
|
|
|
return _hr;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
HRESULT CActivator::HandlePlatformCheckResult()
|
|
{
|
|
if (_dwMissingPlatform > 0)
|
|
{
|
|
// L"Single link: <a href=\"http://foo\" id=\"id1\">link</a>"
|
|
DWORD dwReturn = 0;
|
|
CString sText;
|
|
|
|
IF_FAILED_EXIT(sText.Assign(L"The required version of "));
|
|
IF_FAILED_EXIT(sText.Append((_ptPlatform[0]).pwzName));
|
|
IF_FAILED_EXIT(sText.Append(L" is not available on this system.\n\nMore information about this platform can be found at \n<a href=\""));
|
|
IF_FAILED_EXIT(sText.Append((_ptPlatform[0]).pwzURL));
|
|
IF_FAILED_EXIT(sText.Append(L"\">"));
|
|
IF_FAILED_EXIT(sText.Append((_ptPlatform[0]).pwzURL));
|
|
IF_FAILED_EXIT(sText.Append(L"</a>"));
|
|
|
|
IF_FAILED_EXIT(ShowDialog(NULL, IDD_LINKDIALOG, sText._pwz, L"Platform Update Required", dwReturn));
|
|
_hr = E_ABORT;
|
|
goto exit;
|
|
}
|
|
else
|
|
_hr = S_OK;
|
|
exit:
|
|
return _hr;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// BUGBUG: this should be in-sync with what server does to register update
|
|
#define REG_KEY_FUSION_SETTINGS L"Software\\Microsoft\\Fusion\\Installer\\1.0.0.0\\Policy"
|
|
|
|
#define REG_VAL_INTRANET_DISALLOW L"Download from Intranet Disallowed"
|
|
#define REG_VAL_TRUSTED_DISALLOW L"Download from Trusted Zone Disallowed"
|
|
#define REG_VAL_INTERNET_DISALLOW L"Download from Internet Disallowed"
|
|
#define REG_VAL_UNTRUSTED_DISALLOW L"Download from Untrusted Zone Disallowed"
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// CActivator::CheckZonePolicy
|
|
// return: S_OK for yes/ok, E_ABORT for no/abort
|
|
// default is allow all
|
|
// ---------------------------------------------------------------------------
|
|
HRESULT CActivator::CheckZonePolicy(LPWSTR pwzURL)
|
|
{
|
|
DWORD dwZone = 0;
|
|
DWORD dwType = 0;
|
|
DWORD dwValue = -1;
|
|
DWORD dwSize = sizeof(dwValue);
|
|
|
|
if (_pSecurityMgr == NULL)
|
|
{
|
|
// lazy init.
|
|
_hr = CoCreateInstance(CLSID_InternetSecurityManager, NULL, CLSCTX_INPROC_SERVER,
|
|
IID_IInternetSecurityManager, (void**)&_pSecurityMgr);
|
|
if (FAILED(_hr))
|
|
_pSecurityMgr = NULL;
|
|
IF_FAILED_EXIT(_hr);
|
|
}
|
|
|
|
IF_FAILED_EXIT(_pSecurityMgr->MapUrlToZone(pwzURL, &dwZone, 0));
|
|
|
|
// BUGBUG: hack up code here... not much error checking...
|
|
switch(dwZone)
|
|
{
|
|
case 1: // Intranet Zone
|
|
// Get registry entry
|
|
if (GetRegKeyValue(HKEY_CURRENT_USER,
|
|
REG_KEY_FUSION_SETTINGS, REG_VAL_INTRANET_DISALLOW,
|
|
&dwType, (PBYTE) &dwValue, &dwSize)
|
|
== ERROR_SUCCESS)
|
|
{
|
|
if (dwValue == 1)
|
|
{
|
|
_hr = E_ABORT;
|
|
Msg(L"Zone policy: Download from Intranet is disallowed. Aborting...");
|
|
}
|
|
}
|
|
break;
|
|
case 2: // Trusted Zone
|
|
// Get registry entry
|
|
if (GetRegKeyValue(HKEY_CURRENT_USER,
|
|
REG_KEY_FUSION_SETTINGS, REG_VAL_TRUSTED_DISALLOW,
|
|
&dwType, (PBYTE) &dwValue, &dwSize)
|
|
== ERROR_SUCCESS)
|
|
{
|
|
if (dwValue == 1)
|
|
{
|
|
_hr = E_ABORT;
|
|
Msg(L"Zone policy: Download from Trusted Zone is disallowed. Aborting...");
|
|
}
|
|
}
|
|
break;
|
|
case 3: // Internet Zone
|
|
// Get registry entry
|
|
if (GetRegKeyValue(HKEY_CURRENT_USER,
|
|
REG_KEY_FUSION_SETTINGS, REG_VAL_INTERNET_DISALLOW,
|
|
&dwType, (PBYTE) &dwValue, &dwSize)
|
|
== ERROR_SUCCESS)
|
|
{
|
|
if (dwValue == 1)
|
|
{
|
|
_hr = E_ABORT;
|
|
Msg(L"Zone policy: Download from Internet is disallowed. Aborting...");
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
case 4: // Untrusted Zone
|
|
// Get registry entry
|
|
if (GetRegKeyValue(HKEY_CURRENT_USER,
|
|
REG_KEY_FUSION_SETTINGS, REG_VAL_UNTRUSTED_DISALLOW,
|
|
&dwType, (PBYTE) &dwValue, &dwSize)
|
|
== ERROR_SUCCESS)
|
|
{
|
|
if (dwValue == 1)
|
|
{
|
|
_hr = E_ABORT;
|
|
Msg(L"Zone policy: Download from Untrusted Zone is disallowed. Aborting...");
|
|
}
|
|
}
|
|
break;
|
|
case 0: //Local machine
|
|
break;
|
|
}
|
|
|
|
exit:
|
|
return _hr;
|
|
}
|
|
|