Source code of Windows XP (NT5)
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.

392 lines
10 KiB

  1. /********************************************************************
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. pcache.cpp
  5. Revision History:
  6. DerekM created 11/26/01
  7. ********************************************************************/
  8. #if defined(UNICODE)
  9. #include <windows.h>
  10. #include "dlcache.h"
  11. #include <strsafe.h>
  12. #include <mistsafe.h>
  13. // **************************************************************************
  14. inline
  15. DWORD RolloverSubtract(DWORD dwA, DWORD dwB)
  16. {
  17. return (dwA >= dwB) ? (dwA - dwB) : (dwA + ((DWORD)-1 - dwB));
  18. }
  19. // **************************************************************************
  20. CWUDLProxyCache::CWUDLProxyCache()
  21. {
  22. m_rgpObj = NULL;
  23. }
  24. // **************************************************************************
  25. CWUDLProxyCache::~CWUDLProxyCache()
  26. {
  27. this->Empty();
  28. }
  29. // **************************************************************************
  30. SWUDLProxyCacheObj *CWUDLProxyCache::internalFind(LPCWSTR wszSrv)
  31. {
  32. SWUDLProxyCacheObj *pObj = m_rgpObj;
  33. SWUDLProxyCacheObj **ppNextPtr = &m_rgpObj;
  34. // see if it exists
  35. while(pObj != NULL)
  36. {
  37. if (pObj->wszSrv != NULL && _wcsicmp(pObj->wszSrv, wszSrv) == 0)
  38. {
  39. // detach it from the list
  40. *ppNextPtr = pObj->pNext;
  41. pObj->pNext = NULL;
  42. break;
  43. }
  44. ppNextPtr = &pObj->pNext;
  45. pObj = pObj->pNext;
  46. }
  47. return pObj;
  48. }
  49. // **************************************************************************
  50. BOOL CWUDLProxyCache::Set(LPCWSTR wszSrv, LPCWSTR wszProxy, LPCWSTR wszBypass,
  51. DWORD dwAccessType)
  52. {
  53. SWUDLProxyCacheObj *pObj = NULL;
  54. HRESULT hr = NOERROR;
  55. DWORD cbProxy = 0, cbBypass = 0, cbSrv, cbNeed;
  56. BOOL fRet = FALSE;
  57. if (wszSrv == NULL || *wszSrv == L'\0')
  58. {
  59. SetLastError(ERROR_INVALID_PARAMETER);
  60. goto done;
  61. }
  62. cbSrv = (wcslen(wszSrv) + 1) * sizeof(WCHAR);
  63. cbNeed = cbSrv + sizeof(SWUDLProxyCacheObj);
  64. if (wszProxy != NULL)
  65. {
  66. cbProxy = (wcslen(wszProxy) + 1) * sizeof(WCHAR);
  67. cbNeed += cbProxy;
  68. if (wszBypass != NULL)
  69. {
  70. cbBypass = (wcslen(wszBypass) + 1) * sizeof(WCHAR);
  71. cbNeed += cbBypass;
  72. }
  73. }
  74. // Now, in theory, we should look for an existing object in the list for this
  75. // server, but a couple things make it unnecessary:
  76. // 1. we only use this class in one place
  77. // 2. we will always attempt a find first
  78. // 3. we will only get to this function if find returns NULL
  79. // 4. if one exists, but it's outdated, find will delete it and return NULL
  80. //
  81. // Given the above, there should never be an existing object when Set is
  82. // called.
  83. pObj = (SWUDLProxyCacheObj *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
  84. cbNeed);
  85. if (pObj == NULL)
  86. {
  87. SetLastError(ERROR_OUTOFMEMORY);
  88. goto done;
  89. }
  90. // set up pointers into the blob for the strings & copy the data down
  91. pObj->wszSrv = (LPWSTR)((LPBYTE)pObj + sizeof(SWUDLProxyCacheObj));
  92. hr = StringCbCopyExW(pObj->wszSrv, cbSrv, wszSrv,
  93. NULL, NULL, MISTSAFE_STRING_FLAGS);
  94. if (FAILED(hr))
  95. {
  96. SetLastError(HRESULT_CODE(hr));
  97. goto done;
  98. }
  99. if (wszProxy != NULL)
  100. {
  101. pObj->wszProxy = (LPWSTR)((LPBYTE)pObj->wszSrv + cbSrv);
  102. hr = StringCbCopyExW(pObj->wszProxy, cbProxy, wszProxy,
  103. NULL, NULL, MISTSAFE_STRING_FLAGS);
  104. if (FAILED(hr))
  105. {
  106. SetLastError(HRESULT_CODE(hr));
  107. goto done;
  108. }
  109. if (wszBypass != NULL)
  110. {
  111. pObj->wszBypass = (LPWSTR)((LPBYTE)pObj->wszProxy + cbProxy);
  112. hr = StringCbCopyExW(pObj->wszBypass, cbBypass, wszBypass,
  113. NULL, NULL, MISTSAFE_STRING_FLAGS);
  114. if (FAILED(hr))
  115. {
  116. SetLastError(HRESULT_CODE(hr));
  117. goto done;
  118. }
  119. }
  120. }
  121. pObj->dwLastCacheTime = GetTickCount();
  122. pObj->dwAccessType = dwAccessType;
  123. pObj->cbBypass = cbBypass;
  124. pObj->cbProxy = cbProxy;
  125. pObj->iLastKnownGood = (DWORD)-1;
  126. pObj->pNext = m_rgpObj;
  127. m_rgpObj = pObj;
  128. pObj = NULL;
  129. fRet = TRUE;
  130. done:
  131. if (pObj != NULL)
  132. HeapFree(GetProcessHeap(), 0, pObj);
  133. return fRet;
  134. }
  135. // **************************************************************************
  136. BOOL CWUDLProxyCache::Find(LPCWSTR wszSrv, LPWSTR *pwszProxy, LPWSTR *pwszBypass,
  137. DWORD *pdwAccessType)
  138. {
  139. SWUDLProxyCacheObj *pObj = NULL;
  140. HRESULT hr = NOERROR;
  141. LPWSTR wszProxy = NULL;
  142. LPWSTR wszBypass = NULL;
  143. DWORD dwNow;
  144. BOOL fRet = FALSE, fFreeObjMemory = FALSE;
  145. if (wszSrv == NULL || pwszProxy == NULL || pwszBypass == NULL ||
  146. pdwAccessType == NULL)
  147. {
  148. SetLastError(ERROR_INVALID_PARAMETER);
  149. goto done;
  150. }
  151. *pdwAccessType = 0;
  152. *pwszBypass = NULL;
  153. *pwszProxy = NULL;
  154. // does it exist?
  155. pObj = this->internalFind(wszSrv);
  156. if (pObj == NULL)
  157. goto done;
  158. // has the object expired?
  159. dwNow = GetTickCount();
  160. if (RolloverSubtract(dwNow, pObj->dwLastCacheTime) > c_dwProxyCacheTimeLimit)
  161. {
  162. fFreeObjMemory = TRUE;
  163. goto done;
  164. }
  165. // reset object to front of list
  166. pObj->pNext = m_rgpObj;
  167. m_rgpObj = pObj;
  168. // need to use GloablAlloc here cuz that's what WinHttp uses and we need
  169. // to match it
  170. if (pObj->cbBypass > 0 && pObj->wszBypass != NULL)
  171. {
  172. wszBypass = (LPWSTR)GlobalAlloc(GMEM_FIXED, pObj->cbBypass);
  173. if (wszBypass == NULL)
  174. {
  175. SetLastError(ERROR_OUTOFMEMORY);
  176. goto done;
  177. }
  178. hr = StringCbCopyExW(wszBypass, pObj->cbBypass, pObj->wszBypass,
  179. NULL, NULL, MISTSAFE_STRING_FLAGS);
  180. if (FAILED(hr))
  181. {
  182. SetLastError(HRESULT_CODE(hr));
  183. goto done;
  184. }
  185. }
  186. if (pObj->cbProxy > 0 && pObj->wszProxy != NULL)
  187. {
  188. wszProxy = (LPWSTR)GlobalAlloc(GMEM_FIXED, pObj->cbProxy);
  189. if (wszProxy == NULL)
  190. {
  191. SetLastError(ERROR_OUTOFMEMORY);
  192. goto done;
  193. }
  194. hr = StringCbCopyExW(wszProxy, pObj->cbProxy, pObj->wszProxy,
  195. NULL, NULL, MISTSAFE_STRING_FLAGS);
  196. if (FAILED(hr))
  197. {
  198. SetLastError(HRESULT_CODE(hr));
  199. goto done;
  200. }
  201. }
  202. *pdwAccessType = pObj->dwAccessType;
  203. *pwszBypass = wszBypass;
  204. *pwszProxy = wszProxy;
  205. wszBypass = NULL;
  206. wszProxy = NULL;
  207. pObj = NULL;
  208. fRet = TRUE;
  209. done:
  210. if (fFreeObjMemory && pObj != NULL)
  211. HeapFree(GetProcessHeap(), 0, pObj);
  212. if (wszProxy != NULL)
  213. GlobalFree(wszProxy);
  214. if (wszBypass != NULL)
  215. GlobalFree(wszBypass);
  216. return fRet;
  217. }
  218. // **************************************************************************
  219. BOOL CWUDLProxyCache::SetLastGoodProxy(LPCWSTR wszSrv, DWORD iProxy)
  220. {
  221. SWUDLProxyCacheObj *pObj = NULL;
  222. BOOL fRet = FALSE;
  223. // does it exist?
  224. pObj = this->internalFind(wszSrv);
  225. if (pObj == NULL)
  226. goto done;
  227. // reset object to front of list
  228. pObj->pNext = m_rgpObj;
  229. m_rgpObj = pObj;
  230. pObj->iLastKnownGood = iProxy;
  231. fRet = TRUE;
  232. done:
  233. return fRet;
  234. }
  235. // **************************************************************************
  236. BOOL CWUDLProxyCache::GetLastGoodProxy(LPCWSTR wszSrv, SAUProxySettings *paups)
  237. {
  238. SWUDLProxyCacheObj *pObj = NULL;
  239. HRESULT hr = NOERROR;
  240. LPWSTR wszBypass = NULL, wszProxy = NULL;
  241. BOOL fRet = FALSE;
  242. if (wszSrv == NULL || paups == NULL)
  243. {
  244. SetLastError(ERROR_INVALID_PARAMETER);
  245. goto done;
  246. }
  247. // does it exist?
  248. pObj = this->internalFind(wszSrv);
  249. if (pObj == NULL)
  250. {
  251. SetLastError(ERROR_FILE_NOT_FOUND);
  252. goto done;
  253. }
  254. // reset object to front of list
  255. pObj->pNext = m_rgpObj;
  256. m_rgpObj = pObj;
  257. // need to use GloablAlloc here cuz that's what WinHttp uses and we need
  258. // to match it
  259. if (pObj->cbBypass > 0 && pObj->wszBypass != NULL)
  260. {
  261. wszBypass = (LPWSTR)GlobalAlloc(GMEM_FIXED, pObj->cbBypass);
  262. if (wszBypass == NULL)
  263. {
  264. SetLastError(ERROR_OUTOFMEMORY);
  265. goto done;
  266. }
  267. hr = StringCbCopyExW(wszBypass, pObj->cbBypass, pObj->wszBypass,
  268. NULL, NULL, MISTSAFE_STRING_FLAGS);
  269. if (FAILED(hr))
  270. {
  271. SetLastError(HRESULT_CODE(hr));
  272. goto done;
  273. }
  274. }
  275. if (pObj->cbProxy > 0 && pObj->wszProxy != NULL)
  276. {
  277. wszProxy = (LPWSTR)GlobalAlloc(GMEM_FIXED, pObj->cbProxy);
  278. if (wszProxy == NULL)
  279. {
  280. SetLastError(ERROR_OUTOFMEMORY);
  281. goto done;
  282. }
  283. hr = StringCbCopyExW(wszProxy, pObj->cbProxy, pObj->wszProxy,
  284. NULL, NULL, MISTSAFE_STRING_FLAGS);
  285. if (FAILED(hr))
  286. {
  287. SetLastError(HRESULT_CODE(hr));
  288. goto done;
  289. }
  290. }
  291. ZeroMemory(paups, sizeof(SAUProxySettings));
  292. paups->dwAccessType = pObj->dwAccessType;
  293. paups->wszBypass = wszBypass;
  294. paups->wszProxyOrig = wszProxy;
  295. paups->iProxy = pObj->iLastKnownGood;
  296. wszBypass = NULL;
  297. wszProxy = NULL;
  298. fRet = TRUE;
  299. done:
  300. if (wszProxy != NULL)
  301. GlobalFree(wszProxy);
  302. if (wszBypass != NULL)
  303. GlobalFree(wszBypass);
  304. return fRet;
  305. }
  306. // **************************************************************************
  307. BOOL CWUDLProxyCache::Empty(void)
  308. {
  309. SWUDLProxyCacheObj *pObj = m_rgpObj;
  310. while (pObj != NULL)
  311. {
  312. m_rgpObj = pObj->pNext;
  313. HeapFree(GetProcessHeap(), 0, pObj);
  314. pObj = m_rgpObj;
  315. }
  316. return TRUE;
  317. }
  318. #endif