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.

520 lines
11 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. httpfilt.cxx
  5. Abstract:
  6. This file contains implementation for HTTP filters.
  7. Contents:
  8. HTTPFILT methods
  9. HttpFiltOpen
  10. HttpFiltClose
  11. HttpFiltOnRequest
  12. HttpFiltOnResponse
  13. HttpFiltOnBlockingOps
  14. HttpFiltOnTransactionComplete
  15. Author:
  16. Rajeev Dujari (RajeevD) 01-Jul-1996
  17. Revision History:
  18. TO DO
  19. Get urlmon to call InternetErrorDlg on ERROR_INTERNET_NEED_UI
  20. Deal with OnRequest returning ERROR_INTERNET_NEED_UI
  21. Generate list of filters from registry.
  22. Call filters only if matching headers.
  23. Wrap debug statements around filter calls
  24. Update documentation.
  25. Allow filters to modify response headers
  26. NOTES
  27. Don't unload filters before shutdown because request handles
  28. may have references to them.
  29. --*/
  30. #include "wininetp.h"
  31. #include "httpfilt.h"
  32. struct CONTEXT_ENTRY : public SERIALIZED_LIST_ENTRY
  33. {
  34. HINTERNET hRequest;
  35. LPVOID lpContext;
  36. };
  37. class HTTPFILT
  38. {
  39. HMODULE hFilter;
  40. LPVOID lpFilterContext;
  41. SERIALIZED_LIST slContexts; // list of CONTEXT_ENTRY
  42. PFN_FILTEROPEN pfnOpen;
  43. PFN_FILTERBEGINNINGTRANSACTION pfnOnRequest;
  44. PFN_FILTERONRESPONSE pfnOnResponse;
  45. PFN_FILTERONBLOCKINGOPS pfnOnBlockingOps;
  46. PFN_FILTERONTRANSACTIONCOMPLETE pfnOnTransactionComplete;
  47. LPVOID* GetContextPtr (HINTERNET hRequest);
  48. public:
  49. BOOL Open (void);
  50. BOOL Close (void);
  51. BOOL OnRequest (HINTERNET hRequest);
  52. BOOL OnResponse (HINTERNET hRequest);
  53. BOOL OnTransactionComplete (HINTERNET hRequest);
  54. BOOL OnBlockingOps (HINTERNET hRequest, HWND hwnd);
  55. };
  56. PRIVATE BOOL fOpen = FALSE;
  57. PRIVATE HTTPFILT httpfiltRPA;
  58. PRIVATE HTTPFILT *pRPA = NULL;
  59. /*++
  60. Routine Description:
  61. Arguments:
  62. Return Value:
  63. BOOL
  64. Success - TRUE
  65. Failure - FALSE. Call GetLastError() for more info
  66. --*/
  67. LPVOID* HTTPFILT::GetContextPtr (HINTERNET hRequest)
  68. {
  69. // Search for this entry.
  70. LockSerializedList (&slContexts);
  71. // Get the head of the list. Be sure it is not the dummy entry.
  72. CONTEXT_ENTRY *pce = (CONTEXT_ENTRY *) HeadOfSerializedList (&slContexts);
  73. if ((PLIST_ENTRY) pce == &slContexts.List)
  74. pce = NULL;
  75. while (pce)
  76. {
  77. if (pce->hRequest == hRequest)
  78. goto done;
  79. pce = (CONTEXT_ENTRY *) NextInSerializedList (&slContexts, pce);
  80. }
  81. // Create a new entry.
  82. if (!(pce = new CONTEXT_ENTRY))
  83. {
  84. SetLastError (ERROR_NOT_ENOUGH_MEMORY);
  85. UnlockSerializedList (&slContexts);
  86. return NULL;
  87. }
  88. pce->hRequest = hRequest;
  89. pce->lpContext = NULL;
  90. InsertAtHeadOfSerializedList (&slContexts, &pce->List);
  91. done:
  92. UnlockSerializedList (&slContexts);
  93. return &pce->lpContext;
  94. }
  95. /*++
  96. Routine Description:
  97. Arguments:
  98. Return Value:
  99. BOOL
  100. Success - TRUE
  101. Failure - FALSE. Call GetLastError() for more info
  102. --*/
  103. BOOL HttpFiltOpen (void)
  104. {
  105. if (!fOpen)
  106. {
  107. HKEY hkey;
  108. char szRpaKey[MAX_PATH];
  109. strcpy (szRpaKey, INTERNET_SETTINGS_KEY);
  110. strcat (szRpaKey, "\\Http Filters\\RPA");
  111. if ( !RegOpenKeyEx (HKEY_CURRENT_USER, szRpaKey, 0, KEY_READ, &hkey)
  112. || !RegOpenKeyEx (HKEY_LOCAL_MACHINE, szRpaKey, 0, KEY_READ, &hkey))
  113. {
  114. REGCLOSEKEY (hkey);
  115. if (httpfiltRPA.Open())
  116. pRPA = &httpfiltRPA;
  117. }
  118. fOpen = TRUE;
  119. }
  120. return TRUE;
  121. }
  122. BOOL HTTPFILT::Open(void)
  123. {
  124. hFilter = LoadLibrary ("RPAWINET.DLL");
  125. if (!hFilter)
  126. goto err;
  127. // If there's an open function, call it.
  128. pfnOpen = (PFN_FILTEROPEN) GetProcAddress (hFilter, SZFN_FILTEROPEN);
  129. if (pfnOpen)
  130. {
  131. BOOL fFilter;
  132. __try
  133. {
  134. fFilter = (*pfnOpen) (&lpFilterContext, "RPA", NULL);
  135. }
  136. __except (EXCEPTION_EXECUTE_HANDLER)
  137. {
  138. DEBUG_PRINT(HTTP, ERROR, ("HttpFilterOpen faulted\n"));
  139. fFilter = FALSE;
  140. }
  141. ENDEXCEPT
  142. if (!fFilter)
  143. goto err;
  144. }
  145. InitializeSerializedList (&slContexts);
  146. // Look up other entry points.
  147. pfnOnRequest = (PFN_FILTERBEGINNINGTRANSACTION)
  148. GetProcAddress (hFilter, SZFN_FILTERBEGINNINGTRANSACTION);
  149. pfnOnResponse = (PFN_FILTERONRESPONSE)
  150. GetProcAddress (hFilter, SZFN_FILTERONRESPONSE);
  151. pfnOnTransactionComplete = (PFN_FILTERONTRANSACTIONCOMPLETE)
  152. GetProcAddress (hFilter, SZFN_FILTERONTRANSACTIONCOMPLETE);
  153. pfnOnBlockingOps = (PFN_FILTERONBLOCKINGOPS)
  154. GetProcAddress (hFilter, SZFN_FILTERONBLOCKINGOPS);
  155. return TRUE;
  156. err:
  157. if (hFilter)
  158. {
  159. FreeLibrary (hFilter);
  160. hFilter = NULL;
  161. }
  162. return FALSE;
  163. }
  164. /*++
  165. Routine Description:
  166. Arguments:
  167. Return Value:
  168. BOOL
  169. Success - TRUE
  170. Failure - FALSE. Call GetLastError() for more info
  171. --*/
  172. HttpFiltClose(void)
  173. {
  174. if (fOpen)
  175. {
  176. if (pRPA)
  177. {
  178. pRPA->Close();
  179. pRPA = NULL;
  180. }
  181. fOpen = FALSE;
  182. }
  183. return TRUE;
  184. }
  185. BOOL HTTPFILT::Close (void)
  186. {
  187. TerminateSerializedList (&slContexts);
  188. if (hFilter)
  189. {
  190. if (pfnOpen)
  191. {
  192. PFN_FILTERCLOSE pfnClose;
  193. pfnClose = (PFN_FILTERCLOSE)
  194. GetProcAddress (hFilter, SZFN_FILTERCLOSE);
  195. __try
  196. {
  197. (*pfnClose) (lpFilterContext, InDllCleanup);
  198. }
  199. __except (EXCEPTION_EXECUTE_HANDLER)
  200. {
  201. DEBUG_PRINT(HTTP, ERROR, ("HttpFilterClose faulted\n"));
  202. }
  203. ENDEXCEPT
  204. }
  205. FreeLibrary (hFilter);
  206. }
  207. return TRUE;
  208. }
  209. /*++
  210. Routine Description:
  211. Arguments:
  212. Return Value:
  213. BOOL
  214. Success - TRUE
  215. Failure - FALSE. Call GetLastError() for more info
  216. --*/
  217. BOOL HttpFiltOnRequest (LPVOID pRequest)
  218. {
  219. INET_ASSERT (fOpen);
  220. if (!pRPA)
  221. return TRUE;
  222. return pRPA->OnRequest(((HTTP_REQUEST_HANDLE_OBJECT *)pRequest)->GetPseudoHandle());
  223. }
  224. BOOL HTTPFILT::OnRequest(HINTERNET hRequest)
  225. {
  226. if (pfnOnRequest)
  227. {
  228. LPVOID *lppvContext = GetContextPtr(hRequest);
  229. if (!lppvContext)
  230. return FALSE;
  231. BOOL fFilter;
  232. __try
  233. {
  234. fFilter = (*pfnOnRequest)
  235. (lpFilterContext, lppvContext, hRequest, NULL);
  236. INET_ASSERT (fFilter);
  237. }
  238. __except (EXCEPTION_EXECUTE_HANDLER)
  239. {
  240. DEBUG_PRINT(HTTP, ERROR, ("HttpFilterOnRequest faulted\n"));
  241. fFilter = FALSE;
  242. }
  243. ENDEXCEPT
  244. }
  245. return TRUE;
  246. }
  247. /*++
  248. Routine Description:
  249. Arguments:
  250. Return Value:
  251. BOOL
  252. Success - TRUE
  253. Failure - FALSE. Call GetLastError() for more info
  254. --*/
  255. BOOL HttpFiltOnResponse (LPVOID pObject)
  256. {
  257. INET_ASSERT (fOpen);
  258. if (!pRPA)
  259. return TRUE;
  260. HTTP_REQUEST_HANDLE_OBJECT * pRequest = (HTTP_REQUEST_HANDLE_OBJECT *)pObject;
  261. BOOL fFilter = pRPA->OnResponse (pRequest->GetPseudoHandle());
  262. if (!fFilter)
  263. {
  264. switch (GetLastError())
  265. {
  266. case ERROR_INTERNET_NEED_UI:
  267. {
  268. pRequest->SetBlockingFilter (pRPA);
  269. break;
  270. }
  271. case ERROR_INTERNET_FORCE_RETRY:
  272. {
  273. // Sink any bytes before restarting the send request.
  274. BYTE szSink[1024];
  275. DWORD dwBytesRead = 1;
  276. while (dwBytesRead && ERROR_SUCCESS == pRequest->ReadData
  277. (szSink, sizeof(szSink), &dwBytesRead, TRUE, 0));
  278. SetLastError (ERROR_INTERNET_FORCE_RETRY);
  279. break;
  280. }
  281. }
  282. }
  283. return fFilter;
  284. }
  285. BOOL HTTPFILT::OnResponse(HINTERNET hRequest)
  286. {
  287. BOOL fFilter;
  288. if (pfnOnResponse)
  289. {
  290. LPVOID *lppvContext = GetContextPtr(hRequest);
  291. if (!lppvContext)
  292. return FALSE;
  293. __try
  294. {
  295. fFilter = (*pfnOnResponse)
  296. (lpFilterContext, lppvContext, hRequest, NULL);
  297. }
  298. __except (EXCEPTION_EXECUTE_HANDLER)
  299. {
  300. DEBUG_PRINT(HTTP, ERROR, ("HttpFilterOnResponse faulted\n"));
  301. fFilter = FALSE;
  302. }
  303. ENDEXCEPT
  304. if (!fFilter)
  305. return FALSE;
  306. }
  307. return TRUE;
  308. }
  309. /*++
  310. Routine Description:
  311. Arguments:
  312. Return Value:
  313. BOOL
  314. Success - TRUE
  315. Failure - FALSE. Call GetLastError() for more info
  316. --*/
  317. BOOL HttpFiltOnBlockingOps
  318. (LPVOID pObject, HINTERNET hRequest, HWND hwnd)
  319. {
  320. INET_ASSERT (fOpen);
  321. INET_ASSERT (pRPA);
  322. HTTP_REQUEST_HANDLE_OBJECT * pRequest =
  323. (HTTP_REQUEST_HANDLE_OBJECT *) pObject;
  324. HTTPFILT *lpFilter = (HTTPFILT *) pRequest->GetBlockingFilter();
  325. INET_ASSERT (lpFilter == pRPA);
  326. BOOL fFilter = lpFilter->OnBlockingOps(hRequest, hwnd);
  327. if (!fFilter && GetLastError() == ERROR_INTERNET_FORCE_RETRY)
  328. {
  329. // Sink any bytes before restarting the send request.
  330. BYTE szSink[1024];
  331. DWORD dwBytesRead = 1;
  332. while (dwBytesRead && ERROR_SUCCESS == pRequest->ReadData
  333. (szSink, sizeof(szSink), &dwBytesRead, TRUE, 0));
  334. SetLastError (ERROR_INTERNET_FORCE_RETRY);
  335. }
  336. return fFilter;
  337. }
  338. BOOL HTTPFILT::OnBlockingOps (HINTERNET hRequest, HWND hwnd)
  339. {
  340. if (pfnOnBlockingOps)
  341. {
  342. LPVOID *lppvContext = GetContextPtr(hRequest);
  343. if (!lppvContext)
  344. return FALSE;
  345. BOOL fFilter;
  346. __try
  347. {
  348. fFilter = (*pfnOnBlockingOps)
  349. (lpFilterContext, lppvContext, hRequest, hwnd, NULL);
  350. }
  351. __except (EXCEPTION_EXECUTE_HANDLER)
  352. {
  353. DEBUG_PRINT(HTTP, ERROR, ("HttpFilterOnBlockingOps faulted\n"));
  354. fFilter = FALSE;
  355. }
  356. ENDEXCEPT
  357. return fFilter;
  358. }
  359. return TRUE;
  360. }
  361. /*++
  362. Routine Description:
  363. Arguments:
  364. Return Value:
  365. BOOL
  366. Success - TRUE
  367. Failure - FALSE. Call GetLastError() for more info
  368. --*/
  369. BOOL HttpFiltOnTransactionComplete (HINTERNET hRequest)
  370. {
  371. INET_ASSERT (fOpen);
  372. if (!pRPA)
  373. return TRUE;
  374. else
  375. return pRPA->OnTransactionComplete (hRequest);
  376. }
  377. BOOL HTTPFILT::OnTransactionComplete (HINTERNET hRequest)
  378. {
  379. LPVOID* lppvContext = GetContextPtr(hRequest);
  380. if (pfnOnTransactionComplete)
  381. {
  382. __try
  383. {
  384. (*pfnOnTransactionComplete)
  385. (lpFilterContext, lppvContext, hRequest, NULL);
  386. }
  387. __except (EXCEPTION_EXECUTE_HANDLER)
  388. {
  389. DEBUG_PRINT (HTTP, ERROR, ("HttpFilterOnTransactionComplete faulted\n"));
  390. }
  391. ENDEXCEPT
  392. }
  393. // Destroy any context that was created.
  394. if (lppvContext)
  395. {
  396. CONTEXT_ENTRY* pce = CONTAINING_RECORD
  397. (lppvContext, CONTEXT_ENTRY, lpContext);
  398. RemoveFromSerializedList (&slContexts, &pce->List);
  399. }
  400. return TRUE;
  401. }