winamp/Src/omBrowser/storageDwnld.cpp

395 lines
8.3 KiB
C++

#include "main.h"
#include "./storageDwnld.h"
#include "./ifc_omwebstorage.h"
#include "./ifc_wasabihelper.h"
#include "./ifc_omservicehost.h"
#include "..\Components\wac_network\wac_network_http_receiver_api.h"
OmStorageDwnld::OmStorageDwnld(api_downloadManager *downloadManager, BOOL enableCompression)
: ref(1), userCallback(NULL), userData(NULL), completed(NULL), flags(0),
opState(stateInitializing), resultCode(api_downloadManager::TICK_SUCCESS),
cookie(NULL), manager(downloadManager), serviceHost(NULL)
{
if (NULL != manager)
manager->AddRef();
if (FALSE != enableCompression)
flags |= flagEnableCompression;
InitializeCriticalSection(&lock);
}
OmStorageDwnld::~OmStorageDwnld()
{
EnterCriticalSection(&lock);
if (NULL != manager)
{
if (NULL != cookie)
{
manager->ReleaseDownload(cookie);
cookie = NULL;
}
manager->Release();
manager = NULL;
}
if (NULL != completed)
{
CloseHandle(completed);
completed = NULL;
}
if (NULL != serviceHost)
{
serviceHost->Release();
serviceHost = NULL;
}
LeaveCriticalSection(&lock);
DeleteCriticalSection(&lock);
}
HRESULT OmStorageDwnld::CreateInstance(api_downloadManager *downloadManager, BOOL enableCompression, OmStorageDwnld **instance)
{
if (NULL == instance) return E_POINTER;
*instance = NULL;
if (NULL == downloadManager)
return E_INVALIDARG;
*instance = new OmStorageDwnld(downloadManager, enableCompression);
if (NULL == *instance) return E_OUTOFMEMORY;
return S_OK;
}
size_t OmStorageDwnld::AddRef()
{
return InterlockedIncrement((LONG*)&ref);
}
size_t OmStorageDwnld::Release()
{
if (0 == ref)
return ref;
LONG r = InterlockedDecrement((LONG*)&ref);
if (0 == r)
delete(this);
return r;
}
int OmStorageDwnld::QueryInterface(GUID interface_guid, void **object)
{
if (NULL == object) return E_POINTER;
if (IsEqualIID(interface_guid, IFC_OmStorageAsync))
*object = static_cast<ifc_omstorageasync*>(this);
else
{
*object = NULL;
return E_NOINTERFACE;
}
if (NULL == *object)
return E_UNEXPECTED;
AddRef();
return S_OK;
}
HRESULT OmStorageDwnld::GetState(UINT *state)
{
if (NULL == state)
return E_POINTER;
EnterCriticalSection(&lock);
*state = opState;
LeaveCriticalSection(&lock);
return S_OK;
}
HRESULT OmStorageDwnld::GetWaitHandle(HANDLE *handle)
{
if (NULL == handle)
return E_POINTER;
HRESULT hr = S_OK;
EnterCriticalSection(&lock);
if (NULL == completed)
{
completed = CreateEvent(NULL, TRUE, FALSE, NULL);
if (NULL == completed)
{
*handle = NULL;
DWORD error = GetLastError();
hr = HRESULT_FROM_WIN32(error);
}
}
if (SUCCEEDED(hr) && FALSE == DuplicateHandle(GetCurrentProcess(), completed,
GetCurrentProcess(), handle, 0, FALSE, DUPLICATE_SAME_ACCESS))
{
*handle = NULL;
DWORD error = GetLastError();
hr = HRESULT_FROM_WIN32(error);
}
LeaveCriticalSection(&lock);
return hr;
}
HRESULT OmStorageDwnld::GetData(void **data)
{
if (NULL == data)
return E_POINTER;
EnterCriticalSection(&lock);
*data = userData;
LeaveCriticalSection(&lock);
return S_OK;
}
HRESULT OmStorageDwnld::GetCallback(AsyncCallback *callback)
{
if (NULL == callback)
return E_POINTER;
EnterCriticalSection(&lock);
*callback = userCallback;
LeaveCriticalSection(&lock);
return S_OK;
}
void OmStorageDwnld::OnInit(DownloadToken token)
{
EnterCriticalSection(&lock);
AddRef();
cookie = token;
opState = stateConnecting;
if (NULL != manager)
{
manager->RetainDownload(cookie);
if (0 != (flagEnableCompression & flags))
{
api_httpreceiver *receiver = manager->GetReceiver(token);
if (NULL != receiver)
receiver->AllowCompression();
}
}
LeaveCriticalSection(&lock);
}
void OmStorageDwnld::OnConnect(DownloadToken token)
{
EnterCriticalSection(&lock);
opState = stateReceiving;
LeaveCriticalSection(&lock);
}
void OmStorageDwnld::OnTick(DownloadToken token)
{
EnterCriticalSection(&lock);
if (stateConnecting == opState)
opState = stateReceiving;
LeaveCriticalSection(&lock);
}
void OmStorageDwnld::OnFinish(DownloadToken token)
{
DownloadCompleted(api_downloadManager::TICK_SUCCESS);
}
void OmStorageDwnld::OnError(DownloadToken token, int errorCode)
{
DownloadCompleted(errorCode);
}
void OmStorageDwnld::OnCancel(DownloadToken token)
{
DownloadCompleted(api_downloadManager::TICK_NODATA);
}
void OmStorageDwnld::DownloadCompleted( INT errorCode )
{
EnterCriticalSection( &lock );
resultCode = errorCode;
opState = stateCompleted;
HANDLE event = completed;
LeaveCriticalSection( &lock );
if ( NULL != event )
{
SetEvent( event );
}
EnterCriticalSection( &lock );
AsyncCallback cb = userCallback;
LeaveCriticalSection( &lock );
if ( NULL != cb )
{
cb( this );
}
Release();
}
HRESULT OmStorageDwnld::SetData(void *data)
{
EnterCriticalSection(&lock);
userData = data;
LeaveCriticalSection(&lock);
return S_OK;
}
HRESULT OmStorageDwnld::SetCallback(AsyncCallback callback)
{
EnterCriticalSection(&lock);
userCallback = callback;
LeaveCriticalSection(&lock);
return S_OK;
}
HRESULT OmStorageDwnld::GetResultCode()
{
EnterCriticalSection(&lock);
HRESULT hr;
if (NULL == cookie || NULL == manager)
{
hr = E_UNEXPECTED;
}
else
{
switch(resultCode)
{
case api_downloadManager::TICK_SUCCESS: hr = E_DWNLD_OK; break;
case api_downloadManager::TICK_FAILURE: hr = (0 != (flagUserAbort & flags)) ? E_DWNLD_ABORT : E_DWNLD_FAIL; break;
case api_downloadManager::TICK_TIMEOUT: hr = E_DWNLD_TIMEOUT; break;
case api_downloadManager::TICK_CANT_CONNECT: hr = E_DWNLD_CANT_CONNECT; break;
case api_downloadManager::TICK_WRITE_ERROR: hr = E_DWNLD_WRITE_ERROR; break;
default: hr = E_DWNLD_BUSY; break;
}
}
LeaveCriticalSection(&lock);
return hr;
}
HRESULT OmStorageDwnld::GetBuffer(void **buffer, size_t *bufferSize)
{
if (NULL == buffer) return E_POINTER;
EnterCriticalSection(&lock);
HRESULT hr = GetResultCode();
if (SUCCEEDED(hr) && 0 != manager->GetBuffer(cookie, buffer, bufferSize))
hr = E_DWNLD_FAIL;
LeaveCriticalSection(&lock);
if (FAILED(hr))
{
*buffer = NULL;
*bufferSize = 0;
}
return hr;
}
HRESULT OmStorageDwnld::RequestAbort(BOOL fDrop)
{
EnterCriticalSection(&lock);
if (FALSE != fDrop)
{
userData = NULL;
userCallback = NULL;
}
if (NULL != cookie && NULL != manager)
{
opState = stateAborting;
flags |= flagUserAbort;
manager->CancelDownload(cookie);
}
LeaveCriticalSection(&lock);
return S_OK;
}
HRESULT OmStorageDwnld::SetServiceHost(ifc_omservicehost *host)
{
EnterCriticalSection(&lock);
if (NULL != serviceHost)
serviceHost->Release();
serviceHost = host;
if (NULL != serviceHost)
serviceHost->AddRef();
LeaveCriticalSection(&lock);
return S_OK;
}
HRESULT OmStorageDwnld::GetServiceHost(ifc_omservicehost **host)
{
if (NULL == host)
return E_POINTER;
EnterCriticalSection(&lock);
*host = serviceHost;
if (NULL != serviceHost)
serviceHost->AddRef();
LeaveCriticalSection(&lock);
return S_OK;
}
#define CBCLASS OmStorageDwnld
START_MULTIPATCH;
START_PATCH(MPIID_OMSTORAGEASYNC)
M_CB(MPIID_OMSTORAGEASYNC, ifc_omstorageasync, ADDREF, AddRef);
M_CB(MPIID_OMSTORAGEASYNC, ifc_omstorageasync, RELEASE, Release);
M_CB(MPIID_OMSTORAGEASYNC, ifc_omstorageasync, QUERYINTERFACE, QueryInterface);
M_CB(MPIID_OMSTORAGEASYNC, ifc_omstorageasync, API_GETSTATE, GetState);
M_CB(MPIID_OMSTORAGEASYNC, ifc_omstorageasync, API_GETWAITHANDLE, GetWaitHandle);
M_CB(MPIID_OMSTORAGEASYNC, ifc_omstorageasync, API_GETDATA, GetData);
NEXT_PATCH(MPIID_DOWNLOADCALLBACK)
M_CB(MPIID_DOWNLOADCALLBACK, ifc_downloadManagerCallback, ADDREF, AddRef);
M_CB(MPIID_DOWNLOADCALLBACK, ifc_downloadManagerCallback, RELEASE, Release);
M_CB(MPIID_DOWNLOADCALLBACK, ifc_downloadManagerCallback, QUERYINTERFACE, QueryInterface);
M_VCB(MPIID_DOWNLOADCALLBACK, ifc_downloadManagerCallback, IFC_DOWNLOADMANAGERCALLBACK_ONFINISH, OnFinish);
M_VCB(MPIID_DOWNLOADCALLBACK, ifc_downloadManagerCallback, IFC_DOWNLOADMANAGERCALLBACK_ONTICK, OnTick);
M_VCB(MPIID_DOWNLOADCALLBACK, ifc_downloadManagerCallback, IFC_DOWNLOADMANAGERCALLBACK_ONERROR, OnError);
M_VCB(MPIID_DOWNLOADCALLBACK, ifc_downloadManagerCallback, IFC_DOWNLOADMANAGERCALLBACK_ONCANCEL, OnCancel);
M_VCB(MPIID_DOWNLOADCALLBACK, ifc_downloadManagerCallback, IFC_DOWNLOADMANAGERCALLBACK_ONCONNECT, OnConnect);
M_VCB(MPIID_DOWNLOADCALLBACK, ifc_downloadManagerCallback, IFC_DOWNLOADMANAGERCALLBACK_ONINIT, OnInit);
END_PATCH
END_MULTIPATCH;
#undef CBCLASS