/*++ Copyright (c) 1996 Microsoft Corporation Module Name: autoprox.hxx Abstract: Contains interface definition for a specialized DLL that automatically configurares WININET proxy information. The DLL can reroute proxy infromation based on a downloaded set of data that matches it registered MIME type. The DLL can also control WININET proxy use, on a request by request basis. Contents: AUTO_PROXY_LIST_ENTRY AUTO_PROXY_DLLS AUTO_PROXY_ASYNC_MSG PROXY_STATE Author: Arthur L Bierer (arthurbi) 01-Dec-1996 Revision History: 01-Dec-1996 arthurbi Created --*/ #ifndef _AUTOPROX_HXX_ #define _AUTOPROX_HXX_ #define CSZMAINSECKEY "AutoProxyTypes" // // functions // BOOL InitalizeAutoConfigDllIfNeeded( VOID ); // // Callback functions implimented in WININET // class AUTO_PROXY_HELPER_APIS { public: virtual BOOL IsResolvable( IN LPSTR lpszHost ); virtual DWORD GetIPAddress( IN OUT LPSTR lpszIPAddress, IN OUT LPDWORD lpdwIPAddressSize ); virtual DWORD ResolveHostName( IN LPSTR lpszHostName, IN OUT LPSTR lpszIPAddress, IN OUT LPDWORD lpdwIPAddressSize ); virtual BOOL IsInNet( IN LPSTR lpszIPAddress, IN LPSTR lpszDest, IN LPSTR lpszMask ); }; // // external func declariations // #define AUTO_PROXY_VERSION 0x00010000 #define EXT_PROXY_FUNC * typedef BOOL (EXT_PROXY_FUNC PROXY_INFO_INVALID_FN) ( IN LPSTR lpszMime, IN LPSTR lpszUrl, IN DWORD dwUrlLength, IN LPSTR lpszProxyHostName, IN DWORD dwProxyHostNameLength ); typedef BOOL (EXT_PROXY_FUNC PROXY_DLL_DEINIT_FN) ( IN LPSTR lpszMime, IN DWORD dwReserved ); typedef BOOL (EXT_PROXY_FUNC GET_PROXY_INFO_FN) ( IN LPCSTR lpszUrl, IN DWORD dwUrlLength, IN LPSTR lpszUrlHostName, IN DWORD dwUrlHostNameLength, OUT LPSTR * lplpszProxyHostName, OUT LPDWORD lpdwProxyHostNameLength ) ; typedef BOOL (EXT_PROXY_FUNC GET_PROXY_INFO_EX_FN) ( IN INTERNET_SCHEME tUrlProtocol, IN LPCSTR lpszUrl, IN DWORD dwUrlLength, IN LPSTR lpszUrlHostName, IN DWORD dwUrlHostNameLength, IN INTERNET_PORT nUrlPort, OUT LPINTERNET_SCHEME lptProxyScheme, OUT LPSTR * lplpszProxyHostName, OUT LPDWORD lpdwProxyHostNameLength, OUT LPINTERNET_PORT lpProxyHostPort ) ; typedef BOOL (EXT_PROXY_FUNC PROXY_DLL_INIT_FN) ( IN DWORD dwVersion, IN LPSTR lpszDownloadedTempFile, IN LPSTR lpszMime, IN AUTO_PROXY_HELPER_APIS *pAutoProxyCallbacks, IN DWORD_PTR dwReserved ); #define PROXY_INFO_INVALID_FN_NAME "InternetProxyInfoInvalid" #define GET_PROXY_INFO_FN_NAME "InternetGetProxyInfo" #define GET_PROXY_INFO_EX_FN_NAME "InternetGetProxyInfoEx" #define PROXY_DLL_INIT_FN_NAME "InternetInitializeAutoProxyDll" #define PROXY_DLL_DEINIT_FN_NAME "InternetDeInitializeAutoProxyDll" // // Flags stored in registry for Auto-Proxy Entry // #define AUTOPROX_FLAGS_SINGLE_THREAD 0x01 // // defines ... // #define DEFAULT_AUTO_PROXY_THREAD_TIME_OUT 30000 // 30 secs BUGBUG, up before checkin // // PROXY_MESSAGE_TYPE - this represents a type of query that is used // to submit a request through proxy "knowledge-base" ( ie script, db, etc ) // for async processing of Java-Script auto-proxy scripts. // typedef enum { PROXY_MSG_INVALID, PROXY_MSG_INIT, PROXY_MSG_DEINIT, PROXY_MSG_SELF_DESTRUCT, PROXY_MSG_GET_PROXY_INFO, PROXY_MSG_SET_BAD_PROXY } PROXY_MESSAGE_TYPE; // // PROXY_MESSAGE_ALLOC_TYPE - this is needed to track what allocation of member vars // are currently used in my object. This allows us to use stack vars // for simple, local calls, but then have allocation done-on-the-fly // when we need to queue the message. // typedef enum { MSG_ALLOC_NONE, MSG_ALLOC_STACK_ONLY, MSG_ALLOC_HEAP, MSG_ALLOC_HEAP_MSG_OBJ_OWNS } PROXY_MESSAGE_ALLOC_TYPE; // // AUTO_PROXY_STATE - is used to track the state of the auto-proxy list object // in order to maintain syncronization across readers and writers. // typedef enum { AUTO_PROXY_DISABLED, AUTO_PROXY_BLOCKED, AUTO_PROXY_PENDING, // blocked, but we can still fallback to static settings AUTO_PROXY_ENABLED } AUTO_PROXY_STATE; class BAD_PROXY_LIST; // forward decl // // PROXY_STATE - keeps track of multiple proxies stored in a Netscape Style // proxy list string format. Ex: // "PROXY itgproxy:80; PROXY proxy:80; PROXY 192.168.100.2:1080; SOCKS 192.168.100.2; DIRECT" // // Can also be used to link the GetProxyInfo return with a failure in the proxies it gave. // This needed so we call back into an Auto-Proxy DLL letting them know that we failed // to be able to utilize its auto-proxy that it gave us. // class PROXY_STATE { private: // // _lpszAutoProxyList - List, or Proxy that we are tracking. // LPSTR _lpszAutoProxyList; // // _dwcbAutoProxyList - size of _lpszAutoProxyList. // DWORD _dwcbAutoProxyList; // // _lpszOffset - Current Offset into _lpszAutoProxyList // LPSTR _lpszOffset; // // _lpszLastProxyUsed - Tracks the last proxy that was returned. // LPSTR _lpszLastProxyUsed; // // _LastProxyUsedPort - Last used Internet Port on the Proxy // INTERNET_PORT _LastProxyUsedPort; // // _Error - Error code in constructor. // DWORD _Error; // // _fIsMultiProxyList - TRUE if we a Netscape type list of proxies, as opposed to a simple proxyhostname string. // BOOL _fIsMultiProxyList; // // _fIsAnotherProxyAvail - TRUE if we have another proxy to process // BOOL _fIsAnotherProxyAvail; // // tProxyScheme - for the non-multi proxy case we track the type of proxy we are storing. // INTERNET_SCHEME _tProxyScheme; // // ProxyHostPort - for the non-multi proxy case we track the host port. // INTERNET_PORT _proxyHostPort; public: PROXY_STATE( LPSTR lpszAutoProxyList, DWORD dwcbAutoProxyList, BOOL fIsMultiProxyList, INTERNET_SCHEME tProxyScheme, INTERNET_PORT proxyHostPort ) { _lpszAutoProxyList = NULL; _dwcbAutoProxyList = 0; _lpszOffset = NULL; _Error = ERROR_SUCCESS; _lpszLastProxyUsed = NULL; _LastProxyUsedPort = INTERNET_DEFAULT_HTTP_PORT; _fIsMultiProxyList = fIsMultiProxyList; _tProxyScheme = tProxyScheme; _proxyHostPort = proxyHostPort; _fIsAnotherProxyAvail = FALSE; if ( lpszAutoProxyList && dwcbAutoProxyList > 0 ) { _lpszAutoProxyList = (LPSTR) ALLOCATE_MEMORY(LMEM_FIXED, dwcbAutoProxyList+1); if ( _lpszAutoProxyList ) { lstrcpyn(_lpszAutoProxyList, lpszAutoProxyList, dwcbAutoProxyList ); _lpszAutoProxyList[dwcbAutoProxyList] = '\0'; _dwcbAutoProxyList = dwcbAutoProxyList; _lpszOffset = _lpszAutoProxyList; } else { _Error = ERROR_NOT_ENOUGH_MEMORY; } } } ~PROXY_STATE() { DEBUG_ENTER((DBG_OBJECTS, None, "~PROXY_STATE", NULL )); if ( _lpszAutoProxyList ) { FREE_MEMORY(_lpszAutoProxyList ); _lpszAutoProxyList = NULL; } DEBUG_LEAVE(0); } DWORD GetError(VOID) const { return _Error; } BOOL IsEmpty(VOID) const { return (!_lpszOffset || *_lpszOffset == '\0' ) ? TRUE : FALSE; } BOOL IsAnotherProxyAvail(VOID) const { return _fIsAnotherProxyAvail; } LPSTR GetLastProxyUsed(INTERNET_PORT *pProxyPort) { *pProxyPort = _LastProxyUsedPort; return _lpszLastProxyUsed; } BOOL GetNextProxy( IN INTERNET_SCHEME tUrlScheme, IN BAD_PROXY_LIST & BadProxyList, OUT LPINTERNET_SCHEME lptProxyScheme, OUT LPSTR * lplpszProxyHostName, OUT LPBOOL lpbFreeProxyHostName, OUT LPDWORD lpdwProxyHostNameLength, OUT LPINTERNET_PORT lpProxyHostPort ); }; // // AUTO_PROXY_ASYNC_MSG - this object is used to pass queries for proxy information across // from requestors (HTTP_REQUEST_HANDLE_OBJECT, parseUrl, etc) to responders // (AutoProxy DLL, PROXY_INFO object) who can process the request in a syncronious // or asyncrouns manner. // class AUTO_PROXY_ASYNC_MSG { friend class AUTO_PROXY_LIST_ENTRY; public: //BUGBUG, I'm being lazy, need to make methods to guard access // // _List - We're a list entry on a queue. But we don't always have to be, // We can be borne a structure that justs gets passed around and is never // queued. // LIST_ENTRY _List; // // _tUrlProtocol - Protocol that this request is using. // INTERNET_SCHEME _tUrlProtocol; // // _lpszUrl - The requested URL that we are navigating to. // LPSTR _lpszUrl; // // _dwUrlLength - The size of the URL. // DWORD _dwUrlLength; // // _lpszUrlHostName - The host name found in the URL. // LPSTR _lpszUrlHostName; // // _dwUrlHostNameLength - Host name Length // DWORD _dwUrlHostNameLength; // // _nUrlPort - Dest port used on this Url. // INTERNET_PORT _nUrlPort; // // _tProxyScheme - Type of proxy we will use. ( HTTP, HTTPS, etc ) // INTERNET_SCHEME _tProxyScheme; // // _lpszProxyHostName - Host name of the proxy we are to use. // LPSTR _lpszProxyHostName; // // _bFreeProxyHostName - TRUE if _lpszProxyHostName is a copy // BOOL _bFreeProxyHostName; // // _dwProxyHostNameLength - Proxy Host name length. // DWORD _dwProxyHostNameLength; // // _nProxyHostPort - Proxy port to use // INTERNET_PORT _nProxyHostPort; // // _pProxyState - State for enumerating multiple proxies. // PROXY_STATE *_pProxyState; // // _pmProxyQuery - The Action aka Query we're are doing with this message. // PROXY_MESSAGE_TYPE _pmProxyQuery; // // _pmaAllocMode - Used to track who owns the allocated string ptrs. // PROXY_MESSAGE_ALLOC_TYPE _pmaAllocMode; // // _dwQueryResult - TRUE if we are going through a proxy // DWORD _dwQueryResult; // // _Error - Return code after this call is made. // DWORD _Error; // // dwProxyVersion - Proxy Verion this was issue a result for // DWORD _dwProxyVersion; VOID SetVersion(VOID) { _dwProxyVersion = GlobalProxyVersionCount; } DWORD GetVersion(VOID) { return _dwProxyVersion; } // // _MessageFlags - Various // union { struct { // // DontWantProxyStrings, don't waste time with allocating strings for my result, // since I all I care about is generalized proxy info (ie do I have a proxy for ...). // DWORD DontWantProxyStrings : 1; // // BlockUntilCompletetion, don't return from an async call until the async thread has // completed processing my proxy query. // DWORD BlockUntilCompletetion : 1; // // AvoidAsyncCall, don't go async under any curcumstances, so we will return // what every we can get, even if this means giving incorrect data. // DWORD AvoidAsyncCall : 1; // // BlockedOnFsm, true a fsm is blocked on this message to complete // DWORD BlockedOnFsm : 1 ; // // QueryOnCallback, TRUE if we're making a call with this object // on a FSM callback. Basically we've received results from // the async thread, but we need to do a final a call so // the results can be parsed out. // DWORD QueryOnCallback : 1; // // ForceRefresh, TRUE if we are to force a refresh of cached settings and scripts. // DWORD ForceRefresh : 1; // // ShowIndication, TRUE if we indicate via callback // to the user that we performing auto-detection // DWORD ShowIndication : 1; // // BackroundDetectionPending, TRUE if a backround detection // is being done while this page is loading // DWORD BackroundDetectionPending : 1; // // CanCacheResult - TRUE if this result can be cached // DWORD CanCacheResult : 1; } Flags; // // Dword - used in initialization ONLY, do NOT use ELSEWHERE ! // DWORD Dword; } _MessageFlags; //public: AUTO_PROXY_ASYNC_MSG( IN INTERNET_SCHEME isUrlScheme, IN LPSTR lpszUrl, IN LPSTR lpszUrlHostName, IN DWORD dwUrlHostNameLength ); AUTO_PROXY_ASYNC_MSG( IN INTERNET_SCHEME isUrlScheme, IN LPSTR lpszUrl, IN DWORD dwUrlLength, IN LPSTR lpszUrlHostName, IN DWORD dwUrlHostNameLength, IN INTERNET_PORT nUrlPort ); AUTO_PROXY_ASYNC_MSG( PROXY_MESSAGE_TYPE pmProxyQuery ); AUTO_PROXY_ASYNC_MSG( AUTO_PROXY_ASYNC_MSG *pStaticAutoProxy ); AUTO_PROXY_ASYNC_MSG( IN INTERNET_SCHEME isUrlScheme, IN LPSTR lpszUrlHostName, IN DWORD dwUrlHostNameLength ); AUTO_PROXY_ASYNC_MSG( VOID ) { Initalize(); } ~AUTO_PROXY_ASYNC_MSG( VOID ); VOID Initalize( VOID ) { InitializeListHead(&_List); // this is bogus, we should just memset this. _tUrlProtocol = INTERNET_SCHEME_UNKNOWN; _lpszUrl = NULL; _dwUrlLength = 0; _lpszUrlHostName = NULL; _dwUrlHostNameLength = 0; _nUrlPort = INTERNET_INVALID_PORT_NUMBER; _tProxyScheme = INTERNET_SCHEME_UNKNOWN; _lpszProxyHostName = NULL; _bFreeProxyHostName = FALSE; _dwProxyHostNameLength = 0; _nProxyHostPort = INTERNET_INVALID_PORT_NUMBER; _pmProxyQuery = PROXY_MSG_INVALID; _pmaAllocMode = MSG_ALLOC_NONE; _pProxyState = NULL; _dwQueryResult = FALSE; _Error = ERROR_SUCCESS; _dwProxyVersion = 0; _MessageFlags.Dword = 0; } VOID SetProxyMsg( IN INTERNET_SCHEME isUrlScheme, IN LPSTR lpszUrl, IN DWORD dwUrlLength, IN LPSTR lpszUrlHostName, IN DWORD dwUrlHostNameLength, IN INTERNET_PORT nUrlPort ); BOOL IsProxyEnumeration(VOID) const { if ( _pProxyState && !IsDontWantProxyStrings() && !_pProxyState->IsEmpty() ) { return TRUE; } return FALSE; } BOOL IsAlloced(VOID) const { return ( _pmaAllocMode == MSG_ALLOC_HEAP || _pmaAllocMode == MSG_ALLOC_HEAP_MSG_OBJ_OWNS ) ? TRUE : FALSE; } BOOL IsUrl(VOID) const { return (_lpszUrl && _dwUrlLength > 0 ); } BOOL IsUseProxy(VOID) const { return _dwQueryResult; } VOID SetUseProxy(BOOL Value) { _dwQueryResult = Value; } INTERNET_SCHEME GetProxyScheme(VOID) const { return _tProxyScheme; } INTERNET_SCHEME GetUrlScheme(VOID) const { return _tUrlProtocol; } BOOL IsShowIndication(VOID) const { return (BOOL) _MessageFlags.Flags.ShowIndication; } VOID SetShowIndication(BOOL Value) { _MessageFlags.Flags.ShowIndication = (Value) ? TRUE : FALSE; } BOOL IsBackroundDetectionPending(VOID) const { return (BOOL) _MessageFlags.Flags.BackroundDetectionPending; } VOID SetBackroundDetectionPending(BOOL Value) { _MessageFlags.Flags.BackroundDetectionPending = (Value) ? TRUE : FALSE; } BOOL IsDontWantProxyStrings(VOID) const { return (BOOL) _MessageFlags.Flags.DontWantProxyStrings; } VOID SetDontWantProxyStrings(BOOL Value) { _MessageFlags.Flags.DontWantProxyStrings = (Value) ? TRUE : FALSE; } BOOL IsAvoidAsyncCall(VOID) const { return (BOOL) _MessageFlags.Flags.AvoidAsyncCall; } VOID SetAvoidAsyncCall(BOOL Value) { _MessageFlags.Flags.AvoidAsyncCall = (Value) ? TRUE : FALSE; } BOOL IsQueryOnCallback(VOID) const { return (BOOL) _MessageFlags.Flags.QueryOnCallback; } VOID SetQueryOnCallback(BOOL Value) { _MessageFlags.Flags.QueryOnCallback = (Value) ? TRUE : FALSE; } BOOL IsForceRefresh(VOID) const { return (BOOL) _MessageFlags.Flags.ForceRefresh; } VOID SetForceRefresh(BOOL Value) { _MessageFlags.Flags.ForceRefresh = (Value) ? TRUE : FALSE; } BOOL IsBlockUntilCompletetion(VOID) const { return (BOOL) _MessageFlags.Flags.BlockUntilCompletetion; } VOID SetBlockUntilCompletetion(BOOL Value) { _MessageFlags.Flags.BlockUntilCompletetion = (Value) ? TRUE : FALSE; } BOOL IsCanCacheResult(VOID) const { return (BOOL) _MessageFlags.Flags.CanCacheResult; } VOID SetCanCacheResult(BOOL Value) { _MessageFlags.Flags.CanCacheResult = (Value) ? TRUE : FALSE; } BOOL IsBlockedOnFsm(VOID) const { return (BOOL) _MessageFlags.Flags.BlockedOnFsm; } VOID SetBlockedOnFsm(BOOL Value) { _MessageFlags.Flags.BlockedOnFsm = (Value) ? TRUE : FALSE; } PROXY_MESSAGE_TYPE QueryForInfoMessage(VOID) const { return _pmProxyQuery; } DWORD GetError(VOID) { return _Error; } DWORD GetNextProxy( IN BAD_PROXY_LIST & BadProxyList ) { BOOL fSuccess; INET_ASSERT(_pProxyState); fSuccess = _pProxyState->GetNextProxy( _tUrlProtocol, BadProxyList, &_tProxyScheme, &_lpszProxyHostName, &_bFreeProxyHostName, &_dwProxyHostNameLength, &_nProxyHostPort ); SetUseProxy(fSuccess); return ERROR_SUCCESS; } }; // // AUTO_PROXY_LIST_ENTRY - contains DLL entry points, and state information, // for a particalar Auto-Proxy DLL. // class AUTO_PROXY_LIST_ENTRY { private: friend class AUTO_PROXY_DLLS; // // _fDelayedInitialization - TRUE when we are to have queued initializiation of // this DLL so, it is not done until the first GetProxyInfo call. // BOOL _fDelayedInitialization; // // _List - there may be a variable number of bypass entries // LIST_ENTRY _List; // // _fDefault - TRUE, if this entry is the default auto-proxy entry. // BOOL _fDefault; // // _fInitializedSuccessfully - TRUE, if we have an initalization function // in the autoproxy dll that initalized successfully. This is to // prevent calling other callbacks in the auto-proxy dll if it // failed to initalize. // BOOL _fInitializedSuccessfully; // // _lpszDllFilePath - file path of DLL to load // LPSTR _lpszDllFilePath; // // _lpszFileExtensions - string of ';' delimited file extensions to match against // LPSTR _lpszFileExtensions; // // _lpszMimeType - Mime type string associated with this Auto-Proxy type. // LPSTR _lpszMimeType; // // _hAutoConfigDLL - open handle to DLL that we are handling. // HINSTANCE _hAutoConfigDLL; // // (_pGetProxyInfo) ( ... ) - Callback made into auto-proxy DLL to gather // what proxy(s) we should use for a specific connection. // GET_PROXY_INFO_FN _pGetProxyInfo; // // (_pGetProxyInfoEx) ( ... ) - Callback made into auto-proxy DLL to gather // what proxy(s) we should use for a specific connection. Ex versions // givers caller more control. If Ex is exported, it is used otherwise // GetProyInfo is used. // GET_PROXY_INFO_EX_FN _pGetProxyInfoEx; // // (_pProxyDllInit) ( ... ) - Callback made into auto-proxy DLL to notify // DLL of initialization. // PROXY_DLL_INIT_FN _pProxyDllInit; // // (_pProxyDllInit) ( ... ) - Notifies DLL before shutdown // PROXY_DLL_DEINIT_FN _pProxyDllDeInit; // // (_pProxyInfoInvalid) ( ... ) - A request using the returned proxy in GetProxyInfo was invalid. // PROXY_INFO_INVALID_FN _pProxyInfoInvalid; // // _dwFlags - DWORD flags stored in the registry for this entry. // DWORD _dwFlags; #ifdef INET_DEBUG BOOL _fUnInited; #endif public: AUTO_PROXY_LIST_ENTRY( IN LPSTR lpszDllName, IN LPSTR lpszExtensions, IN LPSTR lpszMimeType, IN BOOL fIsDefault, IN DWORD dwFlags ) { DEBUG_ENTER((DBG_OBJECTS, None, "AUTO_PROXY_LIST_ENTRY", NULL )); InitializeListHead(&_List); _pGetProxyInfo = NULL; _pGetProxyInfoEx = NULL; _pProxyDllInit = NULL; _pProxyDllDeInit = NULL; _pProxyInfoInvalid = NULL; _hAutoConfigDLL = NULL; _lpszDllFilePath = lpszDllName ? NewString(lpszDllName) : NULL; _lpszFileExtensions = lpszExtensions ? NewString(lpszExtensions) : NULL; _lpszMimeType = lpszMimeType ? NewString(lpszMimeType) : NULL; _fDefault = fIsDefault; _fInitializedSuccessfully = FALSE; _fDelayedInitialization = FALSE; _dwFlags = dwFlags; #ifdef INET_DEBUG _fUnInited = FALSE; #endif DEBUG_LEAVE(0); } ~AUTO_PROXY_LIST_ENTRY() { DEBUG_ENTER((DBG_OBJECTS, None, "~AUTO_PROXY_LIST_ENTRY", NULL )); if ( _lpszFileExtensions ) { _lpszFileExtensions = (LPSTR) FREE_MEMORY(_lpszFileExtensions); INET_ASSERT(_lpszFileExtensions == NULL); } if ( _lpszDllFilePath ) { _lpszDllFilePath = (LPSTR) FREE_MEMORY(_lpszDllFilePath ); INET_ASSERT(_lpszDllFilePath == NULL); } if ( _lpszMimeType ) { _lpszMimeType = (LPSTR) FREE_MEMORY(_lpszMimeType); INET_ASSERT(_lpszMimeType == NULL); } //INET_ASSERT(_hAutoConfigDLL == NULL); // should have free libed DLL before calling destructor DEBUG_LEAVE(0); } VOID SetDllName( IN LPSTR lpszDllPath ) { if ( _lpszDllFilePath ) { _lpszDllFilePath = (LPSTR) FREE_MEMORY(_lpszDllFilePath); INET_ASSERT(_lpszDllFilePath == NULL); } _lpszDllFilePath = lpszDllPath; } DWORD LoadEntry( VOID ); VOID UnloadEntry( VOID ); BOOL ProxyInfoInvalid( IN LPSTR lpszMime, IN LPSTR lpszUrl, IN DWORD dwUrlLength, IN LPSTR lpszProxyHostName, IN DWORD dwProxyHostNameLength ); BOOL ProxyDllDeInit( IN LPSTR lpszMime, IN DWORD dwReserved ); DWORD GetProxyInfoEx( IN AUTO_PROXY_ASYNC_MSG *pQueryForProxyInfo ); DWORD GetProxyInfo( IN AUTO_PROXY_ASYNC_MSG *pQueryForProxyInfo ); BOOL DelayProxyDllInit( IN DWORD dwVersion, IN LPSTR lpszDownloadedTempFile, IN LPSTR lpszMime, IN AUTO_PROXY_HELPER_APIS *pAutoProxyCallbacks, IN DWORD dwReserved, OUT LPBOOL lpfCleanupFile ); BOOL ProxyDllInit ( IN DWORD dwVersion, IN LPSTR lpszDownloadedTempFile, IN LPSTR lpszMime, IN AUTO_PROXY_HELPER_APIS *pAutoProxyCallbacks, IN DWORD_PTR dwReserved ); BOOL IsGetProxyInfoEx( VOID ) { if ( _pGetProxyInfoEx ) { return TRUE; } else { return FALSE; } } BOOL IsGetProxyInfo( VOID ) { if ( _pGetProxyInfo ) { return TRUE; } else { return FALSE; } } BOOL IsLoaded( VOID ) { if ( _hAutoConfigDLL ) { return TRUE; } return FALSE; } BOOL IsDefault( VOID ) { return _fDefault; } }; #define MAX_RELOAD_DELAY 45000 // in mins // // AUTO_PROXY_DLLS - tracks a list of regisitered DLLs that handle auto-proxy. // Auto-Proxy is the ability to download a specialized configuration file, // match the file with a registered DLL. The DLL, once matched, will calculate // which proxy(s) to use. // class AUTO_PROXY_DLLS { private: // // _List - serialized list of AUTO_PROXY_LIST_ENTRY objects // SERIALIZED_LIST _List; // // _Error - errors stored here from initialization // DWORD _Error; // // _ProxySettings - the various fields to track our proxy settings // INTERNET_PROXY_INFO_EX _ProxySettings; INTERNET_PROXY_INFO_EX * _pTempProxySettings; // // _pSelectedAutoProxyEntry - selected auto-proxy entry that will // accept all auto-proxy operations. // AUTO_PROXY_LIST_ENTRY * _pSelectedAutoProxyEntry; // // _aphAutoProxyAPIs - A V-Table that is passed into to the Auto-ProxyDll // to allow them to call us for DNS requests. // AUTO_PROXY_HELPER_APIS _aphAutoProxyAPIs; // // _CritSec - acquire this when accessing header structure - stops multiple // threads clashing while modifying or changing auto-proxy information // CRITICAL_SECTION _CritSec; // // _apsState - Used to track the state of this object state, for // syncronization purposes, ( ie when to go async or not ) // AUTO_PROXY_STATE _apsState; // // _dwWaitTimeOut - time till WaitForSingleObject times out. // DWORD _dwWaitTimeOut; // // _fEnableReload - Forces a reload of auto-proxy files every X seconds. // BOOL _fEnableReload; // // _dwLastThreadAccess - Last GetTickCount(). Used to calculate a basic // timer for reloads of auto-proxy files. // DWORD _dwLastThreadAccess; // // _lpszUserAgent - User agent passed in. // LPSTR _lpszUserAgent; // // _hInstUrlmon - to get user agent from // HINSTANCE _hInstUrlmon; // // _fModifiedInProcess - TRUE, if the settings passed in, SHOULD NOT BE PERSISTED to the registry // BOOL _fModifiedInProcess; // // _dwUpdatedProxySettingsVersion - an counter that is updated to match the current version. // that has been refreshed to. Used to note when we need to refresh proxy settings. // DWORD _dwUpdatedProxySettingsVersion; VOID ResetTimerCounter( BOOL fEnableTimer, DWORD dwWaitTimeOut ) { _fEnableReload = fEnableTimer ; if ( _fEnableReload ) { _dwWaitTimeOut = dwWaitTimeOut; _dwLastThreadAccess = GetTickCountWrap(); INET_ASSERT(_dwWaitTimeOut != 0); } else { _dwWaitTimeOut = g_bHibernating ? (DWORD(MAX_RELOAD_DELAY) * 1000 * 60) : DEFAULT_AUTO_PROXY_THREAD_TIME_OUT; } } BOOL ChkForAndUpdateTimerCounter( VOID ) { BOOL fTimetoUpdate = FALSE; if ( _fEnableReload ) { DWORD dwMsecsElapsed = GetTickCountWrap() - _dwLastThreadAccess; if ( dwMsecsElapsed >= _dwWaitTimeOut ) { _dwWaitTimeOut = 0; fTimetoUpdate = TRUE; } else { fTimetoUpdate = FALSE; _dwWaitTimeOut -= dwMsecsElapsed; } _dwLastThreadAccess = GetTickCountWrap(); } else { _dwWaitTimeOut = g_bHibernating ? (DWORD(MAX_RELOAD_DELAY) * 1000 * 60) : DEFAULT_AUTO_PROXY_THREAD_TIME_OUT; } return fTimetoUpdate; } DWORD ReadAutoProxyRegistrySettings( VOID ); VOID SelectAutoProxy( AUTO_PROXY_LIST_ENTRY * pSelectedEntry ) { _pSelectedAutoProxyEntry = pSelectedEntry; } VOID SetState(AUTO_PROXY_STATE apsState) { _apsState = apsState; } AUTO_PROXY_STATE GetState(VOID) { return _apsState; } // // _AsyncQueueList - serialized list of AUTO_PROXY_ASYNC_MSG objects // SERIALIZED_LIST _AsyncQueueList; // // _hAutoProxyThread - handle to thread that processes Auto-Proxy commands. // HANDLE _hAutoProxyThread; // // _hAutoProxyThreadEvent - handle to event that will become signaled when // new auto-proxy messages are to be processed // HANDLE _hAutoProxyThreadEvent; // // _hAutoProxyStartEvent - handle to event that will be used to block // until the auto-proxy thread starts to run. // HANDLE _hAutoProxyStartEvent; // // _dwAutoProxyCurrentThreadId - thread ID of our Auto-Proxy Thread. // DWORD _dwAutoProxyThreadId; // // _hInternetAbortHandle - handle used to forcibly unblock, and thus shutdown auto-proxy // HINTERNET _hInternetAbortHandle; // // _fInAutoProxyThreadShutDown - Set to TRUE when attempting to shutdown Auto-Proxy thread. // BOOL _fInAutoProxyThreadShutDown; VOID SafeThreadShutdown( BOOL fItsTheFinalShutDown ); DWORD StartDownloadOfProxyInfo( IN BOOL fForceRefresh ); DWORD DownloadProxyInfo( IN LPCSTR lpszAutoProxy, IN BOOL fForceRefresh ); DWORD DoNestedProxyInfoDownload( IN LPCSTR lpszAutoProxy, IN LPINTERNET_PROXY_INFO_EX lpProxySettings, IN BOOL fForceRefresh ); DWORD StartBackroundDetectionIfNeeded( VOID ); DWORD GetAutoProxyStringEntry( IN LPSTR lpszRegName, IN OUT LPSTR * lplpszAllocatedRegValue ); DWORD GetHostAddresses( DWORD ** ppdwDetectedInterfaceIp, DWORD * pdwDetectedInterfaceIpCount ) ; BOOL IsExpiredUrl( LPCSTR lpszUrl ); VOID SetExpiredUrl( LPCSTR lpszUrl ); BOOL IsModifiedInProcess(VOID) { return _fModifiedInProcess; } public: AUTO_PROXY_DLLS() { DEBUG_ENTER((DBG_OBJECTS, None, "AUTO_PROXY_DLLS", "" )); InitializeSerializedList(&_List); InitializeSerializedList(&_AsyncQueueList); // // Warning: Initalize vars to NULL, BEFORE AddListFromRegistry is called. // _pSelectedAutoProxyEntry = NULL; _hAutoProxyThreadEvent = NULL; _hAutoProxyThread = NULL; _hAutoProxyStartEvent = NULL; _apsState = AUTO_PROXY_DISABLED; _dwWaitTimeOut = g_bHibernating ? (DWORD(MAX_RELOAD_DELAY) * 1000 * 60) : DEFAULT_AUTO_PROXY_THREAD_TIME_OUT; _fEnableReload = FALSE; _hInternetAbortHandle = NULL; _fInAutoProxyThreadShutDown = FALSE; _dwUpdatedProxySettingsVersion = 0; //_adMode = APDETECT_CHECK_DISABLE; // default for now //_dwLastIPHost = 0; //_dwLastRunCount = 0; //_lpszLastKnownGoodAutoConfigUrl = NULL; //_fNeedInitialDetect = TRUE; // // Zero out our settings structure // memset((void *) &_ProxySettings, 0, sizeof(_ProxySettings)); _pTempProxySettings = NULL; _lpszUserAgent = NULL; _hInstUrlmon = NULL; //_fNeedsDownload = TRUE; //_fAllQueriesMustGoAsync = FALSE; InitializeCriticalSection(&_CritSec); _Error = ReadAutoProxyRegistrySettings(); DEBUG_LEAVE(0); } ~AUTO_PROXY_DLLS() { DEBUG_ENTER((DBG_OBJECTS, None, "~AUTO_PROXY_DLLS", NULL )); INET_ASSERT(!_fInAutoProxyThreadShutDown); // should have shut down thread before hitting destructor DestroyAutoProxyDll(FALSE); // only destroys reg vars. DestroyAutoProxyMsgQueue(); WipeProxySettings(); TerminateSerializedList(&_AsyncQueueList); TerminateSerializedList(&_List); DeleteCriticalSection(&_CritSec); if ( _lpszUserAgent ) { FREE_MEMORY(_lpszUserAgent); } if (_hInstUrlmon) { FreeLibrary (_hInstUrlmon); } DEBUG_LEAVE(0); } VOID ActivateThread() { if (_hAutoProxyThreadEvent) { SetEvent(_hAutoProxyThreadEvent); } } VOID DestroyAutoProxyDll( IN BOOL fUnloadDlls ) { LockAutoProxy(); LockSerializedList(&_List); while (!IsSerializedListEmpty(&_List)) { // // remove the PROXY_BYPASS_LIST_ENTRY at the head of the serialized // list // LPVOID entry = SlDequeueHead(&_List); AUTO_PROXY_LIST_ENTRY *pAutoProxyDllEntry; // // entry should not be NULL - IsSerializedListEmpty() told us we // could expect something // INET_ASSERT(entry != NULL); pAutoProxyDllEntry = CONTAINING_RECORD(entry, AUTO_PROXY_LIST_ENTRY, _List); if ( fUnloadDlls ) { pAutoProxyDllEntry->UnloadEntry(); } delete pAutoProxyDllEntry; } UnlockSerializedList(&_List); UnlockAutoProxy(); } VOID DestroyAutoProxyMsgQueue( VOID ) { // // Destroy any Async Queue. // LockSerializedList(&_AsyncQueueList); while (!IsSerializedListEmpty(&_AsyncQueueList)) { //INET_ASSERT(IsOnAsyncAutoProxyThread()); // // remove the PROXY_BYPASS_LIST_ENTRY at the head of the serialized // list // LPVOID entry = SlDequeueHead(&_AsyncQueueList); // // entry should not be NULL - IsSerializedListEmpty() told us we // could expect something // INET_ASSERT(entry != NULL); // // get the address of the object (should be the same as entry) and // delete it // delete CONTAINING_RECORD(entry, AUTO_PROXY_ASYNC_MSG, _List); } UnlockSerializedList(&_AsyncQueueList); } VOID WipeProxySettings( LPINTERNET_PROXY_INFO_EX lpProxySettings ); VOID WipeProxySettings(VOID) { WipeProxySettings(&_ProxySettings); } DWORD GetError(VOID) const { return _Error; } VOID SetAbortHandle(HINTERNET hInternet) { _hInternetAbortHandle = hInternet; } VOID AbortAutoProxy(VOID) { if ( _hInternetAbortHandle ) { InternetCloseHandle(_hInternetAbortHandle); } } BOOL SelectAutoProxyByFileExtension( LPCSTR lpszAutoProxyPath ); BOOL SelectAutoProxyByDefault( VOID ); BOOL SelectAutoProxyByMime( IN LPSTR lpszMimeType ); BOOL IsAutoProxy( VOID ) { BOOL fIsAutoProxy; LockAutoProxy(); fIsAutoProxy = ! IsSerializedListEmpty(&_List); UnlockAutoProxy(); return fIsAutoProxy; } BOOL IsAutoProxyThreadReadyForRequests( VOID ) { BOOL fReady; LockAutoProxy(); fReady = (GetState() == AUTO_PROXY_ENABLED) ? TRUE : FALSE; UnlockAutoProxy(); return fReady; } AUTO_PROXY_LIST_ENTRY * GetSelectedAutoProxyEntry( VOID ) { return _pSelectedAutoProxyEntry; } VOID LockAutoProxy(VOID) { EnterCriticalSection(&_CritSec); } VOID UnlockAutoProxy(VOID) { LeaveCriticalSection(&_CritSec); } BOOL IsOnAsyncAutoProxyThread(VOID) const { return ( GetCurrentThreadId() == _dwAutoProxyThreadId ); } BOOL IsProxyAutoDetectEnabled(LPINTERNET_PROXY_INFO_EX lpProxySettings) { return (lpProxySettings->dwFlags & PROXY_TYPE_AUTO_DETECT); } BOOL IsProxyAutoDetectEnabled(VOID) { return (IsProxyAutoDetectEnabled(&_ProxySettings)); } BOOL IsProxyAutoConfigEnabled(LPINTERNET_PROXY_INFO_EX lpProxySettings) { return (lpProxySettings->dwFlags & PROXY_TYPE_AUTO_PROXY_URL); } BOOL IsProxyAutoConfigEnabled(VOID) { return (IsProxyAutoConfigEnabled(&_ProxySettings)); } BOOL IsConfigValidForAutoProxyThread( VOID ); BOOL IsProxyAutoDetectNeeded( LPINTERNET_PROXY_INFO_EX lpProxySettings ); BOOL IsStaticFallbackEnabled( VOID ); DWORD CheckForTimerConfigChanges( IN DWORD dwMinsToPoll ); BOOL IsAutoProxyEnabled( VOID ); BOOL IsAutoProxyGetProxyInfoCallNeeded( IN AUTO_PROXY_ASYNC_MSG *pQueryForInfo ); DWORD QueueAsyncAutoProxyRequest( IN OUT AUTO_PROXY_ASYNC_MSG **ppQueryForInfo ); DWORD ProcessProxyQueryForInfo( IN OUT AUTO_PROXY_ASYNC_MSG **ppQueryForInfo ) ; DWORD DoThreadProcessing( VOID ); DWORD ProcessAsyncAutoProxyRequest( VOID ); DWORD SignalAsyncRequestCompleted( IN AUTO_PROXY_ASYNC_MSG *pQueryForInfo ); VOID FreeAutoProxyInfo( VOID ); DWORD SetProxySettings( IN LPINTERNET_PROXY_INFO_EX lpProxySettings, IN BOOL fModifiedInProcess, IN BOOL fAllowOverwrite ); DWORD GetProxySettings( OUT LPINTERNET_PROXY_INFO_EX lpProxySettings, IN BOOL fCheckVersion = FALSE ); BOOL GetAutoProxyThreadSettings( OUT LPINTERNET_PROXY_INFO_EX lpProxySettings ) { if ( _pTempProxySettings ) { *lpProxySettings = *_pTempProxySettings; return TRUE; } //else return FALSE; } BOOL SetAutoProxyThreadSettings( OUT LPINTERNET_PROXY_INFO_EX lpProxySettings ) { if ( _pTempProxySettings ) { *_pTempProxySettings = *lpProxySettings; return TRUE; } // else return FALSE; } DWORD RefreshProxySettings( IN BOOL fForceRefresh ); DWORD QueryProxySettings( IN OUT AUTO_PROXY_ASYNC_MSG **ppQueryForInfo ); VOID SaveDetectedProxySettings( IN LPINTERNET_PROXY_INFO_EX lpProxySettings, IN BOOL fNeedHostIPChk ); }; // // external func declariations, note that the DLL does not have to export the full set of these // functions, rather the DLL can export only the functions it impliments. // BOOL CALLBACK InternetProxyInfoInvalid ( // NOT implimented IN LPSTR lpszMime, IN LPSTR lpszUrl, IN DWORD dwUrlLength, IN LPSTR lpszProxyHostName, IN DWORD dwProxyHostNameLength ); EXTERN_C BOOL CALLBACK AUTOCONF_InternetDeInitializeAutoProxyDll( IN LPSTR lpszMime, IN DWORD dwReserved ); EXTERN_C BOOL CALLBACK InternetGetProxyInfo( IN LPCSTR lpszUrl, IN DWORD dwUrlLength, IN LPSTR lpszUrlHostName, IN DWORD dwUrlHostNameLength, OUT LPSTR * lplpszProxyHostName, OUT LPDWORD lpdwProxyHostNameLength ) ; BOOL CALLBACK InternetGetProxyInfoEx( IN INTERNET_SCHEME tUrlProtocol, IN LPCSTR lpszUrl, IN DWORD dwUrlLength, IN LPSTR lpszUrlHostName, IN DWORD dwUrlHostNameLength, IN INTERNET_PORT nUrlPort, OUT LPINTERNET_SCHEME lptProxyScheme, OUT LPSTR * lplpszProxyHostName, OUT LPDWORD lpdwProxyHostNameLength, OUT LPINTERNET_PORT lpProxyHostPort ) ; EXTERN_C BOOL CALLBACK AUTOCONF_InternetInitializeAutoProxyDll( IN DWORD dwVersion, IN LPSTR lpszDownloadedTempFile, IN LPSTR lpszMime, IN AUTO_PROXY_HELPER_APIS *pAutoProxyCallbacks, IN DWORD dwReserved ); INTERNETAPI_(BOOL) DetectAutoProxyUrl( IN OUT LPSTR lpszAutoProxyUrl, IN DWORD dwAutoProxyUrlLength, IN DWORD dwDetectFlags ); EXTERN_C BOOL CALLBACK InternetInitializeAutoProxyDll( DWORD dwReserved ); #endif /* _AUTOPROX_HXX_ */