| Left: | ||
| Right: |
| LEFT | RIGHT |
|---|---|
| 1 #include "PluginStdAfx.h" | 1 #include "PluginStdAfx.h" |
| 2 | 2 |
| 3 #include "PluginWbPassThrough.h" | 3 #include "PluginWbPassThrough.h" |
| 4 #include "PluginClient.h" | 4 #include "PluginClient.h" |
| 5 #include "PluginClientFactory.h" | 5 #include "PluginClientFactory.h" |
| 6 #ifdef SUPPORT_FILTER | |
| 7 #include "PluginFilter.h" | 6 #include "PluginFilter.h" |
| 8 #endif | |
| 9 #include "PluginSettings.h" | 7 #include "PluginSettings.h" |
| 10 #include "PluginClass.h" | 8 #include "PluginClass.h" |
| 11 #include "PluginSystem.h" | 9 #include "PluginSystem.h" |
| 12 #include <WinInet.h> | 10 #include <WinInet.h> |
| 13 #include "wtypes.h" | 11 #include "wtypes.h" |
| 14 | 12 |
| 15 namespace | 13 namespace |
| 16 { | 14 { |
| 17 std::string g_blockedByABPPage = "<!DOCTYPE html>" | 15 std::string g_blockedByABPPage = "<!DOCTYPE html>" |
| 18 "<html>" | 16 "<html>" |
| 19 "<body>" | 17 "<body>" |
| 20 "<!-- blocked by AdblockPlus -->" | 18 "<!-- blocked by AdblockPlus -->" |
| 21 "</body>" | 19 "</body>" |
| 22 "</html>"; | 20 "</html>"; |
| 23 } | 21 } |
| 24 | 22 |
| 25 WBPassthruSink::WBPassthruSink() | 23 WBPassthruSink::WBPassthruSink() |
| 26 : m_currentPositionOfSentPage(0) | 24 : m_currentPositionOfSentPage(0) |
|
Oleksandr
2014/09/21 23:30:40
I wouldn't be entirely sure that IE does not reuse
sergei
2014/09/22 16:18:05
It does not reuse them. If it happens we will be a
Oleksandr
2014/10/03 14:36:37
Even though I can't provide an example when this m
| |
| 27 , m_contentType(CFilter::EContentType::contentTypeAny) | 25 , m_contentType(CFilter::EContentType::contentTypeAny) |
| 28 , m_blockedInTransaction(false) | 26 , m_blockedInTransaction(false) |
| 29 { | 27 { |
| 30 } | 28 } |
| 31 | 29 |
| 32 int WBPassthruSink::GetContentTypeFromMimeType(const CString& mimeType) | 30 int WBPassthruSink::GetContentTypeFromMimeType(const CString& mimeType) |
| 33 { | 31 { |
| 34 if (mimeType.Find(L"image/") >= 0) | 32 if (mimeType.Find(L"image/") >= 0) |
| 35 { | 33 { |
| 36 return CFilter::contentTypeImage; | 34 return CFilter::contentTypeImage; |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 94 { | 92 { |
| 95 return CFilter::contentTypeObject; | 93 return CFilter::contentTypeObject; |
| 96 } | 94 } |
| 97 else if (ext == L".jsp" || ext == L".php" || ext == L".html") | 95 else if (ext == L".jsp" || ext == L".php" || ext == L".html") |
| 98 { | 96 { |
| 99 return CFilter::contentTypeSubdocument; | 97 return CFilter::contentTypeSubdocument; |
| 100 } | 98 } |
| 101 return CFilter::contentTypeAny; | 99 return CFilter::contentTypeAny; |
| 102 } | 100 } |
| 103 | 101 |
| 104 int WBPassthruSink::GetContentType(const CString& mimeType, const CString& domai n, const CString& src) | 102 int WBPassthruSink::GetContentType(const CString& mimeType, const std::wstring& domain, const CString& src) |
| 105 { | 103 { |
| 106 // No referer or mime type | 104 // No referer or mime type |
| 107 // BINDSTRING_XDR_ORIGIN works only for IE v8+ | 105 // BINDSTRING_XDR_ORIGIN works only for IE v8+ |
| 108 if (mimeType.IsEmpty() && domain.IsEmpty() && CPluginClient::GetInstance()->Ge tIEVersion() >= 8) | 106 if (mimeType.IsEmpty() && domain.empty() && CPluginClient::GetInstance()->GetI EVersion() >= 8) |
| 109 { | 107 { |
| 110 return CFilter::contentTypeXmlHttpRequest; | 108 return CFilter::contentTypeXmlHttpRequest; |
| 111 } | 109 } |
| 112 int contentType = GetContentTypeFromMimeType(mimeType); | 110 int contentType = GetContentTypeFromMimeType(mimeType); |
| 113 if (contentType == CFilter::contentTypeAny) | 111 if (contentType == CFilter::contentTypeAny) |
| 114 { | 112 { |
| 115 contentType = GetContentTypeFromURL(src); | 113 contentType = GetContentTypeFromURL(src); |
| 116 } | 114 } |
| 117 return contentType; | 115 return contentType; |
| 118 } | 116 } |
| 119 | 117 |
| 120 //////////////////////////////////////////////////////////////////////////////// //////// | 118 //////////////////////////////////////////////////////////////////////////////// //////// |
| 121 //WBPassthruSink | 119 //WBPassthruSink |
| 122 //Monitor and/or cancel every request and responde | 120 //Monitor and/or cancel every request and responde |
| 123 //WB makes, including images, sounds, scripts, etc | 121 //WB makes, including images, sounds, scripts, etc |
| 124 //////////////////////////////////////////////////////////////////////////////// //////// | 122 //////////////////////////////////////////////////////////////////////////////// //////// |
| 125 HRESULT WBPassthruSink::OnStart(LPCWSTR szUrl, IInternetProtocolSink *pOIProtSin k, | 123 HRESULT WBPassthruSink::OnStart(LPCWSTR szUrl, IInternetProtocolSink *pOIProtSin k, |
| 126 IInternetBindInfo *pOIBindInfo, DWORD grfPI, HAN DLE_PTR dwReserved, | 124 IInternetBindInfo *pOIBindInfo, DWORD grfPI, HAN DLE_PTR dwReserved, |
| 127 IInternetProtocol* pTargetProtocol, bool& handle d) | 125 IInternetProtocol* pTargetProtocol, bool& handle d) |
| 128 { | 126 { |
| 129 m_pTargetProtocol = pTargetProtocol; | 127 m_pTargetProtocol = pTargetProtocol; |
| 130 bool isBlocked = false; | 128 bool isBlocked = false; |
| 131 CString src = szUrl; | 129 CString src = szUrl; |
| 132 DEBUG_GENERAL(src); | 130 DEBUG_GENERAL(src); |
| 133 CPluginClient::UnescapeUrl(src); | 131 CPluginClient::UnescapeUrl(src); |
| 134 | 132 |
| 135 // call the impl of the base class as soon as possible because it initializes the base class | 133 // call the impl of the base class as soon as possible because it initializes the base class |
| 136 // members, used by this method. It queries for the required interfaces. | 134 // members, used by this method. It queries for the required interfaces. |
| 137 HRESULT hr = BaseClass::OnStart(szUrl, pOIProtSink, pOIBindInfo, grfPI, dwRese rved, pTargetProtocol); | 135 HRESULT hr = BaseClass::OnStart(szUrl, pOIProtSink, pOIBindInfo, grfPI, dwRese rved, pTargetProtocol); |
|
Oleksandr
2014/09/21 23:30:40
I still have my concerns if the requests are actua
sergei
2014/09/22 16:18:05
I have checked it before and now again, it works i
Oleksandr
2014/10/03 14:36:37
Not really. Just wanted to double check if you've
| |
| 138 if (FAILED(hr)) | 136 if (FAILED(hr)) |
| 139 { | 137 { |
| 140 return hr; | 138 return hr; |
| 141 } | 139 } |
| 142 | 140 |
| 143 CString mimeType; | 141 CString mimeType; |
| 144 if (pOIBindInfo) | 142 if (pOIBindInfo) |
| 145 { | 143 { |
| 146 ULONG resLen = 0; | 144 ULONG resLen = 0; |
| 147 | 145 |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 165 } | 163 } |
| 166 } | 164 } |
| 167 // We can obtain IBindCtx* here, but IEnumString obtained via IBindCtx::Enum ObjectParam | 165 // We can obtain IBindCtx* here, but IEnumString obtained via IBindCtx::Enum ObjectParam |
| 168 // does not return any parameter, so it's useless. | 166 // does not return any parameter, so it's useless. |
| 169 } | 167 } |
| 170 | 168 |
| 171 CString cookie; | 169 CString cookie; |
| 172 ULONG len1 = 2048; | 170 ULONG len1 = 2048; |
| 173 ULONG len2 = 2048; | 171 ULONG len2 = 2048; |
| 174 | 172 |
| 175 #ifdef SUPPORT_FILTER | |
| 176 CPluginTab* tab = CPluginClass::GetTab(::GetCurrentThreadId()); | 173 CPluginTab* tab = CPluginClass::GetTab(::GetCurrentThreadId()); |
| 177 CPluginClient* client = CPluginClient::GetInstance(); | 174 CPluginClient* client = CPluginClient::GetInstance(); |
| 178 | 175 |
| 179 if (tab && client) | 176 if (tab && client) |
| 180 { | 177 { |
| 181 CString documentUrl = tab->GetDocumentUrl(); | 178 CString documentUrl = tab->GetDocumentUrl(); |
| 182 // Page is identical to document => don't block | 179 // Page is identical to document => don't block |
| 183 if (documentUrl == src) | 180 if (documentUrl == src) |
| 184 { | 181 { |
| 185 // fall through | 182 // fall through |
| 186 } | 183 } |
| 187 else if (CPluginSettings::GetInstance()->IsPluginEnabled() && !client->IsWhi telistedUrl(std::wstring(documentUrl))) | 184 else if (CPluginSettings::GetInstance()->IsPluginEnabled() && !client->IsWhi telistedUrl(std::wstring(documentUrl))) |
| 188 { | 185 { |
| 189 m_boundDomain = tab->GetDocumentUrl(); | 186 m_boundDomain = tab->GetDocumentUrl(); |
| 190 m_contentType = CFilter::contentTypeAny; | 187 m_contentType = CFilter::contentTypeAny; |
| 191 #ifdef SUPPORT_FRAME_CACHING | 188 if (tab != nullptr && tab->IsFrameCached(src)) |
| 192 if (nullptr != tab && tab->IsFrameCached(src)) | |
|
Oleksandr
2014/09/21 23:30:40
No yoda conditions, please
if (tab != nullptr && .
| |
| 193 { | 189 { |
| 194 m_contentType = CFilter::contentTypeSubdocument; | 190 m_contentType = CFilter::contentTypeSubdocument; |
| 195 } | 191 } |
| 196 else | 192 else |
| 197 #endif // SUPPORT_FRAME_CACHING | |
| 198 { | 193 { |
| 199 m_contentType = GetContentType(mimeType, m_boundDomain, src); | 194 m_contentType = GetContentType(mimeType, m_boundDomain, src); |
| 200 } | 195 } |
| 201 } | 196 } |
| 202 } | 197 } |
| 203 | 198 |
| 204 if (nullptr == tab) | 199 if (tab == nullptr) |
|
Oleksandr
2014/09/21 23:30:40
No yoda conditions, please
| |
| 205 { | 200 { |
| 206 m_contentType = GetContentType(mimeType, m_boundDomain, src); | 201 m_contentType = GetContentType(mimeType, m_boundDomain, src); |
| 207 } | 202 } |
| 208 | 203 |
| 209 { | 204 { |
| 210 // Here is the heuristic which detects the requests issued by Flash.ocx. | 205 // Here is the heuristic which detects the requests issued by Flash.ocx. |
| 211 // It turned out that the implementation from ''Flash.ocx'' (tested version is 15.0.0.152) | 206 // It turned out that the implementation from ''Flash.ocx'' (tested version is 15.0.0.152) |
| 212 // returns quite minimal configuration in comparison with the implementation from Microsofts' | 207 // returns quite minimal configuration in comparison with the implementation from Microsofts' |
| 213 // libraries (see grfBINDF and bindInfo.dwOptions). The impl from MS often i ncludes something | 208 // libraries (see grfBINDF and bindInfo.dwOptions). The impl from MS often i ncludes something |
| 214 // else. | 209 // else. |
| 215 ATL::CComPtr<IBindStatusCallback> bscb; | 210 ATL::CComPtr<IBindStatusCallback> bscb; |
| 216 if (SUCCEEDED(QueryServiceFromClient(&bscb)) && !!bscb) | 211 if (SUCCEEDED(QueryServiceFromClient(&bscb)) && !!bscb) |
| 217 { | 212 { |
| 218 DWORD grfBINDF = 0; | 213 DWORD grfBINDF = 0; |
| 219 BINDINFO bindInfo = {}; | 214 BINDINFO bindInfo = {}; |
| 220 bindInfo.cbSize = sizeof(bindInfo); | 215 bindInfo.cbSize = sizeof(bindInfo); |
| 221 if (SUCCEEDED(bscb->GetBindInfo(&grfBINDF, &bindInfo)) | 216 if (SUCCEEDED(bscb->GetBindInfo(&grfBINDF, &bindInfo)) |
| 222 && (BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE| BINDF_PULLDATA) == grfBINDF | 217 && (BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE| BINDF_PULLDATA) == grfBINDF |
| 223 && (BINDINFO_OPTIONS_ENABLE_UTF8 | BINDINFO_OPTIONS_USE_IE_ENCODING) == bindInfo.dwOptions | 218 && (BINDINFO_OPTIONS_ENABLE_UTF8 | BINDINFO_OPTIONS_USE_IE_ENCODING) == bindInfo.dwOptions |
| 224 ) | 219 ) |
|
Oleksandr
2014/09/21 23:30:40
This looks quite neat, however can you maybe test
sergei
2014/09/22 16:18:05
I will test it with different <IE, Flash> as far a
| |
| 225 { | 220 { |
| 226 m_contentType = CFilter::EContentType::contentTypeObjectSubrequest; | 221 m_contentType = CFilter::EContentType::contentTypeObjectSubrequest; |
| 227 } | 222 } |
| 228 } | 223 } |
| 229 } | 224 } |
| 230 | 225 |
| 231 // The descision about EContentType::contentTypeAny is made later in | 226 // The descision about EContentType::contentTypeAny is made later in |
| 232 // WBPassthruSink::BeginningTransaction. Sometimes here we cannot detect the r equest type, but | 227 // WBPassthruSink::BeginningTransaction. Sometimes here we cannot detect the r equest type, but |
| 233 // in WBPassthruSink::BeginningTransaction the header Accept is available whic h allows to | 228 // in WBPassthruSink::BeginningTransaction the header Accept is available whic h allows to |
| 234 // obtain the "request type" in our terminology. | 229 // obtain the "request type" in our terminology. |
| 235 if (nullptr != client | 230 if (nullptr != client |
| 236 && CFilter::EContentType::contentTypeAny != m_contentType | 231 && CFilter::EContentType::contentTypeAny != m_contentType |
| 237 && client->ShouldBlock(src, m_contentType, m_boundDomain, true)) | 232 && client->ShouldBlock(static_cast<const wchar_t*>(src), m_contentType, m_bo undDomain, true)) |
| 238 { | 233 { |
| 239 isBlocked = true; | 234 isBlocked = true; |
| 240 } | 235 } |
| 241 | 236 |
| 242 // For IE6 and earlier there is iframe back button issue, so avoid it. | 237 // For IE6 and earlier there is iframe back button issue, so avoid it. |
| 243 if (isBlocked && client->GetIEVersion() > 6) | 238 if (isBlocked && client->GetIEVersion() > 6) |
| 244 { | 239 { |
| 245 handled = true; | 240 handled = true; |
| 246 if (CFilter::EContentType::contentTypeImage == m_contentType) | 241 if (CFilter::EContentType::contentTypeImage == m_contentType) |
| 247 { | 242 { |
| 248 // IE shows a cross that img is not loaded | 243 // IE shows a cross that img is not loaded |
|
Oleksandr
2014/09/21 23:30:40
Does this happen even if we "eat" the ReportResult
sergei
2014/09/22 16:18:05
Have not tested yet, also I'm afraid that sending
Oleksandr
2014/10/03 14:36:37
This can go into other review anyway.
On 2014/09/2
| |
| 249 return INET_E_REDIRECT_FAILED; | 244 return INET_E_REDIRECT_FAILED; |
| 250 } | 245 } |
| 251 if (CFilter::EContentType::contentTypeSubdocument == m_contentType) | 246 if (CFilter::EContentType::contentTypeSubdocument == m_contentType) |
| 252 { | 247 { |
| 253 PassthroughAPP::CustomSinkStartPolicy<WBPassthru, WBPassthruSink>::GetProt ocol(this)->m_shouldSupplyCustomContent = true; | 248 PassthroughAPP::CustomSinkStartPolicy<WBPassthru, WBPassthruSink>::GetProt ocol(this)->m_shouldSupplyCustomContent = true; |
| 254 m_spInternetProtocolSink->ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE, L"t ext/html"); | 249 m_spInternetProtocolSink->ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE, L"t ext/html"); |
| 255 m_spInternetProtocolSink->ReportData(BSCF_FIRSTDATANOTIFICATION, 0, static _cast<ULONG>(g_blockedByABPPage.size())); | 250 m_spInternetProtocolSink->ReportData(BSCF_FIRSTDATANOTIFICATION, 0, static _cast<ULONG>(g_blockedByABPPage.size())); |
| 256 return S_OK; | 251 return S_OK; |
| 257 } | 252 } |
| 258 if (CFilter::EContentType::contentTypeScript == m_contentType) | 253 if (CFilter::EContentType::contentTypeScript == m_contentType) |
| 259 { | 254 { |
| 260 m_spInternetProtocolSink->ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE, L"t ext/javascript"); | 255 m_spInternetProtocolSink->ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE, L"t ext/javascript"); |
| 261 m_spInternetProtocolSink->ReportResult(INET_E_REDIRECTING, 301, L"data:"); | 256 m_spInternetProtocolSink->ReportResult(INET_E_REDIRECTING, 301, L"data:"); |
| 262 return INET_E_REDIRECT_FAILED; | 257 return INET_E_REDIRECT_FAILED; |
| 263 } | 258 } |
| 264 if (CFilter::EContentType::contentTypeXmlHttpRequest == m_contentType) | 259 if (CFilter::EContentType::contentTypeXmlHttpRequest == m_contentType) |
| 265 { | 260 { |
| 266 m_spInternetProtocolSink->ReportResult(INET_E_REDIRECTING, 301, L"data:"); | 261 m_spInternetProtocolSink->ReportResult(INET_E_REDIRECTING, 301, L"data:"); |
| 267 return INET_E_REDIRECT_FAILED; | 262 return INET_E_REDIRECT_FAILED; |
| 268 } | 263 } |
| 269 if (CFilter::EContentType::contentTypeAny != m_contentType) | 264 if (CFilter::EContentType::contentTypeAny != m_contentType) |
| 270 { | 265 { |
| 271 m_spInternetProtocolSink->ReportResult(INET_E_REDIRECTING, 301, L"data:"); | 266 m_spInternetProtocolSink->ReportResult(INET_E_REDIRECTING, 301, L"data:"); |
| 272 return INET_E_REDIRECT_FAILED; | 267 return INET_E_REDIRECT_FAILED; |
| 273 } | 268 } |
| 274 } | 269 } |
| 275 #endif // SUPPORT_FILTER | |
| 276 | 270 |
| 277 return isBlocked ? S_FALSE : hr; | 271 return isBlocked ? S_FALSE : hr; |
| 278 } | 272 } |
| 279 | 273 |
| 280 HRESULT WBPassthruSink::OnRead(void* pv, ULONG cb, ULONG* pcbRead) | 274 HRESULT WBPassthruSink::OnRead(void* pv, ULONG cb, ULONG* pcbRead) |
| 281 { | 275 { |
| 282 if (nullptr == pv) | 276 if (pv == nullptr) |
|
Oleksandr
2014/09/21 23:30:40
if (pv == nullptr) looks better, imho
| |
| 283 { | 277 { |
| 284 return E_POINTER; | 278 return E_POINTER; |
| 285 } | 279 } |
| 286 if (nullptr == pcbRead) | 280 if (pcbRead == nullptr) |
|
Oleksandr
2014/09/21 23:30:40
Same as above
| |
| 287 { | 281 { |
| 288 return E_POINTER; | 282 return E_POINTER; |
| 289 } | 283 } |
| 290 *pcbRead = 0; | 284 *pcbRead = 0; |
| 291 | 285 |
| 292 if (PassthroughAPP::CustomSinkStartPolicy<WBPassthru, WBPassthruSink>::GetProt ocol(this)->m_shouldSupplyCustomContent) | 286 if (PassthroughAPP::CustomSinkStartPolicy<WBPassthru, WBPassthruSink>::GetProt ocol(this)->m_shouldSupplyCustomContent) |
| 293 { | 287 { |
| 294 ULONG myPageSize = static_cast<ULONG>(g_blockedByABPPage.size()); | 288 ULONG blockedByABPPageSize = static_cast<ULONG>(g_blockedByABPPage.size()); |
|
Oleksandr
2014/09/21 23:30:40
abpPageSize would be a better name, IMHO
sergei
2014/09/22 16:18:05
Sorry, forgot to change the name. During the playi
| |
| 295 auto positionGrow = std::min<ULONG>(cb, static_cast<ULONG>(g_blockedByABPPag e.size() - m_currentPositionOfSentPage)); | 289 auto positionGrow = std::min<ULONG>(cb, static_cast<ULONG>(blockedByABPPageS ize - m_currentPositionOfSentPage)); |
| 296 if (0 == positionGrow) { | 290 if (positionGrow == 0) { |
|
Oleksandr
2014/09/21 23:30:40
positionGrow == 0 seems more logical
| |
| 297 return S_FALSE; | 291 return S_FALSE; |
| 298 } | 292 } |
| 299 std::copy(g_blockedByABPPage.begin(), g_blockedByABPPage.begin() + positionG row, | 293 std::copy(g_blockedByABPPage.begin(), g_blockedByABPPage.begin() + positionG row, |
| 300 stdext::make_checked_array_iterator(static_cast<char*>(pv), cb)); | 294 stdext::make_checked_array_iterator(static_cast<char*>(pv), cb)); |
|
Oleksandr
2014/09/21 23:30:40
So this will throw a runtime error if cb < positio
sergei
2014/09/22 16:18:05
- It's not possible to compile without checked ite
Oleksandr
2014/10/03 14:36:37
I suppose you could use memcpy here instead, but I
| |
| 301 *pcbRead = positionGrow; | 295 *pcbRead = positionGrow; |
| 302 m_currentPositionOfSentPage += positionGrow; | 296 m_currentPositionOfSentPage += positionGrow; |
| 303 | 297 |
| 304 if (m_spInternetProtocolSink) | 298 if (m_spInternetProtocolSink) |
| 305 { | 299 { |
| 306 m_spInternetProtocolSink->ReportData(BSCF_INTERMEDIATEDATANOTIFICATION, | 300 m_spInternetProtocolSink->ReportData(BSCF_INTERMEDIATEDATANOTIFICATION, |
| 307 static_cast<ULONG>(m_currentPositionOfSentPage), myPageSize); | 301 static_cast<ULONG>(m_currentPositionOfSentPage), blockedByABPPageSize); |
| 308 } | 302 } |
| 309 if (myPageSize == m_currentPositionOfSentPage && m_spInternetProtocolSink) | 303 if (blockedByABPPageSize == m_currentPositionOfSentPage && m_spInternetProto colSink) |
| 310 { | 304 { |
| 311 m_spInternetProtocolSink->ReportData(BSCF_DATAFULLYAVAILABLE, myPageSize, myPageSize); | 305 m_spInternetProtocolSink->ReportData(BSCF_DATAFULLYAVAILABLE, blockedByABP PageSize, blockedByABPPageSize); |
| 312 m_spInternetProtocolSink->ReportResult(S_OK, 0, nullptr); | 306 m_spInternetProtocolSink->ReportResult(S_OK, 0, nullptr); |
| 313 } | 307 } |
| 314 return S_OK; | 308 return S_OK; |
| 315 } | 309 } |
| 316 return m_pTargetProtocol->Read(pv, cb, pcbRead); | 310 return m_pTargetProtocol->Read(pv, cb, pcbRead); |
| 317 } | 311 } |
| 318 STDMETHODIMP WBPassthruSink::Switch( | 312 STDMETHODIMP WBPassthruSink::Switch( |
| 319 /* [in] */ PROTOCOLDATA *pProtocolData) | 313 /* [in] */ PROTOCOLDATA *pProtocolData) |
| 320 { | 314 { |
| 321 ATLASSERT(m_spInternetProtocolSink != 0); | 315 ATLASSERT(m_spInternetProtocolSink != 0); |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 469 } | 463 } |
| 470 | 464 |
| 471 STDMETHODIMP WBPassthru::UnlockRequest() | 465 STDMETHODIMP WBPassthru::UnlockRequest() |
| 472 { | 466 { |
| 473 if (!m_hasOriginalStartCalled) | 467 if (!m_hasOriginalStartCalled) |
| 474 { | 468 { |
| 475 return S_OK; | 469 return S_OK; |
| 476 } | 470 } |
| 477 return BaseClass::UnlockRequest(); | 471 return BaseClass::UnlockRequest(); |
| 478 } | 472 } |
| LEFT | RIGHT |