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.

941 lines
23 KiB

  1. #include "wininetp.h"
  2. static const CHAR szRegPathConnections[] = REGSTR_PATH_INTERNET_SETTINGS "\\Connections";
  3. // some winsock stacks fault if we do a gethostbyname(NULL). If we come
  4. // accross one of these, don't do any more autodetecting.
  5. BOOL g_fGetHostByNameNULLFails = FALSE;
  6. //
  7. // IsConnectionMatch - a worker function to simply some logic elsewhere,
  8. // it just handles Connection Name Matching.
  9. //
  10. BOOL
  11. IsConnectionMatch(
  12. LPCSTR lpszConnection1,
  13. LPCSTR lpszConnection2)
  14. {
  15. if ( lpszConnection1 == NULL &&
  16. lpszConnection2 == NULL)
  17. {
  18. return TRUE;
  19. }
  20. if ( lpszConnection1 && lpszConnection2 &&
  21. stricmp(lpszConnection1, lpszConnection2) == 0 )
  22. {
  23. return TRUE;
  24. }
  25. return FALSE;
  26. }
  27. ///////////////////////////////////////////////////////////////////////////
  28. //
  29. // CRegBlob implementation
  30. //
  31. ///////////////////////////////////////////////////////////////////////////
  32. CRegBlob::CRegBlob(
  33. BOOL fWrite
  34. )
  35. {
  36. // initialize members
  37. _fWrite = fWrite;
  38. _fCommit = TRUE;
  39. _dwOffset = 0;
  40. _pBuffer = NULL;
  41. _dwBufferLimit = 0;
  42. _hkey = NULL;
  43. }
  44. CRegBlob::~CRegBlob(
  45. )
  46. {
  47. Commit();
  48. if(_hkey)
  49. REGCLOSEKEY(_hkey);
  50. if(_pBuffer)
  51. FREE_FIXED_MEMORY(_pBuffer);
  52. // caller owns _pszValue pointer
  53. }
  54. DWORD
  55. CRegBlob::Init(
  56. HKEY hBaseKey,
  57. LPCSTR pszSubKey,
  58. LPCSTR pszValue
  59. )
  60. {
  61. long lRes;
  62. REGSAM regsam = KEY_QUERY_VALUE;
  63. DWORD dwDisposition;
  64. // If we're writing, save reg value name and set access
  65. if(_fWrite)
  66. {
  67. _pszValue = pszValue;
  68. regsam = KEY_SET_VALUE;
  69. lRes = REGCREATEKEYEX(hBaseKey, pszSubKey, 0, "", 0,
  70. regsam, NULL, &_hkey, &dwDisposition);
  71. }
  72. else
  73. {
  74. // If not writing, then use RegOpenKeyEx so we don't need
  75. // registry write permissions.
  76. lRes = REGOPENKEYEX(hBaseKey, pszSubKey, 0, regsam, &_hkey);
  77. }
  78. if(lRes != ERROR_SUCCESS)
  79. {
  80. return lRes;
  81. }
  82. // figure out buffer size
  83. _dwBufferLimit = BLOB_BUFF_GRANULARITY;
  84. if(FALSE == _fWrite)
  85. {
  86. // get size of registry blob
  87. lRes = RegQueryValueEx(_hkey, pszValue, NULL, NULL, NULL, &_dwBufferLimit);
  88. if(lRes != ERROR_SUCCESS)
  89. {
  90. // nothing there - make zero size buffer
  91. _dwBufferLimit = 0;
  92. }
  93. }
  94. // allocate buffer if necessary
  95. if(_dwBufferLimit)
  96. {
  97. _pBuffer = (BYTE *)ALLOCATE_FIXED_MEMORY(_dwBufferLimit);
  98. if(NULL == _pBuffer)
  99. return GetLastError();
  100. }
  101. // if we're reading, fill in buffer
  102. if(FALSE == _fWrite && _dwBufferLimit)
  103. {
  104. // read reg key
  105. DWORD dwSize = _dwBufferLimit;
  106. lRes = RegQueryValueEx(_hkey, pszValue, NULL, NULL, _pBuffer, &dwSize);
  107. if(lRes != ERROR_SUCCESS)
  108. {
  109. return lRes;
  110. }
  111. }
  112. // reset pointer to beginning of blob
  113. _dwOffset = 0;
  114. return 0;
  115. }
  116. DWORD
  117. CRegBlob::Abandon(
  118. VOID
  119. )
  120. {
  121. // don't commit changes when the time comes
  122. _fCommit = FALSE;
  123. return 0;
  124. }
  125. DWORD
  126. CRegBlob::Commit(
  127. )
  128. {
  129. long lres = 0;
  130. if(_fCommit && _fWrite && _pszValue && _pBuffer)
  131. {
  132. // save blob to reg key
  133. lres = RegSetValueEx(_hkey, _pszValue, 0, REG_BINARY, _pBuffer, _dwOffset);
  134. }
  135. return lres;
  136. }
  137. DWORD
  138. CRegBlob::WriteString(
  139. LPCSTR pszString
  140. )
  141. {
  142. DWORD dwBytes, dwLen = 0;
  143. if(pszString)
  144. {
  145. dwLen = lstrlen(pszString);
  146. }
  147. dwBytes = WriteBytes(&dwLen, sizeof(DWORD));
  148. if(dwLen && dwBytes == sizeof(DWORD))
  149. dwBytes = WriteBytes(pszString, dwLen);
  150. return dwBytes;
  151. }
  152. DWORD
  153. CRegBlob::ReadString(
  154. LPCSTR * ppszString
  155. )
  156. {
  157. DWORD dwLen, dwBytes = 0;
  158. LPSTR lpszTemp = NULL;
  159. dwBytes = ReadBytes(&dwLen, sizeof(DWORD));
  160. if(dwBytes == sizeof(DWORD))
  161. {
  162. if(dwLen)
  163. {
  164. lpszTemp = (LPSTR)GlobalAlloc(GPTR, dwLen + 1);
  165. if(lpszTemp)
  166. {
  167. dwBytes = ReadBytes(lpszTemp, dwLen);
  168. lpszTemp[dwBytes] = 0;
  169. }
  170. }
  171. }
  172. *ppszString = lpszTemp;
  173. return dwBytes;
  174. }
  175. DWORD
  176. CRegBlob::WriteBytes(
  177. LPCVOID pBytes,
  178. DWORD dwByteCount
  179. )
  180. {
  181. BYTE * pNewBuffer;
  182. // can only do this on write blob
  183. if(FALSE == _fWrite)
  184. return 0;
  185. // grow buffer if necessary
  186. if(_dwBufferLimit - _dwOffset < dwByteCount)
  187. {
  188. DWORD dw = _dwBufferLimit + ((dwByteCount / BLOB_BUFF_GRANULARITY)+1)*BLOB_BUFF_GRANULARITY;
  189. pNewBuffer = (BYTE *)ALLOCATE_FIXED_MEMORY(dw);
  190. if(NULL == pNewBuffer)
  191. {
  192. // failed to get more memory
  193. return 0;
  194. }
  195. memset(pNewBuffer, 0, dw);
  196. memcpy(pNewBuffer, _pBuffer, _dwBufferLimit);
  197. FREE_FIXED_MEMORY(_pBuffer);
  198. _pBuffer = pNewBuffer;
  199. _dwBufferLimit = dw;
  200. }
  201. // copy callers data to buffer
  202. memcpy(_pBuffer + _dwOffset, pBytes, dwByteCount);
  203. _dwOffset += dwByteCount;
  204. // tell caller how much we wrote
  205. return dwByteCount;
  206. }
  207. DWORD
  208. CRegBlob::ReadBytes(
  209. LPVOID pBytes,
  210. DWORD dwByteCount
  211. )
  212. {
  213. DWORD dwActual = _dwBufferLimit - _dwOffset;
  214. // can only do this on read blob
  215. if(_fWrite)
  216. return 0;
  217. // don't read past end of blob
  218. if(dwByteCount < dwActual)
  219. dwActual = dwByteCount;
  220. // copy bytes and increment offset
  221. if(dwActual > 0)
  222. {
  223. memcpy(pBytes, _pBuffer + _dwOffset, dwActual);
  224. _dwOffset += dwActual;
  225. }
  226. // tell caller how much we actually read
  227. return dwActual;
  228. }
  229. //
  230. // Function Declarations
  231. //
  232. DWORD
  233. LoadProxySettings()
  234. /*
  235. ** Load global proxy info from registry.
  236. **
  237. */
  238. {
  239. DWORD error;
  240. //
  241. // Get proxy struct for proxy object
  242. //
  243. INTERNET_PROXY_INFO_EX info;
  244. memset(&info, 0, sizeof(info));
  245. info.dwStructSize = sizeof(info);
  246. info.lpszConnectionName = NULL;
  247. //
  248. // Read LAN proxy settings and stuff them into the GlobalProxyInfo object.
  249. //
  250. error = ReadProxySettings(&info);
  251. if (error == ERROR_SUCCESS)
  252. {
  253. error = g_pGlobalProxyInfo->SetProxySettings(&info, FALSE);
  254. info.lpszConnectionName = NULL; // we don't allocate this field
  255. CleanProxyStruct(&info);
  256. }
  257. return error;
  258. }
  259. #define INTERNET_SETTINGS_KEY "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"
  260. HKEY
  261. FindBaseProxyKey(
  262. VOID
  263. )
  264. /*
  265. ** Determine whether proxy settings live in HKLM or HKCU
  266. **
  267. ** WinHttpX is hard-coded to always use HKEY_LOCAL_MACHINE
  268. **
  269. */
  270. {
  271. return HKEY_LOCAL_MACHINE;
  272. }
  273. DWORD
  274. ReadProxySettings(
  275. LPINTERNET_PROXY_INFO_EX pInfo
  276. )
  277. {
  278. CRegBlob r(FALSE);
  279. LPCSTR pszConnectionName;
  280. LPCSTR pszSavedConnectionName;
  281. DWORD error = ERROR_SUCCESS;
  282. long lRes;
  283. HKEY hBaseKey;
  284. DEBUG_ENTER((DBG_PROXY,
  285. Dword,
  286. "ReadProxySettings",
  287. "%#x",
  288. pInfo
  289. ));
  290. // verify pInfo
  291. if(NULL == pInfo || pInfo->dwStructSize != sizeof(INTERNET_PROXY_INFO_EX))
  292. {
  293. DEBUG_LEAVE(ERROR_INVALID_PARAMETER);
  294. return ERROR_INVALID_PARAMETER;
  295. }
  296. // figure out connection name (NULL == 'network')
  297. pszConnectionName = pInfo->lpszConnectionName;
  298. pszSavedConnectionName = pInfo->lpszConnectionName;
  299. if(NULL == pszConnectionName || 0 == *pszConnectionName)
  300. {
  301. pszConnectionName = "WinHttpSettings";
  302. }
  303. // figure out base key
  304. hBaseKey = FindBaseProxyKey();
  305. // initialize structure
  306. memset(pInfo, 0, sizeof(*pInfo));
  307. pInfo->dwStructSize = sizeof(*pInfo);
  308. pInfo->lpszConnectionName = pszSavedConnectionName;
  309. pInfo->dwFlags = PROXY_TYPE_DIRECT;
  310. // init blob
  311. lRes = r.Init(hBaseKey, szRegPathConnections, pszConnectionName);
  312. if(lRes)
  313. {
  314. error = (lRes == ERROR_FILE_NOT_FOUND) ? ERROR_SUCCESS : lRes;
  315. goto quit;
  316. }
  317. // read fields from blob
  318. if(0 == r.ReadBytes(&pInfo->dwStructSize, sizeof(DWORD)) ||
  319. (pInfo->dwStructSize < sizeof(*pInfo)))
  320. {
  321. // blob didn't exist or in correct format - set default values
  322. pInfo->dwStructSize = sizeof(*pInfo);
  323. }
  324. else
  325. {
  326. // read the rest of the blob
  327. r.ReadBytes(&pInfo->dwCurrentSettingsVersion, sizeof(DWORD));
  328. r.ReadBytes(&pInfo->dwFlags, sizeof(DWORD));
  329. r.ReadString(&pInfo->lpszProxy);
  330. r.ReadString(&pInfo->lpszProxyBypass);
  331. }
  332. //
  333. // WinHttpX does not support proxy autodection or autoconfig URL's,
  334. // so make sure those PROXY_TYPE flags are turned off.
  335. //
  336. pInfo->dwFlags &= ~(PROXY_TYPE_AUTO_DETECT | PROXY_TYPE_AUTO_PROXY_URL);
  337. DEBUG_PRINT(PROXY, INFO, ("conn=%s, vers=%u, flag=%X, prox=%s, by=%s\n",
  338. pszConnectionName,
  339. pInfo->dwCurrentSettingsVersion,
  340. pInfo->dwFlags,
  341. (pInfo->lpszProxy ? pInfo->lpszProxy : "<none>"),
  342. (pInfo->lpszProxyBypass ? pInfo->lpszProxyBypass : "<none>")
  343. ));
  344. quit:
  345. DEBUG_LEAVE(error);
  346. return error;
  347. }
  348. void
  349. CleanProxyStruct(
  350. LPINTERNET_PROXY_INFO_EX pInfo
  351. )
  352. {
  353. if(pInfo->lpszConnectionName) GlobalFree((LPSTR) pInfo->lpszConnectionName);
  354. if(pInfo->lpszProxy) GlobalFree((LPSTR) pInfo->lpszProxy);
  355. if(pInfo->lpszProxyBypass) GlobalFree((LPSTR) pInfo->lpszProxyBypass);
  356. memset(pInfo, 0, sizeof(INTERNET_PROXY_INFO_EX));
  357. pInfo->dwFlags = PROXY_TYPE_DIRECT;
  358. }
  359. DWORD WriteProxySettings(INTERNET_PROXY_INFO_EX * pInfo)
  360. {
  361. CRegBlob r(TRUE);
  362. DWORD error = ERROR_SUCCESS;
  363. long lRes;
  364. // verify pInfo
  365. if(NULL == pInfo || pInfo->dwStructSize != sizeof(INTERNET_PROXY_INFO_EX))
  366. {
  367. return ERROR_INVALID_PARAMETER;
  368. }
  369. // init blob
  370. lRes = r.Init(HKEY_LOCAL_MACHINE, szRegPathConnections, "WinHttpSettings");
  371. if (lRes)
  372. {
  373. error = lRes;
  374. goto quit;
  375. }
  376. if (r.WriteBytes(&pInfo->dwStructSize, sizeof(DWORD)) == 0
  377. || r.WriteBytes(&pInfo->dwCurrentSettingsVersion, sizeof(DWORD)) == 0
  378. || r.WriteBytes(&pInfo->dwFlags, sizeof(DWORD)) == 0
  379. || r.WriteString(pInfo->lpszProxy) == 0
  380. || r.WriteString(pInfo->lpszProxyBypass) == 0)
  381. {
  382. error = ERROR_NOT_ENOUGH_MEMORY;
  383. r.Abandon();
  384. goto quit;
  385. }
  386. lRes = r.Commit();
  387. if (lRes)
  388. {
  389. error = lRes;
  390. goto quit;
  391. }
  392. quit:
  393. return error;
  394. }
  395. //
  396. // support routines for WinHttpGetIEProxyConfigForCurrentUser API ///////////
  397. //
  398. //
  399. //
  400. // Maximum size of TOKEN_USER information.
  401. //
  402. #define SIZE_OF_TOKEN_INFORMATION \
  403. sizeof( TOKEN_USER ) \
  404. + sizeof( SID ) \
  405. + sizeof( ULONG ) * SID_MAX_SUB_AUTHORITIES
  406. #define MAX_SID_STRING 256
  407. // type for RtlConvertSidToUnicodeString, exported from ntdll.dll
  408. typedef NTSTATUS (* PCONVERTSID)(
  409. PUNICODE_STRING UnicodeString,
  410. PSID Sid,
  411. BOOLEAN AllocateDestinationString
  412. );
  413. //
  414. // Function Declarations
  415. //
  416. BOOL
  417. InitClientUserString (
  418. LPWSTR pString
  419. )
  420. /*++
  421. Routine Description:
  422. Arguments:
  423. pString - output string of current user
  424. Return Value:
  425. TRUE = success,
  426. FALSE = fail
  427. Returns in pString a ansi string if the impersonated client's
  428. SID can be expanded successfully into Unicode string. If the conversion
  429. was unsuccessful, returns FALSE.
  430. --*/
  431. {
  432. DEBUG_ENTER((DBG_PROXY,
  433. Bool,
  434. "InitClientUserString",
  435. "%#x",
  436. pString
  437. ));
  438. HANDLE TokenHandle;
  439. UCHAR TokenInformation[ SIZE_OF_TOKEN_INFORMATION ];
  440. ULONG ReturnLength;
  441. BOOL Status;
  442. DWORD dwLastError;
  443. UNICODE_STRING UnicodeString;
  444. HMODULE hNtDll;
  445. PCONVERTSID pRtlConvertSid;
  446. //
  447. // get RtlConvertSideToUnicodeString entry point in NTDLL
  448. //
  449. hNtDll = LoadLibrary("ntdll.dll");
  450. if(NULL == hNtDll)
  451. {
  452. return FALSE;
  453. }
  454. pRtlConvertSid = (PCONVERTSID)GetProcAddress(hNtDll, "RtlConvertSidToUnicodeString");
  455. if(NULL == pRtlConvertSid)
  456. {
  457. FreeLibrary(hNtDll);
  458. DEBUG_LEAVE(FALSE);
  459. return FALSE;
  460. }
  461. //
  462. // We can use OpenThreadToken because this server thread
  463. // is impersonating a client
  464. //
  465. Status = OpenThreadToken(
  466. GetCurrentThread(),
  467. TOKEN_READ,
  468. TRUE, // Open as self
  469. &TokenHandle
  470. );
  471. dwLastError = GetLastError();
  472. if( Status == FALSE )
  473. {
  474. DEBUG_PRINT(PROXY, INFO, ("OpenThreadToken() failed: Error=%d\n",
  475. dwLastError
  476. ));
  477. Status = OpenProcessToken(
  478. GetCurrentProcess(),
  479. TOKEN_READ,
  480. &TokenHandle
  481. );
  482. dwLastError = GetLastError();
  483. if( Status == FALSE )
  484. {
  485. DEBUG_LEAVE(FALSE);
  486. return FALSE ;
  487. }
  488. }
  489. //
  490. // Notice that we've allocated enough space for the
  491. // TokenInformation structure. so if we fail, we
  492. // return a NULL pointer indicating failure
  493. //
  494. Status = GetTokenInformation( TokenHandle,
  495. TokenUser,
  496. TokenInformation,
  497. sizeof( TokenInformation ),
  498. &ReturnLength
  499. );
  500. dwLastError = GetLastError();
  501. CloseHandle( TokenHandle );
  502. if ( Status == FALSE ) {
  503. DEBUG_PRINT(PROXY, INFO, ("GetTokenInformation failed: Error=%d\n",
  504. dwLastError
  505. ));
  506. DEBUG_LEAVE(FALSE);
  507. return FALSE;
  508. }
  509. //
  510. // Convert the Sid (pointed to by pSid) to its
  511. // equivalent Unicode string representation.
  512. //
  513. UnicodeString.Length = 0;
  514. UnicodeString.MaximumLength = MAX_SID_STRING;
  515. UnicodeString.Buffer = pString;
  516. Status = (*pRtlConvertSid)(
  517. &UnicodeString,
  518. ((PTOKEN_USER)TokenInformation)->User.Sid,
  519. FALSE );
  520. FreeLibrary(hNtDll);
  521. if( !NT_SUCCESS( Status )){
  522. DEBUG_PRINT(PROXY, INFO, ("RtlConvertSidToUnicodeString failed: Error=%d\n",
  523. Status
  524. ));
  525. DEBUG_LEAVE(FALSE);
  526. return FALSE;
  527. }
  528. DEBUG_PRINT(PROXY, INFO, ("User SID = %ws\n",
  529. pString
  530. ));
  531. DEBUG_LEAVE(TRUE);
  532. return TRUE;
  533. }
  534. HKEY
  535. GetClientUserHandle(
  536. IN REGSAM samDesired
  537. )
  538. /*++
  539. Routine Description:
  540. Arguments:
  541. Returns:
  542. ---*/
  543. {
  544. DEBUG_ENTER((DBG_PROXY,
  545. Dword,
  546. "GetClientUserHandle",
  547. "%#x",
  548. samDesired
  549. ));
  550. HKEY hKeyClient;
  551. WCHAR String[MAX_SID_STRING];
  552. LONG ReturnValue;
  553. if (!InitClientUserString(String)) {
  554. DEBUG_LEAVE(0);
  555. return NULL ;
  556. }
  557. //
  558. // We now have the Unicode string representation of the
  559. // local client's Sid we'll use this string to open a handle
  560. // to the client's key in the registry.
  561. ReturnValue = RegOpenKeyExW( HKEY_USERS,
  562. String,
  563. 0,
  564. samDesired,
  565. &hKeyClient );
  566. //
  567. // If we couldn't get a handle to the local key
  568. // for some reason, return a NULL handle indicating
  569. // failure to obtain a handle to the key
  570. //
  571. if ( ReturnValue != ERROR_SUCCESS )
  572. {
  573. DEBUG_PRINT(PROXY, INFO, ("RegOpenKeyW failed: Error=%d\n",
  574. ReturnValue
  575. ));
  576. DEBUG_ERROR(PROXY, ReturnValue);
  577. SetLastError( ReturnValue );
  578. DEBUG_LEAVE(0);
  579. return NULL;
  580. }
  581. DEBUG_LEAVE(hKeyClient);
  582. return( hKeyClient );
  583. }
  584. HKEY
  585. FindWinInetBaseProxyKey(
  586. VOID
  587. )
  588. /*
  589. ** Determine whether proxy settings live in HKLM or HKCU
  590. **
  591. ** Returns HKEY_CURRENT_USER or HKEY_LOCAL_MACHINE
  592. **
  593. ** Checks \HKLM\SW\MS\Win\CV\Internet Settings\ProxySettingsPerUser. If
  594. ** exists and is zero, use HKLM otherwise use HKCU.
  595. */
  596. {
  597. HKEY hkeyBase = NULL;
  598. DWORD dwType, dwValue, dwSize = sizeof(DWORD);
  599. if (ERROR_SUCCESS ==
  600. SHGetValue(HKEY_LOCAL_MACHINE, INTERNET_POLICY_KEY,
  601. TEXT("ProxySettingsPerUser"), &dwType, &dwValue, &dwSize) &&
  602. 0 == dwValue)
  603. {
  604. hkeyBase = HKEY_LOCAL_MACHINE;
  605. }
  606. else
  607. {
  608. //
  609. // Find an HKCU equivalent for this process
  610. //
  611. hkeyBase = GetClientUserHandle(KEY_QUERY_VALUE | KEY_SET_VALUE);
  612. if (!hkeyBase)
  613. {
  614. BOOL fLocalSystem = FALSE;
  615. if (GlobalIsProcessNtService)
  616. {
  617. char szUserName[32];
  618. DWORD cbUserNameSize = sizeof(szUserName);
  619. if (GetUserName(szUserName, &cbUserNameSize))
  620. {
  621. if (0 == lstrcmpi(szUserName, "SYSTEM") ||
  622. 0 == lstrcmpi(szUserName, "LOCAL SERVICE") ||
  623. 0 == lstrcmpi(szUserName, "NETWORK SERVICE"))
  624. {
  625. fLocalSystem = TRUE;
  626. }
  627. }
  628. }
  629. if (hkeyBase == NULL && !fLocalSystem)
  630. {
  631. hkeyBase = HKEY_CURRENT_USER;
  632. }
  633. }
  634. }
  635. return hkeyBase;
  636. }
  637. DWORD
  638. ReadWinInetProxySettings(
  639. LPWININET_PROXY_INFO_EX pInfo
  640. )
  641. {
  642. CRegBlob r(FALSE);
  643. LPCSTR pszConnectionName;
  644. LPCSTR pszSavedConnectionName;
  645. DWORD error = ERROR_SUCCESS;
  646. long lRes;
  647. BOOL fLanConnection = FALSE;
  648. HKEY hBaseKey = NULL;
  649. DWORD dwStructVersion = 0;
  650. DEBUG_ENTER((DBG_PROXY,
  651. Dword,
  652. "ReadWinInetProxySettings",
  653. "%#x",
  654. pInfo
  655. ));
  656. // verify pInfo
  657. if (NULL == pInfo || pInfo->dwStructSize != sizeof(WININET_PROXY_INFO_EX))
  658. {
  659. return ERROR_INVALID_PARAMETER;
  660. }
  661. // figure out connection name (NULL == 'network')
  662. pszConnectionName = pInfo->lpszConnectionName;
  663. pszSavedConnectionName = pInfo->lpszConnectionName;
  664. if(NULL == pszConnectionName || 0 == *pszConnectionName)
  665. {
  666. fLanConnection = TRUE;
  667. pszConnectionName = "DefaultConnectionSettings";
  668. }
  669. // figure out base key
  670. hBaseKey = FindWinInetBaseProxyKey();
  671. if (hBaseKey == NULL)
  672. {
  673. error = ERROR_FILE_NOT_FOUND;
  674. goto quit;
  675. }
  676. // initialize structure
  677. memset(pInfo, 0, sizeof(*pInfo));
  678. pInfo->dwStructSize = sizeof(*pInfo);
  679. pInfo->lpszConnectionName = pszSavedConnectionName;
  680. pInfo->dwFlags = PROXY_TYPE_DIRECT;
  681. // init blob
  682. lRes = r.Init(hBaseKey, szRegPathConnections, pszConnectionName);
  683. if(lRes)
  684. {
  685. error = lRes;
  686. goto quit;
  687. }
  688. // read fields from blob
  689. if(0 == r.ReadBytes(&dwStructVersion, sizeof(DWORD)) ||
  690. (dwStructVersion < WININET_PROXY_INFO_EX_VERSION))
  691. {
  692. // blob didn't exist or in correct format - set default values
  693. //
  694. // All lan connections and overridden dial-ups get autodetect
  695. //
  696. if(fLanConnection)
  697. {
  698. pInfo->dwFlags |= PROXY_TYPE_AUTO_DETECT;
  699. }
  700. }
  701. else
  702. {
  703. // read the rest of the blob
  704. r.ReadBytes(&pInfo->dwCurrentSettingsVersion, sizeof(DWORD));
  705. r.ReadBytes(&pInfo->dwFlags, sizeof(DWORD));
  706. r.ReadString(&pInfo->lpszProxy);
  707. r.ReadString(&pInfo->lpszProxyBypass);
  708. r.ReadString(&pInfo->lpszAutoconfigUrl);
  709. r.ReadBytes(&pInfo->dwAutoDiscoveryFlags, sizeof(DWORD));
  710. r.ReadString(&pInfo->lpszLastKnownGoodAutoConfigUrl);
  711. #if 0 // WinHttp does not need the rest of the WinInet proxy config data.
  712. /*
  713. r.ReadBytes(&pInfo->ftLastKnownDetectTime, sizeof(FILETIME));
  714. // read interface ips
  715. r.ReadBytes(&pInfo->dwDetectedInterfaceIpCount, sizeof(DWORD));
  716. if(pInfo->dwDetectedInterfaceIpCount)
  717. {
  718. pInfo->pdwDetectedInterfaceIp = (DWORD *)GlobalAlloc(GPTR, sizeof(DWORD) * pInfo->dwDetectedInterfaceIpCount);
  719. if(pInfo->pdwDetectedInterfaceIp)
  720. {
  721. for(i=0; i<pInfo->dwDetectedInterfaceIpCount; i++)
  722. {
  723. r.ReadBytes(&pInfo->pdwDetectedInterfaceIp[i], sizeof(DWORD));
  724. }
  725. }
  726. }
  727. r.ReadString(&pInfo->lpszAutoconfigSecondaryUrl);
  728. r.ReadBytes(&pInfo->dwAutoconfigReloadDelayMins, sizeof(DWORD));
  729. */
  730. #endif
  731. }
  732. DEBUG_PRINT(PROXY, INFO, ("conn=%s, vers=%u, flag=%X, prox=%s, by=%s, acu=%s\n",
  733. pszConnectionName,
  734. pInfo->dwCurrentSettingsVersion,
  735. pInfo->dwFlags,
  736. (pInfo->lpszProxy ? pInfo->lpszProxy : "<none>"),
  737. (pInfo->lpszProxyBypass ? pInfo->lpszProxyBypass : "<none>"),
  738. (pInfo->lpszAutoconfigUrl ? pInfo->lpszAutoconfigUrl : "<none>")
  739. ));
  740. quit:
  741. if (hBaseKey != NULL &&
  742. hBaseKey != INVALID_HANDLE_VALUE &&
  743. hBaseKey != HKEY_LOCAL_MACHINE &&
  744. hBaseKey != HKEY_CURRENT_USER)
  745. {
  746. RegCloseKey(hBaseKey);
  747. }
  748. DEBUG_LEAVE(error);
  749. return error;
  750. }
  751. void
  752. CleanWinInetProxyStruct(
  753. LPWININET_PROXY_INFO_EX pInfo
  754. )
  755. {
  756. if(pInfo->lpszConnectionName) GlobalFree((LPSTR) pInfo->lpszConnectionName);
  757. if(pInfo->lpszProxy) GlobalFree((LPSTR) pInfo->lpszProxy);
  758. if(pInfo->lpszProxyBypass) GlobalFree((LPSTR) pInfo->lpszProxyBypass);
  759. if(pInfo->lpszAutoconfigUrl) GlobalFree((LPSTR) pInfo->lpszAutoconfigUrl);
  760. if(pInfo->lpszLastKnownGoodAutoConfigUrl) GlobalFree((LPSTR) pInfo->lpszLastKnownGoodAutoConfigUrl);
  761. if(pInfo->pdwDetectedInterfaceIp) GlobalFree(pInfo->pdwDetectedInterfaceIp);
  762. memset(pInfo, 0, sizeof(WININET_PROXY_INFO_EX));
  763. pInfo->dwFlags = PROXY_TYPE_DIRECT;
  764. }