410 lines
13 KiB
C++
410 lines
13 KiB
C++
#include "precomp.hxx"
|
|
|
|
#include "process.h"
|
|
#include "shellapi.h"
|
|
#include "urlmon.h"
|
|
|
|
class CBindStatusCallback : public IBindStatusCallback, public ICodeInstall
|
|
{
|
|
public:
|
|
// IUnknown methods
|
|
STDMETHODIMP QueryInterface(REFIID riid,void ** ppv);
|
|
STDMETHODIMP_(ULONG) AddRef();
|
|
STDMETHODIMP_(ULONG) Release();
|
|
|
|
// IBindStatusCallback methods
|
|
STDMETHODIMP OnStartBinding(DWORD grfBSCOption, IBinding* pbinding);
|
|
STDMETHODIMP GetPriority(LONG* pnPriority);
|
|
STDMETHODIMP OnLowResource(DWORD dwReserved);
|
|
STDMETHODIMP OnProgress(ULONG ulProgress,
|
|
ULONG ulProgressMax,
|
|
ULONG ulStatusCode,
|
|
LPCWSTR szStatusText);
|
|
|
|
STDMETHODIMP OnStopBinding(HRESULT hrResult, LPCWSTR szError);
|
|
STDMETHODIMP GetBindInfo(DWORD* pgrfBINDF, BINDINFO* pbindinfo);
|
|
STDMETHODIMP OnDataAvailable(DWORD grfBSCF, DWORD dwSize, FORMATETC *pfmtetc,
|
|
STGMEDIUM* pstgmed);
|
|
STDMETHODIMP OnObjectAvailable(REFIID riid, IUnknown* punk);
|
|
|
|
// ICodeInstall methods
|
|
STDMETHODIMP GetWindow(REFGUID guidReason, HWND * phwnd);
|
|
STDMETHODIMP OnCodeInstallProblem(ULONG ulStatusCode,
|
|
LPCWSTR szDestination,
|
|
LPCWSTR szSource,
|
|
DWORD dwReserved);
|
|
|
|
// constructors/destructors
|
|
CBindStatusCallback();
|
|
~CBindStatusCallback();
|
|
|
|
private:
|
|
IBindStatusCallback * m_pIBSC;
|
|
long _cRef;
|
|
HRESULT _hr;
|
|
};
|
|
|
|
extern HINSTANCE ghInstance;
|
|
|
|
#include "..\appmgr\resource.h"
|
|
|
|
HRESULT
|
|
CAB_FILE::InstallIntoRegistry( HKEY * RegistryKey)
|
|
{
|
|
// UNDONE - put in dialog box informing the user that we will
|
|
// install the cab file here.
|
|
#if 0
|
|
TCHAR szCaption[256];
|
|
TCHAR szBuffer[256];
|
|
::LoadString(ghInstance, IDS_CABCAPTION, szCaption, 256);
|
|
::LoadString(ghInstance, IDS_CABWARNING, szBuffer, 256);
|
|
int iReturn = ::MessageBox(NULL, szBuffer,
|
|
szCaption,
|
|
MB_YESNO);
|
|
if (iReturn == IDNO)
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
#endif
|
|
// Go ahead and install the cab file
|
|
IBindCtx *pBC=NULL;
|
|
|
|
//Synchronous call with bind context.
|
|
CBindStatusCallback *pCallback = new CBindStatusCallback();
|
|
if (!pCallback)
|
|
{
|
|
exit (-1);
|
|
}
|
|
HRESULT hr;
|
|
|
|
hr = CreateAsyncBindCtx(0, pCallback, NULL, &pBC);
|
|
|
|
|
|
char * szName = GetPackageName();
|
|
WCHAR wszName[_MAX_PATH];
|
|
MultiByteToWideChar(CP_ACP, 0, szName, -1, wszName, sizeof(wszName)/sizeof(wszName[0]));
|
|
|
|
IUnknown* punk=NULL;
|
|
#if 1
|
|
typedef HRESULT (STDAPICALLTYPE *PFNASYNCGETCLASSBITS)(
|
|
REFCLSID rclsid, // CLSID
|
|
LPCWSTR, LPCWSTR,
|
|
DWORD dwFileVersionMS, // CODE=http://foo#Version=a,b,c,d
|
|
DWORD dwFileVersionLS, // MAKEDWORD(c,b) of above
|
|
LPCWSTR szURL, // CODE= in INSERT tag
|
|
IBindCtx *pbc, // bind ctx
|
|
DWORD dwClsContext, // CLSCTX flags
|
|
LPVOID pvReserved, // Must be NULL
|
|
REFIID riid, // Usually IID_IClassFactory
|
|
DWORD flags);
|
|
|
|
PFNASYNCGETCLASSBITS pfnAsyncGetClassBits=NULL;
|
|
|
|
HINSTANCE hDll;
|
|
|
|
hDll = LoadLibraryEx("URLMON.DLL", NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
|
|
|
|
if (hDll != 0)
|
|
{
|
|
pfnAsyncGetClassBits = (PFNASYNCGETCLASSBITS)
|
|
GetProcAddress(hDll, "AsyncGetClassBits");
|
|
|
|
if (pfnAsyncGetClassBits == 0)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
|
|
IUnknown* punk=NULL;
|
|
hr=CoGetClassObjectFromURL (
|
|
IID_IUnknown,
|
|
wszName,
|
|
(DWORD) -1,(DWORD) -1, L"", pBC, CLSCTX_SERVER, NULL, IID_IUnknown, (void**) &punk);
|
|
if (punk)
|
|
{
|
|
punk->Release();
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
hr = (*pfnAsyncGetClassBits)(
|
|
IID_IUnknown, // bogus CLSID
|
|
NULL, NULL,
|
|
(DWORD) -1,(DWORD) -1, // don't care about version #
|
|
wszName, // URL/Path
|
|
pBC, // Bind context with IBSC
|
|
CLSCTX_SERVER,
|
|
NULL,
|
|
IID_IClassFactory,
|
|
1); // 1 == CD_FLAGS_FORCE_DOWNLOAD
|
|
}
|
|
FreeLibrary(hDll);
|
|
}
|
|
#else
|
|
hr=CoGetClassObjectFromURL (
|
|
IID_IUnknown,
|
|
wszName,
|
|
(DWORD) -1,(DWORD) -1, L"", pBC, CLSCTX_SERVER, NULL, IID_IUnknown, (void**) &punk);
|
|
if (punk)
|
|
{
|
|
punk->Release();
|
|
}
|
|
#endif
|
|
if (hr==MK_S_ASYNCHRONOUS)
|
|
{
|
|
MSG msg;
|
|
while (GetMessage(&msg, NULL, 0,0))
|
|
{
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
hr=msg.wParam;
|
|
}
|
|
|
|
if (hr==REGDB_E_CLASSNOTREG)
|
|
{
|
|
hr=S_OK; // Ignore instantiation error since we are asking for IID_IUnknown...
|
|
}
|
|
|
|
pCallback->Release();
|
|
pBC->Release();
|
|
|
|
// i = _spawnlp( P_WAIT,
|
|
// "cabinst.exe", // argument
|
|
// GetPackageName(), // argument
|
|
// 0 ); // argument
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
CAB_FILE::InitRegistryKeyToInstallInto(
|
|
HKEY * phKey )
|
|
{
|
|
return CreateMappedRegistryKey( phKey );
|
|
}
|
|
|
|
HRESULT
|
|
CAB_FILE::RestoreRegistryKey( HKEY * phKey)
|
|
{
|
|
return RestoreMappedRegistryKey( phKey);
|
|
}
|
|
|
|
HRESULT
|
|
CAB_FILE::DeleteTempKey(HKEY hKey, FILETIME ftLow, FILETIME ftHigh)
|
|
{
|
|
CleanMappedRegistryKey(hKey, ftLow, ftHigh);
|
|
return S_OK;
|
|
}
|
|
|
|
// ===========================================================================
|
|
// CBindStatusCallback Implementation
|
|
// ===========================================================================
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CBindStatusCallback::CBindStatusCallback
|
|
//
|
|
// Synopsis: Creates a bind status callback object.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
CBindStatusCallback::CBindStatusCallback()
|
|
: _cRef(1), _hr(MK_S_ASYNCHRONOUS)
|
|
{
|
|
CreateStdProgressIndicator(GetDesktopWindow(), NULL, NULL, &m_pIBSC);
|
|
}
|
|
|
|
CBindStatusCallback::~CBindStatusCallback()
|
|
{
|
|
m_pIBSC->Release();
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CBindStatusCallback::QueryInterface
|
|
//
|
|
// Synopsis: Gets an interface pointer to the bind status callback object.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CBindStatusCallback::QueryInterface(REFIID riid, void** ppv)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
*ppv = NULL;
|
|
|
|
if (IsEqualIID(riid, IID_IUnknown) ||
|
|
IsEqualIID(riid, IID_IBindStatusCallback))
|
|
{
|
|
AddRef();
|
|
*ppv = (IBindStatusCallback *) this;
|
|
}
|
|
else
|
|
if (IsEqualIID(riid, IID_ICodeInstall))
|
|
{
|
|
AddRef();
|
|
*ppv = (ICodeInstall *) this;
|
|
}
|
|
else
|
|
{
|
|
hr = E_NOINTERFACE;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CBindStatusCallback::AddRef
|
|
//
|
|
// Synopsis: Increments the reference count.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP_(ULONG)
|
|
CBindStatusCallback::AddRef()
|
|
{
|
|
InterlockedIncrement((long *) &_cRef);
|
|
return _cRef;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CBindStatusCallback::Release
|
|
//
|
|
// Synopsis: Decrements the reference count.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP_(ULONG)
|
|
CBindStatusCallback::Release()
|
|
{
|
|
LONG count = _cRef - 1;
|
|
|
|
if (0 == InterlockedDecrement((long *) &_cRef))
|
|
{
|
|
delete this;
|
|
count = 0;
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// %%Function: CBindStatusCallback::OnStartBinding
|
|
// ---------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CBindStatusCallback::OnStartBinding(DWORD grfBSCOption, IBinding* pbinding)
|
|
{
|
|
return m_pIBSC->OnStartBinding(grfBSCOption, pbinding);
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// %%Function: CBindStatusCallback::GetPriority
|
|
// ---------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CBindStatusCallback::GetPriority(LONG* pnPriority)
|
|
{
|
|
return m_pIBSC->GetPriority(pnPriority);
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// %%Function: CBindStatusCallback::OnLowResource
|
|
// ---------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CBindStatusCallback::OnLowResource(DWORD dwReserved)
|
|
{
|
|
return m_pIBSC->OnLowResource(dwReserved);
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// %%Function: CBindStatusCallback::OnStopBinding
|
|
// ---------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CBindStatusCallback::OnStopBinding(HRESULT hrStatus, LPCWSTR pszError)
|
|
{
|
|
_hr = hrStatus;
|
|
PostQuitMessage(hrStatus);
|
|
return m_pIBSC->OnStopBinding(hrStatus, pszError);
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// %%Function: CBindStatusCallback::GetBindInfo
|
|
// ---------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CBindStatusCallback::GetBindInfo(DWORD* pgrfBINDF, BINDINFO* pbindInfo)
|
|
{
|
|
return m_pIBSC->GetBindInfo(pgrfBINDF, pbindInfo);
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// %%Function: CBindStatusCallback::OnDataAvailable
|
|
// This function is called whenever data starts arriving. When the file download is
|
|
// complete then the BSCF_LASTDATANOTIFICATION comes and you can get the local cached
|
|
// File Name.
|
|
// ---------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CBindStatusCallback::OnDataAvailable
|
|
(
|
|
DWORD grfBSCF,
|
|
DWORD dwSize,
|
|
FORMATETC* pfmtetc,
|
|
STGMEDIUM* pstgmed
|
|
)
|
|
{
|
|
return m_pIBSC->OnDataAvailable(grfBSCF, dwSize, pfmtetc, pstgmed);
|
|
}
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// %%Function: CBindStatusCallback::OnObjectAvailable
|
|
// ---------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CBindStatusCallback::OnObjectAvailable(REFIID riid, IUnknown* punk)
|
|
{
|
|
return m_pIBSC->OnObjectAvailable(riid, punk);
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// %%Function: CBindStatusCallback::OnProgress
|
|
// ---------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CBindStatusCallback::OnProgress
|
|
(
|
|
ULONG ulProgress,
|
|
ULONG ulProgressMax,
|
|
ULONG ulStatusCode,
|
|
LPCWSTR pwszStatusText
|
|
)
|
|
{
|
|
return m_pIBSC->OnProgress(ulProgress, ulProgressMax, ulStatusCode, pwszStatusText);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CBindStatusCallback::GetWindow(REFGUID guidReason, HWND * phwnd)
|
|
{
|
|
*phwnd = GetDesktopWindow();
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CBindStatusCallback::OnCodeInstallProblem(ULONG ulStatusCode,
|
|
LPCWSTR szDestination,
|
|
LPCWSTR szSource,
|
|
DWORD dwReserved)
|
|
{
|
|
HRESULT hr = E_ABORT;
|
|
switch (ulStatusCode)
|
|
{
|
|
case CIP_OLDER_VERSION_EXISTS:
|
|
case CIP_NEWER_VERSION_EXISTS:
|
|
case CIP_NAME_CONFLICT:
|
|
case CIP_TRUST_VERIFICATION_COMPONENT_MISSING:
|
|
hr = S_OK;
|
|
break;
|
|
//case CIP_DRIVE_FULL:
|
|
case CIP_ACCESS_DENIED:
|
|
default:
|
|
break;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|