proxysup.cpp
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 46k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. /*++
  2. Copyright (c) 1996  Microsoft Corporation
  3. Module Name:
  4.     proxysup.c
  5. Abstract:
  6.     Contains implementation for proxy server and proxy bypass list
  7.     dialog interface.
  8.     WARNING: Changes in this code need to be syncronizated
  9.     with changes in proxysup.cxx in the WININET project.
  10.     Contents:
  11. Author:
  12.     Arthur L Bierer (arthurbi) 18-Apr-1996
  13. Revision History:
  14.     18-Apr-1996 arthurbi
  15.     Created
  16. --*/
  17. #include "inetcplp.h"
  18. #include <mluisupp.h>
  19. // Disable warning for VC6 (ASSERT macro causing the problem)
  20. #pragma warning(4:4509) // nonstandard extension used: 'ftn' uses SEH and 'object' has destructor
  21. //
  22. // Don't use CRTs so define our own isdigit
  23. //
  24. #undef isdigit
  25. #define isdigit(ch) (ch >= '0' && ch <= '9')
  26. //
  27. // ARRAY_ELEMENTS - returns number of elements in array
  28. //
  29. #define ARRAY_ELEMENTS(array)   (sizeof(array)/sizeof(array[0]))
  30. #define GET_TERMINATOR(string)  while(*string != '') string++
  31. #define IS_BLANK(string)        (*string == '')
  32. //
  33. // private types
  34. //
  35. typedef enum {
  36.     STATE_START,
  37.     STATE_PROTOCOL,
  38.     STATE_SCHEME,
  39.     STATE_SERVER,
  40.     STATE_PORT,
  41.     STATE_END,
  42.     STATE_ERROR
  43. } PARSER_STATE;
  44. typedef struct tagMY_URL_SCHEME
  45. {
  46.     LPSTR           SchemeName;
  47.     DWORD           SchemeLength;
  48.     INTERNET_SCHEME SchemeType;
  49.     DWORD           dwControlId;
  50.     DWORD           dwPortControlId;
  51. } MY_URL_SCHEME;
  52. const MY_URL_SCHEME UrlSchemeList[] =
  53. {
  54.     NULL,       0,  INTERNET_SCHEME_DEFAULT,IDC_NOTUSED,                  IDC_NOTUSED,
  55.     "ftp",      3,  INTERNET_SCHEME_FTP,    IDC_PROXY_FTP_ADDRESS,        IDC_PROXY_FTP_PORT,
  56.     "gopher",   6,  INTERNET_SCHEME_GOPHER, IDC_PROXY_GOPHER_ADDRESS,     IDC_PROXY_GOPHER_PORT,
  57.     "http",     4,  INTERNET_SCHEME_HTTP,   IDC_PROXY_HTTP_ADDRESS,       IDC_PROXY_HTTP_PORT,
  58.     "https",    5,  INTERNET_SCHEME_HTTPS,  IDC_PROXY_SECURITY_ADDRESS,   IDC_PROXY_SECURITY_PORT,
  59.     "socks",    5,  INTERNET_SCHEME_SOCKS,  IDC_PROXY_SOCKS_ADDRESS,      IDC_PROXY_SOCKS_PORT,
  60. };
  61. #define INTERNET_MAX_PORT_LENGTH    sizeof("123456789")
  62. typedef struct tagBEFOREUSESAME
  63. {
  64.     // addresses
  65.     TCHAR szFTP      [ INTERNET_MAX_URL_LENGTH + 1 ];
  66.     TCHAR szGOPHER   [ INTERNET_MAX_URL_LENGTH + 1 ];
  67.     TCHAR szSECURE   [ INTERNET_MAX_URL_LENGTH + 1 ];
  68.     TCHAR szSOCKS    [ INTERNET_MAX_URL_LENGTH + 1 ];
  69.     // ports
  70.     TCHAR szFTPport      [ INTERNET_MAX_PORT_LENGTH + 1 ];
  71.     TCHAR szGOPHERport   [ INTERNET_MAX_PORT_LENGTH + 1 ];
  72.     TCHAR szSECUREport   [ INTERNET_MAX_PORT_LENGTH + 1 ];
  73.     TCHAR szSOCKSport    [ INTERNET_MAX_PORT_LENGTH + 1 ];
  74. } BEFOREUSESAME, *LPBEFOREUSESAME;
  75. static const int g_iProxies[] = {IDC_PROXY_HTTP_ADDRESS, IDC_PROXY_FTP_ADDRESS, IDC_PROXY_GOPHER_ADDRESS, IDC_PROXY_SECURITY_ADDRESS, IDC_PROXY_SOCKS_ADDRESS};
  76. typedef struct tagPROXYPAGE
  77. {
  78.     LPBEFOREUSESAME lpOldSettings;
  79.     BOOL            fNT;
  80.     LPPROXYINFO     lpi;
  81.     HINSTANCE       hinstUrlMon;    // runtime load URLMON.DLL
  82. } PROXYPAGE, *LPPROXYPAGE;
  83. extern const TCHAR cszLocalString[] = TEXT("<local>");
  84. #define MAX_SCHEME_NAME_LENGTH  sizeof("gopher")
  85. #define MAX_TITLE           80
  86. #define MAX_DIALOG_MESSAGE  300
  87. //
  88. // private function prototypes
  89. //
  90. LPBEFOREUSESAME SaveCurrentSettings(HWND hDlg);
  91. void RestorePreviousSettings(HWND hDlg, LPBEFOREUSESAME lpSave);
  92. BOOL
  93. ProxyDlgInitProxyServers(
  94.     IN HWND hDlg
  95.     );
  96. BOOL
  97. ProxyDlgOK(
  98.     IN HWND hDlg
  99.     );
  100. BOOL
  101. ProxyDlgInit(
  102.     IN HWND hDlg, LPARAM lParam
  103.     );
  104. VOID
  105. EnableProxyControls(
  106.     IN HWND hDlg
  107.     );
  108. BOOL
  109. IsProxyValid(
  110.     IN HWND     hDlg
  111.     );
  112. BOOL
  113. ParseEditCtlForPort(
  114.     IN OUT LPSTR   lpszProxyName,
  115.     IN HWND        hDlg,
  116.     IN DWORD       dwProxyNameCtlId,
  117.     IN DWORD       dwProxyPortCtlId
  118.     );
  119. BOOL
  120. FormatOutProxyEditCtl(
  121.     IN HWND        hDlg,
  122.     IN DWORD       dwProxyNameCtlId,
  123.     IN DWORD       dwProxyPortCtlId,
  124.     OUT LPSTR     lpszOutputStr,
  125.     IN OUT LPDWORD lpdwOutputStrSize,
  126.     IN DWORD       dwOutputStrLength,
  127.     IN BOOL        fDefaultProxy
  128.     );
  129. INTERNET_SCHEME
  130. MapUrlSchemeName(
  131.     IN LPSTR lpszSchemeName,
  132.     IN DWORD dwSchemeNameLength
  133.     );
  134. DWORD
  135. MapUrlSchemeTypeToCtlId(
  136.     IN INTERNET_SCHEME SchemeType,
  137.     IN BOOL        fIdForPortCtl
  138.     );
  139. BOOL
  140. MapCtlIdUrlSchemeName(
  141.     IN DWORD    dwEditCtlId,
  142.     OUT LPSTR   lpszSchemeOut
  143.     );
  144. DWORD
  145. MapAddrCtlIdToPortCtlId(
  146.     IN DWORD    dwEditCtlId
  147.     );
  148. BOOL
  149. RemoveLocalFromExceptionList(
  150.     IN LPTSTR lpszExceptionList
  151.     );
  152. //
  153. // functions
  154. //
  155. /*******************************************************************
  156.     NAME:       ProxyDlgProc
  157.     SYNOPSIS:   Proxy property sheet dialog proc.
  158. ********************************************************************/
  159. INT_PTR CALLBACK ProxyDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam,
  160.     LPARAM lParam)
  161. {
  162.     LPPROXYPAGE pPxy= (LPPROXYPAGE) GetWindowLongPtr(hDlg, DWLP_USER);
  163.     switch (uMsg)
  164.     {
  165.         
  166.         case WM_INITDIALOG:
  167.         {
  168.             BOOL fInited;
  169.             
  170.             fInited = ProxyDlgInit(hDlg, lParam);
  171.             return fInited;
  172.         }
  173.         
  174.         case WM_NOTIFY:
  175.         {
  176.             NMHDR * lpnm = (NMHDR *) lParam;
  177.             switch (lpnm->code)
  178.             {
  179.                 case PSN_APPLY:
  180.                 {
  181.                     BOOL fRet = ProxyDlgOK(hDlg);
  182.                     SetPropSheetResult(hDlg,!fRet);
  183.                     return !fRet;
  184.                     break;
  185.                 }
  186.                 
  187.                 case PSN_RESET:
  188.                     SetPropSheetResult(hDlg,FALSE);
  189.                     break;
  190.             }
  191.             break;
  192.         }
  193.         
  194.         case WM_COMMAND:
  195.             switch (GET_WM_COMMAND_ID(wParam, lParam))
  196.             {
  197.                 case IDC_PROXY_ENABLE:
  198.                     EnableProxyControls(hDlg);
  199.                     break;
  200.                 case IDC_PROXY_HTTP_ADDRESS:
  201.                 case IDC_PROXY_GOPHER_ADDRESS:
  202.                 case IDC_PROXY_SECURITY_ADDRESS:
  203.                 case IDC_PROXY_FTP_ADDRESS:
  204.                 case IDC_PROXY_SOCKS_ADDRESS:
  205.                     if ( GET_WM_COMMAND_CMD(wParam, lParam) == EN_KILLFOCUS )
  206.                     {
  207.                         ParseEditCtlForPort(NULL, hDlg, (GET_WM_COMMAND_ID(wParam, lParam)), 0);
  208.                         EnableProxyControls(hDlg);
  209.                     }
  210.                     break;
  211.                 case IDC_PROXY_HTTP_PORT:
  212.                 case IDC_PROXY_GOPHER_PORT:
  213.                 case IDC_PROXY_SECURITY_PORT:
  214.                 case IDC_PROXY_FTP_PORT:
  215.                 case IDC_PROXY_SOCKS_PORT:
  216.                     if ( GET_WM_COMMAND_CMD(wParam, lParam) == EN_KILLFOCUS )
  217.                     {
  218.                         EnableProxyControls(hDlg);
  219.                     }
  220.                     break;
  221.                 case IDC_PROXY_USE_SAME_SERVER:
  222.                     if ( GET_WM_COMMAND_CMD(wParam, lParam) == BN_CLICKED )
  223.                     {
  224.                         if (IsDlgButtonChecked(hDlg, IDC_PROXY_USE_SAME_SERVER))
  225.                             pPxy->lpOldSettings = SaveCurrentSettings(hDlg);
  226.                         else if (pPxy->lpOldSettings !=NULL)
  227.                         {
  228.                             RestorePreviousSettings(hDlg, pPxy->lpOldSettings);
  229.                             pPxy->lpOldSettings = NULL;
  230.                         }
  231.                         EnableProxyControls(hDlg);
  232.                     }
  233.                     break;
  234.                 case IDOK:
  235.                     if ( GET_WM_COMMAND_CMD(wParam, lParam) == BN_CLICKED )
  236.                     {
  237.                         BOOL fLeaveDialog = TRUE;
  238.                         if (!IsProxyValid(hDlg))
  239.                         {
  240.                             // The proxy is invalid, so we need to ask the user if they want to turn it off.
  241.                             TCHAR szTitle[MAX_TITLE];
  242.                             TCHAR szMessage[MAX_DIALOG_MESSAGE];
  243.                             int nUserResponce;
  244.                             MLLoadShellLangString(IDS_INVALID_PROXY_TITLE, szTitle, ARRAYSIZE(szTitle));
  245.                             MLLoadShellLangString(IDS_INVALID_PROXY, szMessage, ARRAYSIZE(szMessage));
  246.                             // Ask the user if they want to turn off the proxy.
  247.                             nUserResponce = MessageBox(hDlg, szMessage, szTitle, MB_YESNOCANCEL | MB_ICONERROR);
  248.                             if (IDYES == nUserResponce)
  249.                                 pPxy->lpi->fEnable = FALSE;
  250.                             else if (IDCANCEL == nUserResponce)
  251.                                 fLeaveDialog = FALSE;   // The user hit cancel, so let's not leave the dialog.
  252.                         }
  253.                         if (fLeaveDialog)
  254.                         {
  255.                             //
  256.                             // Read the Ctls and Save out to the proxy..
  257.                             //
  258.                             ProxyDlgOK(hDlg);
  259.                             EndDialog(hDlg, IDOK);
  260.                         }
  261.                     }
  262.                     break;
  263.                 case IDCANCEL:
  264.                     if ( GET_WM_COMMAND_CMD(wParam, lParam) == BN_CLICKED )
  265.                     {
  266.                         EndDialog(hDlg, IDCANCEL);
  267.                     }
  268.                     break;
  269.             }
  270.             break;
  271.         case WM_DESTROY:
  272.             if (pPxy->lpOldSettings)
  273.                 LocalFree(pPxy->lpOldSettings);
  274.             if (pPxy->hinstUrlMon)
  275.                 FreeLibrary(pPxy->hinstUrlMon);
  276.             LocalFree(pPxy);
  277.             return TRUE;
  278.         case WM_HELP:      // F1
  279.             ResWinHelp((HWND) ((LPHELPINFO)lParam)->hItemHandle, IDS_HELPFILE,
  280.                 HELP_WM_HELP, (DWORD_PTR)(LPSTR)mapIDCsToIDHs);
  281.             break;
  282.         case WM_CONTEXTMENU:      // right mouse click
  283.             ResWinHelp((HWND)wParam, IDS_HELPFILE,
  284.                 HELP_CONTEXTMENU, (DWORD_PTR)(LPSTR)mapIDCsToIDHs);
  285.             break;
  286.         default:
  287.             return FALSE;
  288.     }
  289.     return TRUE;
  290. }
  291. //
  292. // Private Functions.
  293. //
  294. VOID
  295. EnableProxyControls(HWND hDlg)
  296. /*++
  297. Routine Description:
  298.     Enables controls appropriately depending on what
  299.     checkboxes are checked.
  300. Arguments:
  301.     hDlg        - Page Dialog Box.
  302. Return Value:
  303.     VOID
  304. --*/
  305. {
  306.     BOOL fNT = ((LPPROXYPAGE)GetWindowLongPtr(hDlg, DWLP_USER))->fNT;
  307.     
  308.     BOOL fEnable = !g_restrict.fProxy;
  309.             
  310.     BOOL fUseOneProxy = IsDlgButtonChecked(hDlg,IDC_PROXY_USE_SAME_SERVER);
  311.     
  312.     EnableDlgItem(hDlg,IDC_GRP_SETTINGS2, fEnable);
  313.     EnableDlgItem(hDlg,IDC_PROXY_EXCEPTIONS_GROUPBOX, fEnable);
  314.     EnableDlgItem(hDlg,IDC_TYPE_TEXT, fEnable);
  315.     EnableDlgItem(hDlg,IDC_ADDR_TEXT, fEnable);
  316.     EnableDlgItem(hDlg,IDC_PORT_TEXT, fEnable);
  317.     EnableDlgItem(hDlg,IDC_EXCEPT_TEXT, fEnable);
  318.     EnableDlgItem(hDlg,IDC_EXCEPT2_TEXT, fEnable);
  319.     EnableDlgItem(hDlg,IDC_PROXY_ICON1, fEnable);
  320.     EnableDlgItem(hDlg,IDC_PROXY_ICON2, fEnable);
  321.     
  322.     EnableDlgItem(hDlg,IDC_PROXY_HTTP_CAPTION, fEnable);
  323.     EnableDlgItem(hDlg,IDC_PROXY_SECURITY_CAPTION, fEnable);
  324.     EnableDlgItem(hDlg,IDC_PROXY_FTP_CAPTION, fEnable);
  325.     EnableDlgItem(hDlg,IDC_PROXY_GOPHER_CAPTION, fEnable);
  326.     EnableDlgItem(hDlg,IDC_PROXY_SOCKS_CAPTION, fEnable);
  327.     EnableDlgItem(hDlg, IDC_PROXY_USE_SAME_SERVER, fEnable);
  328.     EnableDlgItem(hDlg,IDC_PROXY_HTTP_ADDRESS,fEnable);
  329.     EnableDlgItem(hDlg,IDC_PROXY_HTTP_PORT,fEnable);
  330.            
  331.     EnableDlgItem(hDlg,IDC_PROXY_OVERRIDE,fEnable);
  332.     //
  333.     // If we only want one Proxy, then make all others use the same
  334.     //  proxy.
  335.     //
  336.     EnableDlgItem(hDlg,IDC_PROXY_SECURITY_ADDRESS,!fUseOneProxy && fEnable);
  337.     EnableDlgItem(hDlg,IDC_PROXY_SECURITY_PORT,!fUseOneProxy && fEnable);
  338.     EnableDlgItem(hDlg,IDC_PROXY_FTP_ADDRESS,!fUseOneProxy && fEnable);
  339.     EnableDlgItem(hDlg,IDC_PROXY_FTP_PORT,!fUseOneProxy && fEnable);
  340.     EnableDlgItem(hDlg,IDC_PROXY_GOPHER_ADDRESS,!fUseOneProxy && fEnable);
  341.     EnableDlgItem(hDlg,IDC_PROXY_GOPHER_PORT,!fUseOneProxy && fEnable);
  342.     EnableDlgItem(hDlg,IDC_PROXY_SOCKS_ADDRESS,!fUseOneProxy && fEnable);
  343.     EnableDlgItem(hDlg,IDC_PROXY_SOCKS_PORT,!fUseOneProxy && fEnable);
  344.     //
  345.     // If we only want one proxy, prepopulate the other fields
  346.     //  so they use the the mirror of the first one.
  347.     //
  348.     if (fUseOneProxy)
  349.     {
  350.         TCHAR szProxyName[MAX_URL_STRING+1];
  351.         TCHAR szProxyPort[INTERNET_MAX_PORT_LENGTH];
  352.         GetDlgItemText(hDlg,
  353.             IDC_PROXY_HTTP_ADDRESS,
  354.             szProxyName,
  355.             ARRAYSIZE(szProxyName));
  356.         GetDlgItemText(hDlg,
  357.             IDC_PROXY_HTTP_PORT,
  358.             szProxyPort,
  359.             ARRAYSIZE(szProxyPort));
  360.         SetDlgItemText(hDlg,IDC_PROXY_SECURITY_ADDRESS,szProxyName);
  361.         SetDlgItemText(hDlg,IDC_PROXY_SECURITY_PORT,szProxyPort);
  362.         SetDlgItemText(hDlg,IDC_PROXY_FTP_ADDRESS,szProxyName);
  363.         SetDlgItemText(hDlg,IDC_PROXY_FTP_PORT,szProxyPort);
  364.         SetDlgItemText(hDlg,IDC_PROXY_GOPHER_ADDRESS,szProxyName);
  365.         SetDlgItemText(hDlg,IDC_PROXY_GOPHER_PORT,szProxyPort);
  366.         SetDlgItemText(hDlg,IDC_PROXY_SOCKS_ADDRESS,TEXT(""));
  367.         SetDlgItemText(hDlg,IDC_PROXY_SOCKS_PORT,TEXT(""));
  368.     }
  369. }
  370. //
  371. // SaveCurrentSettings()
  372. //
  373. // Saves current settings... just in case user changes their mind.
  374. //
  375. // Returns a pointer to a structure filled with current settings.
  376. //
  377. LPBEFOREUSESAME SaveCurrentSettings(HWND hDlg)
  378. {
  379.     LPBEFOREUSESAME lpSave = (LPBEFOREUSESAME)LocalAlloc(LPTR, sizeof(*lpSave));
  380.     if (!lpSave)
  381.         return lpSave; // if NULL return NULL
  382.     GetDlgItemText(hDlg, IDC_PROXY_FTP_ADDRESS,      lpSave->szFTP,    INTERNET_MAX_URL_LENGTH);
  383.     GetDlgItemText(hDlg, IDC_PROXY_GOPHER_ADDRESS,   lpSave->szGOPHER, INTERNET_MAX_URL_LENGTH);
  384.     GetDlgItemText(hDlg, IDC_PROXY_SECURITY_ADDRESS, lpSave->szSECURE, INTERNET_MAX_URL_LENGTH);
  385.     GetDlgItemText(hDlg, IDC_PROXY_SOCKS_ADDRESS,    lpSave->szSOCKS,  INTERNET_MAX_URL_LENGTH);
  386.     GetDlgItemText(hDlg, IDC_PROXY_FTP_PORT,      lpSave->szFTPport,    INTERNET_MAX_URL_LENGTH);
  387.     GetDlgItemText(hDlg, IDC_PROXY_GOPHER_PORT,   lpSave->szGOPHERport, INTERNET_MAX_URL_LENGTH);
  388.     GetDlgItemText(hDlg, IDC_PROXY_SECURITY_PORT, lpSave->szSECUREport, INTERNET_MAX_URL_LENGTH);
  389.     GetDlgItemText(hDlg, IDC_PROXY_SOCKS_PORT,    lpSave->szSOCKSport,  INTERNET_MAX_URL_LENGTH);
  390.     return lpSave;
  391. } // SaveCurrentSettings()
  392. //
  393. // RestorePreviousSettings()
  394. //
  395. // Restores settings... just in case user changes their mind.
  396. //
  397. void RestorePreviousSettings(HWND hDlg, LPBEFOREUSESAME lpSave)
  398. {
  399.     if (!lpSave)
  400.     return; // nothing to do
  401.     SetDlgItemText(hDlg, IDC_PROXY_FTP_ADDRESS,      lpSave->szFTP    );
  402.     SetDlgItemText(hDlg, IDC_PROXY_GOPHER_ADDRESS,   lpSave->szGOPHER );
  403.     SetDlgItemText(hDlg, IDC_PROXY_SECURITY_ADDRESS, lpSave->szSECURE );
  404.     SetDlgItemText(hDlg, IDC_PROXY_SOCKS_ADDRESS,    lpSave->szSOCKS  );
  405.     SetDlgItemText(hDlg, IDC_PROXY_FTP_PORT,      lpSave->szFTPport    );
  406.     SetDlgItemText(hDlg, IDC_PROXY_GOPHER_PORT,   lpSave->szGOPHERport );
  407.     SetDlgItemText(hDlg, IDC_PROXY_SECURITY_PORT, lpSave->szSECUREport );
  408.     SetDlgItemText(hDlg, IDC_PROXY_SOCKS_PORT,    lpSave->szSOCKSport  );
  409.     LocalFree(lpSave);  // give back the memory
  410. } // RestorePreviousSettings()
  411. BOOL
  412. ProxyDlgInit(
  413.     IN HWND hDlg, LPARAM lParam
  414.     )
  415. /*++
  416. Routine Description:
  417.     Initialization proc for proxy prop page
  418. Arguments:
  419.     hDlg        - Page Dialog Box.
  420. Return Value:
  421.     BOOL
  422.     Success - TRUE
  423.     Failure - FALSE
  424. --*/
  425. {
  426.     BOOL fSuccess;
  427.     LPPROXYPAGE pPxy;
  428.     pPxy = (LPPROXYPAGE)LocalAlloc(LPTR, sizeof(*pPxy));
  429.     // NOTE: this NULLS lpOldSettings
  430.     if (!pPxy)
  431.         return FALSE;   // no memory?
  432.     OSVERSIONINFOA osvi;
  433.     osvi.dwOSVersionInfoSize = sizeof(osvi);
  434.     GetVersionExA(&osvi);
  435.     
  436.     pPxy->fNT = (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT);
  437.     ASSERT(pPxy->lpOldSettings == NULL);
  438.         
  439.     // tell dialog where to get info
  440.     SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)pPxy);
  441.     pPxy->lpi = (LPPROXYINFO)lParam;
  442.     //
  443.     // Begin by reading and setting the list of proxy
  444.     //  servers we have.
  445.     //
  446.     fSuccess = ProxyDlgInitProxyServers( hDlg );
  447.     if (!fSuccess)
  448.         return FALSE;
  449.     //
  450.     // read settings from registry, for the list of Exclusion Hosts.
  451.     //
  452.     RegEntry re(REGSTR_PATH_INTERNETSETTINGS,HKEY_CURRENT_USER);
  453.     if (re.GetError() == ERROR_SUCCESS)
  454.     {
  455.         BUFFER bufProxyString(MAX_URL_STRING+1);
  456.         
  457.         if (!bufProxyString)
  458.         {
  459.             MsgBox(NULL,IDS_ERROutOfMemory,MB_ICONEXCLAMATION,MB_OK);
  460.             return FALSE;
  461.         }
  462.         //  
  463.         // get proxy override settings from registry and stuff fields
  464.         //
  465.         if(pPxy->lpi->fReadProxyFromRegistry) {
  466.             re.GetString(REGSTR_VAL_PROXYOVERRIDE,bufProxyString.QueryPtr(),
  467.                      bufProxyString.QuerySize());
  468.             //
  469.             // Parse Overide list, remove "<local>"
  470.             RemoveLocalFromExceptionList(bufProxyString.QueryPtr());
  471.             SetDlgItemText(hDlg,IDC_PROXY_OVERRIDE,bufProxyString.QueryPtr());
  472.         } else {
  473.             SetDlgItemText(hDlg, IDC_PROXY_OVERRIDE, pPxy->lpi->szOverride);
  474.         }
  475.     }
  476.     //
  477.     // initialize the UI appropriately
  478.     //
  479.     EnableProxyControls(hDlg);
  480.     
  481.     return TRUE;
  482. }
  483. BOOL
  484. ProxyDlgOK(
  485.     IN HWND hDlg
  486.     )
  487. /*++
  488. Routine Description:
  489.     OK button handler for proxy prop page
  490. Arguments:
  491.     hDlg        - Page Dialog Box.
  492. Return Value:
  493.     BOOL
  494.     Success - TRUE
  495.     Failure - FALSE
  496. --*/
  497. {
  498.     LPPROXYPAGE pPxy = (LPPROXYPAGE)GetWindowLongPtr(hDlg, DWLP_USER);       
  499.     TCHAR szProxyListOutputBuffer[MAX_URL_STRING];
  500.     CHAR  szProxyListOutputBufferA[MAX_URL_STRING];
  501.     DWORD dwBufferOffset = 0;
  502.     //
  503.     // Get the state of our two check boxes.
  504.     //
  505.     BOOL fUseOneProxy =
  506.         IsDlgButtonChecked(hDlg,IDC_PROXY_USE_SAME_SERVER);
  507.     //
  508.     // Open our Registry Key.
  509.     //
  510.     
  511.     RegEntry re(REGSTR_PATH_INTERNETSETTINGS,HKEY_CURRENT_USER);
  512.     if (re.GetError() == ERROR_SUCCESS)
  513.     {       
  514.         //
  515.         //  Now Format, and write out the list of proxies to
  516.         //  the registry.  We special case the case of
  517.         //  only proxy.
  518.         //
  519.         szProxyListOutputBufferA[dwBufferOffset] = '';
  520.         if ( fUseOneProxy )
  521.         {
  522.             FormatOutProxyEditCtl(
  523.                                   hDlg,
  524.                                   IDC_PROXY_HTTP_ADDRESS,
  525.                                   IDC_PROXY_HTTP_PORT,
  526.                                   szProxyListOutputBufferA,
  527.                                   &dwBufferOffset,
  528.                                   ARRAY_ELEMENTS(szProxyListOutputBufferA),
  529.                                   TRUE
  530.                                  );
  531.         }
  532.         else
  533.         {
  534.             for (int i = 1; i < ARRAY_ELEMENTS(UrlSchemeList); ++i)
  535.             {
  536.                 FormatOutProxyEditCtl(
  537.                                       hDlg,
  538.                                       UrlSchemeList[i].dwControlId,
  539.                                       UrlSchemeList[i].dwPortControlId,
  540.                                       szProxyListOutputBufferA,
  541.                                       &dwBufferOffset,
  542.                                       ARRAY_ELEMENTS(szProxyListOutputBufferA),
  543.                                       FALSE
  544.                                      );
  545.             }
  546.         }
  547.         szProxyListOutputBufferA[dwBufferOffset] = '';
  548. #ifdef UNICODE
  549.         SHAnsiToUnicode(szProxyListOutputBufferA, szProxyListOutputBuffer, MAX_URL_STRING);
  550. #else
  551.         lstrcpy(szProxyListOutputBuffer, szProxyListOutputBufferA);
  552. #endif
  553.         if(pPxy->lpi->fReadProxyFromRegistry) {
  554.             re.SetValue(REGSTR_VAL_PROXYSERVER, szProxyListOutputBuffer);
  555.         } else {
  556.             StrCpyN(pPxy->lpi->szProxy, szProxyListOutputBuffer, MAX_URL_STRING);
  557.         }
  558.         //
  559.         // Now Write out the Proxy Exception List
  560.         //  (list of addresses to use for local connections)
  561.         //
  562.         szProxyListOutputBuffer[0] = '';
  563.         
  564.         GetDlgItemText(hDlg,
  565.                        IDC_PROXY_OVERRIDE,
  566.                        szProxyListOutputBuffer,
  567.                        ARRAY_ELEMENTS(szProxyListOutputBuffer));
  568.                 
  569.         if(pPxy->lpi->fReadProxyFromRegistry) {
  570.             re.SetValue(REGSTR_VAL_PROXYOVERRIDE, szProxyListOutputBuffer);            
  571.         } else {
  572.             StrCpyN(pPxy->lpi->szOverride, szProxyListOutputBuffer, MAX_URL_STRING);
  573.         }
  574.     }
  575.     
  576.     else    
  577.     {
  578.         AssertMsg(0, TEXT("Couldn't save settings to registry!"));
  579.     }
  580.     // let any active (participating) wininet's get notified
  581.     //
  582.     InternetSetOption(NULL, INTERNET_OPTION_SETTINGS_CHANGED, NULL, 0);
  583.     return TRUE;
  584. }
  585. INTERNET_SCHEME
  586. MapUrlSchemeName(
  587.     IN LPSTR lpszSchemeName,
  588.     IN DWORD dwSchemeNameLength
  589.     )
  590. /*++
  591. Routine Description:
  592.     Maps a scheme name/length to a scheme name type
  593. Arguments:
  594.     lpszSchemeName  - pointer to name of scheme to map
  595.     dwSchemeNameLength  - length of scheme (if -1, lpszSchemeName is ASCIZ)
  596. Return Value:
  597.     INTERNET_SCHEME
  598. --*/
  599. {
  600.     if (dwSchemeNameLength == (DWORD)-1)
  601.     {
  602.         dwSchemeNameLength = (DWORD)lstrlenA(lpszSchemeName);
  603.     }
  604.     
  605.     for (int i = 0; i < ARRAY_ELEMENTS(UrlSchemeList); ++i)
  606.     {
  607.         if (UrlSchemeList[i].SchemeLength == dwSchemeNameLength)
  608.         {   
  609.             CHAR chBackup = lpszSchemeName[dwSchemeNameLength];
  610.             lpszSchemeName[dwSchemeNameLength] = '';
  611.             
  612.             if(StrCmpIA(UrlSchemeList[i].SchemeName,lpszSchemeName) == 0)
  613.             {
  614.                 lpszSchemeName[dwSchemeNameLength] = chBackup;
  615.                 return UrlSchemeList[i].SchemeType;
  616.             }
  617.             
  618.             lpszSchemeName[dwSchemeNameLength] = chBackup;
  619.         }
  620.     }
  621.     return INTERNET_SCHEME_UNKNOWN;
  622. }
  623. DWORD
  624. MapUrlSchemeTypeToCtlId(
  625.     IN INTERNET_SCHEME SchemeType,
  626.     IN BOOL        fIdForPortCtl
  627.     )
  628. /*++
  629. Routine Description:
  630.     Maps a scheme to a dlg child control id.
  631. Arguments:
  632.     Scheme    - Scheme to Map
  633.     fIdForPortCtl - If TRUE, means we really want the ID for a the PORT control
  634.             not the ADDRESS control.
  635. Return Value:
  636.     DWORD
  637. --*/
  638. {
  639.     for (int i = 0; i < ARRAY_ELEMENTS(UrlSchemeList); ++i)
  640.     {
  641.         if (SchemeType == UrlSchemeList[i].SchemeType)
  642.         {
  643.             return (fIdForPortCtl ? UrlSchemeList[i].dwPortControlId :
  644.                     UrlSchemeList[i].dwControlId );
  645.         }
  646.     }
  647.     return IDC_NOTUSED;
  648. }
  649. BOOL
  650. MapCtlIdUrlSchemeName(
  651.     IN DWORD    dwEditCtlId,
  652.     OUT LPSTR   lpszSchemeOut
  653.     )
  654. /*++
  655. Routine Description:
  656.     Maps a dlg child control id to String represnting
  657.     the name of the scheme.
  658. Arguments:
  659.     dwEditCtlId   - Edit Control to Map Out.
  660.     lpszSchemeOut - Scheme to Map Out.
  661.             WARNING: ASSUMED to be size of largest scheme type.
  662. Return Value:
  663.     BOOL
  664.     Success - TRUE
  665.     Failure - FALSE
  666. --*/
  667. {
  668.     ASSERT(lpszSchemeOut);
  669.     for (int i = 0; i < ARRAY_ELEMENTS(UrlSchemeList); ++i)
  670.     {
  671.         if (dwEditCtlId == UrlSchemeList[i].dwControlId )
  672.         {
  673.             StrCpyA(lpszSchemeOut, UrlSchemeList[i].SchemeName);
  674.             return TRUE;
  675.         }
  676.     }
  677.     return FALSE;
  678. }
  679. DWORD
  680. MapAddrCtlIdToPortCtlId(
  681.     IN DWORD    dwEditCtlId
  682.     )
  683. /*++
  684. Routine Description:
  685.     Maps a dlg child control id for addresses to
  686.     a dlg control id for ports.
  687. Arguments:
  688.     dwEditCtlId   - Edit Control to Map Out.
  689. Return Value:
  690.     DWORD
  691.     Success - Correctly mapped ID.
  692.     Failure - 0.
  693. --*/
  694. {
  695.     for (int i = 0; i < ARRAY_ELEMENTS(UrlSchemeList); ++i)
  696.     {
  697.         if (dwEditCtlId == UrlSchemeList[i].dwControlId )
  698.         {
  699.             return UrlSchemeList[i].dwPortControlId ;
  700.         }
  701.     }
  702.     return FALSE;
  703. }
  704. BOOL
  705. ProxyDlgInitProxyServers(
  706.     IN HWND hDlg
  707.     )
  708. /*++
  709. Routine Description:
  710.     Parses a list of proxy servers and sets them into the newly created
  711.     Proxy Dialog.
  712.     Ruthlessly stolen from RFirth's proxysup.cxx in WININET by
  713.     ArthurBi.
  714. Arguments:
  715.     hDlg    -      HWin to add our stuff to.
  716. Return Value:
  717.     BOOL
  718.     Success - TRUE
  719.     Failure - FALSE
  720. Comments:
  721.     Designed to handle Proxy string entry of the Form:
  722.       pointer to list of proxies of the form:
  723.       [<protocol>=][<scheme>"://"]<server>[":"<port>][";"*]
  724.       The list can is read from the registry.
  725. --*/
  726. {
  727.     DWORD error = !ERROR_SUCCESS;
  728.     DWORD entryLength;
  729.     LPSTR protocolName;
  730.     DWORD protocolLength;
  731.     LPSTR schemeName;
  732.     DWORD schemeLength;
  733.     LPSTR serverName;
  734.     DWORD serverLength;
  735.     PARSER_STATE state;
  736.     DWORD nSlashes;
  737.     INTERNET_PORT port;
  738.     BOOL done;
  739.     LPSTR lpszList;
  740.     entryLength = 0;
  741.     protocolLength = 0;
  742.     schemeName = NULL;
  743.     schemeLength = 0;
  744.     serverName = NULL;
  745.     serverLength = 0;
  746.     state = STATE_PROTOCOL;
  747.     nSlashes = 0;
  748.     port = 0;
  749.     done = FALSE;
  750.     //
  751.     // Open the Reg Key.
  752.     //
  753.     RegEntry re(REGSTR_PATH_INTERNETSETTINGS,HKEY_CURRENT_USER);
  754.     if (re.GetError() != ERROR_SUCCESS)
  755.         return FALSE; // no REG values..
  756.     //
  757.     // Crack the Registry values, read the proxy list
  758.     //
  759.     BUFFER bufProxyString(MAX_URL_STRING+1);
  760.     BOOL   fProxyEnabled;
  761.     if (!bufProxyString)
  762.     {
  763.         MsgBox(NULL,IDS_ERROutOfMemory,MB_ICONEXCLAMATION,MB_OK);
  764.         return FALSE;
  765.     }
  766.     //
  767.     // is proxy enabled?
  768.     // It should if we got into this dialog.
  769.     //
  770.     fProxyEnabled = (BOOL)re.GetNumber(REGSTR_VAL_PROXYENABLE,0);
  771.     //
  772.     // get proxy server and override settings from registry and stuff fields
  773.     //
  774.     re.GetString(REGSTR_VAL_PROXYSERVER,bufProxyString.QueryPtr(),
  775.         bufProxyString.QuerySize());
  776.     LPPROXYPAGE pPxy = (LPPROXYPAGE)GetWindowLongPtr(hDlg, DWLP_USER);
  777.     // if there's a proxy passed in from the main page, then use it; otherwise use the registry val
  778. #ifndef UNICODE
  779.     lpszList = pPxy->lpi->fReadProxyFromRegistry ? bufProxyString.QueryPtr() : pPxy->lpi->szProxy;
  780. #else
  781.     char*  szList = NULL;
  782.     LPTSTR lpTmp = pPxy->lpi->fReadProxyFromRegistry ? bufProxyString.QueryPtr() : pPxy->lpi->szProxy;
  783.     DWORD  cch = lstrlen(lpTmp) + 1;
  784.     szList = new char[2 * cch];
  785.     if (szList)
  786.     {
  787.         SHUnicodeToAnsi(lpTmp, szList, 2 * cch);
  788.         lpszList = szList;
  789.     }
  790.     else
  791.     {
  792.         MsgBox(NULL,IDS_ERROutOfMemory,MB_ICONEXCLAMATION,MB_OK);
  793.         return FALSE;
  794.     }
  795. #endif
  796.     protocolName = lpszList;
  797.     //
  798.     // walk the list, pulling out the various scheme parts
  799.     //
  800.     do
  801.     {
  802.         char ch = *lpszList++;
  803.         if ((nSlashes == 1) && (ch != '/'))
  804.         {
  805.             state = STATE_ERROR;
  806.             break;
  807.         }
  808.         
  809.         switch (ch)
  810.         {
  811.             case '=':
  812.                 if ((state == STATE_PROTOCOL) && (entryLength != 0))
  813.                 {
  814.                     protocolLength = entryLength;
  815.                     entryLength = 0;
  816.                     state = STATE_SCHEME;
  817.                     schemeName = lpszList;
  818.                 }
  819.                 else
  820.                 {
  821.                     //
  822.                     // '=' can't legally appear anywhere else
  823.                     //
  824.                     state = STATE_ERROR;
  825.                 }
  826.                 break;
  827.                 
  828.             case ':':
  829.                 switch (state)
  830.                 {
  831.                     case STATE_PROTOCOL:
  832.                         if (*lpszList == '/')
  833.                         {
  834.                             schemeName = protocolName;
  835.                             protocolName = NULL;
  836.                             schemeLength = entryLength;
  837.                             protocolLength = 0;
  838.                             state = STATE_SCHEME;
  839.                         }
  840.                         else if (*lpszList != '')
  841.                         {
  842.                             serverName = protocolName;
  843.                             serverLength = entryLength;
  844.                             state = STATE_PORT;
  845.                         }
  846.                         else
  847.                         {
  848.                             state = STATE_ERROR;
  849.                         }
  850.                         entryLength = 0;
  851.                         break;
  852.                         
  853.                     case STATE_SCHEME:
  854.                         if (*lpszList == '/')
  855.                         {
  856.                             schemeLength = entryLength;
  857.                         }
  858.                         else if (*lpszList != '')
  859.                         {
  860.                             serverName = schemeName;
  861.                             serverLength = entryLength;
  862.                             state = STATE_PORT;
  863.                         }
  864.                         else
  865.                         {
  866.                             state = STATE_ERROR;
  867.                         }
  868.                         entryLength = 0;
  869.                         break;
  870.                         
  871.                     case STATE_SERVER:
  872.                         serverLength = entryLength;
  873.                         state = STATE_PORT;
  874.                         entryLength = 0;
  875.                         break;
  876.                     default:
  877.                         state = STATE_ERROR;
  878.                         break;
  879.                 }
  880.                 break;
  881.             case '/':
  882.                 if ((state == STATE_SCHEME) && (nSlashes < 2) && (entryLength == 0))
  883.                 {
  884.                     if (++nSlashes == 2)
  885.                     {
  886.                         state = STATE_SERVER;
  887.                         serverName = lpszList;
  888.                     }
  889.                 }
  890.                 else
  891.                 {
  892.                     state = STATE_ERROR;
  893.                 }
  894.                 break;
  895.             case 'v':  // vertical tab, 0x0b
  896.             case 'f':  // form feed, 0x0c
  897.                 if (!((state == STATE_PROTOCOL) && (entryLength == 0)))
  898.                 {
  899.                     //
  900.                     // can't have embedded whitespace
  901.                     //
  902.                     state = STATE_ERROR;
  903.                 }
  904.                 break;
  905.             default:
  906.                 if (state != STATE_PORT)
  907.                 {
  908.                     ++entryLength;
  909.                 }
  910.                 else if (isdigit(ch))
  911.                 {
  912.                     //
  913.                     // BUGBUG - we will overflow if >65535
  914.                     //
  915.                     port = port * 10 + (ch - '0');
  916.                 }
  917.                 else
  918.                 {                   
  919.                     //
  920.                     // STATE_PORT && non-digit character - error
  921.                     //
  922.                     state = STATE_ERROR;
  923.                 }
  924.                 break;
  925.             case '':
  926.                 done = TRUE;
  927.                 //
  928.                 // fall through
  929.                 //
  930.             case ' ':
  931.             case 't':
  932.             case 'n':
  933.             case 'r':
  934.             case ';':
  935.             case ',':
  936.                 if (serverLength == 0)
  937.                 {
  938.                     serverLength = entryLength;
  939.                 }
  940.                 if (serverLength != 0)
  941.                 {
  942.                     if (serverName == NULL)
  943.                     {
  944.                         serverName = (schemeName != NULL)
  945.                             ? schemeName : protocolName;
  946.                     }
  947.                     ASSERT(serverName != NULL);
  948.                     INTERNET_SCHEME protocol;
  949.                     if (protocolLength != 0)
  950.                     {
  951.                         protocol = MapUrlSchemeName(protocolName, protocolLength);
  952.                     }
  953.                     else
  954.                     {
  955.                         protocol = INTERNET_SCHEME_DEFAULT;
  956.                     }
  957.                     INTERNET_SCHEME scheme;
  958.                     if (schemeLength != 0)
  959.                     {
  960.                         scheme = MapUrlSchemeName(schemeName, schemeLength);
  961.                     }
  962.                     else
  963.                     {
  964.                         scheme = INTERNET_SCHEME_DEFAULT;
  965.                     }
  966.                     //
  967.                     // add an entry if this is a protocol we handle and we don't
  968.                     // already have an entry for it
  969.                     //
  970.                     if ((protocol != INTERNET_SCHEME_UNKNOWN)
  971.                         && (scheme != INTERNET_SCHEME_UNKNOWN))
  972.                     {
  973.                         DWORD dwCtlId = IDC_NOTUSED;
  974.                         DWORD dwPortCtlId = IDC_NOTUSED;
  975.                         CHAR chBackup;
  976.                         error = ERROR_SUCCESS;
  977.                         //
  978.                         // we can only currently handle CERN proxies (unsecure or
  979.                         // secure) so kick out anything that wants to go via a different
  980.                         // proxy scheme
  981.                         //
  982.                         if (protocol == INTERNET_SCHEME_DEFAULT)
  983.                         {
  984.                             CheckDlgButton( hDlg, IDC_PROXY_USE_SAME_SERVER, TRUE );
  985.                             dwCtlId     = IDC_PROXY_HTTP_ADDRESS;
  986.                             dwPortCtlId = IDC_PROXY_HTTP_PORT;
  987.                         }
  988.                         else
  989.                         {
  990.                             dwCtlId     = MapUrlSchemeTypeToCtlId(protocol,FALSE);
  991.                             dwPortCtlId = MapUrlSchemeTypeToCtlId(protocol,TRUE);
  992.                         }
  993.                         //
  994.                         // Set the Field Entry.
  995.                         //
  996.                         LPSTR lpszProxyNameText;
  997.                         if (scheme != INTERNET_SCHEME_DEFAULT)
  998.                         {
  999.                             ASSERT(schemeLength != 0);
  1000.                             lpszProxyNameText = schemeName;
  1001.                         }
  1002.                         else
  1003.                             lpszProxyNameText = serverName;
  1004.                         chBackup = serverName[serverLength];
  1005.                         serverName[serverLength] = '';
  1006.                         
  1007.                         SetDlgItemTextA( hDlg, dwCtlId, lpszProxyNameText );
  1008.                         if ( port )
  1009.                             SetDlgItemInt( hDlg, dwPortCtlId, port, FALSE );
  1010.                         serverName[serverLength] = chBackup;
  1011.                         
  1012.                     }
  1013.                     
  1014.                     else
  1015.                     {                      
  1016.                         //
  1017.                         // bad/unrecognised protocol or scheme. Treat it as error
  1018.                         // for now
  1019.                         //
  1020.                         error = !ERROR_SUCCESS;
  1021.                     }
  1022.                 }
  1023.                 entryLength = 0;
  1024.                 protocolName = lpszList;
  1025.                 protocolLength = 0;
  1026.                 schemeName = NULL;
  1027.                 schemeLength = 0;
  1028.                 serverName = NULL;
  1029.                 serverLength = 0;
  1030.                 nSlashes = 0;
  1031.                 port = 0;
  1032.                 if (error == ERROR_SUCCESS)
  1033.                 {
  1034.                     state = STATE_PROTOCOL;
  1035.                 }
  1036.                 else
  1037.                 {
  1038.                     state = STATE_ERROR;
  1039.                 }
  1040.                 break;
  1041.         }
  1042.         if (state == STATE_ERROR)
  1043.         {
  1044.             break;
  1045.         }
  1046.         
  1047.     } while (!done);
  1048. #ifdef UNICODE
  1049.     delete [] szList;
  1050. #endif
  1051.     if (state == STATE_ERROR)
  1052.     {
  1053.         error = ERROR_INVALID_PARAMETER;
  1054.     }
  1055.     if ( error == ERROR_SUCCESS )
  1056.         error = TRUE;
  1057.     else
  1058.         error = FALSE;
  1059.     return error;
  1060. }
  1061. BOOL
  1062. IsProxyValid(
  1063.     IN HWND     hDlg
  1064.     )
  1065. /*++
  1066. Routine Description:
  1067.     Determines if the Proxy is valid.  The proxy is invalid if
  1068.     all of the proxy entries are empty.
  1069. Arguments:
  1070.     hDlg      - HWIN of the dialog to play with.
  1071. Return Value:
  1072.     BOOL
  1073.     Success TRUE - Valid.
  1074.     FALSE - Invalid.
  1075. --*/
  1076. {
  1077.     BOOL  fProxyIsValid = FALSE;
  1078.     TCHAR szProxyUrl[MAX_URL_STRING+1];
  1079.     int   iCurrentProxy = 0;
  1080.     ASSERT(IsWindow(hDlg));
  1081.     for (int iIndex = 0; iIndex < ARRAYSIZE(g_iProxies); iIndex++)
  1082.     {
  1083.         szProxyUrl[0] = '';
  1084.         GetDlgItemText(hDlg,
  1085.                        g_iProxies[iIndex],
  1086.                        szProxyUrl,
  1087.                        sizeof(szProxyUrl));
  1088.         
  1089.         if (szProxyUrl[0])
  1090.         {
  1091.             fProxyIsValid = TRUE;
  1092.             break;
  1093.         }
  1094.     }
  1095.     return fProxyIsValid;
  1096. }
  1097. BOOL
  1098. ParseEditCtlForPort(
  1099.     IN OUT LPSTR   lpszProxyName,
  1100.     IN HWND        hDlg,
  1101.     IN DWORD       dwProxyNameCtlId,
  1102.     IN DWORD       dwProxyPortCtlId
  1103.     )
  1104. /*++
  1105. Routine Description:
  1106.     Parses a Port Number off then end of a Proxy Server URL that is
  1107.     located either in the Proxy Name Edit Box, or passed in as
  1108.     a string pointer.
  1109. Arguments:
  1110.     lpszProxyName - (OPTIONAL) string pointer with Proxy Name to parse, and
  1111.             set into the Proxy Name edit ctl field.
  1112.     hDlg      - HWIN of the dialog to play with.
  1113.     dwProxyNameCtlId -  Res Ctl Id to play with.
  1114.     dwProxyPortCtlId -  Res Ctl Id of Port Number Edit Box.
  1115. Return Value:
  1116.     BOOL
  1117.     Success TRUE -
  1118.     Failure FALSE
  1119. --*/
  1120. {
  1121.     CHAR   szProxyUrl[MAX_URL_STRING+1];
  1122.     LPSTR  lpszPort;
  1123.     LPSTR  lpszProxyUrl;
  1124.     ASSERT(IsWindow(hDlg));
  1125.     if ( dwProxyPortCtlId == 0 )
  1126.     {
  1127.         dwProxyPortCtlId = MapAddrCtlIdToPortCtlId(dwProxyNameCtlId);
  1128.         ASSERT(dwProxyPortCtlId);
  1129.     }
  1130.     //
  1131.     // Get the Proxy String from the Edit Control
  1132.     //  (OR) from the Registry [passed in]
  1133.     //
  1134.     if ( lpszProxyName )
  1135.         lpszProxyUrl = lpszProxyName;
  1136.     else
  1137.     {
  1138.     //
  1139.     // Need to Grab it out of the edit control.
  1140.     //
  1141.         GetDlgItemTextA(hDlg,
  1142.             dwProxyNameCtlId,
  1143.             szProxyUrl,
  1144.             sizeof(szProxyUrl));
  1145.         lpszProxyUrl = szProxyUrl;
  1146.     }
  1147.     //
  1148.     // Now find the port.
  1149.     //
  1150.     lpszPort = lpszProxyUrl;
  1151.     GET_TERMINATOR(lpszPort);
  1152.     lpszPort--;
  1153.     //
  1154.     // Walk backwards from the end of url looking
  1155.     //  for a port number sitting on the end like this
  1156.     //  http://proxy:1234
  1157.     //
  1158.     while ( (lpszPort > lpszProxyUrl) &&
  1159.         (*lpszPort != ':')         &&
  1160.         (isdigit(*lpszPort))  )
  1161.     {
  1162.         lpszPort--;
  1163.     }
  1164.     //
  1165.     // If we found a match for our rules
  1166.     //  then set the port, otherwise
  1167.     //  we assume the user knows what he's
  1168.     //  doing.
  1169.     //
  1170.     if ( *lpszPort == ':'   &&   isdigit(*(lpszPort+1)) )
  1171.     {
  1172.         *lpszPort = '';
  1173.         SetDlgItemTextA(hDlg, dwProxyPortCtlId, (lpszPort+1));
  1174.     }
  1175.     SetDlgItemTextA(hDlg, dwProxyNameCtlId, lpszProxyUrl);
  1176.     return TRUE;
  1177. }
  1178. BOOL
  1179. FormatOutProxyEditCtl(
  1180.     IN HWND    hDlg,
  1181.     IN DWORD       dwProxyNameCtlId,
  1182.     IN DWORD       dwProxyPortCtlId,
  1183.     OUT LPSTR      lpszOutputStr,
  1184.     IN OUT LPDWORD lpdwOutputStrSize,
  1185.     IN DWORD       dwOutputStrLength,
  1186.     IN BOOL    fDefaultProxy
  1187.     )
  1188. /*++
  1189. Routine Description:
  1190.     Combines Proxy URL components into a string that can be saved
  1191.     in the registry.  Can be called multiple times to build
  1192.     a list of proxy servers, or once to special case a "default"
  1193.     proxy.
  1194. Arguments:
  1195.     hDlg      - HWIN of the dialog to play with.
  1196.     dwProxyNameCtlId -  Res Ctl Id to play with.
  1197.     dwProxyPortCtlId -  Res Ctl Id of Port Number Edit Box.
  1198.     lpszOutputStr    -  The start of the output string to send
  1199.             the product of this function.
  1200.     lpdwOutputStrSize - The amount of used space in lpszOutputStr
  1201.             that is already used.  New output should
  1202.             start from (lpszOutputStr + *lpdwOutputStrSize)
  1203.     fDefaultProxy     - Default Proxy, don't add scheme= in front of the proxy
  1204.             just use plop one proxy into the registry.
  1205. Return Value:
  1206.     BOOL
  1207.     Success TRUE
  1208.     Failure FALSE
  1209. --*/
  1210. {
  1211.     LPSTR lpszOutput;
  1212.     LPSTR lpszEndOfOutputStr;
  1213.     ASSERT(IsWindow(hDlg));
  1214.     ASSERT(lpdwOutputStrSize);
  1215.     lpszOutput = lpszOutputStr + *lpdwOutputStrSize;
  1216.     lpszEndOfOutputStr = lpszOutputStr + dwOutputStrLength;
  1217.     ASSERT( lpszEndOfOutputStr > lpszOutput );
  1218.     if ( lpszEndOfOutputStr <= lpszOutput )
  1219.         return FALSE; // bail out, ran out of space
  1220.     //
  1221.     // Plop ';' if we're not the first in this string buffer.
  1222.     //
  1223.     if (*lpdwOutputStrSize != 0  )
  1224.     {
  1225.         *lpszOutput = ';';
  1226.         lpszOutput++;
  1227.         if ( lpszEndOfOutputStr <= lpszOutput )
  1228.             return FALSE; // bail out, ran out of space
  1229.     }
  1230.     //
  1231.     // Put the schemetype= into the string
  1232.     //  ex:  http=
  1233.     //
  1234.     if ( ! fDefaultProxy )
  1235.     {
  1236.         if ( lpszEndOfOutputStr <= (MAX_SCHEME_NAME_LENGTH + lpszOutput + 1) )
  1237.             return FALSE; // bail out, ran out of space
  1238.         
  1239.         if (!MapCtlIdUrlSchemeName(dwProxyNameCtlId,lpszOutput))
  1240.             return FALSE;
  1241.         
  1242.         lpszOutput += lstrlenA(lpszOutput);
  1243.     
  1244.         *lpszOutput = '=';
  1245.         lpszOutput++;
  1246.     }
  1247.     
  1248.     //
  1249.     // Need to Grab ProxyUrl out of the edit control.
  1250.     //
  1251.     
  1252.     GetDlgItemTextA(hDlg, dwProxyNameCtlId, lpszOutput, (int)(lpszEndOfOutputStr - lpszOutput));
  1253.     if ( IS_BLANK(lpszOutput) )
  1254.         return FALSE;
  1255.     //
  1256.     // Now seperate out the port so we can save them seperately.
  1257.     //   But go past the Proxy Url while we're at it.
  1258.     //      ex: http=http://netscape-proxy
  1259.     //
  1260.     if (!ParseEditCtlForPort(lpszOutput, hDlg, dwProxyNameCtlId, dwProxyPortCtlId))
  1261.         return FALSE;
  1262.     lpszOutput += lstrlenA(lpszOutput);
  1263.     //
  1264.     // Now, add in a ':" for the port number, if we don't
  1265.     //  have a port we'll remove it.
  1266.     //
  1267.     {
  1268.         *lpszOutput = ':';
  1269.         
  1270.         lpszOutput++;
  1271.         
  1272.         if ( lpszEndOfOutputStr <= lpszOutput )
  1273.             return FALSE; // bail out, ran out of space
  1274.     }
  1275.     //
  1276.     // Grab Proxy Port if its around.
  1277.     //  Back out the ':' if its not.
  1278.     //
  1279.     GetDlgItemTextA(hDlg, dwProxyPortCtlId,lpszOutput, (int)(lpszEndOfOutputStr - lpszOutput));
  1280.     if ( IS_BLANK(lpszOutput) )
  1281.     {
  1282.         lpszOutput--;
  1283.         
  1284.         ASSERT(*lpszOutput == ':');
  1285.         *lpszOutput = '';
  1286.     }
  1287.     
  1288.     lpszOutput += lstrlenA(lpszOutput);
  1289.     
  1290.     //
  1291.     // Now we're done return our final sizes.
  1292.     //
  1293.     
  1294.     *lpdwOutputStrSize = (DWORD)(lpszOutput - lpszOutputStr);
  1295.     return TRUE;
  1296. }
  1297. BOOL
  1298. RemoveLocalFromExceptionList(
  1299.     IN LPTSTR lpszExceptionList
  1300.     )
  1301. /*++
  1302. Routine Description:
  1303.     Scans a delimited list of entries, and removed "<local>
  1304.     if found.  If <local> is found we return TRUE.
  1305. Arguments:
  1306.     lpszExceptionList - String List of proxy excepion entries.
  1307. Return Value:
  1308.     BOOL
  1309.     TRUE - If found <local>
  1310.     FALSE - If local was not found.
  1311. --*/
  1312. {
  1313.     LPTSTR lpszLocalInstToRemove;
  1314.     BOOL   fFoundLocal;
  1315.     if ( !lpszExceptionList || ! *lpszExceptionList )
  1316.     return FALSE;
  1317.     fFoundLocal = FALSE;
  1318.     lpszLocalInstToRemove = lpszExceptionList;
  1319.     //
  1320.     // Loop looking "<local>" entries in the list.
  1321.     //
  1322.     do {
  1323.         lpszLocalInstToRemove =
  1324.                                StrStr(lpszLocalInstToRemove,cszLocalString);
  1325.         
  1326.         
  1327.         if ( lpszLocalInstToRemove )
  1328.         {
  1329.             
  1330.             fFoundLocal = TRUE;
  1331.             
  1332.             //
  1333.             // Nuke <local> out of the string. <local>;otherstuff
  1334.             //  Dest is: '<'local>;otherstuff
  1335.             //     ??? (OR) ';'<local> if the ; is the first character.???
  1336.             //  Src  is: >'o'therstuff
  1337.             //  size is: sizeof(';otherstuff')
  1338.             //
  1339.             
  1340.             MoveMemory(
  1341.                        lpszLocalInstToRemove,
  1342.                        (lpszLocalInstToRemove+lstrlen(cszLocalString)),
  1343.                        lstrlen(lpszLocalInstToRemove+lstrlen(cszLocalString))*sizeof(TCHAR)+sizeof(TCHAR)
  1344.                       );
  1345.             
  1346.         }
  1347.         
  1348.     } while (lpszLocalInstToRemove && *lpszLocalInstToRemove);
  1349.     //
  1350.     // If we produced a ; on the end, nuke it.
  1351.     //
  1352.     lpszLocalInstToRemove = lpszExceptionList;
  1353.     GET_TERMINATOR(lpszLocalInstToRemove);
  1354.     if ( lpszLocalInstToRemove != lpszExceptionList &&
  1355.          *(lpszLocalInstToRemove-1) == ';' )
  1356.     {
  1357.         *(lpszLocalInstToRemove-1) = '';
  1358.     }
  1359.     
  1360.     return fFoundLocal;
  1361. }
  1362. /***
  1363. *char *strstr(string1, string2) - search for string2 in string1
  1364. *
  1365. *Purpose:
  1366. *   finds the first occurrence of string2 in string1
  1367. *   (STOLEN from MSDEV CRT Library)
  1368. *
  1369. *Entry:
  1370. *   char *string1 - string to search in
  1371. *   char *string2 - string to search for
  1372. *
  1373. *Exit:
  1374. *   returns a pointer to the first occurrence of string2 in
  1375. *   string1, or NULL if string2 does not occur in string1
  1376. *
  1377. *Uses:
  1378. *
  1379. *Exceptions:
  1380. *
  1381. *******************************************************************************/
  1382. char * __cdecl strstr (
  1383.     const char * str1,
  1384.     const char * str2
  1385.     )
  1386. {
  1387.     char *cp = (char *) str1;
  1388.     char *s1, *s2;
  1389.     if ( !*str2 )
  1390.         return((char *)str1);
  1391.     while (*cp)
  1392.     {
  1393.         s1 = cp;
  1394.         s2 = (char *) str2;
  1395.         while ( *s1 && *s2 && !(*s1-*s2) )
  1396.             s1++, s2++;
  1397.         if (!*s2)
  1398.             return(cp);
  1399.         cp++;
  1400.     }
  1401.     return(NULL);
  1402. }