为何在不同连接(新建InternetOpen与InternetConnect)下调用HttpSendRequest结果不同?
HttpSendRequest Behaves Differently Across New WinINet Connections Alright, let’s break down why you’re seeing inconsistent results when calling HttpSendRequest across fresh InternetOpen/InternetConnect pairs versus reused sessions—this ties directly into how WinINet manages state, handle lifetimes, and error cleanup under the hood.
Key Reasons for the Discrepancy
1. Isolated Session State in InternetOpen
Every InternetOpen call creates a completely isolated WinINet session, with its own internal cache, certificate context tracking, and error state. When you spin up a new InternetOpen/InternetConnect pair, you’re starting from a blank slate—no residual state from your failed certificate attempt carries over.
If you were reusing handles (even with your cleanup code), WinINet might leave behind broken internal state from the aborted request (like a half-initialized certificate selection context). This leftover state can skew how HttpSendRequest behaves on subsequent calls in the same session.
2. Cleanup Code Timing & Handle Validity
Your cleanup block calls InternetCloseHandle for request and connection handles, but timing is critical here. When your SelectCertificate callback throws an exception mid-request, some handles might not be fully initialized yet, or WinINet might have already started its own internal cleanup for the failed attempt.
With a new connection instance, all handles are properly initialized from scratch—there’s no ambiguity about which resources need releasing. Reusing handles (even after cleanup) can lead to dangling references or partially released resources that interfere with the next request’s flow.
3. Corrupted Certificate Selection Context
When your SelectCertificate callback throws an exception, WinINet doesn’t always clean up the certificate selection context associated with that request properly. In a reused session, this broken context can linger in the session’s internal data structures. When you call HttpSendRequest again, WinINet might try to reference this corrupted context instead of triggering a fresh callback, leading to an immediate abort.
A new InternetOpen/InternetConnect pair has no such leftover context, so the callback is triggered cleanly as expected.
4. Session-Specific Error Caching
WinINet caches errors at the session level. When your exception aborts the first request, that error state is tied to the original session. If you reuse that session, HttpSendRequest might hit the cached error and abort early instead of going through the certificate selection flow again. A fresh session starts with no cached errors, so it follows the normal request flow.
Quick Recommendations to Fix This
- Avoid exceptions in WinINet callbacks: WinINet’s callback functions aren’t designed to handle structured exceptions. Instead of throwing, validate parameters gracefully and return an appropriate error code (like
ERROR_CANCELLED) to abort the request cleanly. - Fully tear down sessions between tests: Don’t just close request handles—make sure you’re closing
InternetConnectandInternetOpenhandles completely before creating new ones. This ensures no residual state lingers. - Reset sessions cautiously: If you need to reuse a session, use
InternetSetOptionwithINTERNET_OPTION_RESET_CONNECTIONto reset connection state, but note this doesn’t guarantee the same clean slate as a freshInternetOpencall.
内容的提问来源于stack exchange,提问作者Carlos B. Feitoza Filho

