Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

4904 lines
122 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. autoprox.cxx
  5. Abstract:
  6. Contains class implementation for auto-proxy DLLs which can extent WININET's
  7. abilities (logic) for deciding what proxies to use.
  8. How auto-proxy works:
  9. By offloading requests to a specialized Win32 Thread which picks
  10. up queued up message requests for Queries, Shutdown, and Initialization
  11. Contents:
  12. InternetInitializeAutoProxyDll
  13. AUTO_PROXY_DLLS::CheckForTimerConfigChanges
  14. AUTO_PROXY_DLLS::DoNestedProxyInfoDownload
  15. AUTO_PROXY_DLLS::SelectAutoProxyByMime
  16. AUTO_PROXY_DLLS::SelectAutoProxyByFileExtension
  17. AUTO_PROXY_DLLS::SelectAutoProxyByDefault
  18. AUTO_PROXY_DLLS::ReadAutoProxyRegistrySettings
  19. AUTO_PROXY_DLLS::IsAutoProxyEnabled
  20. AUTO_PROXY_DLLS::IsAutoProxyGetProxyInfoCallNeeded
  21. AUTO_PROXY_DLLS::QueueAsyncAutoProxyRequest
  22. AUTO_PROXY_DLLS::ProcessProxyQueryForInfo
  23. AUTO_PROXY_DLLS::SafeThreadShutdown
  24. AUTO_PROXY_DLLS::DoThreadProcessing
  25. AUTO_PROXY_DLLS::ProcessAsyncAutoProxyRequest
  26. AUTO_PROXY_DLLS::SignalAsyncRequestCompleted
  27. AUTO_PROXY_DLLS::FreeAutoProxyInfo
  28. AUTO_PROXY_LIST_ENTRY::LoadEntry
  29. AUTO_PROXY_LIST_ENTRY::GetProxyInfoEx
  30. AUTO_PROXY_LIST_ENTRY::ProxyInfoInvalid
  31. AUTO_PROXY_LIST_ENTRY::ProxyDllInit
  32. AUTO_PROXY_LIST_ENTRY::ProxyDllDeInit
  33. (MatchFileExtensionWithUrl)
  34. (AutoProxyThreadFunc)
  35. Author:
  36. Arthur L Bierer (arthurbi) 17-Dec-1996
  37. Revision History:
  38. 17-Dec-1996 arthurbi
  39. Created
  40. --*/
  41. #include <wininetp.h>
  42. #include "autodial.h"
  43. #include "apdetect.h"
  44. //
  45. // definitions
  46. //
  47. #define DEFAULT_SCRIPT_BUFFER_SIZE 4000 // bytes.
  48. //
  49. // BUGBUG [arthurbi] This structures are shared between
  50. // wininet.dll && jsproxy.dll, shouldn't we move them
  51. // into a central file???
  52. //
  53. #define AUTO_PROXY_REG_FLAG_ALLOW_STRUC 0x0001
  54. typedef struct {
  55. //
  56. // Size of struct
  57. //
  58. DWORD dwStructSize;
  59. //
  60. // Buffer to Pass
  61. //
  62. LPSTR lpszScriptBuffer;
  63. //
  64. // Size of buffer above
  65. //
  66. DWORD dwScriptBufferSize;
  67. } AUTO_PROXY_EXTERN_STRUC, *LPAUTO_PROXY_EXTERN_STRUC;
  68. //
  69. // private templates
  70. //
  71. PRIVATE
  72. BOOL
  73. MatchFileExtensionWithUrl(
  74. IN LPCSTR lpszFileExtensionList,
  75. IN LPCSTR lpszUrl
  76. );
  77. //
  78. // private vars
  79. //
  80. //
  81. // functions
  82. //
  83. INTERNETAPI_(BOOL)
  84. InternetInitializeAutoProxyDll(
  85. DWORD dwReserved
  86. )
  87. /*++
  88. Routine Description:
  89. Stub to make INETCPL work. Since they expect to call this function.
  90. Arguments:
  91. none.
  92. Return Value:
  93. BOOL
  94. TRUE - success
  95. --*/
  96. {
  97. BOOL fSuccess;
  98. DWORD error = ERROR_SUCCESS;
  99. DEBUG_ENTER((DBG_PROXY,
  100. Bool,
  101. "InternetInitializeAutoProxyDll",
  102. ""
  103. ));
  104. if (!GlobalDataInitialized) {
  105. error = GlobalDataInitialize();
  106. }
  107. if (error == ERROR_SUCCESS) {
  108. GlobalProxyInfo.ClearBadProxyList();
  109. FixProxySettingsForCurrentConnection(TRUE);
  110. GlobalProxyInfo.RefreshProxySettings(TRUE);
  111. }
  112. fSuccess = (error == ERROR_SUCCESS ) ? TRUE : FALSE;
  113. DEBUG_LEAVE(fSuccess);
  114. return fSuccess;
  115. }
  116. DWORD
  117. WINAPI
  118. AutoProxyThreadFunc(
  119. LPVOID lpAutoProxyObject
  120. )
  121. /*++
  122. Routine Description:
  123. Initialization Win32 Proc called when the auto-proxy thread is started.
  124. Arguments:
  125. none.
  126. Return Value:
  127. DWORD
  128. ERROR_SUCCESS - success
  129. Win32 Error code - failure
  130. --*/
  131. {
  132. return GlobalProxyInfo.DoThreadProcessing(lpAutoProxyObject);
  133. }
  134. //
  135. // methods
  136. //
  137. DWORD
  138. AUTO_PROXY_DLLS::CheckForTimerConfigChanges(
  139. IN DWORD dwMinsToPoll
  140. )
  141. /*++
  142. Routine Description:
  143. Exames the registry to see if a timer has been turned so
  144. that we poll auto-proxy every so often to check for updates
  145. Arguments:
  146. none.
  147. Return Value:
  148. DWORD
  149. ERROR_SUCCESS - success
  150. Win32 Error code - failure
  151. --*/
  152. {
  153. DWORD error = ERROR_SUCCESS;
  154. DWORD dwReloadMins = dwMinsToPoll;
  155. BOOL fEnableTimer = FALSE;
  156. //
  157. // Now check to determine if we have to enable the auto-proxy e
  158. // this is used to force a re-download every "X" minutes.
  159. //
  160. if ( dwReloadMins != 0 )
  161. {
  162. if ( dwReloadMins > MAX_RELOAD_DELAY ) // too big?...
  163. {
  164. dwReloadMins = MAX_RELOAD_DELAY;
  165. }
  166. dwReloadMins *= ( 1000 * 60 ); // convert mins to miliseconds
  167. fEnableTimer = TRUE;
  168. }
  169. //
  170. // enable/disable timer for auto-proxy refresh.
  171. //
  172. ResetTimerCounter(
  173. fEnableTimer, // TRUE/FALSE enable/disable
  174. dwReloadMins // conv-ed already to msecs
  175. );
  176. error = ERROR_SUCCESS;
  177. return error;
  178. }
  179. DWORD
  180. AUTO_PROXY_DLLS::StartDownloadOfProxyInfo(
  181. IN BOOL fForceRefresh
  182. )
  183. /*++
  184. Routine Description:
  185. Does the Overall download of proxy-information from an internally accessable Web Server.
  186. Handles the case where we may have to redownload a secondary script also takes
  187. care of launching detection for proxies.
  188. Arguments:
  189. fForceRefresh - TRUE if we are to attempt to refresh the auto-proxy URLs, and force a redection
  190. Return Value:
  191. DWORD
  192. ERROR_SUCCESS - success
  193. Win32 Error code - failure
  194. --*/
  195. {
  196. DWORD error = ERROR_SUCCESS;
  197. BOOL fLocked = FALSE;
  198. DWORD dwcbAutoConfigProxy = 0;
  199. LPCSTR lpszAutoProxyUrl = NULL;
  200. INTERNET_PROXY_INFO_EX ProxySettings;
  201. BOOL fProxySettingsAlloced = FALSE;
  202. BOOL fNeedRegWrite = FALSE;
  203. BOOL fCachedDialupDetection = FALSE;
  204. BOOL fNeedHostIPChk = FALSE;
  205. DEBUG_ENTER((DBG_PROXY,
  206. Dword,
  207. "AUTO_PROXY_DLLS::StartDownloadOfProxyInfo",
  208. "%B",
  209. fForceRefresh
  210. ));
  211. if ( IsOffline() )
  212. {
  213. error = ERROR_INTERNET_OFFLINE;
  214. goto quit;
  215. }
  216. LockAutoProxy();
  217. fLocked = TRUE;
  218. error = GetProxySettings(&ProxySettings);
  219. if (error != ERROR_SUCCESS ) {
  220. goto quit;
  221. }
  222. fProxySettingsAlloced = TRUE;
  223. //
  224. // Now read from the registry, closing any stale stuff that we may still have
  225. // around. Do we still really need this? Lets only do this for Refresh cases.
  226. //
  227. if ( fForceRefresh )
  228. {
  229. DestroyAutoProxyDll(TRUE); // unloads DLLs and frees up reg vars.
  230. SelectAutoProxy(NULL);
  231. _Error = ReadAutoProxyRegistrySettings();
  232. error = _Error;
  233. if (error != ERROR_SUCCESS ||
  234. !IsConfigValidForAutoProxyThread() )
  235. {
  236. SetState(AUTO_PROXY_DISABLED);
  237. goto quit;
  238. }
  239. if ( GetState() == AUTO_PROXY_DISABLED )
  240. {
  241. INET_ASSERT(FALSE); // do we need this code?
  242. goto quit;
  243. }
  244. }
  245. //INET_ASSERT(GetState() == AUTO_PROXY_BLOCKED ||
  246. // GetState() == AUTO_PROXY_PENDING);
  247. fLocked = FALSE;
  248. UnlockAutoProxy();
  249. //
  250. // Now begin the work, we should no longer need to touch the Proxy_DLL object
  251. // settings until we grab the AutoProxy Lock again.
  252. //
  253. do
  254. {
  255. if ( IsProxyAutoDetectEnabled(&ProxySettings) )
  256. {
  257. CHAR szUrl[1024];
  258. BOOL fRet;
  259. DWORD dwDetectFlags = PROXY_AUTO_DETECT_TYPE_DNS_A;
  260. if ( fForceRefresh ||
  261. IsProxyAutoDetectNeeded(&ProxySettings) )
  262. {
  263. //
  264. // Release Old Auto-config URL
  265. //
  266. if ( ProxySettings.lpszLastKnownGoodAutoConfigUrl) {
  267. FREE_MEMORY(ProxySettings.lpszLastKnownGoodAutoConfigUrl);
  268. ProxySettings.lpszLastKnownGoodAutoConfigUrl = NULL;
  269. }
  270. // only do dhcp on net connections
  271. if ( ProxySettings.lpszConnectionName == NULL ) {
  272. dwDetectFlags |= PROXY_AUTO_DETECT_TYPE_DHCP;
  273. }
  274. //
  275. // Save out the Host IP addresses, before we start the detection,
  276. // after the detection is complete, we confirm that we're still
  277. // on the same set of Host IPs, in case the user switched connections.
  278. //
  279. error = GetHostAddresses(&(ProxySettings.pdwDetectedInterfaceIp),
  280. &(ProxySettings.dwDetectedInterfaceIpCount));
  281. if ( error != ERROR_SUCCESS) {
  282. goto quit;
  283. }
  284. fNeedHostIPChk = TRUE; // because we've saved our IPs
  285. //
  286. // Do the actual Detection work
  287. //
  288. fRet = DetectAutoProxyUrl(
  289. szUrl,
  290. ARRAY_ELEMENTS(szUrl),
  291. dwDetectFlags
  292. );
  293. GetCurrentGmtTime(&ProxySettings.ftLastKnownDetectTime); // mark when detection was run.
  294. //
  295. // Process the Results of detection.
  296. //
  297. if ( fRet )
  298. {
  299. ProxySettings.dwAutoDiscoveryFlags |= AUTO_PROXY_FLAG_DETECTION_RUN;
  300. ProxySettings.lpszLastKnownGoodAutoConfigUrl = NewString(szUrl);
  301. if ( ProxySettings.lpszLastKnownGoodAutoConfigUrl == NULL )
  302. {
  303. error = ERROR_NOT_ENOUGH_MEMORY;
  304. goto quit;
  305. }
  306. SetExpiredUrl(szUrl);
  307. fNeedRegWrite = TRUE;
  308. }
  309. else
  310. {
  311. //
  312. // Disable auto-detection, if we failed
  313. //
  314. if ( ! (ProxySettings.dwAutoDiscoveryFlags & (AUTO_PROXY_FLAG_DETECTION_RUN | AUTO_PROXY_FLAG_USER_SET)) )
  315. {
  316. ProxySettings.dwFlags &= ~(PROXY_TYPE_AUTO_DETECT);
  317. }
  318. ProxySettings.dwAutoDiscoveryFlags |= AUTO_PROXY_FLAG_DETECTION_RUN;
  319. fNeedRegWrite = TRUE;
  320. }
  321. }
  322. else if ( ProxySettings.lpszLastKnownGoodAutoConfigUrl != NULL &&
  323. ProxySettings.lpszConnectionName != NULL )
  324. {
  325. //
  326. // If we're not doing any detection, and we're on a dial-up adapter,
  327. // then we should remember that fact, since we may be called upon
  328. // to actually force a detect, in case the cached URL was stale/bad.
  329. //
  330. INET_ASSERT(! fForceRefresh );
  331. fCachedDialupDetection = TRUE;
  332. }
  333. lpszAutoProxyUrl = ProxySettings.lpszLastKnownGoodAutoConfigUrl;
  334. }
  335. //
  336. // Falback if we are unable to detect something
  337. //
  338. if ( lpszAutoProxyUrl == NULL &&
  339. IsProxyAutoConfigEnabled(&ProxySettings))
  340. {
  341. lpszAutoProxyUrl = ProxySettings.lpszAutoconfigUrl;
  342. }
  343. //
  344. // Do the actual download of the file
  345. //
  346. if (lpszAutoProxyUrl != NULL)
  347. {
  348. error = DoNestedProxyInfoDownload(lpszAutoProxyUrl, &ProxySettings, fForceRefresh);
  349. if ( error != ERROR_SUCCESS )
  350. {
  351. //
  352. // If we're cached + on a dialup, and we fail with the URL,
  353. // then perhaps the URL/net is really expired.
  354. //
  355. if ( fCachedDialupDetection &&
  356. ! fForceRefresh )
  357. {
  358. fForceRefresh = TRUE;
  359. continue;
  360. }
  361. //
  362. // Fallback to autoconfig if we failed and we were using
  363. // auto-detect
  364. //
  365. if ( IsProxyAutoConfigEnabled(&ProxySettings) &&
  366. lpszAutoProxyUrl != ProxySettings.lpszAutoconfigUrl &&
  367. ProxySettings.lpszAutoconfigUrl != NULL )
  368. {
  369. lpszAutoProxyUrl = ProxySettings.lpszAutoconfigUrl;
  370. error = DoNestedProxyInfoDownload(lpszAutoProxyUrl, &ProxySettings, fForceRefresh);
  371. }
  372. }
  373. }
  374. } while (FALSE);
  375. LockAutoProxy();
  376. fLocked = TRUE;
  377. if (lpszAutoProxyUrl == NULL)
  378. {
  379. SetState(AUTO_PROXY_DISABLED);
  380. goto quit;
  381. }
  382. else
  383. {
  384. // stamp version so we know we just ran detection
  385. _dwUpdatedProxySettingsVersion =
  386. ProxySettings.dwCurrentSettingsVersion;
  387. SetState(AUTO_PROXY_ENABLED);
  388. }
  389. CheckForTimerConfigChanges(ProxySettings.dwAutoconfigReloadDelayMins);
  390. quit:
  391. if ( error != ERROR_SUCCESS )
  392. {
  393. if (!fLocked)
  394. {
  395. LockAutoProxy();
  396. fLocked = TRUE;
  397. }
  398. SetState(AUTO_PROXY_DISABLED);
  399. }
  400. //
  401. // Unlock the AutoProxy
  402. //
  403. if ( fLocked ) {
  404. UnlockAutoProxy();
  405. }
  406. if ( fProxySettingsAlloced )
  407. {
  408. //
  409. // We need to save results to registry,
  410. // then stamp the version in our global we now we detected for this,
  411. // and then finally clean up any allocated stuff.
  412. //
  413. SaveDetectedProxySettings(&ProxySettings, fNeedHostIPChk);
  414. WipeProxySettings(&ProxySettings);
  415. }
  416. DEBUG_LEAVE(error);
  417. return error;
  418. }
  419. DWORD
  420. AUTO_PROXY_DLLS::DoNestedProxyInfoDownload(
  421. IN LPCSTR lpszAutoProxy,
  422. IN LPINTERNET_PROXY_INFO_EX lpProxySettings,
  423. IN BOOL fForceRefresh
  424. )
  425. /*++
  426. Routine Description:
  427. Does the download of proxy-information from an internally accessable Web Server.
  428. Handles the case where we may have to redownload a secondary script and then
  429. calls on to DownloadProxyInfo to actually do the dirty work.
  430. Arguments:
  431. lpszAutoProxy - URL to download
  432. lpProxySettings - active Proxy Settings Copy for auto-proxy thread.
  433. fForceRefresh - force refresh of downloaded file
  434. Return Value:
  435. DWORD
  436. ERROR_SUCCESS - success
  437. Win32 Error code - failure
  438. --*/
  439. {
  440. LPCSTR lpszNestedAutoProxyUrl = NULL;
  441. DWORD error;
  442. _pTempProxySettings = lpProxySettings; // in case they reset proxy settings
  443. if ( _fInAutoProxyThreadShutDown )
  444. {
  445. error = ERROR_INTERNET_SHUTDOWN;
  446. goto quit;
  447. }
  448. //
  449. // IEAK flag, don't retry INS file unless either one of the following:
  450. // 1) INS URL is expired
  451. // 2) caching INS run is disabled
  452. // 3) we're not forcing a refresh
  453. //
  454. if ( !(lpProxySettings->dwAutoDiscoveryFlags & AUTO_PROXY_FLAG_CACHE_INIT_RUN ) ||
  455. // !(ProxySettings.dwAutoDiscoveryFlags & AUTO_PROXY_FLAG_DETECTION_RUN ) ||
  456. !fForceRefresh ||
  457. IsExpiredUrl(lpszAutoProxy))
  458. {
  459. //
  460. // Now do the actual download of the proxy info.
  461. //
  462. error =
  463. DownloadProxyInfo(lpszAutoProxy, fForceRefresh);
  464. if ( error != ERROR_SUCCESS )
  465. {
  466. goto quit;
  467. }
  468. }
  469. //
  470. // Now check to determine if we have an overriding Auto-Proxy that
  471. // supersides the one we just download. If we do, we will
  472. // need to redownload auto-proxy
  473. //
  474. lpszNestedAutoProxyUrl = lpProxySettings->lpszAutoconfigSecondaryUrl;
  475. if ( lpszNestedAutoProxyUrl )
  476. {
  477. //
  478. // Success - now restart the download process for this special Url
  479. //
  480. error = DownloadProxyInfo(
  481. lpszNestedAutoProxyUrl,
  482. fForceRefresh
  483. );
  484. }
  485. // fall through even in error
  486. error = ERROR_SUCCESS;
  487. quit:
  488. INET_ASSERT(_pTempProxySettings);
  489. _pTempProxySettings = NULL;
  490. return error;
  491. }
  492. DWORD
  493. AUTO_PROXY_DLLS::DownloadProxyInfo(
  494. IN LPCSTR lpszAutoProxy,
  495. IN BOOL fForceRefresh
  496. )
  497. /*++
  498. Routine Description:
  499. Does the download of proxy-information from an internally accessable Web Server.
  500. The data will be checked, written to a temp file, and then an associated
  501. DLL will be called to handle it.
  502. Arguments:
  503. lpszUrl - The URL to download.
  504. fForceRefresh - force file to be reloaded from the wire
  505. Return Value:
  506. DWORD
  507. ERROR_SUCCESS - success
  508. Win32 Error code - failure
  509. --*/
  510. {
  511. HINTERNET hInternet = NULL;
  512. HINTERNET hRequest = NULL;
  513. HANDLE hFile = NULL;
  514. CHAR szTemporyFile[MAX_PATH+1];
  515. DWORD dwTempFileSize;
  516. HANDLE hLockHandle = NULL;
  517. BOOL fSuccess;
  518. DWORD error = ERROR_SUCCESS;
  519. CHAR szBuffer[MAX_PATH+1];
  520. DWORD dwBytesRead;
  521. BOOL fCleanupFile = FALSE;
  522. BOOL fLocked = FALSE;
  523. BOOL fBuffering = FALSE;
  524. LPSTR lpszScriptBuffer = NULL;
  525. DWORD dwScriptBufferSize;
  526. DWORD dwStatusCode = ERROR_SUCCESS;
  527. DWORD cbSize = sizeof(DWORD);
  528. int nRetries = 3; // Num auth attempts
  529. DEBUG_ENTER((DBG_PROXY,
  530. Dword,
  531. "AUTO_PROXY_DLLS::DownloadProxyInfo",
  532. "%q",
  533. lpszAutoProxy
  534. ));
  535. INET_ASSERT(lpszAutoProxy);
  536. //
  537. // Fire up a mini InternetOpen/InternetOpenUrl to download a
  538. // config file found on some internal server.
  539. //
  540. hInternet = InternetOpen(
  541. (_lpszUserAgent) ? _lpszUserAgent : gszDefaultUserAgent,
  542. INTERNET_OPEN_TYPE_DIRECT,
  543. NULL,
  544. NULL,
  545. 0
  546. );
  547. if ( !hInternet )
  548. {
  549. error = GetLastError();
  550. INET_ASSERT(error != ERROR_SUCCESS);
  551. goto quit;
  552. }
  553. do
  554. {
  555. hRequest = InternetOpenUrl(
  556. hInternet,
  557. lpszAutoProxy,
  558. "Accept: */*\r\n",
  559. (DWORD) -1,
  560. (fForceRefresh ?
  561. INTERNET_FLAG_RELOAD :
  562. 0) |
  563. INTERNET_FLAG_NEED_FILE,
  564. INTERNET_NO_CALLBACK
  565. );
  566. if ( !hRequest )
  567. {
  568. //error = ERROR_INTERNET_UNABLE_TO_DOWNLOAD_SCRIPT;
  569. error = GetLastError();
  570. if(GlobalDisplayScriptDownloadFailureUI && !GlobalIsProcessNtService)
  571. {
  572. InternetErrorDlg(
  573. GetDesktopWindow(),
  574. hRequest,
  575. ERROR_INTERNET_UNABLE_TO_DOWNLOAD_SCRIPT,
  576. FLAGS_ERROR_UI_FILTER_FOR_ERRORS,
  577. NULL);
  578. }
  579. goto quit;
  580. }
  581. cbSize = sizeof(dwStatusCode);
  582. if (HttpQueryInfo(
  583. hRequest,
  584. HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER,
  585. (LPVOID) &dwStatusCode,
  586. &cbSize,
  587. NULL
  588. ) && HTTP_STATUS_DENIED == dwStatusCode)
  589. {
  590. if (GlobalIsProcessNtService)
  591. {
  592. error = ERROR_INTERNET_INTERNAL_ERROR;
  593. goto quit;
  594. }
  595. // Check the status code and throw an InternetErrorDlg
  596. // if auth is needed and try again.
  597. if (InternetErrorDlg(
  598. GetDesktopWindow(),
  599. hRequest,
  600. ERROR_INTERNET_INCORRECT_PASSWORD,
  601. FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS,
  602. NULL
  603. ) != ERROR_INTERNET_FORCE_RETRY)
  604. {
  605. nRetries = 0;
  606. }
  607. else
  608. {
  609. cbSize = sizeof(szBuffer);
  610. HttpQueryInfo(
  611. hRequest,
  612. HTTP_QUERY_WWW_AUTHENTICATE,
  613. (LPVOID) szBuffer,
  614. &cbSize,
  615. NULL
  616. );
  617. szBuffer[5]='\0';
  618. if (!lstrcmpi(szBuffer, "Basic"))
  619. {
  620. HttpSendRequest(
  621. hRequest,
  622. "Accept: */*\r\n",
  623. (DWORD)-1,
  624. NULL,
  625. 0);
  626. cbSize = sizeof(dwStatusCode);
  627. if (HttpQueryInfo(
  628. hRequest,
  629. HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER,
  630. (LPVOID) &dwStatusCode,
  631. &cbSize,
  632. NULL
  633. ) && HTTP_STATUS_DENIED == dwStatusCode)
  634. {
  635. InternetCloseHandle(hRequest);
  636. }
  637. else
  638. {
  639. GlobalAutoProxyNeedsInit = FALSE;
  640. break;
  641. }
  642. }
  643. else
  644. InternetCloseHandle(hRequest);
  645. }
  646. }
  647. else
  648. {
  649. // Call it good
  650. GlobalAutoProxyNeedsInit = FALSE;
  651. break;
  652. }
  653. } while ( --nRetries>0);
  654. if(nRetries <= 0)
  655. {
  656. // Still haven't initialized.
  657. GlobalAutoProxyNeedsInit = TRUE;
  658. }
  659. // Reset to success
  660. error = ERROR_SUCCESS;
  661. if(HTTP_STATUS_NOT_FOUND == dwStatusCode)
  662. {
  663. error = ERROR_INTERNET_UNABLE_TO_DOWNLOAD_SCRIPT;
  664. if(GlobalDisplayScriptDownloadFailureUI && !GlobalIsProcessNtService)
  665. {
  666. InternetErrorDlg(
  667. GetDesktopWindow(),
  668. hRequest,
  669. ERROR_INTERNET_UNABLE_TO_DOWNLOAD_SCRIPT,
  670. FLAGS_ERROR_UI_FILTER_FOR_ERRORS,
  671. NULL);
  672. }
  673. goto quit;
  674. }
  675. DWORD dwIndex;
  676. DWORD dwTempSize;
  677. dwIndex = 0;
  678. dwTempSize = sizeof(dwScriptBufferSize);
  679. dwScriptBufferSize = 0;
  680. if ( ! HttpQueryInfo(hRequest,
  681. (HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER),
  682. (LPVOID) &dwScriptBufferSize,
  683. &dwTempSize,
  684. &dwIndex) )
  685. {
  686. // failure, just defaults
  687. dwScriptBufferSize = DEFAULT_SCRIPT_BUFFER_SIZE;
  688. fBuffering = TRUE;
  689. }
  690. else if ( dwScriptBufferSize > DEFAULT_SCRIPT_BUFFER_SIZE )
  691. {
  692. // success, but too big.
  693. dwScriptBufferSize = DEFAULT_SCRIPT_BUFFER_SIZE;
  694. fBuffering = FALSE;
  695. }
  696. else
  697. {
  698. // success, and this one is just right.
  699. fBuffering = TRUE;
  700. }
  701. lpszScriptBuffer = (LPSTR)
  702. ALLOCATE_MEMORY(LMEM_FIXED, ((dwScriptBufferSize+1)
  703. * sizeof(CHAR)));
  704. if ( lpszScriptBuffer == NULL )
  705. {
  706. error = ERROR_NOT_ENOUGH_MEMORY;
  707. goto quit;
  708. }
  709. //
  710. // pull down bytes, and write to file
  711. //
  712. DWORD dwBytes;
  713. dwBytesRead = 0;
  714. do
  715. {
  716. DWORD dwBytesLeft;
  717. LPSTR lpszDest;
  718. dwBytes = 0;
  719. lpszDest = lpszScriptBuffer;
  720. dwBytesLeft = dwScriptBufferSize;
  721. fSuccess = InternetReadFile(
  722. hRequest,
  723. lpszDest,
  724. dwBytesLeft,
  725. &dwBytes
  726. );
  727. if ( ! fSuccess )
  728. {
  729. error = GetLastError();
  730. goto quit;
  731. }
  732. if ( _fInAutoProxyThreadShutDown )
  733. {
  734. error = ERROR_INTERNET_SHUTDOWN;
  735. goto quit;
  736. }
  737. if ( dwBytes > 0 )
  738. {
  739. if ( dwBytesRead > 0 )
  740. {
  741. fBuffering = FALSE;
  742. }
  743. dwBytesRead += dwBytes;
  744. }
  745. } while ( dwBytes != 0 );
  746. //
  747. // Figure out what kind of file we're dealing with.
  748. // ONLY allow files with the correct extension or the correct MIME type.
  749. //
  750. szBuffer[0] = '\0';
  751. dwBytes = ARRAY_ELEMENTS(szBuffer)-1;
  752. fSuccess = HttpQueryInfo( hRequest,
  753. HTTP_QUERY_CONTENT_TYPE,
  754. szBuffer,
  755. &dwBytes,
  756. NULL );
  757. fLocked = TRUE;
  758. LockAutoProxy();
  759. if ( !(fSuccess
  760. && SelectAutoProxyByMime(szBuffer)) )
  761. {
  762. if ( ! SelectAutoProxyByFileExtension(lpszAutoProxy) )
  763. {
  764. if ( ! SelectAutoProxyByDefault() )
  765. {
  766. //
  767. // Could not find a registered handler for this data.
  768. //
  769. error = ERROR_INTERNET_BAD_AUTO_PROXY_SCRIPT;
  770. goto quit;
  771. }
  772. }
  773. }
  774. //
  775. // Now, launch the handler to tell them about the file.
  776. // we downloaded it first.
  777. //
  778. AUTO_PROXY_LIST_ENTRY * papleAutoProxy;
  779. AUTO_PROXY_EXTERN_STRUC apeStruct;
  780. LPAUTO_PROXY_EXTERN_STRUC pExtraStruct;
  781. papleAutoProxy = GetSelectedAutoProxyEntry();
  782. pExtraStruct = NULL;
  783. //
  784. // Get a temp file from cache if we need it.
  785. //
  786. if ( fBuffering &&
  787. (papleAutoProxy->_dwFlags & AUTO_PROXY_REG_FLAG_ALLOW_STRUC) &&
  788. dwBytesRead > 0 )
  789. {
  790. // slam a \0 terminator
  791. INET_ASSERT(dwBytesRead <= dwScriptBufferSize);
  792. lpszScriptBuffer[dwBytesRead] = '\0';
  793. pExtraStruct = &apeStruct;
  794. apeStruct.dwStructSize = sizeof(AUTO_PROXY_EXTERN_STRUC);
  795. apeStruct.lpszScriptBuffer = lpszScriptBuffer;
  796. apeStruct.dwScriptBufferSize = dwBytesRead + 1;
  797. }
  798. else
  799. {
  800. fCleanupFile = TRUE;
  801. //Qfe 3430: When parsing ins file, with reference to pac file, wininet needs to
  802. //know the connectoid name in order to set the pac file correctly. Currently there
  803. //is no way for wininet to pass the connectoid name to branding dll. To workaround
  804. //this, we use the AUTO_PROXY_EXTERN_STRUC to pass the connectoid name in lpszScriptBuffer
  805. //variable.
  806. if(!(papleAutoProxy->_dwFlags & AUTO_PROXY_REG_FLAG_ALLOW_STRUC))
  807. {
  808. pExtraStruct = &apeStruct;
  809. apeStruct.dwStructSize = sizeof(AUTO_PROXY_EXTERN_STRUC);
  810. apeStruct.lpszScriptBuffer = GlobalProxyInfo.GetConnectionName();
  811. }
  812. if ( ! InternetLockRequestFile(hRequest, &hLockHandle) )
  813. {
  814. fCleanupFile = FALSE;
  815. }
  816. dwTempFileSize = MAX_PATH;
  817. if ( ! InternetQueryOption(hRequest, INTERNET_OPTION_DATAFILE_NAME,
  818. szTemporyFile, &dwTempFileSize ) ||
  819. dwTempFileSize == 0 )
  820. {
  821. error = ERROR_INTERNET_BAD_AUTO_PROXY_SCRIPT;
  822. goto quit;
  823. }
  824. }
  825. //
  826. // The loading and unloading of DLLs is owned/allowed
  827. // only by the auto-proxy thread, ONCE THIS THREAD IS RUNNING
  828. // so once we're here, we can be assured its safe to
  829. // make the following calls without holding the crit sec.
  830. //
  831. INET_ASSERT(fLocked);
  832. UnlockAutoProxy();
  833. fLocked = FALSE;
  834. fSuccess = TRUE;
  835. //
  836. // If we're not configured, or cannot match the URL
  837. // with a Handler to actually run the script,
  838. // then we need to error out
  839. //
  840. if ( papleAutoProxy == NULL)
  841. {
  842. error = ERROR_INTERNET_UNABLE_TO_DOWNLOAD_SCRIPT;
  843. goto quit;
  844. }
  845. if ( ! papleAutoProxy->_hAutoConfigDLL )
  846. {
  847. if ( _fInAutoProxyThreadShutDown )
  848. {
  849. error = ERROR_INTERNET_SHUTDOWN;
  850. goto quit;
  851. }
  852. error = papleAutoProxy->LoadEntry();
  853. if ( error != ERROR_SUCCESS )
  854. {
  855. goto quit;
  856. }
  857. }
  858. else if ( papleAutoProxy->_fInitializedSuccessfully &&
  859. papleAutoProxy->_pProxyDllInit &&
  860. papleAutoProxy->_pProxyDllDeInit )
  861. {
  862. //
  863. // If this DLL has already been loaded,
  864. // then unitialize it before re-initalizeing with
  865. // new data, otherwise we risk leaking some its
  866. // objects
  867. //
  868. papleAutoProxy->ProxyDllDeInit(
  869. szBuffer,
  870. 0
  871. );
  872. INET_ASSERT(papleAutoProxy->_fUnInited);
  873. }
  874. //
  875. // Make the call into the external DLL,
  876. // and let it run, possibly initilization and doing a bunch
  877. // of stuff.
  878. //
  879. fSuccess = papleAutoProxy->ProxyDllInit (
  880. AUTO_PROXY_VERSION,
  881. szTemporyFile, // temp file we down loaded
  882. szBuffer, // mime
  883. &_aphAutoProxyAPIs,
  884. (DWORD_PTR) pExtraStruct
  885. );
  886. if ( _fInAutoProxyThreadShutDown )
  887. {
  888. error = ERROR_INTERNET_SHUTDOWN;
  889. goto quit;
  890. }
  891. if ( ! fSuccess )
  892. {
  893. error = ERROR_INTERNET_BAD_AUTO_PROXY_SCRIPT;
  894. goto quit;
  895. }
  896. if ( papleAutoProxy->IsGetProxyInfoEx() ||
  897. papleAutoProxy->IsGetProxyInfo() )
  898. {
  899. SetState(AUTO_PROXY_ENABLED);
  900. }
  901. else
  902. {
  903. SetState(AUTO_PROXY_DISABLED);
  904. }
  905. quit:
  906. if ( error != ERROR_SUCCESS )
  907. {
  908. if (!fLocked)
  909. {
  910. LockAutoProxy();
  911. fLocked = TRUE;
  912. }
  913. SetState(AUTO_PROXY_DISABLED);
  914. }
  915. if ( fLocked )
  916. {
  917. UnlockAutoProxy();
  918. }
  919. if ( fCleanupFile )
  920. {
  921. InternetUnlockRequestFile(hLockHandle);
  922. }
  923. if ( lpszScriptBuffer )
  924. {
  925. FREE_MEMORY(lpszScriptBuffer);
  926. }
  927. if ( hRequest )
  928. {
  929. InternetCloseHandle(hRequest);
  930. }
  931. if ( hInternet )
  932. {
  933. InternetCloseHandle(hInternet);
  934. }
  935. SetAbortHandle(NULL);
  936. DEBUG_LEAVE(error);
  937. return error;
  938. }
  939. BOOL
  940. AUTO_PROXY_DLLS::IsAutoProxyEnabled(
  941. VOID
  942. )
  943. /*++
  944. Routine Description:
  945. Determines whether the auto-proxy thread is enabled and ready
  946. to accept async proxy requests. This is needed to prevent
  947. senceless calls to the auto-proxy thread when the request
  948. could made more directly to the PROXY_INFO object.
  949. Return Value:
  950. BOOL
  951. TRUE - the AutoProxy thread is accepting async requests
  952. FALSE - the AutoProxy thread is refusung async requests.
  953. --*/
  954. {
  955. BOOL fIsGetProxyCallProxyNeeded = FALSE;
  956. DEBUG_ENTER((DBG_PROXY,
  957. Bool,
  958. "AUTO_PROXY_DLLS::IsAutoProxyEnabled",
  959. ""
  960. ));
  961. LockAutoProxy();
  962. //
  963. // If we're downloading new information, OR we have a async thread ready to process
  964. // autoproxy queries, then go async and do the request. The worst case will
  965. // result in the async thread being created and then returning the request
  966. // unprocessed ( the FSM will resubmit it to the general proxy code )
  967. //
  968. if ( GetState() == AUTO_PROXY_ENABLED ||
  969. GetState() == AUTO_PROXY_BLOCKED ||
  970. GetState() == AUTO_PROXY_PENDING )
  971. {
  972. fIsGetProxyCallProxyNeeded = TRUE;
  973. }
  974. else
  975. {
  976. fIsGetProxyCallProxyNeeded = FALSE;
  977. }
  978. UnlockAutoProxy();
  979. DEBUG_LEAVE(fIsGetProxyCallProxyNeeded);
  980. return fIsGetProxyCallProxyNeeded;
  981. }
  982. BOOL
  983. AUTO_PROXY_DLLS::IsAutoProxyGetProxyInfoCallNeeded(
  984. IN AUTO_PROXY_ASYNC_MSG *pQueryForInfo
  985. )
  986. /*++
  987. Routine Description:
  988. Wrapper for IsAutoProxyEnabled, verifies that the message object (pQueryForInfo)
  989. in question is capible of going async.
  990. Arguments:
  991. pQueryForInfo - Pointer to Message object that contains state information
  992. used in the query.
  993. Return Value:
  994. BOOL
  995. TRUE - the AutoProxy thread is accepting async requests
  996. FALSE - the AutoProxy thread is refusung async requests.
  997. --*/
  998. {
  999. INET_ASSERT(pQueryForInfo);
  1000. //
  1001. // The caller has explicitly banned auto-proxy calls.
  1002. //
  1003. if ( pQueryForInfo->IsAvoidAsyncCall() )
  1004. {
  1005. return FALSE;
  1006. }
  1007. //
  1008. // We cannot process this request to auto-proxy unless we have an URL
  1009. //
  1010. if ( ! pQueryForInfo->IsUrl() )
  1011. {
  1012. return FALSE;
  1013. }
  1014. //
  1015. // Now check to see if its really enabled.
  1016. //
  1017. return IsAutoProxyEnabled();
  1018. }
  1019. DWORD
  1020. AUTO_PROXY_DLLS::QueueAsyncAutoProxyRequest(
  1021. IN OUT AUTO_PROXY_ASYNC_MSG **ppQueryForInfo
  1022. )
  1023. /*++
  1024. Routine Description:
  1025. Submits the *ppQueryForInfo Object on the async queue for processing
  1026. by the async auto-proxy thread.
  1027. Arguments:
  1028. ppQueryForInfo - Pointer to pointer to Message object that contains state information
  1029. used in the query. If the object needs to be allocated on the heap
  1030. then the pointer will change to reflect the new object ptr.
  1031. Return Value:
  1032. DWORD
  1033. Success - ERROR_SUCCESS
  1034. Failure -
  1035. --*/
  1036. {
  1037. LPINTERNET_THREAD_INFO lpThreadInfo = InternetGetThreadInfo();
  1038. BOOL fLocked = FALSE;
  1039. DWORD error = ERROR_SUCCESS;
  1040. DEBUG_ENTER((DBG_PROXY,
  1041. Dword,
  1042. "AUTO_PROXY_DLLS::QueueAsyncAutoProxyRequest",
  1043. "%x",
  1044. ppQueryForInfo
  1045. ));
  1046. //
  1047. // First allocate an object, if its not allocated,
  1048. // cause we can't pass local stack vars to another thread (duh..)
  1049. //
  1050. if ( ! (*ppQueryForInfo)->IsAlloced() )
  1051. {
  1052. *ppQueryForInfo = new AUTO_PROXY_ASYNC_MSG(*ppQueryForInfo);
  1053. if ( *ppQueryForInfo == NULL )
  1054. {
  1055. error = ERROR_NOT_ENOUGH_MEMORY;
  1056. goto quit;
  1057. }
  1058. }
  1059. LockAutoProxy(); // lock object to prevent anyone messing with thread handles
  1060. fLocked = TRUE;
  1061. //
  1062. // Busy wait for thread to be shutdown before restarting.
  1063. //
  1064. while ( _fInAutoProxyThreadShutDown )
  1065. {
  1066. UnlockAutoProxy();
  1067. Sleep(100);
  1068. LockAutoProxy();
  1069. }
  1070. if ( _hAutoProxyThread == NULL )
  1071. {
  1072. _hAutoProxyThreadEvent = CreateEvent(
  1073. NULL, // pointer to security attributes
  1074. FALSE, // flag for manual-reset event
  1075. TRUE, // flag for initial state
  1076. NULL // event-object name
  1077. );
  1078. if ( _hAutoProxyThreadEvent == NULL )
  1079. {
  1080. error = GetLastError();
  1081. goto quit;
  1082. }
  1083. //
  1084. // We block on this event until the thread is actually running,
  1085. // otherwise we may PROCESS_DETEACH while the auto-proxy
  1086. // thread is in this quasi-state of having been created, but not actually run.
  1087. //
  1088. _hAutoProxyStartEvent = CreateEvent(
  1089. NULL, // pointer to security attributes
  1090. TRUE, // flag for manual-reset event
  1091. FALSE, // flag for initial state
  1092. NULL // event-object name
  1093. );
  1094. if ( _hAutoProxyStartEvent == NULL )
  1095. {
  1096. error = GetLastError();
  1097. goto quit;
  1098. }
  1099. ResetEvent(_hAutoProxyStartEvent);
  1100. _hAutoProxyThread = CreateThread(
  1101. NULL, // pointer to thread security attributes
  1102. 0, // starting stack size
  1103. AutoProxyThreadFunc,
  1104. this, // argument
  1105. 0, // flags
  1106. &_dwAutoProxyThreadId
  1107. );
  1108. if ( _hAutoProxyThread == NULL )
  1109. {
  1110. error = GetLastError();
  1111. CloseHandle(_hAutoProxyThreadEvent);
  1112. CloseHandle(_hAutoProxyStartEvent);
  1113. _hAutoProxyThreadEvent = NULL;
  1114. _hAutoProxyStartEvent = NULL;
  1115. goto quit;
  1116. }
  1117. const HANDLE aWaitHandles[2] = {_hAutoProxyStartEvent, _hAutoProxyThread};
  1118. // wait on the thread handle too in case it terminates for some unknown reason
  1119. error = WaitForMultipleObjects(ARRAYSIZE(aWaitHandles),
  1120. aWaitHandles,
  1121. FALSE,
  1122. INFINITE);
  1123. if ( error != WAIT_OBJECT_0 )
  1124. {
  1125. INET_ASSERT(FALSE);
  1126. TerminateThread(_hAutoProxyThread, ERROR_SUCCESS);
  1127. CloseHandle(_hAutoProxyThreadEvent);
  1128. CloseHandle(_hAutoProxyStartEvent);
  1129. CloseHandle(_hAutoProxyThread);
  1130. _hAutoProxyStartEvent = NULL;
  1131. _hAutoProxyThread = NULL;
  1132. _hAutoProxyThreadEvent = NULL;
  1133. _dwAutoProxyThreadId = NULL;
  1134. error = ERROR_INTERNET_INTERNAL_ERROR;
  1135. goto quit;
  1136. }
  1137. else
  1138. {
  1139. CloseHandle(_hAutoProxyStartEvent);
  1140. _hAutoProxyStartEvent = NULL;
  1141. }
  1142. }
  1143. //
  1144. // Now Block the Thread we're on...
  1145. //
  1146. if ( (*ppQueryForInfo)->IsBlockUntilCompletetion() )
  1147. {
  1148. if ( lpThreadInfo &&
  1149. lpThreadInfo->Fsm &&
  1150. lpThreadInfo->IsAsyncWorkerThread &&
  1151. !(lpThreadInfo->Fsm->IsBlocking()))
  1152. {
  1153. //
  1154. // In a FSM, use FSM - thread pool handler to block this.
  1155. //
  1156. (*ppQueryForInfo)->SetBlockedOnFsm(TRUE);
  1157. lpThreadInfo->Fsm->SetState(FSM_STATE_CONTINUE);
  1158. lpThreadInfo->Fsm->SetNextState(FSM_STATE_CONTINUE);
  1159. error = BlockWorkItem(
  1160. lpThreadInfo->Fsm,
  1161. (DWORD_PTR) *ppQueryForInfo, // block the FSM on ourselves
  1162. INFINITE // we block foreever
  1163. );
  1164. if ( error != ERROR_SUCCESS )
  1165. {
  1166. goto quit;
  1167. }
  1168. InsertAtTailOfSerializedList(&_AsyncQueueList, &(*ppQueryForInfo)->_List);
  1169. SetEvent(_hAutoProxyThreadEvent);
  1170. error = ERROR_IO_PENDING;
  1171. }
  1172. else
  1173. {
  1174. AcquireBlockedRequestQueue();
  1175. InsertAtTailOfSerializedList(&_AsyncQueueList, &(*ppQueryForInfo)->_List);
  1176. SetEvent(_hAutoProxyThreadEvent);
  1177. UnlockAutoProxy();
  1178. fLocked = FALSE;
  1179. error = BlockThreadOnEvent(
  1180. (DWORD_PTR) *ppQueryForInfo,
  1181. INFINITE, // we need to block forever !
  1182. TRUE // release BlockedRequestQueue
  1183. );
  1184. }
  1185. }
  1186. else
  1187. {
  1188. InsertAtTailOfSerializedList(&_AsyncQueueList, &(*ppQueryForInfo)->_List);
  1189. SetEvent(_hAutoProxyThreadEvent);
  1190. }
  1191. quit:
  1192. if ( fLocked )
  1193. {
  1194. UnlockAutoProxy();
  1195. fLocked = FALSE;
  1196. }
  1197. DEBUG_LEAVE(error);
  1198. return error;
  1199. }
  1200. DWORD
  1201. AUTO_PROXY_DLLS::ProcessProxyQueryForInfo(
  1202. IN OUT AUTO_PROXY_ASYNC_MSG **ppQueryForInfo
  1203. )
  1204. /*++
  1205. Routine Description:
  1206. Performs a query for proxy information using an external DLL's entry points to
  1207. anwser our query. If we are not on the correct thread, we call QueueAsyncAutoProxyRequest
  1208. to marshall our call across to it.
  1209. Arguments:
  1210. ppQueryForInfo - Pointer to pointer to Message object that contains state information
  1211. used in the query. If the object needs to be allocated on the heap
  1212. then the pointer will change to reflect the new object ptr.
  1213. Return Value:
  1214. DWORD
  1215. Success - ERROR_SUCCESS
  1216. Failure -
  1217. --*/
  1218. {
  1219. AUTO_PROXY_LIST_ENTRY * papleAutoProxy;
  1220. DWORD error = ERROR_SUCCESS;
  1221. BOOL fUnlocked = FALSE;
  1222. DEBUG_ENTER((DBG_PROXY,
  1223. Dword,
  1224. "AUTO_PROXY_DLLS::ProcessProxyQueryForInfo",
  1225. "%x",
  1226. ppQueryForInfo
  1227. ));
  1228. INET_ASSERT(ppQueryForInfo);
  1229. INET_ASSERT(*ppQueryForInfo);
  1230. INET_ASSERT((*ppQueryForInfo)->QueryForInfoMessage() == PROXY_MSG_GET_PROXY_INFO);
  1231. INET_ASSERT(IsOnAsyncAutoProxyThread());
  1232. LockAutoProxy();
  1233. //
  1234. // this function should only ever be executed on the auto-proxy thread
  1235. //
  1236. if ( GetState() == AUTO_PROXY_DISABLED )
  1237. {
  1238. //
  1239. // Fall back to a normal proxy query.
  1240. //
  1241. (*ppQueryForInfo)->SetAvoidAsyncCall(TRUE);
  1242. goto quit;
  1243. }
  1244. papleAutoProxy =
  1245. GetSelectedAutoProxyEntry();
  1246. //
  1247. // We should be the only ones to create or destroy
  1248. // auto-proxy info, therefore we release the holly
  1249. // lock of auto-proxy. If I'm wrong another thread
  1250. // could cause us trouble ...
  1251. //
  1252. UnlockAutoProxy();
  1253. fUnlocked = TRUE;
  1254. if ( papleAutoProxy )
  1255. {
  1256. //
  1257. // If GetProxyInfoEx is supported, we defer to it to handle
  1258. // everything.
  1259. //
  1260. if ( papleAutoProxy->IsGetProxyInfoEx() )
  1261. {
  1262. error = papleAutoProxy->GetProxyInfoEx(
  1263. *ppQueryForInfo
  1264. );
  1265. goto quit;
  1266. }
  1267. else if ( papleAutoProxy->IsGetProxyInfo() )
  1268. {
  1269. error = papleAutoProxy->GetProxyInfo(
  1270. *ppQueryForInfo
  1271. );
  1272. goto quit;
  1273. }
  1274. else
  1275. {
  1276. //
  1277. // Fall back to a normal proxy query.
  1278. //
  1279. (*ppQueryForInfo)->SetAvoidAsyncCall(TRUE);
  1280. }
  1281. }
  1282. else
  1283. {
  1284. //
  1285. // Fall back to a normal proxy query.
  1286. //
  1287. (*ppQueryForInfo)->SetAvoidAsyncCall(TRUE);
  1288. }
  1289. quit:
  1290. if ( !fUnlocked )
  1291. {
  1292. UnlockAutoProxy();
  1293. }
  1294. DEBUG_LEAVE(error);
  1295. return error;
  1296. }
  1297. VOID
  1298. AUTO_PROXY_DLLS::SafeThreadShutdown(
  1299. BOOL fItsTheFinalShutDown
  1300. )
  1301. /*++
  1302. Routine Description:
  1303. Performs a shutdown of the auto-proxy thread by the auto-proxy thread itself.
  1304. Arguments:
  1305. fItsTheFinalShutDown - TRUE, if we are shutting down at the end of a process
  1306. Return Value:
  1307. none.
  1308. --*/
  1309. {
  1310. DEBUG_ENTER((DBG_PROXY,
  1311. None,
  1312. "AUTO_PROXY_DLLS::SafeThreadShutdown",
  1313. "%B",
  1314. fItsTheFinalShutDown
  1315. ));
  1316. //
  1317. // Attempt to Shut down thread due to no-activity OR
  1318. // due to process shutdown.
  1319. //
  1320. LockAutoProxy();
  1321. if ( IsSerializedListEmpty(&_AsyncQueueList) ||
  1322. fItsTheFinalShutDown )
  1323. {
  1324. //HANDLE hAutoProxyThreadEvent = _hAutoProxyThreadEvent;
  1325. //HANDLE hAutoProxyThread = _hAutoProxyThread;
  1326. //_hAutoProxyThread = NULL;
  1327. //_hAutoProxyThreadEvent = NULL;
  1328. _dwAutoProxyThreadId = 0;
  1329. //CloseHandle(hAutoProxyThreadEvent);
  1330. //CloseHandle(hAutoProxyThread);
  1331. UnlockAutoProxy();
  1332. if ( fItsTheFinalShutDown )
  1333. {
  1334. //DestroyAutoProxyMsgQueue();
  1335. DestroyAutoProxyDll(TRUE); // unloads DLLs and frees up reg vars
  1336. }
  1337. DEBUG_LEAVE(0);
  1338. ExitThread(ERROR_SUCCESS);
  1339. INET_ASSERT(FALSE); //we will never get here...
  1340. }
  1341. UnlockAutoProxy();
  1342. DEBUG_LEAVE(0);
  1343. }
  1344. #define NLA_ERROR_RETRY_INTERVAL (5*60*1000)
  1345. class NLA_NET_CHANGE {
  1346. private:
  1347. HANDLE _hLookup;
  1348. WSAOVERLAPPED _ovlp;
  1349. DWORD _lastInitAttempt;
  1350. BOOLEAN
  1351. Initialize ();
  1352. BOOLEAN
  1353. EnumerateNetChanges ();
  1354. public:
  1355. NLA_NET_CHANGE () {
  1356. _ovlp.hEvent = NULL;
  1357. if (GlobalPlatformWhistler &&
  1358. _I_WSALookupServiceBeginW!=NULL) {
  1359. _hLookup = NULL;
  1360. _lastInitAttempt = GetTickCount ()-NLA_ERROR_RETRY_INTERVAL-1;
  1361. }
  1362. else {
  1363. #if DBG
  1364. dprintf ("NLA not available: whistler-%ld, lookup:-%#x\n",
  1365. GlobalPlatformWhistler, _I_WSALookupServiceBeginW);
  1366. #endif
  1367. _hLookup = INVALID_HANDLE_VALUE;
  1368. }
  1369. };
  1370. ~NLA_NET_CHANGE () {
  1371. if (_hLookup!=NULL && _hLookup!=INVALID_HANDLE_VALUE) {
  1372. #if DBG
  1373. dprintf ("NLA - cleaning up");
  1374. #endif
  1375. _I_WSALookupServiceEnd (_hLookup);
  1376. CloseHandle (_ovlp.hEvent);
  1377. }
  1378. };
  1379. BOOLEAN
  1380. IsNetChanged () {
  1381. if (_hLookup!=INVALID_HANDLE_VALUE) {
  1382. if ((_hLookup!=NULL) ||
  1383. ( ((GetTickCount ()-_lastInitAttempt)
  1384. >NLA_ERROR_RETRY_INTERVAL) &&
  1385. Initialize () ) ) {
  1386. if (HasOverlappedIoCompleted (&_ovlp)) {
  1387. #if DBG
  1388. dprintf ("NLA change detected, status:%lx\n",
  1389. _ovlp.Internal);
  1390. #endif
  1391. return EnumerateNetChanges ();
  1392. }
  1393. }
  1394. }
  1395. return FALSE;
  1396. };
  1397. HANDLE
  1398. GetChangeEvent () {
  1399. return _ovlp.hEvent;
  1400. };
  1401. };
  1402. BOOLEAN
  1403. NLA_NET_CHANGE::Initialize (
  1404. )
  1405. /*++
  1406. Routine Description:
  1407. Initializes Network Location Awareness lookup query.
  1408. Arguments:
  1409. Return Value:
  1410. TRUE - succes
  1411. FALSE - failure
  1412. --*/
  1413. {
  1414. WSAQUERYSETW qset;
  1415. GUID nlaServiceClassId = NLA_SERVICE_CLASS_GUID;
  1416. DWORD qSize;
  1417. INT error;
  1418. INET_ASSERT (_ovlp.hEvent==NULL);
  1419. INET_ASSERT (_hLookup==NULL);
  1420. //
  1421. // Create event for async notifications.
  1422. //
  1423. _ovlp.hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
  1424. if (_ovlp.hEvent!=NULL) {
  1425. ZeroMemory (&qset, sizeof (qset));
  1426. qset.dwSize = sizeof (qset);
  1427. qset.lpServiceClassId = &nlaServiceClassId;
  1428. qset.dwNameSpace = NS_NLA;
  1429. if (_I_WSALookupServiceBeginW (
  1430. &qset,
  1431. LUP_RETURN_NAME|LUP_RETURN_BLOB,
  1432. &_hLookup)!=SOCKET_ERROR) {
  1433. DEBUG_PRINT (PROXY, INFO, ("Nla Lookup created\n"));
  1434. #if DBG
  1435. dprintf ("NLA Lookup created, handle:%#x\n", _hLookup);
  1436. #endif
  1437. //
  1438. // Just walk through the net list and setup notification.
  1439. //
  1440. return EnumerateNetChanges ();
  1441. }
  1442. else {
  1443. error = GetLastError ();
  1444. DEBUG_PRINT (PROXY, ERROR,
  1445. ("NLA Lookup creation failed, err: %ld\n",
  1446. error));
  1447. #if DBG
  1448. dprintf ("NLA Lookup creation failed, err: %ld\n",error);
  1449. #endif
  1450. }
  1451. _hLookup = NULL;
  1452. CloseHandle (_ovlp.hEvent);
  1453. _ovlp.hEvent = NULL;
  1454. }
  1455. else {
  1456. error = GetLastError ();
  1457. DEBUG_PRINT (PROXY, ERROR,
  1458. ("NLA notification event creation failed, err: %ld\n",
  1459. error));
  1460. #if DBG
  1461. dprintf ("NLA notification event creation failed, err: %ld\n",
  1462. error);
  1463. #endif
  1464. }
  1465. INET_ASSERT (error!=NO_ERROR);
  1466. //
  1467. // Remember when we failed, so we do not retry very often.
  1468. //
  1469. _lastInitAttempt = GetTickCountWrap ();
  1470. return FALSE;
  1471. }
  1472. BOOLEAN
  1473. NLA_NET_CHANGE::EnumerateNetChanges (
  1474. )
  1475. /*++
  1476. Routine Description:
  1477. Enumerates Network entries returned by the NLA query.
  1478. If this is called after change notification, only
  1479. changes since last enumeration are returned.
  1480. Arguments:
  1481. None.
  1482. Return Value:
  1483. TRUE - there were any relevant changes
  1484. FALSE - no relevant changes.
  1485. --*/
  1486. {
  1487. DWORD error = NO_ERROR;
  1488. // Stack buffer which should be sufficient for most cases.
  1489. struct {
  1490. WSAQUERYSETW set;
  1491. WCHAR name[128];
  1492. NLA_BLOB blob;
  1493. } q;
  1494. LPWSAQUERYSETW pqSet = &q.set;
  1495. DWORD qSize = sizeof (q), retSize;
  1496. BOOLEAN changed = FALSE;
  1497. INET_ASSERT (_hLookup!=NULL && _hLookup!=INVALID_HANDLE_VALUE);
  1498. INET_ASSERT (_ovlp.hEvent!=NULL);
  1499. INET_ASSERT (HasOverlappedIoCompleted (&_ovlp));
  1500. do {// Outer loop - keep calling while we are getting notifications.
  1501. do {// Inner loop - keep calling while enumerating through networks.
  1502. retSize = qSize;
  1503. error = _I_WSALookupServiceNextW (
  1504. _hLookup,
  1505. 0,
  1506. &retSize,
  1507. pqSet);
  1508. if (error!=SOCKET_ERROR) {
  1509. INET_ASSERT (error==NO_ERROR);
  1510. //
  1511. // Success, see if results in this query are relevant
  1512. //
  1513. DEBUG_PRINT (PROXY, INFO,
  1514. ("NLA change for %ws-%lx\n",
  1515. pqSet->lpszServiceInstanceName,
  1516. pqSet->dwOutputFlags));
  1517. #if DBG
  1518. dprintf ("NLA change for %ws-%lx\n",
  1519. pqSet->lpszServiceInstanceName,
  1520. pqSet->dwOutputFlags);
  1521. #endif
  1522. if ((pqSet->lpBlob!=NULL) &&
  1523. (pqSet->lpBlob->pBlobData!=NULL) &&
  1524. (((LPNLA_BLOB)pqSet->lpBlob->pBlobData)->header.type==NLA_INTERFACE) ) {
  1525. #if DBG
  1526. dprintf (" type:%ld, speed:%ld, name: %s\n",
  1527. ((LPNLA_BLOB)pqSet->lpBlob->pBlobData)->data.interfaceData.dwType,
  1528. ((LPNLA_BLOB)pqSet->lpBlob->pBlobData)->data.interfaceData.dwSpeed,
  1529. ((LPNLA_BLOB)pqSet->lpBlob->pBlobData)->data.interfaceData.adapterName);
  1530. #endif
  1531. changed = TRUE;
  1532. }
  1533. }
  1534. else {
  1535. error = GetLastError ();
  1536. INET_ASSERT (error!=NO_ERROR);
  1537. if (error==WSAEFAULT) {
  1538. INET_ASSERT (qSize<retSize);
  1539. //
  1540. // Not enough space for query results.
  1541. // Allocate whatever is requested.
  1542. // First free what we have know is necessary.
  1543. //
  1544. if (pqSet!=NULL && pqSet!=&q.set) {
  1545. FREE_MEMORY (pqSet);
  1546. }
  1547. pqSet = (LPWSAQUERYSETW)ALLOCATE_MEMORY (LMEM_FIXED, retSize);
  1548. if (pqSet!=NULL) {
  1549. qSize = retSize;
  1550. error = NO_ERROR;
  1551. }
  1552. else {
  1553. DEBUG_PRINT (PROXY, ERROR,
  1554. ("NLA - Failed to allocate %ld bytes for query\n",
  1555. retSize));
  1556. #if DBG
  1557. dprintf
  1558. ("NLA - Failed to allocate %ld bytes for query\n",
  1559. retSize);
  1560. #endif
  1561. error = ERROR_NOT_ENOUGH_MEMORY;
  1562. }
  1563. }
  1564. }
  1565. }
  1566. while ( error==NO_ERROR );
  1567. if (error == WSA_E_NO_MORE) {
  1568. WSACOMPLETION wsacmpl;
  1569. DWORD count;
  1570. //
  1571. // This is expected error indicating that we got all that
  1572. // was available at the moment. Set up new notification.
  1573. //
  1574. wsacmpl.Type = NSP_NOTIFY_EVENT;
  1575. wsacmpl.Parameters.Event.lpOverlapped = &_ovlp;
  1576. error = _I_WSANSPIoctl (_hLookup, SIO_NSP_NOTIFY_CHANGE, NULL, 0, NULL, 0, &count, &wsacmpl);
  1577. if (error!=SOCKET_ERROR) {
  1578. //
  1579. // Something has changed, we need to enumerate again.
  1580. //
  1581. INET_ASSERT (error==NO_ERROR);
  1582. #if DBG
  1583. dprintf ("NLA notification signaled immediately");
  1584. #endif
  1585. }
  1586. else {
  1587. //
  1588. // Failure, get the error and get out.
  1589. //
  1590. error = GetLastError ();
  1591. INET_ASSERT (error!=NO_ERROR);
  1592. }
  1593. }
  1594. }
  1595. while (error==NO_ERROR);
  1596. if (pqSet!=NULL && pqSet!=&q.set) {
  1597. FREE_MEMORY (pqSet);
  1598. }
  1599. else {
  1600. INET_ASSERT (qSize==sizeof (q));
  1601. }
  1602. if (error!=WSA_IO_PENDING) {
  1603. DEBUG_PRINT (PROXY, ERROR,
  1604. ("NLA - Failed to setup notification, error: %ld\n",
  1605. error));
  1606. #if DBG
  1607. dprintf (
  1608. "NLA - Failed to setup notification, error: %ld\n",
  1609. error);
  1610. #endif
  1611. //
  1612. // Error other then pending means that we failed.
  1613. // Cleanup everything - query will get recreated
  1614. // next time someone asks for changes.
  1615. //
  1616. CloseHandle (_ovlp.hEvent);
  1617. _ovlp.hEvent = NULL;
  1618. _I_WSALookupServiceEnd (_hLookup);
  1619. _hLookup = NULL;
  1620. //
  1621. // Remember when we failed, so we do not retry very often.
  1622. //
  1623. _lastInitAttempt = GetTickCountWrap ();
  1624. }
  1625. return changed;
  1626. }
  1627. DWORD
  1628. AUTO_PROXY_DLLS::DoThreadProcessing(
  1629. VOID
  1630. )
  1631. /*++
  1632. Routine Description:
  1633. Main function for the auto-proxy thread, maintains a generic loop
  1634. that dispatchs events/messages sent to our thread for processing
  1635. Arguments:
  1636. none.
  1637. Return Value:
  1638. none.
  1639. --*/
  1640. {
  1641. DWORD error = ERROR_SUCCESS;
  1642. LPINTERNET_THREAD_INFO lpThreadInfo;
  1643. HANDLE EventArray[2];
  1644. NLA_NET_CHANGE nlaChange;
  1645. BOOLEAN needRefresh;
  1646. EventArray[0] = _hAutoProxyThreadEvent;
  1647. INET_ASSERT(IsOnAsyncAutoProxyThread());
  1648. INET_ASSERT(_hAutoProxyStartEvent);
  1649. SetEvent(_hAutoProxyStartEvent);
  1650. lpThreadInfo = InternetGetThreadInfo();
  1651. if (lpThreadInfo == NULL) {
  1652. error = ERROR_INTERNET_INTERNAL_ERROR;
  1653. goto quit;
  1654. }
  1655. //
  1656. // Mark ourselves as the Auto-proxy thread...
  1657. //
  1658. _InternetSetAutoProxy(lpThreadInfo);
  1659. while ( TRUE )
  1660. {
  1661. BOOLEAN networkChanged;
  1662. //
  1663. // 1. Check for shut down.
  1664. //
  1665. if ( _fInAutoProxyThreadShutDown )
  1666. {
  1667. SafeThreadShutdown(GlobalDynaUnload);
  1668. }
  1669. //
  1670. // 2. Check for timer causing a refresh of registry settings
  1671. // and network location changes,
  1672. // thus causing a redownload of settings
  1673. // Be carefull to call both functions since they have side-effects.
  1674. //
  1675. needRefresh = nlaChange.IsNetChanged ();
  1676. needRefresh = ChkForAndUpdateTimerCounter() || needRefresh;
  1677. if (needRefresh)
  1678. {
  1679. //
  1680. // Finally, start a download of the new stuff.
  1681. //
  1682. error = StartDownloadOfProxyInfo(FALSE /*full refresh*/);
  1683. }
  1684. //
  1685. // 3. Wait for new messages to come in,
  1686. // for shutdown we should pass right past it
  1687. //
  1688. error = WaitForMultipleObjects(
  1689. (EventArray[1]=nlaChange.GetChangeEvent())==NULL ? 1 : 2,
  1690. EventArray,
  1691. FALSE,
  1692. _dwWaitTimeOut
  1693. );
  1694. if (error==WAIT_OBJECT_0+1) {
  1695. //
  1696. // NLA change identified, skip processing, just redownload.
  1697. //
  1698. #if DBG
  1699. dprintf ("NLA change event signalled\n");
  1700. #endif
  1701. continue;
  1702. }
  1703. //
  1704. // 4. Check to see if we're ready to shut down the thread,
  1705. // due to a process termination or whatnot.
  1706. //
  1707. if ( _fInAutoProxyThreadShutDown )
  1708. {
  1709. SafeThreadShutdown(TRUE);
  1710. }
  1711. GlobalProxyInfo.CheckForExpiredEntries();
  1712. //
  1713. // 5. If we've idled let us shut down until we're needed again
  1714. //
  1715. //
  1716. // BUGBUG [arthurbi] Theoredically this should work,
  1717. // and the thread should shutdown on idle, too risky?
  1718. //
  1719. //if ( error == WAIT_FAILED && GetLastError() == WAIT_TIMEOUT)
  1720. //{
  1721. //SafeThreadShutdown(FALSE);
  1722. //}
  1723. //
  1724. // 6. Walk and process the list the messages to our thread asking for
  1725. // information or reinitalization
  1726. //
  1727. error = ProcessAsyncAutoProxyRequest();
  1728. INET_ASSERT( (error == ERROR_INTERNET_SHUTDOWN) ? _fInAutoProxyThreadShutDown : TRUE );
  1729. }
  1730. quit:
  1731. return error;
  1732. }
  1733. DWORD
  1734. AUTO_PROXY_DLLS::ProcessAsyncAutoProxyRequest(
  1735. VOID
  1736. )
  1737. /*++
  1738. Routine Description:
  1739. Walks the list of queued messages and processes them one by one by
  1740. either rerunning the download/initalization or executing a query for
  1741. proxy information
  1742. Arguments:
  1743. none.
  1744. Return Value:
  1745. none.
  1746. --*/
  1747. {
  1748. DWORD error = ERROR_SUCCESS;
  1749. BOOL fForceRefresh;
  1750. DEBUG_ENTER((DBG_PROXY,
  1751. Dword,
  1752. "AUTO_PROXY_DLLS::ProcessAsyncAutoProxyRequest",
  1753. ""
  1754. ));
  1755. while (!IsSerializedListEmpty(&_AsyncQueueList)) {
  1756. //
  1757. // If we're shuting down, then quit right away
  1758. //
  1759. if ( _fInAutoProxyThreadShutDown )
  1760. {
  1761. error = ERROR_INTERNET_SHUTDOWN;
  1762. goto quit;
  1763. }
  1764. LPVOID entry = SlDequeueHead(&_AsyncQueueList);
  1765. AUTO_PROXY_ASYNC_MSG *pQueryForInfo =
  1766. CONTAINING_RECORD(entry, AUTO_PROXY_ASYNC_MSG, _List);
  1767. //
  1768. // If the request has been unblocked, then destroy
  1769. // the request. ( this is typically due to cancel )
  1770. //
  1771. if ( pQueryForInfo->IsBlockUntilCompletetion() )
  1772. {
  1773. DWORD dwBlockCnt;
  1774. if ( pQueryForInfo->IsBlockedOnFsm() )
  1775. {
  1776. dwBlockCnt = CheckForBlockedWorkItems(
  1777. 1,
  1778. (DWORD_PTR) pQueryForInfo // blocked on message
  1779. );
  1780. if ( dwBlockCnt == 0 )
  1781. {
  1782. delete pQueryForInfo;
  1783. continue;
  1784. }
  1785. }
  1786. }
  1787. switch ( pQueryForInfo->QueryForInfoMessage() )
  1788. {
  1789. case PROXY_MSG_INIT:
  1790. fForceRefresh = pQueryForInfo->IsForceRefresh();
  1791. //
  1792. // First peak ahead to make sure we're not asked to download
  1793. // the same darn thing over and over again.
  1794. //
  1795. while (!IsSerializedListEmpty(&_AsyncQueueList))
  1796. {
  1797. LPVOID entry = SlDequeueHead(&_AsyncQueueList);
  1798. AUTO_PROXY_ASYNC_MSG *pQueryForInfo =
  1799. CONTAINING_RECORD(entry, AUTO_PROXY_ASYNC_MSG, _List);
  1800. if ( pQueryForInfo->QueryForInfoMessage() == PROXY_MSG_INIT )
  1801. {
  1802. INET_ASSERT(!pQueryForInfo->IsBlockUntilCompletetion());
  1803. if ( pQueryForInfo->IsForceRefresh() ) {
  1804. fForceRefresh = TRUE;
  1805. }
  1806. delete pQueryForInfo;
  1807. }
  1808. else
  1809. {
  1810. InsertAtHeadOfSerializedList(&_AsyncQueueList, &pQueryForInfo->_List);
  1811. break;
  1812. }
  1813. }
  1814. //
  1815. // Finally, start a download of the new stuff.
  1816. //
  1817. if ( error == ERROR_SUCCESS )
  1818. {
  1819. error = StartDownloadOfProxyInfo(fForceRefresh);
  1820. }
  1821. if ( error == ERROR_INTERNET_SHUTDOWN )
  1822. {
  1823. goto quit;
  1824. }
  1825. break;
  1826. case PROXY_MSG_SELF_DESTRUCT:
  1827. //
  1828. // Destroy ourselves and AUTO_PROXY_DLLS object.
  1829. //
  1830. //
  1831. SafeThreadShutdown(TRUE);
  1832. INET_ASSERT(FALSE); // never returns...
  1833. break;
  1834. case PROXY_MSG_GET_PROXY_INFO:
  1835. //
  1836. // If we've been updated then we need refresh settings from
  1837. // the net.
  1838. //
  1839. if ( (_dwUpdatedProxySettingsVersion != _ProxySettings.dwCurrentSettingsVersion) )
  1840. {
  1841. error = StartDownloadOfProxyInfo(FALSE /* no full refresh*/);
  1842. }
  1843. //
  1844. // The strait call into GetProxyInfo
  1845. //
  1846. error = ProcessProxyQueryForInfo(
  1847. &pQueryForInfo
  1848. );
  1849. if ( error == ERROR_INTERNET_SHUTDOWN )
  1850. {
  1851. goto quit;
  1852. }
  1853. break;
  1854. case PROXY_MSG_SET_BAD_PROXY:
  1855. case PROXY_MSG_DEINIT:
  1856. case PROXY_MSG_INVALID:
  1857. default:
  1858. INET_ASSERT(FALSE);
  1859. break;
  1860. }
  1861. //
  1862. // Wake up the caller if they are blocking on this completeion
  1863. //
  1864. if ( pQueryForInfo->IsBlockUntilCompletetion() )
  1865. {
  1866. SignalAsyncRequestCompleted(pQueryForInfo); // the thread that gets woken up now owns the object
  1867. }
  1868. else
  1869. {
  1870. delete pQueryForInfo;
  1871. }
  1872. }
  1873. quit:
  1874. DEBUG_LEAVE(error);
  1875. return error;
  1876. }
  1877. DWORD
  1878. AUTO_PROXY_DLLS::SignalAsyncRequestCompleted(
  1879. IN AUTO_PROXY_ASYNC_MSG *pQueryForInfo
  1880. )
  1881. /*++
  1882. Routine Description:
  1883. Notifies a blocked thread or FSM that we have completed its message based request and
  1884. it now can continue.
  1885. Arguments:
  1886. pQueryForInfo - the orginating request
  1887. Return Value:
  1888. none.
  1889. --*/
  1890. {
  1891. DWORD dwCntUnBlocked;
  1892. INET_ASSERT ( pQueryForInfo );
  1893. if ( pQueryForInfo->IsBlockedOnFsm() )
  1894. {
  1895. dwCntUnBlocked = UnblockWorkItems(
  1896. 1,
  1897. (DWORD_PTR) pQueryForInfo, // blocked on message
  1898. ERROR_SUCCESS,
  1899. TP_NO_PRIORITY_CHANGE
  1900. );
  1901. //
  1902. // If we were unable to unblock it, then we need to free it.
  1903. //
  1904. if ( dwCntUnBlocked == 0 )
  1905. {
  1906. delete pQueryForInfo;
  1907. pQueryForInfo = NULL;
  1908. }
  1909. }
  1910. else
  1911. {
  1912. dwCntUnBlocked = SignalThreadOnEvent(
  1913. (DWORD_PTR) pQueryForInfo, // blocked on message
  1914. 1, // should only be one item thats blocked by us
  1915. ERROR_SUCCESS
  1916. );
  1917. //if ( dwCntUnBlocked == 0 )
  1918. //{
  1919. // delete pQueryForInfo;
  1920. // pQueryForInfo = NULL;
  1921. //}
  1922. }
  1923. return ERROR_SUCCESS;
  1924. }
  1925. VOID
  1926. AUTO_PROXY_DLLS::WipeProxySettings(
  1927. LPINTERNET_PROXY_INFO_EX lpProxySettings
  1928. )
  1929. /*++
  1930. Routine Description:
  1931. Frees proxy settings
  1932. Arguments:
  1933. lpProxySettings - pointer to listing of proxy settings
  1934. Return Value:
  1935. none.
  1936. --*/
  1937. {
  1938. if ( lpProxySettings )
  1939. {
  1940. if ( lpProxySettings->lpszConnectionName ) {
  1941. FREE_MEMORY(lpProxySettings->lpszConnectionName);
  1942. }
  1943. if ( lpProxySettings->lpszProxy ) {
  1944. FREE_MEMORY(lpProxySettings->lpszProxy);
  1945. }
  1946. if ( lpProxySettings->lpszProxyBypass ) {
  1947. FREE_MEMORY(lpProxySettings->lpszProxyBypass);
  1948. }
  1949. if ( lpProxySettings->lpszLastKnownGoodAutoConfigUrl ) {
  1950. FREE_MEMORY(lpProxySettings->lpszLastKnownGoodAutoConfigUrl);
  1951. }
  1952. if (lpProxySettings->lpszAutoconfigUrl) {
  1953. FREE_MEMORY(lpProxySettings->lpszAutoconfigUrl);
  1954. }
  1955. if (lpProxySettings->lpszAutoconfigSecondaryUrl) {
  1956. FREE_MEMORY(lpProxySettings->lpszAutoconfigSecondaryUrl);
  1957. }
  1958. if (lpProxySettings->pdwDetectedInterfaceIp) {
  1959. FREE_MEMORY(lpProxySettings->pdwDetectedInterfaceIp);
  1960. }
  1961. }
  1962. }
  1963. DWORD
  1964. AUTO_PROXY_DLLS::SetProxySettings(
  1965. IN LPINTERNET_PROXY_INFO_EX lpProxySettings,
  1966. IN BOOL fModifiedInProcess,
  1967. IN BOOL fAllowOverwrite
  1968. )
  1969. /*++
  1970. Routine Description:
  1971. Write Auto-proxy Settings on the current auto-proxy object,
  1972. this writes the settings into the object, but does not
  1973. refresh it.
  1974. Arguments:
  1975. lpProxySettings - List of new settings that we'd like to write
  1976. fAllowOverwrite - Allow update of the settings in the object even if the version counter
  1977. hasn't changed
  1978. Return Value:
  1979. DWORD
  1980. ERROR_SUCCESS - if we have a valid proxy config
  1981. other-errors - if we were not able to make the settings
  1982. --*/
  1983. {
  1984. DWORD error = ERROR_SUCCESS;
  1985. BOOL fGoPending = FALSE;
  1986. DEBUG_ENTER((DBG_PROXY,
  1987. Dword,
  1988. "AUTO_PROXY_DLLS::SetProxySettings",
  1989. "%x %B, %B",
  1990. lpProxySettings,
  1991. fModifiedInProcess,
  1992. fAllowOverwrite
  1993. ));
  1994. LockAutoProxy();
  1995. if ( fAllowOverwrite ||
  1996. lpProxySettings->dwCurrentSettingsVersion == _ProxySettings.dwCurrentSettingsVersion )
  1997. {
  1998. BOOL fConnectionNameChange = FALSE;
  1999. _fModifiedInProcess = fModifiedInProcess;
  2000. UPDATE_GLOBAL_PROXY_VERSION();
  2001. //
  2002. // Check to see if we're changing the connection name,
  2003. // if so than this means we should plan on resetting
  2004. // the version below, so that we can redetect the new
  2005. // connection.
  2006. //
  2007. if ( ! IsConnectionMatch(
  2008. _ProxySettings.lpszConnectionName,
  2009. lpProxySettings->lpszConnectionName))
  2010. {
  2011. fConnectionNameChange = TRUE;
  2012. }
  2013. WipeProxySettings();
  2014. _ProxySettings = *lpProxySettings;
  2015. if ( fModifiedInProcess ) {
  2016. // update version, only if we don't plan to write out these settings
  2017. _ProxySettings.dwCurrentSettingsVersion++;
  2018. }
  2019. //
  2020. // minus -1 so that when we get to the auto-proxy thread,
  2021. // we can reload/detect or do what's needed to keep settings current
  2022. //
  2023. if ( _dwUpdatedProxySettingsVersion != _ProxySettings.dwCurrentSettingsVersion ||
  2024. _dwUpdatedProxySettingsVersion == 0 /* init state */ ||
  2025. fConnectionNameChange /* connection switch */ )
  2026. {
  2027. _dwUpdatedProxySettingsVersion = (DWORD) (_ProxySettings.dwCurrentSettingsVersion - 1);
  2028. fGoPending = TRUE;
  2029. }
  2030. //
  2031. // we shouldn't care about these settings,
  2032. // but we need to copy them anyway in
  2033. // case we save the stuff to the registry store
  2034. //
  2035. _ProxySettings.lpszProxy =
  2036. lpProxySettings->lpszProxy ?
  2037. NewString(lpProxySettings->lpszProxy) :
  2038. NULL;
  2039. _ProxySettings.lpszProxyBypass =
  2040. lpProxySettings->lpszProxyBypass ?
  2041. NewString(lpProxySettings->lpszProxyBypass) :
  2042. NULL;
  2043. _ProxySettings.lpszConnectionName =
  2044. lpProxySettings->lpszConnectionName ?
  2045. NewString(lpProxySettings->lpszConnectionName) :
  2046. NULL;
  2047. //
  2048. // Copy strings, cause we may be on another thread
  2049. //
  2050. _ProxySettings.lpszAutoconfigUrl =
  2051. lpProxySettings->lpszAutoconfigUrl ?
  2052. NewString(lpProxySettings->lpszAutoconfigUrl) :
  2053. NULL;
  2054. _ProxySettings.lpszAutoconfigSecondaryUrl =
  2055. lpProxySettings->lpszAutoconfigSecondaryUrl ?
  2056. NewString(lpProxySettings->lpszAutoconfigSecondaryUrl) :
  2057. NULL;
  2058. _ProxySettings.lpszLastKnownGoodAutoConfigUrl =
  2059. lpProxySettings->lpszLastKnownGoodAutoConfigUrl ?
  2060. NewString(lpProxySettings->lpszLastKnownGoodAutoConfigUrl) :
  2061. NULL;
  2062. //
  2063. // Copy of IP host addresses from last detection
  2064. //
  2065. if ( lpProxySettings->dwDetectedInterfaceIpCount > 0 &&
  2066. lpProxySettings->pdwDetectedInterfaceIp != NULL )
  2067. {
  2068. _ProxySettings.pdwDetectedInterfaceIp = (LPDWORD)
  2069. ALLOCATE_MEMORY(LMEM_FIXED, lpProxySettings->dwDetectedInterfaceIpCount
  2070. * sizeof(DWORD));
  2071. if (_ProxySettings.pdwDetectedInterfaceIp == NULL )
  2072. {
  2073. error = ERROR_NOT_ENOUGH_MEMORY;
  2074. goto quit;
  2075. }
  2076. memcpy(_ProxySettings.pdwDetectedInterfaceIp, lpProxySettings->pdwDetectedInterfaceIp,
  2077. lpProxySettings->dwDetectedInterfaceIpCount * sizeof(DWORD));
  2078. }
  2079. if (fGoPending &&
  2080. IsConfigValidForAutoProxyThread())
  2081. {
  2082. //
  2083. // Enable a forced refresh if the user orders it through the UI,
  2084. // for unknown new connections we don't block the user on auto-detect,
  2085. // since he didn't really order it
  2086. //
  2087. if ( IsStaticFallbackEnabled() ) {
  2088. SetState(AUTO_PROXY_PENDING);
  2089. } else {
  2090. SetState(AUTO_PROXY_BLOCKED);
  2091. }
  2092. }
  2093. }
  2094. quit:
  2095. UnlockAutoProxy();
  2096. DEBUG_LEAVE(error);
  2097. return error;
  2098. }
  2099. DWORD
  2100. AUTO_PROXY_DLLS::GetProxySettings(
  2101. OUT LPINTERNET_PROXY_INFO_EX lpProxySettings,
  2102. IN BOOL fCheckVersion
  2103. )
  2104. /*++
  2105. Routine Description:
  2106. Reads Auto-proxy Settings off the current auto-proxy object,
  2107. this allocates individual fields as needed to store the result
  2108. Arguments:
  2109. lpProxySettings - Returns the result of the auto-proxy settings
  2110. Return Value:
  2111. DWORD
  2112. ERROR_SUCCESS - if we have a valid proxy config
  2113. other-errors - if we were not able to make the settings
  2114. --*/
  2115. {
  2116. DWORD error = ERROR_SUCCESS;
  2117. DEBUG_ENTER((DBG_PROXY,
  2118. Dword,
  2119. "AUTO_PROXY_DLLS::GetProxySettings",
  2120. "%x %B",
  2121. lpProxySettings
  2122. ));
  2123. LockAutoProxy();
  2124. if ( fCheckVersion &&
  2125. lpProxySettings->dwCurrentSettingsVersion == _ProxySettings.dwCurrentSettingsVersion )
  2126. {
  2127. goto quit; // no change
  2128. }
  2129. *lpProxySettings = _ProxySettings;
  2130. //
  2131. // Copy strings, cause we may be on another thread
  2132. //
  2133. lpProxySettings->lpszProxy =
  2134. _ProxySettings.lpszProxy ?
  2135. NewString(_ProxySettings.lpszProxy) :
  2136. NULL;
  2137. lpProxySettings->lpszProxyBypass =
  2138. _ProxySettings.lpszProxyBypass ?
  2139. NewString(_ProxySettings.lpszProxyBypass) :
  2140. NULL;
  2141. lpProxySettings->lpszConnectionName =
  2142. _ProxySettings.lpszConnectionName ?
  2143. NewString(_ProxySettings.lpszConnectionName) :
  2144. NULL;
  2145. lpProxySettings->lpszAutoconfigUrl =
  2146. _ProxySettings.lpszAutoconfigUrl ?
  2147. NewString(_ProxySettings.lpszAutoconfigUrl) :
  2148. NULL;
  2149. lpProxySettings->lpszAutoconfigSecondaryUrl =
  2150. _ProxySettings.lpszAutoconfigSecondaryUrl ?
  2151. NewString(_ProxySettings.lpszAutoconfigSecondaryUrl) :
  2152. NULL;
  2153. lpProxySettings->lpszLastKnownGoodAutoConfigUrl =
  2154. _ProxySettings.lpszLastKnownGoodAutoConfigUrl ?
  2155. NewString(_ProxySettings.lpszLastKnownGoodAutoConfigUrl) :
  2156. NULL;
  2157. //
  2158. // Copy of IP host addresses from last detection
  2159. //
  2160. if ( _ProxySettings.dwDetectedInterfaceIpCount > 0 &&
  2161. _ProxySettings.pdwDetectedInterfaceIp != NULL )
  2162. {
  2163. lpProxySettings->pdwDetectedInterfaceIp = (LPDWORD)
  2164. ALLOCATE_MEMORY(LMEM_FIXED, _ProxySettings.dwDetectedInterfaceIpCount
  2165. * sizeof(DWORD));
  2166. if (lpProxySettings->pdwDetectedInterfaceIp == NULL )
  2167. {
  2168. error = ERROR_NOT_ENOUGH_MEMORY;
  2169. goto quit;
  2170. }
  2171. memcpy(lpProxySettings->pdwDetectedInterfaceIp, _ProxySettings.pdwDetectedInterfaceIp,
  2172. _ProxySettings.dwDetectedInterfaceIpCount * sizeof(DWORD));
  2173. }
  2174. quit:
  2175. UnlockAutoProxy();
  2176. DEBUG_LEAVE(error);
  2177. return error;
  2178. }
  2179. DWORD
  2180. AUTO_PROXY_DLLS::RefreshProxySettings(
  2181. IN BOOL fForceRefresh
  2182. )
  2183. /*++
  2184. Routine Description:
  2185. Syncronizes the Auto-Proxy engine with the state of the various settings,
  2186. and updates the various state keepers of the results.
  2187. - If there is no proxy settings, or auto-proxy is not needed or not detected,
  2188. we disable the auto-proxy system.
  2189. - If we have auto-proxy information or need to detect for some, then we fire up
  2190. the auto-proxy thread and send it a message to initalize itself.
  2191. Arguments:
  2192. none.
  2193. Return Value:
  2194. DWORD
  2195. ERROR_SUCCESS - success
  2196. Win32 Error code - failure
  2197. --*/
  2198. {
  2199. DWORD error = ERROR_SUCCESS;
  2200. DEBUG_ENTER((DBG_PROXY,
  2201. Dword,
  2202. "AUTO_PROXY_DLLS::RefreshProxySettings",
  2203. "%B",
  2204. fForceRefresh
  2205. ));
  2206. LockAutoProxy();
  2207. if (! IsOnAsyncAutoProxyThread() )
  2208. {
  2209. AUTO_PROXY_ASYNC_MSG *pQueryForInfo;
  2210. error = _Error;
  2211. if ( error != ERROR_SUCCESS)
  2212. {
  2213. goto quit; // obj is not initalized properly
  2214. }
  2215. if (!IsConfigValidForAutoProxyThread() )
  2216. {
  2217. goto quit; // disable & bail, we're not setup for this
  2218. }
  2219. pQueryForInfo = new AUTO_PROXY_ASYNC_MSG(PROXY_MSG_INIT);
  2220. if (pQueryForInfo == NULL )
  2221. {
  2222. error = ERROR_NOT_ENOUGH_MEMORY;
  2223. goto quit;
  2224. }
  2225. //
  2226. // Enabled a forced refresh if the user orders it through the UI,
  2227. // for unknown new connections we don't block the user on auto-detect,
  2228. // since he didn't really order it
  2229. //
  2230. pQueryForInfo->SetForceRefresh(fForceRefresh);
  2231. if ( !fForceRefresh && IsStaticFallbackEnabled() ) {
  2232. SetState(AUTO_PROXY_PENDING);
  2233. } else {
  2234. SetState(AUTO_PROXY_BLOCKED);
  2235. }
  2236. error = QueueAsyncAutoProxyRequest(
  2237. &pQueryForInfo // don't worry, this request won't block us.
  2238. );
  2239. }
  2240. quit:
  2241. if ( error != ERROR_SUCCESS &&
  2242. error != ERROR_IO_PENDING )
  2243. {
  2244. SetState(AUTO_PROXY_DISABLED); // disable in case something critical happens
  2245. }
  2246. UnlockAutoProxy();
  2247. DEBUG_LEAVE(error);
  2248. return error;
  2249. }
  2250. DWORD
  2251. AUTO_PROXY_DLLS::StartBackroundDetectionIfNeeded(
  2252. VOID
  2253. )
  2254. {
  2255. DWORD error = ERROR_SUCCESS;
  2256. LockAutoProxy();
  2257. if ( _hAutoProxyThread == NULL ) {
  2258. error = RefreshProxySettings(FALSE);
  2259. }
  2260. UnlockAutoProxy();
  2261. return error;
  2262. }
  2263. DWORD
  2264. AUTO_PROXY_DLLS::QueryProxySettings(
  2265. IN OUT AUTO_PROXY_ASYNC_MSG **ppQueryForInfo
  2266. )
  2267. /*++
  2268. Routine Description:
  2269. Performs a query for proxy information using auto-proxy to anwser our query.
  2270. Assumes this is not called from auto-proxy thread/
  2271. Arguments:
  2272. ppQueryForInfo - Pointer to pointer to Message object that contains state information
  2273. used in the query. If the object needs to be allocated on the heap
  2274. then the pointer will change to reflect the new object ptr.
  2275. Return Value:
  2276. DWORD
  2277. Success - ERROR_SUCCESS
  2278. Failure -
  2279. --*/
  2280. {
  2281. AUTO_PROXY_LIST_ENTRY * papleAutoProxy;
  2282. DWORD error = ERROR_SUCCESS;
  2283. BOOL fUnlocked = FALSE;
  2284. DEBUG_ENTER((DBG_PROXY,
  2285. Dword,
  2286. "AUTO_PROXY_DLLS::QueryProxySettings",
  2287. "%x",
  2288. ppQueryForInfo
  2289. ));
  2290. INET_ASSERT(ppQueryForInfo);
  2291. INET_ASSERT(*ppQueryForInfo);
  2292. INET_ASSERT((*ppQueryForInfo)->QueryForInfoMessage() == PROXY_MSG_GET_PROXY_INFO);
  2293. //INET_ASSERT(!IsOnAsyncAutoProxyThread());
  2294. LockAutoProxy();
  2295. //
  2296. // ALWAYS force this function to exec it auto-proxy calls on the
  2297. // async auto-proxy thread.
  2298. //
  2299. if ( IsAutoProxy() &&
  2300. !IsOnAsyncAutoProxyThread() &&
  2301. IsAutoProxyGetProxyInfoCallNeeded(*ppQueryForInfo))
  2302. {
  2303. if ( GetState() == AUTO_PROXY_PENDING )
  2304. {
  2305. //
  2306. // If we're doing a pending detection, then
  2307. // fallback to standby settings, and if we fail
  2308. // with standby settings, we should get re-called to here
  2309. // and if we're then still detecting, then
  2310. // we'll block on the detection result
  2311. //
  2312. if ( ! (*ppQueryForInfo)->IsBackroundDetectionPending() )
  2313. {
  2314. error = StartBackroundDetectionIfNeeded();
  2315. if (error != ERROR_SUCCESS ) {
  2316. goto quit;
  2317. }
  2318. (*ppQueryForInfo)->SetBackroundDetectionPending(TRUE);
  2319. if ( ! (*ppQueryForInfo)->IsAlloced() )
  2320. {
  2321. *ppQueryForInfo = new AUTO_PROXY_ASYNC_MSG(*ppQueryForInfo);
  2322. if ( *ppQueryForInfo == NULL ) {
  2323. error = ERROR_NOT_ENOUGH_MEMORY;
  2324. }
  2325. }
  2326. goto quit;
  2327. }
  2328. }
  2329. else if (!(_ProxySettings.dwAutoDiscoveryFlags & AUTO_PROXY_FLAG_DONT_CACHE_PROXY_RESULT) &&
  2330. GlobalAutoProxyCacheEnable)
  2331. {
  2332. (*ppQueryForInfo)->SetCanCacheResult(TRUE);
  2333. }
  2334. //
  2335. // If we need to show indication during detection,
  2336. // then do so now before we block
  2337. //
  2338. if ( (*ppQueryForInfo)->IsShowIndication() &&
  2339. (GetState() == AUTO_PROXY_PENDING ||
  2340. GetState() == AUTO_PROXY_BLOCKED))
  2341. {
  2342. UnlockAutoProxy();
  2343. fUnlocked = TRUE;
  2344. InternetIndicateStatus(INTERNET_STATUS_DETECTING_PROXY, NULL, 0);
  2345. }
  2346. else
  2347. {
  2348. UnlockAutoProxy();
  2349. fUnlocked = TRUE;
  2350. }
  2351. // always disable unless we're ready to renter on a failure
  2352. (*ppQueryForInfo)->SetBackroundDetectionPending(FALSE);
  2353. error = QueueAsyncAutoProxyRequest(ppQueryForInfo);
  2354. goto quit;
  2355. }
  2356. // always disabled it unless we're ready to reenter on a failure
  2357. (*ppQueryForInfo)->SetBackroundDetectionPending(FALSE);
  2358. quit:
  2359. if ( !fUnlocked )
  2360. {
  2361. UnlockAutoProxy();
  2362. }
  2363. DEBUG_LEAVE(error);
  2364. return error;
  2365. }
  2366. BOOL
  2367. AUTO_PROXY_DLLS::IsConfigValidForAutoProxyThread(
  2368. VOID
  2369. )
  2370. /*++
  2371. Routine Description:
  2372. Decide if we need the auto-thread to either download auto-proxy ot
  2373. go off and detect for auto-proxy on the network
  2374. Arguments:
  2375. none.
  2376. Return Value:
  2377. BOOL
  2378. TRUE - if we have a valid proxy config
  2379. FALSE - if we not valid
  2380. --*/
  2381. {
  2382. LPINTERNET_PROXY_INFO_EX lpProxySettings = &_ProxySettings;
  2383. if ( (lpProxySettings->dwFlags & PROXY_TYPE_AUTO_PROXY_URL) &&
  2384. lpProxySettings->lpszAutoconfigUrl != NULL &&
  2385. *lpProxySettings->lpszAutoconfigUrl != '\0' )
  2386. {
  2387. return TRUE; // old behavior for auto-proxy URL config
  2388. }
  2389. if ( IsProxyAutoDetectEnabled(lpProxySettings))
  2390. {
  2391. return TRUE;
  2392. }
  2393. return FALSE; // do nothing
  2394. }
  2395. BOOL
  2396. AUTO_PROXY_DLLS::IsStaticFallbackEnabled(
  2397. VOID
  2398. )
  2399. /*++
  2400. Routine Description:
  2401. Decide if we need to block on the auto-proxy information,
  2402. or if we can fallback to static settings when auto-proxy is initalizing/detecting.
  2403. Arguments:
  2404. none.
  2405. Return Value:
  2406. BOOL
  2407. TRUE - if we keep going with static settings
  2408. FALSE - we'll need to block requests until auto-proxy is intialized
  2409. --*/
  2410. {
  2411. if ( (_ProxySettings.dwFlags & PROXY_TYPE_AUTO_PROXY_URL) &&
  2412. _ProxySettings.lpszAutoconfigUrl != NULL &&
  2413. *_ProxySettings.lpszAutoconfigUrl != '\0' )
  2414. {
  2415. return FALSE; // block, don't bypass, this is old behavior for Auto-proxy URLs
  2416. }
  2417. if ( IsProxyAutoDetectEnabled() )
  2418. {
  2419. if ( !(_ProxySettings.dwAutoDiscoveryFlags & (AUTO_PROXY_FLAG_DETECTION_RUN | AUTO_PROXY_FLAG_USER_SET)) ) {
  2420. return TRUE; // detection SHOULD NOT BLOCK THE FIRST TIME, in case it doesn't work
  2421. }
  2422. if ( _ProxySettings.lpszConnectionName != NULL )
  2423. {
  2424. if ( _ProxySettings.lpszLastKnownGoodAutoConfigUrl == NULL )
  2425. {
  2426. return TRUE; // detection SHOULD NOT BE DEPENDED upon with Dialup, unless it has something
  2427. }
  2428. if ( _ProxySettings.dwAutoDiscoveryFlags & AUTO_PROXY_FLAG_DETECTION_SUSPECT)
  2429. {
  2430. return TRUE; // detection should not block when we're in a hosed state.
  2431. }
  2432. }
  2433. }
  2434. return FALSE; // block
  2435. }
  2436. VOID
  2437. AUTO_PROXY_DLLS::SetExpiredUrl(
  2438. LPCSTR lpszUrl
  2439. )
  2440. /*++
  2441. Routine Description:
  2442. Sets default expiry time on the if none is specified on the cached URL.
  2443. Arguments:
  2444. lpszUrl -
  2445. Return Value:
  2446. DWORD
  2447. ERROR_SUCCESS - success
  2448. Win32 Error code - failure
  2449. --*/
  2450. {
  2451. CACHE_ENTRY_INFOEX Cei;
  2452. DWORD dwCeiSize = sizeof(INTERNET_CACHE_ENTRY_INFOA);
  2453. BOOL fRet;
  2454. fRet = GetUrlCacheEntryInfoExA(
  2455. lpszUrl,
  2456. (INTERNET_CACHE_ENTRY_INFOA *) &Cei,
  2457. &dwCeiSize,
  2458. NULL,
  2459. NULL,
  2460. NULL,
  2461. INTERNET_CACHE_FLAG_GET_STRUCT_ONLY
  2462. );
  2463. if ( fRet &&
  2464. (FT2LL(Cei.ExpireTime) == LONGLONG_ZERO))
  2465. {
  2466. //
  2467. // Set default expiry as: current time + some default expiry
  2468. //
  2469. GetCurrentGmtTime(&Cei.ExpireTime);
  2470. *(LONGLONG *) &(Cei.ExpireTime) += (12 * (24 * ONE_HOUR_DELTA));
  2471. //
  2472. // Re-Save Cache entry with updated default expiry time for PAC/INS file.
  2473. //
  2474. SetUrlCacheEntryInfoA(
  2475. lpszUrl,
  2476. (INTERNET_CACHE_ENTRY_INFOA *) &Cei,
  2477. CACHE_ENTRY_EXPTIME_FC
  2478. );
  2479. }
  2480. }
  2481. BOOL
  2482. AUTO_PROXY_DLLS::IsExpiredUrl(
  2483. LPCSTR lpszUrl
  2484. )
  2485. /*++
  2486. Routine Description:
  2487. Is Url Expired? If it isn't don't force a reload/update of data
  2488. Arguments:
  2489. lpszUrl -
  2490. Return Value:
  2491. DWORD
  2492. ERROR_SUCCESS - success
  2493. Win32 Error code - failure
  2494. --*/
  2495. {
  2496. CACHE_ENTRY_INFOEX Cei;
  2497. DWORD dwCeiSize = sizeof(INTERNET_CACHE_ENTRY_INFOA);
  2498. BOOL fRet;
  2499. fRet = GetUrlCacheEntryInfoExA(
  2500. lpszUrl,
  2501. (INTERNET_CACHE_ENTRY_INFOA *) &Cei,
  2502. &dwCeiSize,
  2503. NULL,
  2504. NULL,
  2505. NULL,
  2506. INTERNET_CACHE_FLAG_GET_STRUCT_ONLY
  2507. );
  2508. if (!fRet) {
  2509. return TRUE; // expired, not in the cache
  2510. }
  2511. if ( IsExpired(&Cei, 0, &fRet) )
  2512. {
  2513. return TRUE; // expired, like really it is
  2514. }
  2515. return FALSE; // not expired
  2516. }
  2517. BOOL
  2518. AUTO_PROXY_DLLS::IsProxyAutoDetectNeeded(
  2519. LPINTERNET_PROXY_INFO_EX lpProxySettings
  2520. )
  2521. /*++
  2522. Routine Description:
  2523. Detects whether we need to actually run a detection on the network,
  2524. or whether we can resuse current results from previous runs
  2525. Arguments:
  2526. lpProxySettings - structure to fill
  2527. Return Value:
  2528. DWORD
  2529. ERROR_SUCCESS - success
  2530. Win32 Error code - failure
  2531. --*/
  2532. {
  2533. DWORD addressCount;
  2534. LPDWORD * addressList;
  2535. LPHOSTENT lpHostent;
  2536. BOOL fSuspectBadDetect = FALSE;
  2537. INET_ASSERT(IsProxyAutoDetectEnabled(lpProxySettings));
  2538. // we haven't detected before on this connection, so we need to do it.
  2539. if ( !(lpProxySettings->dwAutoDiscoveryFlags & AUTO_PROXY_FLAG_DETECTION_RUN) ) {
  2540. return TRUE; // detect needed
  2541. }
  2542. // if we're flagged to ALWAYS force detection, then do this
  2543. if (lpProxySettings->dwAutoDiscoveryFlags & AUTO_PROXY_FLAG_ALWAYS_DETECT) {
  2544. return TRUE; // detect needed
  2545. }
  2546. //
  2547. // Check for an expired detected Url, detect it its expired
  2548. // Since this is RAS we can't rely on the host IP staying
  2549. // the same everytime.
  2550. //
  2551. if ( lpProxySettings->lpszLastKnownGoodAutoConfigUrl &&
  2552. lpProxySettings->lpszConnectionName &&
  2553. ! IsExpiredUrl(lpProxySettings->lpszLastKnownGoodAutoConfigUrl))
  2554. {
  2555. // if we're suspecting bad settings, make sure to redirect.
  2556. if ( ! (lpProxySettings->dwAutoDiscoveryFlags & AUTO_PROXY_FLAG_DETECTION_SUSPECT) ) {
  2557. return FALSE;
  2558. }
  2559. //otherwise, we'll be careful
  2560. fSuspectBadDetect = TRUE;
  2561. }
  2562. //
  2563. // Check for IP addresses that no longer match, indicating a network change
  2564. //
  2565. __try
  2566. {
  2567. lpHostent = _I_gethostbyname(NULL);
  2568. }
  2569. __except(EXCEPTION_EXECUTE_HANDLER)
  2570. {
  2571. g_fGetHostByNameNULLFails = TRUE;
  2572. lpHostent = NULL;
  2573. }
  2574. ENDEXCEPT
  2575. if (lpHostent &&
  2576. lpProxySettings->pdwDetectedInterfaceIp == NULL)
  2577. {
  2578. return TRUE; // detect needed, no current IPs saved from last run
  2579. }
  2580. if ( lpHostent != NULL &&
  2581. lpProxySettings->pdwDetectedInterfaceIp != NULL)
  2582. {
  2583. for ( addressCount = 0;
  2584. lpHostent->h_addr_list[addressCount] != NULL;
  2585. addressCount++ ); // gather count
  2586. if ( addressCount != lpProxySettings->dwDetectedInterfaceIpCount ) {
  2587. return TRUE; // detect needed, the IP count is different
  2588. }
  2589. if ( fSuspectBadDetect) {
  2590. return FALSE; // detect NOT needed, because the IP addresses may change from dialup/to dialup
  2591. }
  2592. for (DWORD i = 0; i < addressCount; i++)
  2593. {
  2594. //dwAddress[iCount] = *((LPDWORD)(ph->h_addr_list[iCount]));
  2595. if ( *((LPDWORD)(lpHostent->h_addr_list[i])) != lpProxySettings->pdwDetectedInterfaceIp[i] ) {
  2596. return TRUE; // detect needed, mismatched values
  2597. }
  2598. }
  2599. }
  2600. return FALSE; // default, do not need to redetect
  2601. }
  2602. DWORD
  2603. AUTO_PROXY_DLLS::GetHostAddresses(
  2604. DWORD ** ppdwDetectedInterfaceIp,
  2605. DWORD * pdwDetectedInterfaceIpCount
  2606. )
  2607. /*++
  2608. Routine Description:
  2609. Copies out the current host information into an
  2610. a array/ProxyInfoStruct for later comparision.
  2611. Arguments:
  2612. lpProxySettings - structure to fill
  2613. Return Value:
  2614. DWORD
  2615. ERROR_SUCCESS - success
  2616. Win32 Error code - failure
  2617. --*/
  2618. {
  2619. DWORD addressCount;
  2620. LPDWORD * addressList;
  2621. LPHOSTENT lpHostent;
  2622. DWORD error = ERROR_SUCCESS;
  2623. *pdwDetectedInterfaceIpCount = 0;
  2624. if ( *ppdwDetectedInterfaceIp )
  2625. {
  2626. FREE_MEMORY(*ppdwDetectedInterfaceIp);
  2627. *ppdwDetectedInterfaceIp = NULL;
  2628. }
  2629. //
  2630. // Gather IP addresses and start copying them over
  2631. //
  2632. __try
  2633. {
  2634. lpHostent = _I_gethostbyname(NULL);
  2635. }
  2636. __except(EXCEPTION_EXECUTE_HANDLER)
  2637. {
  2638. g_fGetHostByNameNULLFails = TRUE;
  2639. lpHostent = NULL;
  2640. }
  2641. ENDEXCEPT
  2642. if (lpHostent == NULL ) {
  2643. goto quit;
  2644. }
  2645. for ( addressCount = 0;
  2646. lpHostent->h_addr_list[addressCount] != NULL;
  2647. addressCount++ ); // gather count
  2648. *ppdwDetectedInterfaceIp = (LPDWORD)
  2649. ALLOCATE_MEMORY(LMEM_FIXED, addressCount
  2650. * sizeof(DWORD));
  2651. if ( *ppdwDetectedInterfaceIp == NULL )
  2652. {
  2653. error = ERROR_NOT_ENOUGH_MEMORY;
  2654. goto quit;
  2655. }
  2656. if ( *ppdwDetectedInterfaceIp != NULL)
  2657. {
  2658. *pdwDetectedInterfaceIpCount = addressCount;
  2659. for (DWORD i = 0; i < addressCount; i++)
  2660. {
  2661. (*ppdwDetectedInterfaceIp)[i] =
  2662. *((LPDWORD)(lpHostent->h_addr_list[i]));
  2663. }
  2664. }
  2665. quit:
  2666. return error;
  2667. }
  2668. VOID
  2669. AUTO_PROXY_DLLS::FreeAutoProxyInfo(
  2670. VOID
  2671. )
  2672. /*++
  2673. Routine Description:
  2674. Attempts to shutdown the auto-proxy thread (from outside of it), by first signalling
  2675. it with an event and boolean, and then if that fails, forcibly forcing a shutdown
  2676. with TerminateThread.
  2677. Arguments:
  2678. none.
  2679. Return Value:
  2680. none.
  2681. --*/
  2682. {
  2683. DWORD dwError;
  2684. LockAutoProxy();
  2685. if ( _hAutoProxyThread != NULL &&
  2686. ! IsOnAsyncAutoProxyThread() )
  2687. {
  2688. HANDLE hAutoProxyThread;
  2689. BOOL fAlreadyInShutDown;
  2690. fAlreadyInShutDown =
  2691. InterlockedExchange((LPLONG)&_fInAutoProxyThreadShutDown, TRUE);
  2692. INET_ASSERT ( ! fAlreadyInShutDown );
  2693. SetEvent(_hAutoProxyThreadEvent);
  2694. if ( _hInternetAbortHandle != NULL )
  2695. {
  2696. InternetCloseHandle(_hInternetAbortHandle);
  2697. }
  2698. hAutoProxyThread = _hAutoProxyThread;
  2699. UnlockAutoProxy();
  2700. //
  2701. // Wait for shutdown of auto-proxy thread.
  2702. //
  2703. if ( hAutoProxyThread )
  2704. {
  2705. dwError = WaitForSingleObject(hAutoProxyThread,
  2706. GlobalIsProcessNtService? INFINITE : 60000);
  2707. if ( dwError != WAIT_OBJECT_0 )
  2708. {
  2709. INET_ASSERT(FALSE);
  2710. // Whistler bug #124628: delete the autoproxy critical section
  2711. // before terminating the autoproxy thread in case the thread
  2712. // is holding the CS.
  2713. SuspendThread(hAutoProxyThread);
  2714. DeleteCriticalSection(&_CritSec);
  2715. // reinitialize cs since it will be deleted in the destructor
  2716. memset((LPVOID) &_CritSec, 0, sizeof(CRITICAL_SECTION));
  2717. InitializeCriticalSection(&_CritSec);
  2718. TerminateThread(hAutoProxyThread,ERROR_SUCCESS);
  2719. _hAutoProxyThreadEvent = NULL;
  2720. _hAutoProxyThread = NULL;
  2721. InterlockedExchange((LPLONG)&_fInAutoProxyThreadShutDown, FALSE);
  2722. return;
  2723. }
  2724. }
  2725. LockAutoProxy();
  2726. CloseHandle(_hAutoProxyThread);
  2727. CloseHandle(_hAutoProxyThreadEvent);
  2728. _hAutoProxyThreadEvent = NULL;
  2729. _hAutoProxyThread = NULL;
  2730. InterlockedExchange((LPLONG)&_fInAutoProxyThreadShutDown, FALSE);
  2731. UnlockAutoProxy();
  2732. }
  2733. else
  2734. {
  2735. UnlockAutoProxy();
  2736. }
  2737. }
  2738. BOOL
  2739. AUTO_PROXY_LIST_ENTRY::ProxyInfoInvalid(
  2740. IN LPSTR lpszMime,
  2741. IN LPSTR lpszUrl,
  2742. IN DWORD dwUrlLength,
  2743. IN LPSTR lpszProxyHostName,
  2744. IN DWORD dwProxyHostNameLength
  2745. )
  2746. {
  2747. BOOL success = TRUE; // don't care if it doesn't succeed
  2748. if ( ! _hAutoConfigDLL )
  2749. {
  2750. if ( LoadEntry() != ERROR_SUCCESS )
  2751. return FALSE;
  2752. }
  2753. if ( ! _fInitializedSuccessfully )
  2754. {
  2755. return FALSE;
  2756. }
  2757. if ( _pProxyInfoInvalid )
  2758. {
  2759. INET_ASSERT(_hAutoConfigDLL);
  2760. INET_ASSERT(!IsBadCodePtr((FARPROC)_pProxyInfoInvalid));
  2761. success = (_pProxyInfoInvalid) ( lpszMime,
  2762. lpszUrl,
  2763. dwUrlLength,
  2764. lpszProxyHostName,
  2765. dwProxyHostNameLength
  2766. );
  2767. }
  2768. return success;
  2769. }
  2770. BOOL
  2771. AUTO_PROXY_LIST_ENTRY::ProxyDllDeInit(
  2772. IN LPSTR lpszMime,
  2773. IN DWORD dwReserved
  2774. )
  2775. {
  2776. BOOL success = TRUE; // don't care if it doesn't succeed
  2777. DEBUG_ENTER((DBG_PROXY,
  2778. Bool,
  2779. "AUTO_PROXY_LIST_ENTRY::ProxyDllDeInit",
  2780. "%s, %u",
  2781. lpszMime,
  2782. dwReserved
  2783. ));
  2784. INET_ASSERT(_hAutoConfigDLL);
  2785. if ( !_hAutoConfigDLL )
  2786. {
  2787. DEBUG_LEAVE(FALSE);
  2788. return FALSE;
  2789. }
  2790. if ( ! _fInitializedSuccessfully )
  2791. {
  2792. DEBUG_LEAVE(FALSE);
  2793. return FALSE;
  2794. }
  2795. if ( _pProxyDllDeInit )
  2796. {
  2797. INET_ASSERT(_hAutoConfigDLL);
  2798. INET_ASSERT(!IsBadCodePtr((FARPROC)_pProxyDllDeInit));
  2799. #ifdef INET_DEBUG
  2800. INET_ASSERT(!_fUnInited);
  2801. _fUnInited = TRUE;
  2802. #endif
  2803. success = (_pProxyDllDeInit) ( lpszMime,
  2804. dwReserved
  2805. );
  2806. }
  2807. DEBUG_LEAVE(success);
  2808. return success;
  2809. }
  2810. DWORD
  2811. AUTO_PROXY_LIST_ENTRY::GetProxyInfoEx(
  2812. IN AUTO_PROXY_ASYNC_MSG *pQueryForProxyInfo
  2813. )
  2814. {
  2815. BOOL success = FALSE;
  2816. DWORD error = ERROR_SUCCESS;
  2817. DEBUG_ENTER((DBG_PROXY,
  2818. Dword,
  2819. "AUTO_PROXY_LIST_ENTRY::GetProxyInfoEx",
  2820. "%x [%s, %s, %u, %s, %d, %x, %x]",
  2821. pQueryForProxyInfo,
  2822. InternetMapScheme(pQueryForProxyInfo->_tUrlProtocol),
  2823. pQueryForProxyInfo->_lpszUrl,
  2824. pQueryForProxyInfo->_dwUrlLength,
  2825. pQueryForProxyInfo->_lpszUrlHostName,
  2826. pQueryForProxyInfo->_dwUrlHostNameLength,
  2827. pQueryForProxyInfo->_lpszProxyHostName,
  2828. &pQueryForProxyInfo->_dwProxyHostNameLength
  2829. ));
  2830. //if ( ! _hAutoConfigDLL )
  2831. //{
  2832. // if ( LoadEntry() != ERROR_SUCCESS )
  2833. // {
  2834. // DEBUG_LEAVE(FALSE);
  2835. // return FALSE;
  2836. // }
  2837. //}
  2838. if ( ! _fInitializedSuccessfully )
  2839. {
  2840. DEBUG_LEAVE(FALSE);
  2841. error = ERROR_INTERNET_INTERNAL_ERROR;
  2842. goto quit;
  2843. }
  2844. INET_ASSERT(_hAutoConfigDLL);
  2845. INET_ASSERT(_pGetProxyInfoEx);
  2846. INET_ASSERT(!IsBadCodePtr((FARPROC)_pGetProxyInfoEx));
  2847. success = (_pGetProxyInfoEx) ( pQueryForProxyInfo->_tUrlProtocol,
  2848. pQueryForProxyInfo->_lpszUrl,
  2849. pQueryForProxyInfo->_dwUrlLength,
  2850. pQueryForProxyInfo->_lpszUrlHostName,
  2851. pQueryForProxyInfo->_dwUrlHostNameLength,
  2852. pQueryForProxyInfo->_nUrlPort,
  2853. &(pQueryForProxyInfo->_tProxyScheme),
  2854. &(pQueryForProxyInfo->_lpszProxyHostName),
  2855. &(pQueryForProxyInfo->_dwProxyHostNameLength),
  2856. &(pQueryForProxyInfo->_nProxyHostPort)
  2857. );
  2858. quit:
  2859. pQueryForProxyInfo->_dwQueryResult = (DWORD) success;
  2860. DEBUG_LEAVE(error);
  2861. return error;
  2862. }
  2863. DWORD
  2864. AUTO_PROXY_LIST_ENTRY::GetProxyInfo(
  2865. IN AUTO_PROXY_ASYNC_MSG *pQueryForProxyInfo
  2866. )
  2867. {
  2868. BOOL success = FALSE;
  2869. DWORD error = ERROR_SUCCESS;
  2870. LPSTR lpszAutoProxyReturnInfo;
  2871. DWORD dwAutoProxyReturnInfoSize;
  2872. INET_ASSERT(pQueryForProxyInfo);
  2873. DEBUG_ENTER((DBG_PROXY,
  2874. Dword,
  2875. "AUTO_PROXY_LIST_ENTRY::GetProxyInfo",
  2876. "%x [%s, %u, %s, %d, %x, %x]",
  2877. pQueryForProxyInfo,
  2878. pQueryForProxyInfo->_lpszUrl,
  2879. pQueryForProxyInfo->_dwUrlLength,
  2880. pQueryForProxyInfo->_lpszUrlHostName,
  2881. pQueryForProxyInfo->_dwUrlHostNameLength,
  2882. pQueryForProxyInfo->_lpszProxyHostName,
  2883. &pQueryForProxyInfo->_dwProxyHostNameLength
  2884. ));
  2885. //if ( ! _hAutoConfigDLL )
  2886. //{
  2887. // if ( LoadEntry() != ERROR_SUCCESS )
  2888. // {
  2889. // DEBUG_LEAVE(FALSE);
  2890. // return FALSE;
  2891. // }
  2892. //}
  2893. if ( ! _fInitializedSuccessfully )
  2894. {
  2895. DEBUG_LEAVE(FALSE);
  2896. error = ERROR_INTERNET_INTERNAL_ERROR;
  2897. goto quit;
  2898. }
  2899. INET_ASSERT ( _pGetProxyInfo );
  2900. INET_ASSERT(_hAutoConfigDLL);
  2901. INET_ASSERT(!IsBadCodePtr((FARPROC)_pGetProxyInfo));
  2902. success = (_pGetProxyInfo) ( pQueryForProxyInfo->_lpszUrl,
  2903. pQueryForProxyInfo->_dwUrlLength,
  2904. pQueryForProxyInfo->_lpszUrlHostName,
  2905. pQueryForProxyInfo->_dwUrlHostNameLength,
  2906. &lpszAutoProxyReturnInfo,
  2907. &dwAutoProxyReturnInfoSize
  2908. );
  2909. if ( success )
  2910. {
  2911. if ( pQueryForProxyInfo->_tUrlProtocol == INTERNET_SCHEME_HTTPS )
  2912. {
  2913. pQueryForProxyInfo->_tProxyScheme = INTERNET_SCHEME_HTTPS;
  2914. }
  2915. else
  2916. {
  2917. pQueryForProxyInfo->_tProxyScheme = INTERNET_SCHEME_HTTP;
  2918. }
  2919. INET_ASSERT(pQueryForProxyInfo->_pProxyState == NULL);
  2920. pQueryForProxyInfo->_pProxyState = new PROXY_STATE(lpszAutoProxyReturnInfo,
  2921. dwAutoProxyReturnInfoSize,
  2922. TRUE, // parse netscape-style proxy list
  2923. pQueryForProxyInfo->_tProxyScheme,
  2924. pQueryForProxyInfo->_nProxyHostPort
  2925. );
  2926. INET_ASSERT(lpszAutoProxyReturnInfo);
  2927. GlobalFree(lpszAutoProxyReturnInfo); // clean up jsproxy.dll return string
  2928. if ( pQueryForProxyInfo->_pProxyState == NULL )
  2929. {
  2930. error = ERROR_NOT_ENOUGH_MEMORY;
  2931. goto quit;
  2932. }
  2933. error = pQueryForProxyInfo->_pProxyState->GetError();
  2934. if ( error != ERROR_SUCCESS )
  2935. {
  2936. goto quit;
  2937. }
  2938. }
  2939. quit:
  2940. pQueryForProxyInfo->_dwQueryResult = (DWORD) success;
  2941. DEBUG_LEAVE(error);
  2942. return error;
  2943. }
  2944. BOOL
  2945. AUTO_PROXY_LIST_ENTRY::ProxyDllInit (
  2946. IN DWORD dwVersion,
  2947. IN LPSTR lpszDownloadedTempFile,
  2948. IN LPSTR lpszMime,
  2949. IN AUTO_PROXY_HELPER_APIS *pAutoProxyCallbacks,
  2950. IN DWORD_PTR dwReserved
  2951. )
  2952. {
  2953. BOOL success = FALSE;
  2954. DEBUG_ENTER((DBG_PROXY,
  2955. Bool,
  2956. "AUTO_PROXY_LIST_ENTRY::ProxyDllInit",
  2957. "%u, %s, %s, %x, %u",
  2958. dwVersion,
  2959. lpszDownloadedTempFile,
  2960. lpszMime,
  2961. pAutoProxyCallbacks,
  2962. dwReserved
  2963. ));
  2964. INET_ASSERT ( _hAutoConfigDLL );
  2965. if ( _pProxyDllInit )
  2966. {
  2967. INET_ASSERT(_hAutoConfigDLL);
  2968. INET_ASSERT(!IsBadCodePtr((FARPROC)_pProxyDllInit));
  2969. success = (_pProxyDllInit) ( dwVersion,
  2970. lpszDownloadedTempFile,
  2971. lpszMime,
  2972. pAutoProxyCallbacks,
  2973. dwReserved
  2974. );
  2975. #ifdef INET_DEBUG
  2976. _fUnInited = FALSE;
  2977. #endif
  2978. _fInitializedSuccessfully = success;
  2979. }
  2980. DEBUG_LEAVE(success);
  2981. return success;
  2982. }
  2983. VOID
  2984. AUTO_PROXY_LIST_ENTRY::UnloadEntry(
  2985. VOID
  2986. )
  2987. /*++
  2988. Routine Description:
  2989. Unloads the DLL function entry points for an Auto-Proxy DLL.
  2990. WARNING: Must be called only on Auto-proxy thread context!
  2991. Arguments:
  2992. none.
  2993. Return Value:
  2994. none.
  2995. --*/
  2996. {
  2997. DEBUG_ENTER((DBG_OBJECTS,
  2998. None,
  2999. "AUTO_PROXY_LIST_ENTRY::UnloadEntry",
  3000. NULL
  3001. ));
  3002. if ( _fInitializedSuccessfully &&
  3003. _pProxyDllDeInit )
  3004. {
  3005. ProxyDllDeInit(
  3006. _lpszMimeType,
  3007. 0
  3008. );
  3009. }
  3010. if ( _hAutoConfigDLL )
  3011. {
  3012. // HACK HACK This call will block an dll unload time because of the
  3013. // loader critical section. Ideally we should move this free to the
  3014. // main thread, but since we are in the midst of IE5 RC's we are doing
  3015. // the least risky change i.e. leaking jsproxy.dll in the process.
  3016. if (!GlobalDynaUnload)
  3017. {
  3018. FreeLibrary(_hAutoConfigDLL);
  3019. }
  3020. _pGetProxyInfo = NULL;
  3021. _pGetProxyInfoEx = NULL;
  3022. _pProxyDllInit = NULL;
  3023. _pProxyDllDeInit = NULL;
  3024. _pProxyInfoInvalid = NULL;
  3025. }
  3026. DEBUG_LEAVE(0);
  3027. }
  3028. DWORD
  3029. AUTO_PROXY_LIST_ENTRY::LoadEntry(
  3030. VOID
  3031. )
  3032. /*++
  3033. Routine Description:
  3034. Loads the DLL function entry points for an Auto-Proxy DLL.
  3035. Arguments:
  3036. none.
  3037. Return Value:
  3038. DWORD
  3039. ERROR_SUCCESS - success
  3040. Win32 Error code - failure
  3041. --*/
  3042. {
  3043. DWORD error = ERROR_SUCCESS;
  3044. DEBUG_ENTER((DBG_PROXY,
  3045. Dword,
  3046. "AUTO_PROXY_LIST_ENTRY::LoadEntry",
  3047. ""
  3048. ));
  3049. if ( _lpszFileExtensions == NULL ||
  3050. _lpszDllFilePath == NULL )
  3051. {
  3052. error = ERROR_NOT_ENOUGH_MEMORY;
  3053. goto quit;
  3054. }
  3055. _pGetProxyInfo = NULL;
  3056. _pProxyInfoInvalid = NULL;
  3057. _pProxyDllDeInit = NULL;
  3058. _pProxyDllInit = NULL;
  3059. _pGetProxyInfoEx = NULL;
  3060. if ( _hAutoConfigDLL )
  3061. {
  3062. FreeLibrary(_hAutoConfigDLL);
  3063. _hAutoConfigDLL = NULL;
  3064. }
  3065. _hAutoConfigDLL = LoadLibrary(_lpszDllFilePath);
  3066. if ( _hAutoConfigDLL == NULL )
  3067. {
  3068. error = GetLastError();
  3069. goto quit;
  3070. }
  3071. _pGetProxyInfo = (GET_PROXY_INFO_FN)
  3072. GetProcAddress(_hAutoConfigDLL, GET_PROXY_INFO_FN_NAME);
  3073. _pGetProxyInfoEx = (GET_PROXY_INFO_EX_FN)
  3074. GetProcAddress(_hAutoConfigDLL, GET_PROXY_INFO_EX_FN_NAME);
  3075. _pProxyInfoInvalid = (PROXY_INFO_INVALID_FN)
  3076. GetProcAddress(_hAutoConfigDLL, PROXY_INFO_INVALID_FN_NAME);
  3077. _pProxyDllDeInit = (PROXY_DLL_DEINIT_FN)
  3078. GetProcAddress(_hAutoConfigDLL, PROXY_DLL_DEINIT_FN_NAME);
  3079. _pProxyDllInit = (PROXY_DLL_INIT_FN)
  3080. GetProcAddress(_hAutoConfigDLL, PROXY_DLL_INIT_FN_NAME );
  3081. if ( !_pProxyDllInit && !_pProxyDllDeInit && !_pProxyInfoInvalid && !_pGetProxyInfo && !_pGetProxyInfoEx)
  3082. {
  3083. error = GetLastError();
  3084. goto quit;
  3085. }
  3086. if ( !_pProxyDllInit )
  3087. {
  3088. //
  3089. // If they don't export this entry point, than we can't initialize them, so
  3090. // we pretend to have initialized them.
  3091. //
  3092. _fInitializedSuccessfully = TRUE;
  3093. }
  3094. quit:
  3095. DEBUG_LEAVE(error);
  3096. return error;
  3097. }
  3098. BOOL
  3099. AUTO_PROXY_DLLS::SelectAutoProxyByMime(
  3100. IN LPSTR lpszMimeType
  3101. )
  3102. /*++
  3103. Routine Description:
  3104. Sets an internal pointer inside the object to point to a found auto-proxy DLL.
  3105. The MIME type given is used to find the match.
  3106. Arguments:
  3107. lpszMimeType - The Mime type to search on.
  3108. Return Value:
  3109. BOOL
  3110. TRUE - success
  3111. FALSE - failure
  3112. --*/
  3113. {
  3114. DEBUG_ENTER((DBG_PROXY,
  3115. Bool,
  3116. "AUTO_PROXY_DLLS::SelectAutoProxyByMime",
  3117. "%s",
  3118. lpszMimeType
  3119. ));
  3120. BOOL found = FALSE;
  3121. AUTO_PROXY_LIST_ENTRY * info = NULL;
  3122. LockAutoProxy();
  3123. LockSerializedList(&_List);
  3124. for (PLIST_ENTRY entry = HeadOfSerializedList(&_List);
  3125. entry != (PLIST_ENTRY)SlSelf(&_List);
  3126. entry = entry->Flink)
  3127. {
  3128. info = CONTAINING_RECORD(entry, AUTO_PROXY_LIST_ENTRY, _List);
  3129. if (info->_lpszMimeType && lstrcmpi(lpszMimeType, info->_lpszMimeType) == 0 )
  3130. {
  3131. found = TRUE;
  3132. break;
  3133. }
  3134. }
  3135. UnlockSerializedList(&_List);
  3136. if ( found )
  3137. {
  3138. SelectAutoProxy(info);
  3139. }
  3140. UnlockAutoProxy();
  3141. DEBUG_LEAVE(found);
  3142. return found;
  3143. }
  3144. BOOL
  3145. AUTO_PROXY_DLLS::SelectAutoProxyByDefault(
  3146. VOID
  3147. )
  3148. {
  3149. DEBUG_ENTER((DBG_PROXY,
  3150. Bool,
  3151. "AUTO_PROXY_DLLS::SelectAutoProxyByDefault",
  3152. NULL
  3153. ));
  3154. BOOL found = FALSE;
  3155. AUTO_PROXY_LIST_ENTRY * info = NULL;
  3156. LockAutoProxy();
  3157. LockSerializedList(&_List);
  3158. for (PLIST_ENTRY entry = HeadOfSerializedList(&_List);
  3159. entry != (PLIST_ENTRY)SlSelf(&_List);
  3160. entry = entry->Flink)
  3161. {
  3162. info = CONTAINING_RECORD(entry, AUTO_PROXY_LIST_ENTRY, _List);
  3163. if (info->IsDefault() )
  3164. {
  3165. found = TRUE;
  3166. break;
  3167. }
  3168. }
  3169. UnlockSerializedList(&_List);
  3170. if ( found )
  3171. {
  3172. SelectAutoProxy(info);
  3173. }
  3174. DEBUG_LEAVE(found);
  3175. UnlockAutoProxy();
  3176. return found;
  3177. }
  3178. BOOL
  3179. AUTO_PROXY_DLLS::SelectAutoProxyByFileExtension(
  3180. LPCSTR lpszAutoProxyPath
  3181. )
  3182. {
  3183. DEBUG_ENTER((DBG_PROXY,
  3184. Bool,
  3185. "AUTO_PROXY_DLLS::SelectAutoProxyByFileExtension",
  3186. "%s",
  3187. lpszAutoProxyPath
  3188. ));
  3189. BOOL found = FALSE;
  3190. AUTO_PROXY_LIST_ENTRY * info = NULL;
  3191. LockAutoProxy();
  3192. LockSerializedList(&_List);
  3193. for (PLIST_ENTRY entry = HeadOfSerializedList(&_List);
  3194. entry != (PLIST_ENTRY)SlSelf(&_List);
  3195. entry = entry->Flink)
  3196. {
  3197. info = CONTAINING_RECORD(entry, AUTO_PROXY_LIST_ENTRY, _List);
  3198. if (info->_lpszFileExtensions &&
  3199. MatchFileExtensionWithUrl(info->_lpszFileExtensions, lpszAutoProxyPath) )
  3200. {
  3201. found = TRUE;
  3202. break;
  3203. }
  3204. }
  3205. UnlockSerializedList(&_List);
  3206. if ( found )
  3207. {
  3208. SelectAutoProxy(info);
  3209. }
  3210. UnlockAutoProxy();
  3211. DEBUG_LEAVE(found);
  3212. return found;
  3213. }
  3214. DWORD
  3215. AUTO_PROXY_DLLS::GetAutoProxyStringEntry(
  3216. IN LPSTR lpszRegName,
  3217. IN OUT LPSTR * lplpszAllocatedRegValue
  3218. )
  3219. {
  3220. DWORD dwcbNewValue = 0;
  3221. DWORD error = ERROR_SUCCESS;
  3222. if ( *lplpszAllocatedRegValue )
  3223. {
  3224. FREE_MEMORY(*lplpszAllocatedRegValue);
  3225. *lplpszAllocatedRegValue = NULL;
  3226. }
  3227. error =
  3228. InternetReadRegistryString(
  3229. lpszRegName,
  3230. NULL,
  3231. &dwcbNewValue
  3232. );
  3233. if ( error == ERROR_SUCCESS )
  3234. {
  3235. dwcbNewValue++;
  3236. *lplpszAllocatedRegValue = (LPSTR) ALLOCATE_MEMORY(LMEM_FIXED, dwcbNewValue);
  3237. if ( *lplpszAllocatedRegValue == NULL )
  3238. {
  3239. error = ERROR_NOT_ENOUGH_MEMORY;
  3240. goto quit;
  3241. }
  3242. error =
  3243. InternetReadRegistryString(
  3244. lpszRegName,
  3245. *lplpszAllocatedRegValue,
  3246. &dwcbNewValue
  3247. );
  3248. if ( error != ERROR_SUCCESS )
  3249. {
  3250. INET_ASSERT((error == ERROR_SUCCESS));
  3251. FREE_MEMORY(*lplpszAllocatedRegValue);
  3252. *lplpszAllocatedRegValue = NULL;
  3253. }
  3254. }
  3255. quit:
  3256. return error;
  3257. }
  3258. DWORD
  3259. AUTO_PROXY_DLLS::ReadAutoProxyRegistrySettings(
  3260. VOID
  3261. )
  3262. /*++
  3263. Routine Description:
  3264. Scans Registry for, and builds linked list of AutoProxy DLLs.
  3265. Return Value:
  3266. Success - ERROR_SUCCESS
  3267. Failure -
  3268. --*/
  3269. {
  3270. HKEY hkSecurity = NULL; // main security key
  3271. DWORD error = ERROR_SUCCESS;
  3272. DWORD dwcbAutoConfigProxy = 0;
  3273. HKEY hkSPMKey = NULL;
  3274. const static CHAR cszMainSecKey[]
  3275. = CSZMAINSECKEY;
  3276. DEBUG_ENTER((DBG_PROXY,
  3277. Dword,
  3278. "AUTO_PROXY_DLLS::ReadAutoProxyRegistrySettings",
  3279. ""
  3280. ));
  3281. LockAutoProxy();
  3282. //
  3283. // QFE 1169: Use the HKCU value as the user agent string if told to do so.
  3284. // Yes this looks ugly, but it's just to prevent a whole bunch
  3285. // of ifs and handlers for failures.
  3286. DWORD dwcbBufLen = 0;
  3287. if (ERROR_SUCCESS == InternetReadRegistryDwordKey(
  3288. HKEY_CURRENT_USER,
  3289. "AutoConfigCustomUA",
  3290. &dwcbBufLen) &&
  3291. dwcbBufLen)
  3292. {
  3293. if (NULL == _hInstUrlmon)
  3294. {
  3295. _hInstUrlmon = LoadLibrary("Urlmon.dll");
  3296. }
  3297. if (_hInstUrlmon)
  3298. {
  3299. typedef HRESULT (*PFNOBTAINUA)(DWORD, LPSTR, DWORD*);
  3300. CHAR lpszUserAgent[MAX_PATH];
  3301. DWORD cbSize = MAX_PATH;
  3302. PFNOBTAINUA pfnUA = (PFNOBTAINUA)GetProcAddress(_hInstUrlmon,"ObtainUserAgentString");
  3303. if (pfnUA)
  3304. {
  3305. HRESULT hr = (*pfnUA)(0, lpszUserAgent, &cbSize);
  3306. if(S_OK == hr)
  3307. {
  3308. if ( _lpszUserAgent && (lstrcmpi(_lpszUserAgent, lpszUserAgent) != 0) )
  3309. {
  3310. _lpszUserAgent = (LPSTR)
  3311. FREE_MEMORY(_lpszUserAgent);
  3312. }
  3313. if ( _lpszUserAgent == NULL )
  3314. {
  3315. _lpszUserAgent = NewString(lpszUserAgent);
  3316. }
  3317. }
  3318. }
  3319. }
  3320. }
  3321. if (REGOPENKEY( HKEY_CLASSES_ROOT, cszMainSecKey, &hkSecurity ) != ERROR_SUCCESS)
  3322. {
  3323. error = GetLastError();
  3324. goto quit;
  3325. }
  3326. DWORD dwIndex;
  3327. dwIndex = 0;
  3328. do
  3329. {
  3330. CHAR szMime[256];
  3331. #ifdef unix
  3332. CHAR szUnixHackMime[256];
  3333. #endif /* unix */
  3334. if ( hkSPMKey != NULL )
  3335. {
  3336. REGCLOSEKEY(hkSPMKey);
  3337. hkSPMKey = NULL;
  3338. }
  3339. //
  3340. // Enumerate a List of MIME types, that we accept for auto-proxy
  3341. //
  3342. if (RegEnumKey( hkSecurity, dwIndex, szMime, sizeof(szMime)) != ERROR_SUCCESS )
  3343. {
  3344. goto quit;
  3345. }
  3346. dwIndex++;
  3347. //
  3348. // Open a potential MIME type entry.
  3349. //
  3350. if (REGOPENKEY( hkSecurity, szMime, &hkSPMKey ) != ERROR_SUCCESS)
  3351. {
  3352. INET_ASSERT(0);
  3353. continue;
  3354. }
  3355. //
  3356. // Grab the DLL file name
  3357. //
  3358. DWORD dwType, cbBuf;
  3359. char szDll[MAX_PATH];
  3360. cbBuf = sizeof(szDll);
  3361. if (ERROR_SUCCESS != RegQueryValueEx
  3362. (hkSPMKey, "DllFile", NULL, &dwType, (LPBYTE) szDll, &cbBuf)
  3363. || ((dwType != REG_SZ) && (dwType != REG_EXPAND_SZ)) )
  3364. {
  3365. continue; // no DLL name
  3366. }
  3367. if ( dwType == REG_EXPAND_SZ )
  3368. {
  3369. DWORD dwSize;
  3370. char szDllPathBeforeExpansion[MAX_PATH];
  3371. lstrcpy(szDllPathBeforeExpansion, szDll);
  3372. dwSize = ExpandEnvironmentStrings(szDllPathBeforeExpansion, szDll, ARRAY_ELEMENTS(szDll));
  3373. if (dwSize > ARRAY_ELEMENTS(szDll) || dwSize == 0 )
  3374. {
  3375. INET_ASSERT(FALSE);
  3376. continue; // not enough room to expand vars?
  3377. }
  3378. }
  3379. //
  3380. // Grab the list of File extensions that are permitted for this Mime Type
  3381. //
  3382. char szFileExtensions[MAX_PATH];
  3383. cbBuf = sizeof(szFileExtensions);
  3384. if (ERROR_SUCCESS != RegQueryValueEx
  3385. (hkSPMKey, "FileExtensions", NULL, &dwType, (LPBYTE) szFileExtensions, &cbBuf)
  3386. || (dwType != REG_SZ))
  3387. {
  3388. continue; // no DLL name
  3389. }
  3390. //
  3391. // Determine whether its the defaut entry.
  3392. //
  3393. DWORD fIsDefault;
  3394. cbBuf = sizeof(fIsDefault);
  3395. if (ERROR_SUCCESS != RegQueryValueEx
  3396. (hkSPMKey, "Default", NULL, &dwType, (LPBYTE) &fIsDefault, &cbBuf)
  3397. || ((dwType != REG_DWORD) && (dwType != REG_BINARY)))
  3398. {
  3399. INET_ASSERT (cbBuf == sizeof(DWORD));
  3400. fIsDefault = 0;
  3401. }
  3402. //
  3403. // Determine whether we have any Flags that need to be read
  3404. // from the registry.
  3405. //
  3406. DWORD dwFlags;
  3407. cbBuf = sizeof(dwFlags);
  3408. if (ERROR_SUCCESS != RegQueryValueEx
  3409. (hkSPMKey, "Flags", NULL, &dwType, (LPBYTE) &dwFlags, &cbBuf)
  3410. || ((dwType != REG_DWORD) && (dwType != REG_BINARY)))
  3411. {
  3412. dwFlags = 0;
  3413. }
  3414. //
  3415. // Now build an entry for it, and add it to our list.
  3416. //
  3417. #ifndef unix
  3418. AUTO_PROXY_LIST_ENTRY *apleAutoProxy
  3419. = new AUTO_PROXY_LIST_ENTRY(szDll, szFileExtensions, szMime, fIsDefault, dwFlags);
  3420. #else
  3421. strcpy(szUnixHackMime,"application/");
  3422. strcat(szUnixHackMime,szMime);
  3423. AUTO_PROXY_LIST_ENTRY *apleAutoProxy
  3424. = new AUTO_PROXY_LIST_ENTRY(szDll, szFileExtensions, szUnixHackMime, fIsDefault, dwFlags);
  3425. #endif /* unix */
  3426. if (!apleAutoProxy)
  3427. {
  3428. error = ERROR_NOT_ENOUGH_MEMORY;
  3429. goto quit;
  3430. }
  3431. if (fIsDefault)
  3432. {
  3433. InsertAtTailOfSerializedList(&_List, &apleAutoProxy->_List);
  3434. }
  3435. else
  3436. {
  3437. InsertAtHeadOfSerializedList(&_List, &apleAutoProxy->_List);
  3438. }
  3439. } while (1);
  3440. error = ERROR_SUCCESS;
  3441. quit:
  3442. if ( hkSPMKey != NULL )
  3443. {
  3444. REGCLOSEKEY(hkSPMKey);
  3445. }
  3446. if ( hkSecurity != NULL )
  3447. {
  3448. REGCLOSEKEY(hkSecurity);
  3449. }
  3450. UnlockAutoProxy();
  3451. DEBUG_LEAVE(error);
  3452. return error;
  3453. }
  3454. AUTO_PROXY_ASYNC_MSG::AUTO_PROXY_ASYNC_MSG(
  3455. IN INTERNET_SCHEME isUrlScheme,
  3456. IN LPSTR lpszUrl,
  3457. IN LPSTR lpszUrlHostName,
  3458. IN DWORD dwUrlHostNameLength
  3459. )
  3460. {
  3461. URL_COMPONENTS urlComponents;
  3462. Initalize();
  3463. if ( lpszUrl )
  3464. {
  3465. _lpszUrl = lpszUrl;
  3466. _dwUrlLength = lstrlen(lpszUrl);
  3467. _tUrlProtocol = isUrlScheme;
  3468. _pmProxyQuery = PROXY_MSG_GET_PROXY_INFO;
  3469. _pmaAllocMode = MSG_ALLOC_STACK_ONLY;
  3470. memset(&urlComponents, 0, sizeof(urlComponents));
  3471. urlComponents.dwStructSize = sizeof(urlComponents);
  3472. urlComponents.lpszHostName = lpszUrlHostName;
  3473. urlComponents.dwHostNameLength = dwUrlHostNameLength;
  3474. //
  3475. // parse out the host name and port. The host name will be decoded; the
  3476. // original URL will not be modified
  3477. //
  3478. if (InternetCrackUrl(lpszUrl, 0, ICU_DECODE, &urlComponents))
  3479. {
  3480. _nUrlPort = urlComponents.nPort;
  3481. _lpszUrlHostName = urlComponents.lpszHostName;
  3482. _dwUrlHostNameLength = urlComponents.dwHostNameLength;
  3483. if ( _tUrlProtocol == INTERNET_SCHEME_UNKNOWN )
  3484. {
  3485. _tUrlProtocol = urlComponents.nScheme;
  3486. }
  3487. }
  3488. else
  3489. {
  3490. _Error = GetLastError();
  3491. }
  3492. }
  3493. else
  3494. {
  3495. _Error = ERROR_NOT_ENOUGH_MEMORY;
  3496. }
  3497. }
  3498. AUTO_PROXY_ASYNC_MSG::AUTO_PROXY_ASYNC_MSG(
  3499. IN INTERNET_SCHEME isUrlScheme,
  3500. IN LPSTR lpszUrlHostName,
  3501. IN DWORD dwUrlHostNameLength
  3502. )
  3503. {
  3504. Initalize();
  3505. _tUrlProtocol = isUrlScheme;
  3506. _pmProxyQuery = PROXY_MSG_GET_PROXY_INFO;
  3507. _pmaAllocMode = MSG_ALLOC_STACK_ONLY;
  3508. _lpszUrlHostName = lpszUrlHostName;
  3509. _dwUrlHostNameLength = dwUrlHostNameLength;
  3510. }
  3511. AUTO_PROXY_ASYNC_MSG::AUTO_PROXY_ASYNC_MSG(
  3512. IN INTERNET_SCHEME isUrlScheme,
  3513. IN LPSTR lpszUrl,
  3514. IN DWORD dwUrlLength,
  3515. IN LPSTR lpszUrlHostName,
  3516. IN DWORD dwUrlHostNameLength,
  3517. IN INTERNET_PORT nUrlPort
  3518. )
  3519. {
  3520. Initalize();
  3521. _tUrlProtocol = isUrlScheme;
  3522. _pmProxyQuery = PROXY_MSG_GET_PROXY_INFO;
  3523. _pmaAllocMode = MSG_ALLOC_STACK_ONLY;
  3524. _nUrlPort = nUrlPort;
  3525. _lpszUrlHostName = lpszUrlHostName;
  3526. _dwUrlHostNameLength = dwUrlHostNameLength;
  3527. _lpszUrl = lpszUrl;
  3528. _dwUrlLength = dwUrlLength;
  3529. }
  3530. VOID
  3531. AUTO_PROXY_ASYNC_MSG::SetProxyMsg(
  3532. IN INTERNET_SCHEME isUrlScheme,
  3533. IN LPSTR lpszUrl,
  3534. IN DWORD dwUrlLength,
  3535. IN LPSTR lpszUrlHostName,
  3536. IN DWORD dwUrlHostNameLength,
  3537. IN INTERNET_PORT nUrlPort
  3538. )
  3539. {
  3540. _tUrlProtocol = isUrlScheme;
  3541. _pmProxyQuery = PROXY_MSG_GET_PROXY_INFO;
  3542. _pmaAllocMode = MSG_ALLOC_STACK_ONLY;
  3543. _nUrlPort = nUrlPort;
  3544. _lpszUrlHostName = lpszUrlHostName;
  3545. _dwUrlHostNameLength = dwUrlHostNameLength;
  3546. _lpszUrl = lpszUrl;
  3547. _dwUrlLength = dwUrlLength;
  3548. }
  3549. AUTO_PROXY_ASYNC_MSG::AUTO_PROXY_ASYNC_MSG(
  3550. IN PROXY_MESSAGE_TYPE pmProxyQuery
  3551. )
  3552. {
  3553. Initalize();
  3554. _pmaAllocMode = MSG_ALLOC_HEAP_MSG_OBJ_OWNS;
  3555. _pmProxyQuery = pmProxyQuery;
  3556. }
  3557. AUTO_PROXY_ASYNC_MSG::AUTO_PROXY_ASYNC_MSG(
  3558. IN AUTO_PROXY_ASYNC_MSG *pStaticAutoProxy
  3559. )
  3560. {
  3561. Initalize();
  3562. _tUrlProtocol = pStaticAutoProxy->_tUrlProtocol;
  3563. _lpszUrl = (pStaticAutoProxy->_lpszUrl) ? NewString(pStaticAutoProxy->_lpszUrl) : NULL;
  3564. _dwUrlLength = pStaticAutoProxy->_dwUrlLength;
  3565. _lpszUrlHostName =
  3566. (pStaticAutoProxy->_lpszUrlHostName ) ?
  3567. NewString(pStaticAutoProxy->_lpszUrlHostName, pStaticAutoProxy->_dwUrlHostNameLength) :
  3568. NULL;
  3569. _dwUrlHostNameLength = pStaticAutoProxy->_dwUrlHostNameLength;
  3570. _nUrlPort = pStaticAutoProxy->_nUrlPort;
  3571. _tProxyScheme = pStaticAutoProxy->_tProxyScheme;
  3572. //
  3573. // ProxyHostName is something that is generated by the request,
  3574. // therefore it should not be copied OR freed.
  3575. //
  3576. INET_ASSERT( pStaticAutoProxy->_lpszProxyHostName == NULL );
  3577. //_lpszProxyHostName = (pStaticAutoProxy->_lpszProxyHostName ) ? NewString(pStaticAutoProxy->_lpszProxyHostName) : NULL;
  3578. _dwProxyHostNameLength = pStaticAutoProxy->_dwProxyHostNameLength;
  3579. _nProxyHostPort = pStaticAutoProxy->_nProxyHostPort;
  3580. _pmProxyQuery = pStaticAutoProxy->_pmProxyQuery;
  3581. _pmaAllocMode = MSG_ALLOC_HEAP_MSG_OBJ_OWNS;
  3582. _pProxyState = pStaticAutoProxy->_pProxyState;
  3583. INET_ASSERT(_pProxyState == NULL);
  3584. _dwQueryResult = pStaticAutoProxy->_dwQueryResult;
  3585. _Error = pStaticAutoProxy->_Error;
  3586. _MessageFlags.Dword = pStaticAutoProxy->_MessageFlags.Dword;
  3587. _dwProxyVersion = pStaticAutoProxy->_dwProxyVersion;
  3588. }
  3589. AUTO_PROXY_ASYNC_MSG::~AUTO_PROXY_ASYNC_MSG(
  3590. VOID
  3591. )
  3592. {
  3593. DEBUG_ENTER((DBG_OBJECTS,
  3594. None,
  3595. "~AUTO_PROXY_ASYNC_MSG",
  3596. NULL
  3597. ));
  3598. if ( IsAlloced() )
  3599. {
  3600. DEBUG_PRINT(OBJECTS,
  3601. INFO,
  3602. ("Freeing Allocated MSG ptr=%x\n",
  3603. this
  3604. ));
  3605. if ( _lpszUrl )
  3606. {
  3607. //DEBUG_PRINT(OBJECTS,
  3608. // INFO,
  3609. // ("Url ptr=%x, %q\n",
  3610. // _lpszUrl,
  3611. // _lpszUrl
  3612. // ));
  3613. FREE_MEMORY(_lpszUrl);
  3614. }
  3615. if ( _lpszUrlHostName )
  3616. {
  3617. FREE_MEMORY(_lpszUrlHostName);
  3618. }
  3619. if ( _pProxyState )
  3620. {
  3621. delete _pProxyState;
  3622. }
  3623. }
  3624. if (_bFreeProxyHostName && (_lpszProxyHostName != NULL)) {
  3625. FREE_MEMORY(_lpszProxyHostName);
  3626. }
  3627. DEBUG_LEAVE(0);
  3628. }
  3629. //
  3630. // functions
  3631. //
  3632. PRIVATE
  3633. BOOL
  3634. MatchFileExtensionWithUrl(
  3635. IN LPCSTR lpszFileExtensionList,
  3636. IN LPCSTR lpszUrl
  3637. )
  3638. /*++
  3639. Routine Description:
  3640. Matches a Url with a string of externsions (looks like ".ins;.jv").
  3641. Confims the Url is using one the approved externsions.
  3642. Arguments:
  3643. lpszFileExtensionList - the list of file extensions to check the Url against.
  3644. lpszUrl - the url to examine.
  3645. Return Value:
  3646. BOOL
  3647. TRUE - success
  3648. FALSE - the Url does not contain any of the extensions.
  3649. --*/
  3650. {
  3651. LPCSTR lpszExtension, lpszExtensionOffset;
  3652. LPCSTR lpszQuestion;
  3653. //
  3654. // We need to be careful about checking for a period on the end of an URL
  3655. // Example: if we have: "http://auto-proxy-srv/fooboo.exe?autogenator.com.ex" ?
  3656. //
  3657. lpszQuestion = strchr( lpszUrl, '?' );
  3658. lpszUrl = ( lpszQuestion ) ? lpszQuestion : lpszUrl;
  3659. lpszExtension = strrchr( lpszUrl, '.' );
  3660. if ( lpszExtension )
  3661. {
  3662. lpszExtensionOffset = lpszExtension;
  3663. BOOL fMatching = FALSE;
  3664. BOOL fCurrentMatch = FALSE;
  3665. BOOL fFirstByte = TRUE;
  3666. while ( *lpszFileExtensionList && *lpszExtensionOffset )
  3667. {
  3668. if ( toupper(*lpszFileExtensionList) == toupper(*lpszExtensionOffset) )
  3669. {
  3670. fCurrentMatch = TRUE;
  3671. }
  3672. else
  3673. {
  3674. fCurrentMatch = FALSE;
  3675. }
  3676. if ( *lpszFileExtensionList == ';')
  3677. {
  3678. lpszExtensionOffset = lpszExtension-1;
  3679. fFirstByte = TRUE;
  3680. if ( fMatching )
  3681. {
  3682. return TRUE;
  3683. }
  3684. }
  3685. else if ( fFirstByte || fMatching )
  3686. {
  3687. fMatching = fCurrentMatch;
  3688. fFirstByte = FALSE;
  3689. }
  3690. lpszExtensionOffset++;
  3691. lpszFileExtensionList++;
  3692. if ( *lpszExtensionOffset == '\0' )
  3693. {
  3694. lpszExtensionOffset = lpszExtension;
  3695. }
  3696. }
  3697. if ( fMatching )
  3698. {
  3699. return TRUE;
  3700. }
  3701. }
  3702. return FALSE;
  3703. }
  3704. #ifdef unix
  3705. static BOOL fForceAutoProxSync = TRUE;
  3706. extern "C"
  3707. void unixForceAutoProxSync()
  3708. {
  3709. if(fForceAutoProxSync)
  3710. {
  3711. if (!GlobalDataInitialized)
  3712. GlobalDataInitialize();
  3713. if (GlobalDataInitialized)
  3714. {
  3715. GlobalProxyInfo.SetRefreshDisabled(FALSE);
  3716. FixProxySettingsForCurrentConnection(TRUE);
  3717. GlobalProxyInfo.ReleaseQueuedRefresh();
  3718. fForceAutoProxSync = FALSE;
  3719. }
  3720. }
  3721. }
  3722. #endif /* unix */