Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

627 lines
18 KiB

// BSCB.cpp -- Implementation for the CBindStatusCallBack class
#include "stdafx.h"
HRESULT STDMETHODCALLTYPE CBindStatusCallBack::CreateHook(IBindCtx pBC, IMoniker pMK)
{
CBindStatusCallBack *pBSCB = New CBindStatusCallBack(NULL);
IBindStatusCallback *pCallBack = NULL;
HRESULT hr = FinishSetup(pBSCB? pBSCB->m_Implementation.Init(pBC, pMK)
: STG_E_INSUFFICIENTMEMORY,
pBSCB, IID_IBindStatusCallback, (PPVOID) &pCallBack
);
if (pCallBack) pCallBack->Release();
}
CBindStatusCallBack::Implementation::Implementation
(CBindStatusCallBack *pBackObj, IUnknown *punkOuter)
: ITBindStatusCallback(pBackObj, punkOuter)
{
m_pBCHooked = NULL;
m_pBSCBClient = NULL;
m_pStream = NULL;
m_grfBINDF = 0;
m_awcsFile[0] = 0;
m_fTempFile = FALSE;
m_bindinfo.cbSize = sizeof(BINDINFO);
}
CBindStatusCallBack::Implementation::~Implementation()
{
if (m_pStream) m_pStream->Release();
if (m_fTempFile)
{
RonM_ASSERT(m_awcsFile[0]);
UINT cwc = wcsLen(m_awcsFile) + 1;
UINT cb = cwc * sizeof(WCHAR);
char *pszFile = PCHAR(_alloca(cb));
RonM_ASSERT(pszFile);
if (pchr)
{
UINT c = WideCharToMultiByte(GetACP(), WC_COMPOSITECHECK, m_awcsFile, cwc,
pszFile, cb, NULL, NULL
);
RonM_ASSERT(c);
if (c) DeleteFile(pszFile);
}
}
if (m_pBC)
RevokeBindStatusCallback(m_pBC, this);
if (m_pBSCBClient) m_pBSCBClient->Release();
}
HRESULT STDMETHODCALLTYPE CBindStatusCallBack::Implementation::Init(IBindCtx pBC, IMoniker pMK)
{
RonM_ASSERT(pBC);
RonM_ASSERT(pMK);
if (!SUCCEEDED(hr)) return hr;
HRESULT hr = pMK->BindToStorage(pBC, NULL, IID_IStream, (PPVOID) &pStrm1);
if (!SUCCEEDED(hr)) return hr;
IUnknown *pUnk = NULL;
hr = pBC->GetObjectParam(L"_BSCB_HOLDER_", &pUnk);
if (!SUCCEEDED(hr)) return hr;
hr = pUnk->QueryInterface(IID_IBindStatusCallback, &m_pBSCBClient);
pUnk->Release();
if (!SUCCEEDED(hr)) return hr;
hr = RegisterBindStatusCallback(pBC, this, &m_pBSCBClient, 0);
if (!SUCCEEDED(hr)) return hr;
m_pBC = pBC;
m_pBC->AddRef();
RonM_ASSERT(statstg.cbSize.HighPart == 0);
m_pBSCBClient->GetBindInfo(&m_grfBINDF, &m_bindinfo);
if (!SUCCEEDED(hr)) return hr;
IStream *pStrmITS = NULL;
hr = GetStreamFromMoniker(pBC, pMK, m_grfBINDF, m_awcsFile, &m_pStream);
if (hr == S_FALSE) m_fTempFile = TRUE;
if (!SUCCEEDED(hr)) return hr;
STATSTG statstg;
hr = m_pStream->Stat(&statstg, STATFLAG_NONAME);
if (!SUCCEEDED(hr)) return hr;
hr = m_pBSCBClient->OnProgress(0, statstg.cbSize.LowPart,
BINDSTATUS_SENDINGREQUEST, L""
);
if (!SUCCEEDED(hr)) return hr;
hr = m_pBSCBClient->OnProgress(0, statstg.cbSize.LowPart,
BINDSTATUS_BEGINDOWNLOADDATA, L""
);
if (!SUCCEEDED(hr)) return hr;
if (m_awcsFile[0])
{
hr = m_pBSCBClient->OnProgress(0, statstg.cbSize.LowPart,
BINDSTATUS_CACHEFILENAMEAVAILABLE, m_awcsFile
);
if (!SUCCEEDED(hr)) return hr;
}
hr = m_pBSCBClient->OnProgress(0, statstg.cbSize.LowPart,
BINDSTATUS_DOWNLOADINGDATA, L""
);
if (!SUCCEEDED(hr)) return hr;
hr = m_pBSCBClient->OnProgress(statstg.cbSize.LowPart, statstg.cbSize.LowPart,
ENDDOWNLOADDATA, L""
);
if (!SUCCEEDED(hr)) return hr;
FORMATETC fmetc;
STGMEDIUM stgmed;
hr = m_pBSCBClient->OnDataAvailable(BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION
| BSCF_DATAFULLYAVAILABLE,
statstg.cbSize.LowPart,
FORMATETC *pfmtetc,
STGMEDIUM *pstgmed
);
return hr;
}
HRESULT STDMETHODCALLTYPE CopyStreamToFile(IStream *ppStreamSrc, const WCHAR *pwcsFilePath)
{
IStream *pStream;
IStream *pStreamSrc = *ppStreamSrc;
IFSStorage *pFSS = NULL;
HRESULT hr = CFileSystemStorage::Create(NULL, IID_IFSStorage, (VOID **) &pFSS);
if (!SUCCEEDED(hr)) return hr;
hr = pFSS->FSOpenStream((const WCHAR *) pwcsFilePath,
STGM_READWRITE | STGM_SHARE_DENY_NONE,
&pStream
);
pFSS->Release();
if (!SUCCEEDED(hr)) return hr;
RonM_ASSERT(pStreamSrc);
STATSTG statstg;
hr = pStreamSrc->Stat(&statstg, STATFLAG_NONAME);
if (!SUCCEEDED(hr)) return hr;
#ifdef _DEBUG
hr =
#endif // _DEBUG
pStreamSrc->Seek(CLINT(0).Li(), STREAM_SEEK_SET, NULL);
RonM_ASSERT(hr == S_OK);
hr = pStreamSrc->CopyTo(pStream, statstg.cbSize, NULL, NULL);
pStream->Release();
if (!SUCCEEDED(hr)) return hr;
#ifdef _DEBUG
hr =
#endif // _DEBUG
pStream->Seek(CLINT(0).Li(), STREAM_SEEK_SET, NULL);
#ifdef _DEBUG
hr =
#endif // _DEBUG
pStreamSrc->Seek(CLINT(0).Li(), STREAM_SEEK_SET, NULL);
RonM_ASSERT(hr == S_OK);
*ppStreamSrc->Release();
*ppStreamSrc = pStream;
return hr;
}
HRESULT STDMETHODCALLTYPE GetStreamFromMoniker
(IBindCtx *pBC, IMoniker *pMK, DWORD grfBINDF, PSZ pwcsFile, IStream **ppStrm)
{
BOOL fNoFile = m_grfBINDF & (BINDF_PULLDATA | BINDF_DIRECT_READ);
BOOL fNoReadCache = m_grfBINDF & (BINDF_GETNEWESTVERSION | BINDF_NOWRITECACHE
| BINDF_PULLDATA
| BINDF_PRAGMA_NO_CACHE
| BINDF_DIRECT_READ
);
BOOL fNoWriteCache = m_grfBINDF & (BINDF_NOWRITECACHE | BINDF_PULLDATA
| BINDF_PRAGMA_NO_CACHE
| BINDF_DIRECT_READ
);
BOOL fTempFile = FALSE;
WCHAR *pwcsDisplayName = NULL;
char *pcsDisplayName = NULL;
WCHAR *pwcsExtension = NULL;
WCHAR *pwcsName = NULL;
IStream *pStrmITS = NULL;
HRESULT hr = pMK->GetDisplayName(pBCtx, NULL, &pwcsDisplayName);
if (!SUCCEEDED(hr)) return hr;
UINT cwc = wcsLen(pwcsDisplayName);
UINT cb = sizeof(WCHAR) * (cwc + 1);
*pcsDisplayName = PCHAR(_alloca(cb));
if (!pcsDisplayName)
{
hr = E_OUTOFMEMORY;
goto exit_GetStreamFromMoniker;
}
cb = WideCharToMultiByte(GetACP(), WC_COMPOSITECHECK, pwcsDisplayName, cwc + 1,
pcsDisplayName, cb, NULL, NULL
);
if (!cb)
{
hr = INET_E_DOWNLOAD_FAILURE;
goto exit_GetStreamFromMoniker;
}
{
UINT cwc = wcsLen(pwcsURL);
WCHAR *pwc = pwcsURL + cwc;
for (;;)
{
WCHAR wc = *--pwc;
if (wc == L'.')
pwcsExtension = pwc + 1;
if (wc == L':' || wc == L'/' || wc == L'\\')
{
pwcsName = ++pwc;
break;
}
RonM_ASSERT(--cwc);
}
}
hr = pMK->BindToStorage(pBC, NULL, IID_IStream, (VOID **) &pStrmITS);
if (!SUCCEEDED(hr)) goto exit_GetStreamFromMoniker;
STATSTG statstg;
hr = pStrmITS->Stat(&statstg, STATFLAG_NONAME);
if (!SUCCEEDED(hr)) goto exit_GetStreamFromMoniker;
FILETIME ftLastModified;
ftLastModified.dwLowDateTime = 0;
ftLastModified.dwHighDateTime = 0;
// pMK->GetTimeOfLastChange(pBCtx, NULL, &ftLastModified);
RonM_ASSERT(statstg.cbSize.HighPart == 0);
*pszFile = 0; // In case we don't get the stream into a file.
if (!fNoFile)
{
CHAR acsFilePath[MAX_PATH];
WCHAR awcsFilePath[MAX_PATH];
char szTempPath[MAX_PATH];
szTempPath[0] = 0;
PCHAR pcsExtension = "";
if (pwcsExtension && pwcsExtension[1])
{
UINT cwc = wcsLen(pwcsExtension);
UINT cb = sizeof(WCHAR) * (cwc + 1);
pcsExtension = PCHAR(_alloca(cb));
if (!pcsExtension)
{
hr = E_OUTOFMEMORY;
goto exit_GetStreamFromMoniker;
}
cb = WideCharToMultiByte(GetACP(), WC_COMPOSITECHECK, pwcsExtension, cwc + 1,
pcsExtension, cb, NULL, NULL
);
if (!cb)
{
hr = INET_E_DOWNLOAD_FAILURE;
goto exit_GetStreamFromMoniker;
}
}
if (fNoWriteCache)
{
DWORD cbPath= GetTempPath(MAX_PATH, szTempPath);
if (!cbPath)
lstrcpyA(szTempPath, ".\\");
char szPrefix[4] = "IMT"; // BugBug! May need to make this a random string.
char szFullPath[MAX_PATH];
if (!GetTempFileName(szTempPath, szPrefix, 0, szFullPath))
{
hr = CFSLockBytes::CImpILockBytes::STGErrorFromFSError(GetLastError());
szTempPath[0] = 0;
goto exit_GetStreamFromMoniker;
}
lstrcpyA(szTempPath, szFullPath);
char *pch = szTempPath + lstrlenA(szTempPath);
for (;;)
{
if (pch == szTempPath)
{
RonM_ASSERT(FALSE);
hr = E_UNEXPECTED;
DeleteFile(szTempPath);
szTempPath[0] = 0;
goto exit_GetStreamFromMoniker;
}
if ('.' == *--pch)
{
++pch;
break;
}
}
UINT cbExtension = lstrlenA(pcsExtension);
if (pch + cbExtension - szTempPath >= MAX_PATH)
{
hr = E_UNEXPECTED;
DeleteFile(szTempPath);
szTempPath[0] = 0;
goto exit_GetStreamFromMoniker;
}
CopyMemory(pch, pcsExtension, cbExtension + 1);
if (!MoveFileEx(szFullPath, szTempPath, MOVEFILE_REPLACE_EXISTING))
{
hr = E_UNEXPECTED;
DeleteFile(szFullPath);
szTempPath[0] = 0;
goto exit_GetStreamFromMoniker;
}
UINT cwc = MultiByteToWideChar(GetACP(), MB_PRECOMPOSED, szTempPath,
1 + lstrlenA(szTempPath), awcsFilePath, MAX_PATH
);
if (cwc)
hr = CopyStreamToFile(&pStrmITS, (const WCHAR *)awcsFilePath);
else hr = E_UNEXPECTED;
if (SUCCEEDED(hr))
{
fTempFile = TRUE;
CopyMemory(pwcsFile, awcsFilePath, cwc * sizeof(WCHAR));
}
else
{
DeleteFile(szTempPath);
goto exit_GetStreamFromMoniker;
}
}
else
{
DWORD dwCEISize = 0;
BOOL fResult = RetrieveUrlCacheEntryFile(pcsDisplayName, NULL, &dwCEISize, 0);
RonM_ASSERT(!fResult);
ULONG ulErr= GetLastError();
if (ulErr == ERROR_INSUFFICIENT_BUFFER)
{
INTERNET_CACHE_ENTRY_INFOA *pCEI = (INTERNET_CACHE_ENTRY_INFOA *) _alloca(dwCEISize);
if (!pCEI)
{
hr = E_OUTOFMEMORY;
goto exit_GetStreamFromMoniker;
}
pCEI->dwStructSize = sizeof(INTERNET_CACHE_ENTRY_INFOA);
fResult = RetrieveUrlCacheEntryFile(pcsDisplayName, pCEI, &dwCEISize, 0);
ulErr = GetLastError();
if (fResult)
if ( pCEI->LastModifiedTime.dwLowDateTime == ftLastModified.dwLowDateTime
&& pCEI->LastModifiedTime.dwHighDateTime == ftLastModified.dwHighDateTime
&& pCEI->dwSizeLow == statstg.cbSize.LowPart
&& pCEI->dwSizeHigh == statstg.cbSize.HighPart
)
{
lstrcpyA(acsFilePath, pCEI->lpszLocalFileName);
cwc = MultiByteToWideChar(GetACP(), MB_PRECOMPOSED,
acsFilePath, 1 + lstrlenA(acsFilePath),
awcsFilePath, MAX_PATH
);
RonM_ASSERT(cwc != 0);
}
else
{
UnlockUrlCacheEntryFile(pcsDisplayName, 0);
fResult = FALSE;
}
}
if (!fResult)
{
fResult = CreateUrlCacheEntryA(pcsDisplayName, statstg.cbSize.LowPart,
pcsExtension, acsFilePath, 0
);
if (!fResult)
{
hr = INET_E_CANNOT_INSTANTIATE_OBJECT;
goto exit_GetStreamFromMoniker;
}
cwc = MultiByteToWideChar(GetACP(), MB_PRECOMPOSED, acsFilePath,
1 + lstrlenA(acsFilePath), awcsFilePath, MAX_PATH
);
hr = CopyStreamToFile(&pStrmITS, (const WCHAR *) awcsFilePath);
if (!fResult)
{
hr = INET_E_CANNOT_INSTANTIATE_OBJECT;
goto exit_GetStreamFromMoniker;
}
FILETIME ftExpire;
ftExpire.dwLowDateTime = 0;
ftExpire.dwHighDateTime = 0;
fResult = CommitUrlCacheEntryA(pcsDisplayName, acsFilePath, ftExpire,
ftLastModified, NORMAL_CACHE_ENTRY, NULL,
0, pcsExtension, 0
);
if (!fResult)
{
ulErr= GetLastError();
hr = INET_E_CANNOT_INSTANTIATE_OBJECT;
goto exit_GetStreamFromMoniker;
}
fResult = RetrieveUrlCacheEntryFile(pcsDisplayName, NULL, &dwCEISize, 0);
RonM_ASSERT(!fResult);
ulErr= GetLastError();
if (ulErr == ERROR_INSUFFICIENT_BUFFER)
{
INTERNET_CACHE_ENTRY_INFOA *pCEI = (INTERNET_CACHE_ENTRY_INFOA *) _alloca(dwCEISize);
if (!pCEI)
{
hr = E_OUTOFMEMORY;
goto exit_GetStreamFromMoniker;
}
pCEI->dwStructSize = sizeof(INTERNET_CACHE_ENTRY_INFOA);
fResult = RetrieveUrlCacheEntryFile(pcsDisplayName, pCEI, &dwCEISize, 0);
if (!fResult)
{
ulErr= GetLastError();
hr = INET_E_CANNOT_INSTANTIATE_OBJECT;
goto exit_GetStreamFromMoniker;
}
}
}
}
}
if (SUCCEEDED(hr)) && awcsFilePath[0])
CopyMemory(pwcsFile, awcsFilePath, (wcsLen(awcsFilePath) + 1) * sizeof(WCHAR));
*ppStrm = pStrmITS; pStrmITS = NULL;
hr = fTempFile? S_FALSE : S_OK;
exit_GetStreamFromMoniker:
if (pStrmITS ) pStrmITS->Release();
if (pwcsDisplayName) OLEHeap()->Free(pwcsDisplayName);
return hr;
}
// IBindStatusCallback methods:
HRESULT STDMETHODCALLTYPE CBindStatusCallBack::Implementation::OnStartBinding(
/* [in] */ DWORD dwReserved,
/* [in] */ IBinding __RPC_FAR *pib)
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE CBindStatusCallBack::Implementation::GetPriority(
/* [out] */ LONG __RPC_FAR *pnPriority)
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE CBindStatusCallBack::Implementation::OnLowResource(
/* [in] */ DWORD reserved)
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE CBindStatusCallBack::Implementation::OnProgress(
/* [in] */ ULONG ulProgress,
/* [in] */ ULONG ulProgressMax,
/* [in] */ ULONG ulStatusCode,
/* [in] */ LPCWSTR szStatusText)
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE CBindStatusCallBack::Implementation::OnStopBinding(
/* [in] */ HRESULT hresult,
/* [unique][in] */ LPCWSTR szError)
{
return S_OK;
}
/* [local] */ HRESULT STDMETHODCALLTYPE CBindStatusCallBack::Implementation::GetBindInfo(
/* [out] */ DWORD __RPC_FAR *grfBINDF,
/* [unique][out][in] */ BINDINFO __RPC_FAR *pbindinfo)
{
return S_OK;
}
/* [local] */ HRESULT STDMETHODCALLTYPE CBindStatusCallBack::Implementation::OnDataAvailable(
/* [in] */ DWORD grfBSCF,
/* [in] */ DWORD dwSize,
/* [in] */ FORMATETC __RPC_FAR *pformatetc,
/* [in] */ STGMEDIUM __RPC_FAR *pstgmed)
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE CBindStatusCallBack::Implementation::OnObjectAvailable(
/* [in] */ REFIID riid,
/* [iid_is][in] */ IUnknown __RPC_FAR *punk)
{
return S_OK;
}