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.

678 lines
16 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::Encrpyt(
  139. )
  140. {
  141. return 0;
  142. }
  143. DWORD
  144. CRegBlob::Decrypt(
  145. )
  146. {
  147. return 0;
  148. }
  149. DWORD
  150. CRegBlob::WriteString(
  151. LPCSTR pszString
  152. )
  153. {
  154. DWORD dwBytes, dwLen = 0;
  155. if(pszString)
  156. {
  157. dwLen = lstrlen(pszString);
  158. }
  159. dwBytes = WriteBytes(&dwLen, sizeof(DWORD));
  160. if(dwLen && dwBytes == sizeof(DWORD))
  161. dwBytes = WriteBytes(pszString, dwLen);
  162. return dwBytes;
  163. }
  164. DWORD
  165. CRegBlob::ReadString(
  166. LPCSTR * ppszString
  167. )
  168. {
  169. DWORD dwLen, dwBytes = 0;
  170. LPSTR lpszTemp = NULL;
  171. dwBytes = ReadBytes(&dwLen, sizeof(DWORD));
  172. if(dwBytes == sizeof(DWORD))
  173. {
  174. if(dwLen)
  175. {
  176. lpszTemp = (LPSTR)GlobalAlloc(GPTR, dwLen + 1);
  177. if(lpszTemp)
  178. {
  179. dwBytes = ReadBytes(lpszTemp, dwLen);
  180. lpszTemp[dwBytes] = 0;
  181. }
  182. }
  183. }
  184. *ppszString = lpszTemp;
  185. return dwBytes;
  186. }
  187. DWORD
  188. CRegBlob::WriteBytes(
  189. LPCVOID pBytes,
  190. DWORD dwByteCount
  191. )
  192. {
  193. BYTE * pNewBuffer;
  194. // can only do this on write blob
  195. if(FALSE == _fWrite)
  196. return 0;
  197. // grow buffer if necessary
  198. if(_dwBufferLimit - _dwOffset < dwByteCount)
  199. {
  200. DWORD dw = _dwBufferLimit + ((dwByteCount / BLOB_BUFF_GRANULARITY)+1)*BLOB_BUFF_GRANULARITY;
  201. pNewBuffer = (BYTE *)ALLOCATE_FIXED_MEMORY(dw);
  202. if(NULL == pNewBuffer)
  203. {
  204. // failed to get more memory
  205. return 0;
  206. }
  207. memset(pNewBuffer, 0, dw);
  208. memcpy(pNewBuffer, _pBuffer, _dwBufferLimit);
  209. FREE_FIXED_MEMORY(_pBuffer);
  210. _pBuffer = pNewBuffer;
  211. _dwBufferLimit = dw;
  212. }
  213. // copy callers data to buffer
  214. memcpy(_pBuffer + _dwOffset, pBytes, dwByteCount);
  215. _dwOffset += dwByteCount;
  216. // tell caller how much we wrote
  217. return dwByteCount;
  218. }
  219. DWORD
  220. CRegBlob::ReadBytes(
  221. LPVOID pBytes,
  222. DWORD dwByteCount
  223. )
  224. {
  225. DWORD dwActual = _dwBufferLimit - _dwOffset;
  226. // can only do this on read blob
  227. if(_fWrite)
  228. return 0;
  229. // don't read past end of blob
  230. if(dwByteCount < dwActual)
  231. dwActual = dwByteCount;
  232. // copy bytes and increment offset
  233. if(dwActual > 0)
  234. {
  235. memcpy(pBytes, _pBuffer + _dwOffset, dwActual);
  236. _dwOffset += dwActual;
  237. }
  238. // tell caller how much we actually read
  239. return dwActual;
  240. }
  241. //
  242. // Function Declarations
  243. //
  244. DWORD
  245. LoadProxySettings()
  246. /*
  247. ** Load global proxy info from registry.
  248. **
  249. */
  250. {
  251. DWORD error;
  252. //
  253. // Get proxy struct for proxy object
  254. //
  255. INTERNET_PROXY_INFO_EX info;
  256. memset(&info, 0, sizeof(info));
  257. info.dwStructSize = sizeof(info);
  258. info.lpszConnectionName = NULL;
  259. //
  260. // Read LAN proxy settings and stuff them into the GlobalProxyInfo object.
  261. //
  262. error = ReadProxySettings(&info);
  263. if (error == ERROR_SUCCESS)
  264. {
  265. error = g_pGlobalProxyInfo->SetProxySettings(&info, FALSE);
  266. info.lpszConnectionName = NULL; // we don't allocate this field
  267. CleanProxyStruct(&info);
  268. }
  269. return error;
  270. }
  271. #define INTERNET_SETTINGS_KEY "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"
  272. HKEY
  273. FindBaseProxyKey(
  274. VOID
  275. )
  276. /*
  277. ** Determine whether proxy settings live in HKLM or HKCU
  278. **
  279. ** WinHttpX is hard-coded to always use HKEY_LOCAL_MACHINE
  280. **
  281. */
  282. {
  283. return HKEY_LOCAL_MACHINE;
  284. }
  285. DWORD
  286. ReadProxySettings(
  287. LPINTERNET_PROXY_INFO_EX pInfo
  288. )
  289. {
  290. CRegBlob r(FALSE);
  291. LPCSTR pszConnectionName;
  292. LPCSTR pszSavedConnectionName;
  293. DWORD error = ERROR_SUCCESS;
  294. long lRes;
  295. DWORD i;
  296. HKEY hBaseKey;
  297. DEBUG_ENTER((DBG_DIALUP,
  298. Dword,
  299. "ReadProxySettings",
  300. "%#x",
  301. pInfo
  302. ));
  303. // verify pInfo
  304. if(NULL == pInfo || pInfo->dwStructSize != sizeof(INTERNET_PROXY_INFO_EX))
  305. {
  306. DEBUG_LEAVE(ERROR_INVALID_PARAMETER);
  307. return ERROR_INVALID_PARAMETER;
  308. }
  309. // figure out connection name (NULL == 'network')
  310. pszConnectionName = pInfo->lpszConnectionName;
  311. pszSavedConnectionName = pInfo->lpszConnectionName;
  312. if(NULL == pszConnectionName || 0 == *pszConnectionName)
  313. {
  314. pszConnectionName = "WinHttpSettings";
  315. }
  316. // figure out base key
  317. hBaseKey = FindBaseProxyKey();
  318. // initialize structure
  319. memset(pInfo, 0, sizeof(*pInfo));
  320. pInfo->dwStructSize = sizeof(*pInfo);
  321. pInfo->lpszConnectionName = pszSavedConnectionName;
  322. pInfo->dwFlags = PROXY_TYPE_DIRECT;
  323. // init blob
  324. lRes = r.Init(hBaseKey, szRegPathConnections, pszConnectionName);
  325. if(lRes)
  326. {
  327. error = (lRes == ERROR_FILE_NOT_FOUND) ? ERROR_SUCCESS : lRes;
  328. goto quit;
  329. }
  330. // read fields from blob
  331. if(0 == r.ReadBytes(&pInfo->dwStructSize, sizeof(DWORD)) ||
  332. (pInfo->dwStructSize < sizeof(*pInfo)))
  333. {
  334. // blob didn't exist or in correct format - set default values
  335. pInfo->dwStructSize = sizeof(*pInfo);
  336. }
  337. else
  338. {
  339. // read the rest of the blob
  340. r.ReadBytes(&pInfo->dwCurrentSettingsVersion, sizeof(DWORD));
  341. r.ReadBytes(&pInfo->dwFlags, sizeof(DWORD));
  342. r.ReadString(&pInfo->lpszProxy);
  343. r.ReadString(&pInfo->lpszProxyBypass);
  344. }
  345. //
  346. // WinHttpX does not support proxy autodection or autoconfig URL's,
  347. // so make sure those PROXY_TYPE flags are turned off.
  348. //
  349. pInfo->dwFlags &= ~(PROXY_TYPE_AUTO_DETECT | PROXY_TYPE_AUTO_PROXY_URL);
  350. DEBUG_PRINT(DIALUP, INFO, ("conn=%s, vers=%u, flag=%X, prox=%s, by=%s\n",
  351. pszConnectionName,
  352. pInfo->dwCurrentSettingsVersion,
  353. pInfo->dwFlags,
  354. (pInfo->lpszProxy ? pInfo->lpszProxy : "<none>"),
  355. (pInfo->lpszProxyBypass ? pInfo->lpszProxyBypass : "<none>")
  356. ));
  357. quit:
  358. DEBUG_LEAVE(error);
  359. return error;
  360. }
  361. void
  362. CleanProxyStruct(
  363. LPINTERNET_PROXY_INFO_EX pInfo
  364. )
  365. {
  366. if(pInfo->lpszConnectionName) GlobalFree((LPSTR) pInfo->lpszConnectionName);
  367. if(pInfo->lpszProxy) GlobalFree((LPSTR) pInfo->lpszProxy);
  368. if(pInfo->lpszProxyBypass) GlobalFree((LPSTR) pInfo->lpszProxyBypass);
  369. memset(pInfo, 0, sizeof(INTERNET_PROXY_INFO_EX));
  370. pInfo->dwFlags = PROXY_TYPE_DIRECT;
  371. }
  372. DWORD
  373. SetPerConnOptions(
  374. HINTERNET hInternet,
  375. BOOL fIsAutoProxyThread,
  376. LPINTERNET_PER_CONN_OPTION_LISTA pList
  377. )
  378. {
  379. INTERNET_PROXY_INFO_EX info;
  380. DWORD i, dwError = ERROR_SUCCESS;
  381. BOOL fCommit = FALSE;
  382. LPSTR pszCopy, pszNew;
  383. INET_ASSERT(fIsAutoProxyThread == FALSE);
  384. INET_ASSERT(hInternet != NULL);
  385. memset(&info, 0, sizeof(info));
  386. info.dwStructSize = sizeof(info);
  387. // loop through option list and set members
  388. for(i=0; i<pList->dwOptionCount; i++)
  389. {
  390. pszNew = NULL;
  391. switch(pList->pOptions[i].dwOption)
  392. {
  393. case INTERNET_PER_CONN_PROXY_SERVER:
  394. case INTERNET_PER_CONN_PROXY_BYPASS:
  395. // make a copy of the string passed in for these guys
  396. pszCopy = pList->pOptions[i].Value.pszValue;
  397. if(pszCopy)
  398. {
  399. pszNew = (LPSTR)GlobalAlloc(GPTR, lstrlen(pszCopy) + 1);
  400. if(pszNew)
  401. {
  402. lstrcpy(pszNew, pszCopy);
  403. }
  404. else
  405. {
  406. dwError = ERROR_NOT_ENOUGH_MEMORY;
  407. pList->dwOptionError = i;
  408. }
  409. }
  410. break;
  411. }
  412. if(dwError)
  413. {
  414. fCommit = FALSE;
  415. break;
  416. }
  417. switch(pList->pOptions[i].dwOption)
  418. {
  419. case INTERNET_PER_CONN_FLAGS:
  420. info.dwFlags = pList->pOptions[i].Value.dwValue;
  421. fCommit = TRUE;
  422. break;
  423. case INTERNET_PER_CONN_PROXY_SERVER:
  424. if(info.lpszProxy)
  425. GlobalFree((LPSTR)info.lpszProxy);
  426. info.lpszProxy = pszNew;
  427. fCommit = TRUE;
  428. break;
  429. case INTERNET_PER_CONN_PROXY_BYPASS:
  430. if(info.lpszProxyBypass)
  431. GlobalFree((LPSTR)info.lpszProxyBypass);
  432. info.lpszProxyBypass = pszNew;
  433. fCommit = TRUE;
  434. break;
  435. case INTERNET_PER_CONN_AUTODISCOVERY_FLAGS:
  436. case INTERNET_PER_CONN_AUTOCONFIG_RELOAD_DELAY_MINS:
  437. case INTERNET_PER_CONN_AUTOCONFIG_URL:
  438. case INTERNET_PER_CONN_AUTOCONFIG_SECONDARY_URL:
  439. case INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_TIME:
  440. case INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_URL:
  441. default:
  442. dwError = ERROR_INVALID_PARAMETER;
  443. pList->dwOptionError = i;
  444. break;
  445. }
  446. if(dwError)
  447. {
  448. fCommit = FALSE;
  449. break;
  450. }
  451. }
  452. if (fCommit && hInternet)
  453. {
  454. g_pGlobalProxyInfo->SetProxySettings(&info, TRUE);
  455. }
  456. return dwError;
  457. }
  458. DWORD
  459. QueryPerConnOptions(
  460. HINTERNET hInternet,
  461. BOOL fIsAutoProxyThread,
  462. LPINTERNET_PER_CONN_OPTION_LISTA pList
  463. )
  464. {
  465. INTERNET_PROXY_INFO_EX info;
  466. LPCSTR pszCopy;
  467. LPSTR pszNew;
  468. DWORD i, dwError = ERROR_SUCCESS;
  469. BOOL fFreeCopy = FALSE;
  470. pList->dwOptionError = 0;
  471. memset(&info, 0, sizeof(info));
  472. info.dwStructSize = sizeof(info);
  473. info.lpszConnectionName = pList->pszConnection;
  474. if ( hInternet == NULL )
  475. {
  476. #ifndef WININET_SERVER_CORE
  477. if ( ! fIsAutoProxyThread ||
  478. ! g_pGlobalProxyInfo->GetAutoProxyThreadSettings(&info) ||
  479. ! IsConnectionMatch(info.lpszConnectionName, pList->pszConnection))
  480. {
  481. CheckForUpgrade();
  482. ReadProxySettings(&info);
  483. fFreeCopy = TRUE;
  484. }
  485. #endif //!WININET_SERVER_CORE
  486. }
  487. else
  488. {
  489. g_pGlobalProxyInfo->GetProxySettings(&info, FALSE);
  490. }
  491. // loop through option list and fill in members
  492. for(i=0; i<pList->dwOptionCount; i++)
  493. {
  494. pList->pOptions[i].Value.pszValue = NULL;
  495. pszCopy = NULL;
  496. switch(pList->pOptions[i].dwOption)
  497. {
  498. case INTERNET_PER_CONN_FLAGS:
  499. pList->pOptions[i].Value.dwValue = info.dwFlags;
  500. break;
  501. case INTERNET_PER_CONN_PROXY_SERVER:
  502. pszCopy = info.lpszProxy;
  503. break;
  504. case INTERNET_PER_CONN_PROXY_BYPASS:
  505. pszCopy = info.lpszProxyBypass;
  506. break;
  507. default:
  508. dwError = ERROR_INVALID_PARAMETER;
  509. pList->dwOptionError = i;
  510. break;
  511. }
  512. // if this is a string value, make a copy of the string for the
  513. // caller
  514. if(pszCopy)
  515. {
  516. // make a copy of the string and stick it in the option
  517. pszNew = (LPSTR)GlobalAlloc(GPTR, lstrlen(pszCopy) + 1);
  518. if(pszNew)
  519. {
  520. lstrcpy(pszNew, pszCopy);
  521. pList->pOptions[i].Value.pszValue = pszNew;
  522. }
  523. else
  524. {
  525. dwError = ERROR_NOT_ENOUGH_MEMORY;
  526. pList->dwOptionError = i;
  527. }
  528. }
  529. if(dwError)
  530. {
  531. break;
  532. }
  533. }
  534. if (dwError)
  535. {
  536. // If an error has occurred, we should get rid of any strings that
  537. // we've allocated.
  538. for (i=0; i<pList->dwOptionError; i++)
  539. {
  540. switch(pList->pOptions[i].dwOption)
  541. {
  542. case INTERNET_PER_CONN_PROXY_SERVER:
  543. case INTERNET_PER_CONN_PROXY_BYPASS:
  544. if (pList->pOptions[i].Value.pszValue)
  545. {
  546. GlobalFree(pList->pOptions[i].Value.pszValue);
  547. pList->pOptions[i].Value.pszValue = NULL;
  548. }
  549. break;
  550. default:
  551. break;
  552. }
  553. }
  554. }
  555. if ( fFreeCopy ) {
  556. info.lpszConnectionName = NULL; // we don't allocate this field
  557. CleanProxyStruct(&info);
  558. }
  559. return dwError;
  560. }