windows-nt/Source/XPSP1/NT/com/ole32/cs/csadmin/detect/cabfile.cxx

410 lines
13 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
#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;
}