windows-nt/Source/XPSP1/NT/enduser/netmeeting/ui/conf/autoconf.cpp
2020-09-26 16:20:57 +08:00

424 lines
11 KiB
C++

#include "precomp.h"
#include "resource.h"
#include "pfnwininet.h"
#include "pfnsetupapi.h"
#include "AutoConf.h"
#include "ConfUtil.h"
// File level globals
CAutoConf * g_pAutoConf = NULL;
void CAutoConf::DoIt( void )
{
RegEntry re(POLICIES_KEY, HKEY_CURRENT_USER);
if( !re.GetNumber(REGVAL_AUTOCONF_USE, DEFAULT_AUTOCONF_USE ) )
{
TRACE_OUT(( TEXT("AutoConf: Not using autoconfiguration")));
return;
}
LPTSTR szAutoConfServer = re.GetString( REGVAL_AUTOCONF_CONFIGFILE );
if( NULL == szAutoConfServer )
{
WARNING_OUT(( TEXT("AutoConf: AutoConf server is unset") ));
DisplayErrMsg( IDS_AUTOCONF_SERVERNAME_MISSING );
return;
}
g_pAutoConf = new CAutoConf( szAutoConfServer );
ASSERT( g_pAutoConf );
if( !g_pAutoConf->OpenConnection() )
{
WARNING_OUT(( TEXT("AutoConf: Connect to net failed") ));
DisplayErrMsg( IDS_AUTOCONF_FAILED );
goto cleanup;
}
if( NULL == g_pAutoConf->m_hOpenUrl )
{
WARNING_OUT(( TEXT("AutoConf: g_pAutoConf->m_hOpenUrl = NULL") ));
DisplayErrMsg( IDS_AUTOCONF_FAILED );
goto cleanup;
}
if( FALSE == g_pAutoConf->GetFile() )
{
WARNING_OUT(( TEXT("AutoConf: g_pAutoConf->GetFile() == FALSE") ));
DisplayErrMsg( IDS_AUTOCONF_FAILED );
goto cleanup;
}
if( FALSE == g_pAutoConf->QueryData() )
{
WARNING_OUT(( TEXT("AutoConf: g_pAutoConf->QueryData() == FALSE") ));
DisplayErrMsg( IDS_AUTOCONF_FAILED );
goto cleanup;
}
if( FAILED( SETUPAPI::Init() ) )
{
WARNING_OUT(( TEXT("AutoConf: Setupapi's failed to init") ));
DisplayErrMsg( IDS_AUTOCONF_NEED_SETUPAPIS );
goto cleanup;
}
if( !g_pAutoConf->ParseFile() )
{
WARNING_OUT(( TEXT("AutoConf: Could not parse inf file") ));
DisplayErrMsg( IDS_AUTOCONF_PARSE_ERROR );
goto cleanup;
}
TRACE_OUT(( TEXT("AutoConf: FILE PARSED!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") ));
cleanup:
delete g_pAutoConf;
return;
}
CAutoConf::CAutoConf( LPTSTR szServer )
: m_szServer( szServer ), m_hInternet( NULL ), m_hOpenUrl( NULL ), m_dwGrab( 0 ),
m_hInf( NULL ), m_hFile( INVALID_HANDLE_VALUE ), m_hEvent( NULL )
{
ZeroMemory( m_szFile, CCHMAX( m_szFile ) );
m_hEvent = CreateEvent( NULL, TRUE, FALSE, TEXT( "NMAutoConf_WaitEvent" ) );
RegEntry re(POLICIES_KEY, HKEY_CURRENT_USER);
m_dwTimeOut = re.GetNumber(REGVAL_AUTOCONF_TIMEOUT, DEFAULT_AUTOCONF_TIMEOUT );
}
CAutoConf::~CAutoConf()
{
CloseInternet();
if( INVALID_HANDLE_VALUE != m_hFile )
{
CloseHandle( m_hFile );
}
DeleteFile( m_szFile );
if( NULL != m_hInf )
{
SETUPAPI::SetupCloseInfFile( m_hInf );
}
//WININET::DeInit();
//SETUPAPI::DeInit();
}
BOOL CAutoConf::OpenConnection()
{
// ASSERT( phInternet );
if( FAILED( WININET::Init() ) )
{
WARNING_OUT(( TEXT("AutoConf: WININET::Init failed") ));
DisplayErrMsg( IDS_AUTOCONF_NO_WININET );
return FALSE;
}
ASSERT( NULL != m_szServer );
m_hInternet = WININET::InternetOpen( TEXT("NetMeeting"),
INTERNET_OPEN_TYPE_DIRECT,
NULL,
NULL,
INTERNET_FLAG_ASYNC );
if( NULL == m_hInternet )
{
WARNING_OUT(( TEXT( "AutoConf: InternetOpen failed" ) ));
return FALSE;
}
if( INTERNET_INVALID_STATUS_CALLBACK ==
WININET::InternetSetStatusCallback( m_hInternet,
(INTERNET_STATUS_CALLBACK) CAutoConf::InetCallback ) )
{
WARNING_OUT(( TEXT("AutoConf: InternetSetStatusCallback failed") ));
return FALSE;
}
m_hOpenUrl = WININET::InternetOpenUrl( m_hInternet,
m_szServer,
NULL,
0,
INTERNET_FLAG_KEEP_CONNECTION |
INTERNET_FLAG_RELOAD,
AUTOCONF_CONTEXT_OPENURL );
if( NULL == m_hOpenUrl && ERROR_IO_PENDING != GetLastError() )
{
WARNING_OUT(( TEXT("AutoConf: InternetOpenUrl failed") ));
return FALSE;
}
if( WAIT_FAILED == WaitForSingleObject( m_hEvent, m_dwTimeOut ) )
{
WARNING_OUT(( TEXT("AutoConf: InternetOpenUrl wait for handle failed") ));
return FALSE;
}
return TRUE;
}
BOOL CAutoConf::ParseFile()
{
LPTSTR lstrInstallSection = TEXT("NetMtg.Install.NMRK");
m_hInf = SETUPAPI::SetupOpenInfFile( m_szFile, // name of the INF to open
NULL, // optional, the class of the INF file
INF_STYLE_WIN4, // specifies the style of the INF file
NULL // optional, receives error information
);
if( INVALID_HANDLE_VALUE == m_hInf )
{
return false;
}
return SETUPAPI::SetupInstallFromInfSection(
NULL, // optional, handle of a parent window
m_hInf, // handle to the INF file
lstrInstallSection, // name of the Install section
SPINST_REGISTRY , // which lines to install from section
NULL, // optional, key for registry installs
NULL, // optional, path for source files
0, // optional, specifies copy behavior
NULL, // optional, specifies callback routine
NULL, // optional, callback routine context
NULL, // optional, device information set
NULL // optional, device info structure
);
}
BOOL CAutoConf::GetFile()
{
// ASSERT( INVALID_HANDLE_VALUE == m_hFile );
TCHAR szPath[ MAX_PATH ];
GetTempPath( CCHMAX( szPath ), // size, in characters, of the buffer
szPath // pointer to buffer for temp. path
);
GetTempFileName( szPath, // pointer to directory name for temporary file
TEXT("NMA"), // pointer to filename prefix
0, // number used to create temporary filename
m_szFile // pointer to buffer that receives the new filename
);
m_hFile = CreateFile( m_szFile,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_TEMPORARY /*| FILE_FLAG_DELETE_ON_CLOSE*/,
NULL );
if( INVALID_HANDLE_VALUE == m_hFile )
{
WARNING_OUT(( TEXT("AutoConf: AutoConfGetFile returned INVALID_HANDLE_VALUE") ));
return FALSE;
}
return TRUE;
}
BOOL CAutoConf::QueryData()
{
ASSERT( NULL != m_hOpenUrl );
m_dwGrab = 0;
if (!WININET::InternetQueryDataAvailable( m_hOpenUrl,
&m_dwGrab,
0,
0 ) )
{
if( ERROR_IO_PENDING != GetLastError() )
{
WARNING_OUT(( TEXT("AutoConf: InternetQueryDataAvailable failed") ));
return FALSE;
}
else if( WAIT_FAILED == WaitForSingleObject( m_hEvent, m_dwTimeOut ) )
{
WARNING_OUT(( TEXT("AutoConf: InternetQueryDataAvailable wait for data failed") ));
return FALSE;
}
}
GrabData();
return TRUE;
}
BOOL CAutoConf::GrabData()
{
ASSERT( NULL != m_hOpenUrl );
ASSERT( INVALID_HANDLE_VALUE != m_hFile );
if( !m_dwGrab )
{
TRACE_OUT(( TEXT("AutoConf: Finished Reading File") ));
CloseHandle( m_hFile );
m_hFile = INVALID_HANDLE_VALUE;
return TRUE;
}
DWORD dwRead;
LPTSTR pInetBuffer = new TCHAR[ m_dwGrab + 1];
ASSERT( pInetBuffer );
if( !WININET::InternetReadFile( m_hOpenUrl,
(void *)pInetBuffer,
m_dwGrab,
&dwRead ) )// && ERROR_IO_PENDING != GetLastError() )
{
WARNING_OUT(( TEXT("AutoConf: InternetReadFile Failed") ));
delete [] pInetBuffer;
return FALSE;
}
else
{
pInetBuffer[ dwRead ] = '\0';
if( !WriteFile( m_hFile,
pInetBuffer,
dwRead,
&m_dwGrab,
NULL ) || dwRead != m_dwGrab )
{
WARNING_OUT(( TEXT("AutoConf: WriteFile Failed") ));
delete [] pInetBuffer;
return FALSE;
}
}
delete [] pInetBuffer;
QueryData();
return TRUE;
}
void CAutoConf::CloseInternet()
{
HINTERNETKILL( m_hInternet );
HINTERNETKILL( m_hOpenUrl );
}
VOID CALLBACK CAutoConf::InetCallback( HINTERNET hInternet, DWORD dwContext, DWORD dwInternetStatus,
LPVOID lpvStatusInformation, DWORD dwStatusInformationLength )
{
if( g_pAutoConf != NULL )
{
switch( dwInternetStatus )
{
case INTERNET_STATUS_REQUEST_COMPLETE:
{
TRACE_OUT(( TEXT("AutoConf: AutoConfInetCallback::INTERNET_STATUS_REQUEST_COMPLETE") ));
if( AUTOCONF_CONTEXT_OPENURL == dwContext && g_pAutoConf->m_hOpenUrl == NULL )
{
TRACE_OUT(( TEXT("AutoConf: InternetOpenUrl Finished") ));
LPINTERNET_ASYNC_RESULT lpIAR = (LPINTERNET_ASYNC_RESULT)lpvStatusInformation;
#ifndef _WIN64
g_pAutoConf->m_hOpenUrl = (HINTERNET)lpIAR->dwResult;
#endif
SetEvent( g_pAutoConf->m_hEvent );
}
else
{
LPINTERNET_ASYNC_RESULT lpIAR = (LPINTERNET_ASYNC_RESULT)lpvStatusInformation;
TRACE_OUT(( TEXT("AutoConf: QueryData returned") ));
g_pAutoConf->m_dwGrab = (DWORD)lpIAR->dwResult;
SetEvent( g_pAutoConf->m_hEvent );
}
break;
}
#ifdef DEBUG
case INTERNET_STATUS_CLOSING_CONNECTION:
//Closing the connection to the server. The lpvStatusInformation parameter is NULL.
TRACE_OUT(( TEXT("Closing connection\n") ) );
break;
case INTERNET_STATUS_CONNECTED_TO_SERVER:
//Successfully connected to the socket address (SOCKADDR) pointed to by lpvStatusInformation.
TRACE_OUT(( TEXT("Connected to server") ) );
break;
case INTERNET_STATUS_CONNECTING_TO_SERVER:
//Connecting to the socket address (SOCKADDR) pointed to by lpvStatusInformation.
TRACE_OUT(( TEXT("Connecting to server") ) );
break;
case INTERNET_STATUS_CONNECTION_CLOSED:
//Successfully closed the connection to the server.
//The lpvStatusInformation parameter is NULL.
TRACE_OUT(( TEXT("Connection Closed") ) );
break;
case INTERNET_STATUS_HANDLE_CLOSING:
//This handle value is now terminated.
TRACE_OUT(( TEXT("Handle value terminated\n") ) );
break;
case INTERNET_STATUS_HANDLE_CREATED:
//Used by InternetConnect to indicate it has created the new handle.
//This lets the application call InternetCloseHandle from another thread,
//if the connect is taking too long.
TRACE_OUT(( TEXT("Handle created\n") ) );
break;
case INTERNET_STATUS_NAME_RESOLVED:
//Successfully found the IP address of the name contained in lpvStatusInformation.
TRACE_OUT(( TEXT("Resolved name of server") ) );
break;
case INTERNET_STATUS_RECEIVING_RESPONSE:
//Waiting for the server to respond to a request.
//The lpvStatusInformation parameter is NULL.
TRACE_OUT(( TEXT("Recieving response\n") ) );
break;
case INTERNET_STATUS_REDIRECT:
//An HTTP request is about to automatically redirect the request.
//The lpvStatusInformation parameter points to the new URL.
//At this point, the application can read any data returned by the server with the
//redirect response, and can query the response headers. It can also cancel the operation
//by closing the handle. This callback is not made if the original request specified
//INTERNET_FLAG_NO_AUTO_REDIRECT.
TRACE_OUT(( TEXT("Redirected to new server") ) );
break;
case INTERNET_STATUS_REQUEST_SENT:
//Successfully sent the information request to the server.
//The lpvStatusInformation parameter points to a DWORD containing the number of bytes sent.
TRACE_OUT(( TEXT("Sent %d bytes in request"), *((DWORD *)lpvStatusInformation) ) );
break;
case INTERNET_STATUS_RESOLVING_NAME:
//Looking up the IP address of the name contained in lpvStatusInformation.
TRACE_OUT(( TEXT("Resolving name") ) );
break;
case INTERNET_STATUS_RESPONSE_RECEIVED:
//Successfully received a response from the server.
//The lpvStatusInformation parameter points to a DWORD containing the number of bytes received.
TRACE_OUT(( TEXT("Recieved %d bytes in response\n"), *((DWORD *)lpvStatusInformation) ) );
break;
case INTERNET_STATUS_SENDING_REQUEST:
//Sending the information request to the server.
//The lpvStatusInformation parameter is NULL.
TRACE_OUT(( TEXT("Sending request") ) );
break;
#endif // DEBUG
default:
break;
}
}
}