diff options
author | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
---|---|---|
committer | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
commit | 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch) | |
tree | 12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/Winamp/jnetcom.cpp | |
parent | 537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff) | |
download | winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz |
Initial community commit
Diffstat (limited to 'Src/Winamp/jnetcom.cpp')
-rw-r--r-- | Src/Winamp/jnetcom.cpp | 528 |
1 files changed, 528 insertions, 0 deletions
diff --git a/Src/Winamp/jnetcom.cpp b/Src/Winamp/jnetcom.cpp new file mode 100644 index 00000000..8a2f429b --- /dev/null +++ b/Src/Winamp/jnetcom.cpp @@ -0,0 +1,528 @@ +#include "jnetcom.h" +#include "../nu/AutoChar.h" +/* --- Jnetlib COM object --- */ +extern "C" extern HANDLE DuplicateCurrentThread(); + +JNetCOM::JNetCOM( IDispatch *_dispatch ) +{ + refCount = 1; + token = 0; + dispatch = _dispatch; + threadId = GetCurrentThreadId(); + threadHandle = DuplicateCurrentThread(); + retained = false; + + if ( NULL != dispatch ) + dispatch->AddRef(); +} + +JNetCOM::~JNetCOM() +{ + if ( retained ) + { + if ( NULL != WAC_API_DOWNLOADMANAGER ) + WAC_API_DOWNLOADMANAGER->ReleaseDownload( token ); + } + + CloseHandle( threadHandle ); + + if ( NULL != dispatch ) + dispatch->Release(); +} + +enum +{ + DISP_JNETCOM_ABORT, + DISP_JNETCOM_ADDHEADER, + DISP_JNETCOM_CONNECT, + DISP_JNETCOM_GETCONTENT, + DISP_JNETCOM_GETCONTENTASSTRING, + DISP_JNETCOM_GETERRORSTRING, + DISP_JNETCOM_GETHEADER, + DISP_JNETCOM_GETREPLY, + DISP_JNETCOM_GETREPLYCODE, + DISP_JNETCOM_GETURL, + DISP_JNETCOM_SETPOSTSTRING, +}; + +#define CHECK_ID(str, id)\ + if (CSTR_EQUAL == CompareStringW(lcid, NORM_IGNORECASE, rgszNames[i], -1, L##str, -1))\ + { rgdispid[i] = id; continue; } + +HRESULT JNetCOM::GetIDsOfNames( REFIID riid, OLECHAR FAR *FAR *rgszNames, unsigned int cNames, LCID lcid, DISPID FAR *rgdispid ) +{ + bool unknowns = false; + for ( unsigned int i = 0; i != cNames; i++ ) + { + CHECK_ID( "Abort", DISP_JNETCOM_ABORT ); + CHECK_ID( "AddHeader", DISP_JNETCOM_ADDHEADER ); + CHECK_ID( "Connect", DISP_JNETCOM_CONNECT ); + CHECK_ID( "GetContent", DISP_JNETCOM_GETCONTENT ); + CHECK_ID( "GetContentAsString", DISP_JNETCOM_GETCONTENTASSTRING ); + CHECK_ID( "GetErrorString", DISP_JNETCOM_GETERRORSTRING ); + CHECK_ID( "GetHeader", DISP_JNETCOM_GETHEADER ); + CHECK_ID( "GetReply", DISP_JNETCOM_GETREPLY ); + CHECK_ID( "GetReplyCode", DISP_JNETCOM_GETREPLYCODE ); + CHECK_ID( "GetURL", DISP_JNETCOM_GETURL ); + CHECK_ID( "SetPOSTString", DISP_JNETCOM_SETPOSTSTRING ); + + rgdispid[ i ] = DISPID_UNKNOWN; + unknowns = true; + } + + if ( unknowns ) + return DISP_E_UNKNOWNNAME; + else + return S_OK; +} + +HRESULT JNetCOM::GetTypeInfo( unsigned int itinfo, LCID lcid, ITypeInfo FAR *FAR *pptinfo ) +{ + return E_NOTIMPL; +} + +HRESULT JNetCOM::GetTypeInfoCount( unsigned int FAR *pctinfo ) +{ + return E_NOTIMPL; +} + +HRESULT JNetCOM::Invoke( DISPID dispid, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS FAR *pdispparams, VARIANT FAR *pvarResult, EXCEPINFO FAR *pexecinfo, unsigned int FAR *puArgErr ) +{ + switch ( dispid ) + { + case DISP_JNETCOM_ABORT: + return Abort(); + case DISP_JNETCOM_ADDHEADER: + return AddHeader( pdispparams->rgvarg[ 0 ].bstrVal ); + case DISP_JNETCOM_CONNECT: + if ( pdispparams->cArgs == 2 ) + return Connect( pdispparams->rgvarg[ 1 ].bstrVal, pdispparams->rgvarg[ 0 ].bstrVal ); + else + return Connect( pdispparams->rgvarg[ 0 ].bstrVal, L"GET" ); + case DISP_JNETCOM_GETCONTENT: + return GetContent( pvarResult ); + case DISP_JNETCOM_GETCONTENTASSTRING: + return GetContentAsString( pvarResult ); + case DISP_JNETCOM_GETERRORSTRING: + return GetErrorString( pvarResult ); + case DISP_JNETCOM_GETHEADER: + return GetHeader( pdispparams->rgvarg[ 0 ].bstrVal, pvarResult ); + case DISP_JNETCOM_GETREPLY: + return GetReply( pvarResult ); + case DISP_JNETCOM_GETREPLYCODE: + return GetReplyCode( pvarResult ); + case DISP_JNETCOM_GETURL: + return GetUrl( pvarResult ); + case DISP_JNETCOM_SETPOSTSTRING: + break; + } + + return DISP_E_MEMBERNOTFOUND; +} + + +STDMETHODIMP JNetCOM::QueryInterface( REFIID riid, PVOID *ppvObject ) +{ + if ( !ppvObject ) + return E_POINTER; + else if ( IsEqualIID( riid, IID_IDispatch ) ) + *ppvObject = (IDispatch *)this; + else if ( IsEqualIID( riid, IID_IUnknown ) ) + *ppvObject = this; + else + { + *ppvObject = NULL; + + return E_NOINTERFACE; + } + + AddRef(); + + return S_OK; +} + +ULONG JNetCOM::AddRef( void ) +{ + return InterlockedIncrement( &refCount ); +} + +ULONG JNetCOM::Release( void ) +{ + LONG lRef = InterlockedDecrement( &refCount ); + if ( lRef == 0 ) + delete this; + + return lRef; +} + +/* ---- */ +HRESULT JNetCOM::Abort() +{ + if ( NULL != WAC_API_DOWNLOADMANAGER ) + WAC_API_DOWNLOADMANAGER->CancelDownload( token ); + + return S_OK; +} + +HRESULT JNetCOM::AddHeader( LPCWSTR header ) +{ + if ( NULL == WAC_API_DOWNLOADMANAGER ) + return E_POINTER; + + api_httpreceiver *http = WAC_API_DOWNLOADMANAGER->GetReceiver( token ); + if ( http ) + http->addheader( AutoChar( header, CP_UTF8 ) ); + + return S_OK; +} + +HRESULT JNetCOM::Connect( LPCWSTR url, LPCWSTR requestMethod ) +{ + if ( NULL == WAC_API_DOWNLOADMANAGER ) + return E_POINTER; + + AddRef(); + + token = WAC_API_DOWNLOADMANAGER->DownloadEx( AutoChar( url, CP_UTF8 ), this, api_downloadManager::DOWNLOADEX_BUFFER ); + + return S_OK; +} + +HRESULT JNetCOM::GetContent( VARIANT *variant ) +{ + char dummy[ 1 ] = { 0 }; + size_t sourcelen = 0; + void *source = 0; + + if ( NULL == WAC_API_DOWNLOADMANAGER ) + return E_POINTER; + + WAC_API_DOWNLOADMANAGER->GetBuffer( token, &source, &sourcelen ); + + if ( !sourcelen || !source ) + { + source = dummy; + sourcelen = 1; + } + + SAFEARRAY *bufferArray = SafeArrayCreateVector( VT_UI1, 0, (ULONG)sourcelen ); + void *data; + SafeArrayAccessData( bufferArray, &data ); + memcpy( data, source, sourcelen ); + SafeArrayUnaccessData( bufferArray ); + VariantInit( variant ); + + V_VT( variant ) = VT_ARRAY | VT_UI1; + V_ARRAY( variant ) = bufferArray; + + return S_OK; +} + +HRESULT JNetCOM::GetContentAsString( VARIANT *variant ) +{ + // TODO: try to determine character encoding + size_t sourcelen = 0; + void *source = 0; + + if ( NULL == WAC_API_DOWNLOADMANAGER ) + return E_POINTER; + + if ( WAC_API_DOWNLOADMANAGER->GetBuffer( token, &source, &sourcelen ) == 0 ) + { + if ( source && sourcelen ) + { + int len = MultiByteToWideChar( CP_UTF8, 0, (LPCSTR)source, (int)sourcelen, 0, 0 ); + BSTR str = SysAllocStringLen( 0, len ); + + MultiByteToWideChar( CP_UTF8, 0, (LPCSTR)source, (int)sourcelen, str, len ); + + VariantInit( variant ); + + V_VT( variant ) = VT_BSTR; + V_BSTR( variant ) = str; + + return S_OK; + } + else + { + VariantInit( variant ); + + V_VT( variant ) = VT_BSTR; + V_BSTR( variant ) = SysAllocString( L"" ); + + return S_OK; + } + } + else + return E_FAIL; +} + +HRESULT JNetCOM::GetErrorString( VARIANT *variant ) +{ + const char *source = 0; + + if ( NULL == WAC_API_DOWNLOADMANAGER ) + return E_POINTER; + + api_httpreceiver *http = WAC_API_DOWNLOADMANAGER->GetReceiver( token ); + if ( http ) + source = http->geterrorstr(); + + if ( !source ) + source = ""; + + int sourcelen = (int)strlen( source ); + int len = MultiByteToWideChar( CP_ACP, 0, source, sourcelen, 0, 0 ); + BSTR str = SysAllocStringLen( 0, len ); + + MultiByteToWideChar( CP_ACP, 0, source, sourcelen, str, len ); + VariantInit( variant ); + + V_VT( variant ) = VT_BSTR; + V_BSTR( variant ) = str; + + return S_OK; +} + +HRESULT JNetCOM::GetHeader( LPCWSTR header, VARIANT *variant ) +{ + const char *source = 0; + + if ( NULL == WAC_API_DOWNLOADMANAGER ) + return E_POINTER; + + api_httpreceiver *http = WAC_API_DOWNLOADMANAGER->GetReceiver( token ); + if ( http ) + source = http->getheader( AutoChar( header, CP_UTF8 ) ); + + if ( !source ) + source = ""; + + int sourcelen = (int)strlen( source ); + int len = MultiByteToWideChar( CP_ACP, 0, source, sourcelen, 0, 0 ); + BSTR str = SysAllocStringLen( 0, len ); + + MultiByteToWideChar( CP_ACP, 0, source, sourcelen, str, len ); + VariantInit( variant ); + + V_VT( variant ) = VT_BSTR; + V_BSTR( variant ) = str; + + return S_OK; +} + + +HRESULT JNetCOM::GetReply( VARIANT *variant ) +{ + const char *source = 0; + + if ( NULL == WAC_API_DOWNLOADMANAGER ) + return E_POINTER; + + api_httpreceiver *http = WAC_API_DOWNLOADMANAGER->GetReceiver( token ); + if ( http ) + source = http->GetReply(); + + if ( !source ) + source = ""; + + int sourcelen = (int)strlen( source ); + int len = MultiByteToWideChar( CP_ACP, 0, source, sourcelen, 0, 0 ); + BSTR str = SysAllocStringLen( 0, len ); + + MultiByteToWideChar( CP_ACP, 0, source, sourcelen, str, len ); + VariantInit( variant ); + + V_VT( variant ) = VT_BSTR; + V_BSTR( variant ) = str; + + return S_OK; +} + +HRESULT JNetCOM::GetReplyCode( VARIANT *variant ) +{ + if ( NULL == WAC_API_DOWNLOADMANAGER ) + return E_POINTER; + + int code = 0; + api_httpreceiver *http = WAC_API_DOWNLOADMANAGER->GetReceiver( token ); + if ( http ) + code = http->getreplycode(); + + VariantInit( variant ); + + V_VT( variant ) = VT_UI4; + V_UI4( variant ) = code; + + return S_OK; +} + +HRESULT JNetCOM::GetUrl( VARIANT *variant ) +{ + if ( NULL == WAC_API_DOWNLOADMANAGER ) + return E_POINTER; + + const char *source = 0; + api_httpreceiver *http = WAC_API_DOWNLOADMANAGER->GetReceiver( token ); + if ( http ) + source = http->get_url(); + + if ( !source ) + source = ""; + + int sourcelen = (int)strlen( source ); + int len = MultiByteToWideChar( 1252, 0, source, sourcelen, 0, 0 ); + BSTR str = SysAllocStringLen( 0, len ); + + MultiByteToWideChar( 1252, 0, source, sourcelen, str, len ); + VariantInit( variant ); + + V_VT( variant ) = VT_BSTR; + V_BSTR( variant ) = str; + + return S_OK; +} + +extern void CallDispatchMethod( IDispatch *dispatch, DISPPARAMS ¶ms, OLECHAR *name ); + +struct APCWait +{ + IDispatch *dispatch; + HANDLE hEvent; +}; + +#define AutoAPC(name) \ + static VOID CALLBACK name ## APC(ULONG_PTR param) {\ + APCWait *wait = (APCWait *)param;\ +\ + DISPPARAMS params;\ + params.cArgs = 0;\ + params.cNamedArgs = 0;\ + params.rgdispidNamedArgs = 0;\ + params.rgvarg = 0;\ + if (wait->dispatch != NULL)\ + CallDispatchMethod(wait->dispatch, params, L ## #name);\ + if (wait->hEvent)\ + SetEvent(wait->hEvent);\ +} + +AutoAPC( OnFinish ); +AutoAPC( OnTick ); +AutoAPC( OnError ); +AutoAPC( OnCancel ); +AutoAPC( OnConnect ); +AutoAPC( OnInit ); + +void JNetCOM::Call( PAPCFUNC func ) +{ + DWORD curThreadId = GetCurrentThreadId(); + + if ( curThreadId == threadId ) + { + APCWait wait; + wait.dispatch = dispatch; + wait.hEvent = 0; + + func( (ULONG_PTR)&wait ); + } + else + { + if ( threadHandle ) + { + APCWait wait; + wait.dispatch = dispatch; + wait.hEvent = CreateEvent( NULL, FALSE, FALSE, NULL ); + + if ( QueueUserAPC( func, threadHandle, (ULONG_PTR)&wait ) != 0 ) + WaitForSingleObject( wait.hEvent, INFINITE ); + + CloseHandle( wait.hEvent ); + } + } + +} + +void JNetCOM::OnFinish( DownloadToken token ) +{ + if ( NULL != WAC_API_DOWNLOADMANAGER ) + WAC_API_DOWNLOADMANAGER->RetainDownload( token ); + + retained = true; + + Call( OnFinishAPC ); + + token = 0; + + Release(); +} + +void JNetCOM::OnTick( DownloadToken token ) +{ + //Call(OnTickAPC); +} + +void JNetCOM::OnError( DownloadToken token, int error ) +{ + if ( NULL != WAC_API_DOWNLOADMANAGER ) + WAC_API_DOWNLOADMANAGER->RetainDownload( token ); + + retained = true; + + Call( OnErrorAPC ); + + token = 0; + + Release(); +} + +void JNetCOM::OnCancel( DownloadToken token ) +{ + if ( NULL != WAC_API_DOWNLOADMANAGER ) + WAC_API_DOWNLOADMANAGER->RetainDownload( token ); + + retained = true; + + Call( OnCancelAPC ); + + token = 0; + + Release(); +} + +void JNetCOM::OnConnect( DownloadToken token ) +{ + Call( OnConnectAPC ); +} + +void JNetCOM::OnInit( DownloadToken token ) +{ + Call( OnInitAPC ); +} + +size_t JNetCOM::Dispatchable_AddRef() +{ + return InterlockedIncrement( &refCount ); +} + +size_t JNetCOM::Dispatchable_Release() +{ + LONG lRef = InterlockedDecrement( &refCount ); + if ( lRef == 0 ) + delete this; + + return lRef; +} + + +#define CBCLASS JNetCOM +START_DISPATCH; +CB( ADDREF, Dispatchable_AddRef ) +CB( RELEASE, Dispatchable_Release ) +VCB( IFC_DOWNLOADMANAGERCALLBACK_ONFINISH, OnFinish ) +VCB( IFC_DOWNLOADMANAGERCALLBACK_ONTICK, OnTick ) +VCB( IFC_DOWNLOADMANAGERCALLBACK_ONERROR, OnError ) +VCB( IFC_DOWNLOADMANAGERCALLBACK_ONCANCEL, OnCancel ) +VCB( IFC_DOWNLOADMANAGERCALLBACK_ONCONNECT, OnConnect ) +VCB( IFC_DOWNLOADMANAGERCALLBACK_ONINIT, OnInit ) +END_DISPATCH; +#undef CBCLASS |