dolphin/Source/Core/Common/Src/PortableSockets.cpp

551 lines
12 KiB
C++

// Under MIT licence from http://www.mindcontrol.org/~hplus/http-get.html
#include "PortableSockets.h"
#if NEED_GETTIMEOFDAY
#if defined( _WIN32 )
#include <sys/types.h>
#include <sys/timeb.h>
#include <math.h>
#include <assert.h>
#include <mmsystem.h>
#pragma comment( lib, "winmm.lib" )
//#pragma comment( lib, "ws2_32.lib" )
namespace {
// This class could be made cheaper using RDTSC for short-term
// measurement. But, whatever.
class init_gettimeofday
{
public:
init_gettimeofday()
{
timeBeginPeriod( 2 );
__int64 rr;
QueryPerformanceFrequency( (LARGE_INTEGER *)&rr );
ticksPerSecInv_ = 1.0 / (double)((DWORD)rr & 0xffffffff);
int watchdog = 0;
again:
lastTicks_ = timeGetTime();
QueryPerformanceCounter( (LARGE_INTEGER *)&lastRead_ );
timeb tb;
ftime( &tb );
timeOffset_ = tb.time + tb.millitm * 0.001 - lastRead_ * ticksPerSecInv_;
lastTime_ = timeOffset_;
// make sure it didn't take too long
if( watchdog++ < 10 && (timeGetTime() != lastTicks_) ) {
goto again;
}
}
~init_gettimeofday()
{
timeEndPeriod( 2 );
}
void get( timeval * tv )
{
__int64 nu;
int watchdog = 0;
again:
DWORD m = timeGetTime();
QueryPerformanceCounter( (LARGE_INTEGER *)&nu );
DWORD n = timeGetTime();
// guard against pre-emption
if( (watchdog++ < 10) && (n != m) ) {
goto again;
}
double nuTime = nu * ticksPerSecInv_ + timeOffset_;
if( (nu - lastRead_) & 0x7fffffff80000000ULL ) {
// there's a chance that we're seeing a jump-ahead
double adjust = (nuTime - lastTime_ - (n - lastTicks_) * 0.001);
if( adjust > 0.1f ) {
timeOffset_ -= adjust;
nuTime -= adjust;
assert( nuTime >= lastTime_ );
}
}
lastRead_ = nu;
lastTicks_ = n;
lastTime_ = nuTime;
tv->tv_sec = (ulong)floor( nuTime );
tv->tv_usec = (ulong)(1000000 * (nuTime - tv->tv_sec));
}
double ticksPerSecInv_;
double timeOffset_;
double lastTime_;
__int64 lastRead_;
DWORD lastTicks_;
};
}
void gettimeofday( timeval * tv, int )
{
static init_gettimeofday data;
data.get( tv );
}
#else
#error "don't know how to do this"
#endif
#endif
#if NEED_WINDOWS_POLL
#if defined( WIN32 )
#include <assert.h>
#include <winsock2.h>
#include <windows.h>
// This is somewhat less than ideal -- better would be if we could
// abstract pollfd enough that it's non-copying on Windows.
int poll( pollfd * iofds, size_t count, int ms )
{
FD_SET rd, wr, ex;
FD_ZERO( &rd );
FD_ZERO( &wr );
FD_ZERO( &ex );
SOCKET m = 0;
for( size_t ix = 0; ix < count; ++ix ) {
iofds[ix].revents = 0;
if( iofds[ix].fd >= m ) {
m = iofds[ix].fd + 1;
}
if( iofds[ix].events & (POLLIN | POLLPRI) ) {
assert( rd.fd_count < FD_SETSIZE );
rd.fd_array[ rd.fd_count++ ] = iofds[ix].fd;
}
if( iofds[ix].events & (POLLOUT) ) {
assert( wr.fd_count < FD_SETSIZE );
wr.fd_array[ wr.fd_count++ ] = iofds[ix].fd;
}
assert( ex.fd_count < FD_SETSIZE );
ex.fd_array[ ex.fd_count++ ] = iofds[ix].fd;
}
timeval tv;
tv.tv_sec = ms/1000;
tv.tv_usec = (ms - (tv.tv_sec * 1000)) * 1000;
int r = 0;
if( m == 0 ) {
::Sleep( ms );
}
else {
r = ::select( (int)m, (rd.fd_count ? &rd : 0), (wr.fd_count ? &wr : 0), (ex.fd_count ? &ex : 0), &tv );
}
if( r < 0 ) {
int err = WSAGetLastError();
errno = err;
return r;
}
r = 0;
for( size_t ix = 0; ix < count; ++ix ) {
for( size_t iy = 0; iy < rd.fd_count; ++iy ) {
if( rd.fd_array[ iy ] == iofds[ix].fd ) {
iofds[ix].revents |= POLLIN;
++r;
break;
}
}
for( size_t iy = 0; iy < wr.fd_count; ++iy ) {
if( wr.fd_array[ iy ] == iofds[ix].fd ) {
iofds[ix].revents |= POLLOUT;
++r;
break;
}
}
for( size_t iy = 0; iy < ex.fd_count; ++iy ) {
if( ex.fd_array[ iy ] == iofds[ix].fd ) {
iofds[ix].revents |= POLLERR;
++r;
break;
}
}
}
return r;
}
#else
#error "don't know how to do this"
#endif
#endif
#if NEED_FIREWALL_ENABLE
#if defined( WIN32 )
#undef _WIN32_WINNT
#define _WIN32_WINNT 0x500
#include <objbase.h>
#include <oleauto.h>
//#include <netfw.h>
/*
#define _ASSERT assert
namespace {
HRESULT WindowsFirewallInitialize(OUT INetFwProfile** fwProfile)
{
HRESULT hr = S_OK;
INetFwMgr* fwMgr = NULL;
INetFwPolicy* fwPolicy = NULL;
_ASSERT(fwProfile != NULL);
*fwProfile = NULL;
// Create an instance of the firewall settings manager.
hr = CoCreateInstance(
__uuidof(NetFwMgr),
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(INetFwMgr),
(void**)&fwMgr
);
if (FAILED(hr))
{
printf("CoCreateInstance failed: 0x%08lx\n", hr);
goto error;
}
// Retrieve the local firewall policy.
hr = fwMgr->get_LocalPolicy(&fwPolicy);
if (FAILED(hr))
{
printf("get_LocalPolicy failed: 0x%08lx\n", hr);
goto error;
}
// Retrieve the firewall profile currently in effect.
hr = fwPolicy->get_CurrentProfile(fwProfile);
if (FAILED(hr))
{
printf("get_CurrentProfile failed: 0x%08lx\n", hr);
goto error;
}
error:
// Release the local firewall policy.
if (fwPolicy != NULL)
{
fwPolicy->Release();
}
// Release the firewall settings manager.
if (fwMgr != NULL)
{
fwMgr->Release();
}
return hr;
}
void WindowsFirewallCleanup(IN INetFwProfile* fwProfile)
{
// Release the firewall profile.
if (fwProfile != NULL)
{
fwProfile->Release();
}
}
HRESULT WindowsFirewallAppIsEnabled(
IN INetFwProfile* fwProfile,
IN const wchar_t* fwProcessImageFileName,
OUT BOOL* fwAppEnabled
)
{
HRESULT hr = S_OK;
BSTR fwBstrProcessImageFileName = NULL;
VARIANT_BOOL fwEnabled;
INetFwAuthorizedApplication* fwApp = NULL;
INetFwAuthorizedApplications* fwApps = NULL;
_ASSERT(fwProfile != NULL);
_ASSERT(fwProcessImageFileName != NULL);
_ASSERT(fwAppEnabled != NULL);
*fwAppEnabled = FALSE;
// Retrieve the authorized application collection.
hr = fwProfile->get_AuthorizedApplications(&fwApps);
if (FAILED(hr))
{
printf("get_AuthorizedApplications failed: 0x%08lx\n", hr);
goto error;
}
// Allocate a BSTR for the process image file name.
fwBstrProcessImageFileName = SysAllocString(fwProcessImageFileName);
if (SysStringLen(fwBstrProcessImageFileName) == 0)
{
hr = E_OUTOFMEMORY;
printf("SysAllocString failed: 0x%08lx\n", hr);
goto error;
}
// Attempt to retrieve the authorized application.
hr = fwApps->Item(fwBstrProcessImageFileName, &fwApp);
if (SUCCEEDED(hr))
{
// Find out if the authorized application is enabled.
hr = fwApp->get_Enabled(&fwEnabled);
if (FAILED(hr))
{
printf("get_Enabled failed: 0x%08lx\n", hr);
goto error;
}
if (fwEnabled != VARIANT_FALSE)
{
// The authorized application is enabled.
*fwAppEnabled = TRUE;
printf(
"Authorized application %lS is enabled in the firewall.\n",
fwProcessImageFileName
);
}
else
{
printf(
"Authorized application %lS is disabled in the firewall.\n",
fwProcessImageFileName
);
}
}
else
{
// The authorized application was not in the collection.
hr = S_OK;
printf(
"Authorized application %lS is disabled in the firewall.\n",
fwProcessImageFileName
);
}
error:
// Free the BSTR.
SysFreeString(fwBstrProcessImageFileName);
// Release the authorized application instance.
if (fwApp != NULL)
{
fwApp->Release();
}
// Release the authorized application collection.
if (fwApps != NULL)
{
fwApps->Release();
}
return hr;
}
HRESULT WindowsFirewallAddApp(
IN INetFwProfile* fwProfile,
IN const wchar_t* fwProcessImageFileName,
IN const wchar_t* fwName
)
{
HRESULT hr = S_OK;
BOOL fwAppEnabled;
BSTR fwBstrName = NULL;
BSTR fwBstrProcessImageFileName = NULL;
INetFwAuthorizedApplication* fwApp = NULL;
INetFwAuthorizedApplications* fwApps = NULL;
_ASSERT(fwProfile != NULL);
_ASSERT(fwProcessImageFileName != NULL);
_ASSERT(fwName != NULL);
// First check to see if the application is already authorized.
hr = WindowsFirewallAppIsEnabled(
fwProfile,
fwProcessImageFileName,
&fwAppEnabled
);
if (FAILED(hr))
{
printf("WindowsFirewallAppIsEnabled failed: 0x%08lx\n", hr);
goto error;
}
// Only add the application if it isn't already authorized.
if (!fwAppEnabled)
{
// Retrieve the authorized application collection.
hr = fwProfile->get_AuthorizedApplications(&fwApps);
if (FAILED(hr))
{
printf("get_AuthorizedApplications failed: 0x%08lx\n", hr);
goto error;
}
// Create an instance of an authorized application.
hr = CoCreateInstance(
__uuidof(NetFwAuthorizedApplication),
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(INetFwAuthorizedApplication),
(void**)&fwApp
);
if (FAILED(hr))
{
printf("CoCreateInstance failed: 0x%08lx\n", hr);
goto error;
}
// Allocate a BSTR for the process image file name.
fwBstrProcessImageFileName = SysAllocString(fwProcessImageFileName);
if (SysStringLen(fwBstrProcessImageFileName) == 0)
{
hr = E_OUTOFMEMORY;
printf("SysAllocString failed: 0x%08lx\n", hr);
goto error;
}
// Set the process image file name.
hr = fwApp->put_ProcessImageFileName(fwBstrProcessImageFileName);
if (FAILED(hr))
{
printf("put_ProcessImageFileName failed: 0x%08lx\n", hr);
goto error;
}
// Allocate a BSTR for the application friendly name.
fwBstrName = SysAllocString(fwName);
if (SysStringLen(fwBstrName) == 0)
{
hr = E_OUTOFMEMORY;
printf("SysAllocString failed: 0x%08lx\n", hr);
goto error;
}
// Set the application friendly name.
hr = fwApp->put_Name(fwBstrName);
if (FAILED(hr))
{
printf("put_Name failed: 0x%08lx\n", hr);
goto error;
}
// Add the application to the collection.
hr = fwApps->Add(fwApp);
if (FAILED(hr))
{
printf("Add failed: 0x%08lx\n", hr);
goto error;
}
printf(
"Authorized application %lS is now enabled in the firewall.\n",
fwProcessImageFileName
);
}
error:
// Free the BSTRs.
SysFreeString(fwBstrName);
SysFreeString(fwBstrProcessImageFileName);
// Release the authorized application instance.
if (fwApp != NULL)
{
fwApp->Release();
}
// Release the authorized application collection.
if (fwApps != NULL)
{
fwApps->Release();
}
return hr;
}
}
bool ENABLE_FIREWALL()
{
BOOL couldEnable = false;
HRESULT hr = S_OK;
HRESULT comInit = E_FAIL;
INetFwProfile* fwProfile = NULL;
// Initialize COM.
#if 1
comInit = CoInitialize( 0 );
#else
comInit = CoInitializeEx(
0,
COINIT_APARTMENTTHREADED //| COINIT_DISABLE_OLE1DDE
);
#endif
// Ignore RPC_E_CHANGED_MODE; this just means that COM has already been
// initialized with a different mode. Since we don't care what the mode is,
// we'll just use the existing mode.
if (comInit != RPC_E_CHANGED_MODE) {
hr = comInit;
if (FAILED(hr)) {
fprintf( stderr, "CoInitializeEx failed: 0x%08lx\n", hr );
goto error;
}
}
// Retrieve the firewall profile currently in effect.
hr = WindowsFirewallInitialize(&fwProfile);
if (FAILED(hr)) {
fprintf( stderr, "WindowsFirewallInitialize failed: 0x%08lx\n", hr );
goto error;
}
HMODULE hm = GetModuleHandle( 0 );
wchar_t path[512];
if( !GetModuleFileNameW( hm, path, sizeof(path)/sizeof(wchar_t) ) ) {
fprintf( stderr, "GetModuleFileName() failed: 0x%lx\n", GetLastError() );
goto error;
}
// Add the application to the authorized application collection.
hr = WindowsFirewallAddApp(
fwProfile,
path,
L"Introduction Library User"
);
if (FAILED(hr)) {
fprintf( stderr, "WindowsFirewallAddApp failed: 0x%08lx\n", hr );
goto error;
}
error:
WindowsFirewallCleanup(fwProfile);
if (SUCCEEDED(comInit)) {
CoUninitialize();
}
return couldEnable != FALSE;
}
*/
#else
#error "don't know how to do this"
#endif
#endif