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.

692 lines
23 KiB

  1. /******************************************************************************
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. Connectivity
  5. Abstract:
  6. This file contains the implementation of the MPC::Connectitivy classes,
  7. that are capable to check the real state of the connection with the internet.
  8. Revision History:
  9. Davide Massarenti (Dmassare) 10/19/2000
  10. created
  11. ******************************************************************************/
  12. #include "stdafx.h"
  13. #include <process.h>
  14. #include <wininet.h>
  15. #include <Iphlpapi.h>
  16. #include <Winsock2.h>
  17. #include <inetreg.h>
  18. ////////////////////////////////////////////////////////////////////////////////
  19. //
  20. // This structure is defined in WinINET.h in terms of TCHAR, but it's wrong, it should be CHAR...
  21. //
  22. typedef struct {
  23. //
  24. // dwAccessType - INTERNET_OPEN_TYPE_DIRECT, INTERNET_OPEN_TYPE_PROXY, or
  25. // INTERNET_OPEN_TYPE_PRECONFIG (set only)
  26. //
  27. DWORD dwAccessType;
  28. //
  29. // lpszProxy - proxy server list
  30. //
  31. LPCSTR lpszProxy;
  32. //
  33. // lpszProxyBypass - proxy bypass list
  34. //
  35. LPCSTR lpszProxyBypass;
  36. } INTERNET_PROXY_INFOA;
  37. ////////////////////////////////////////////////////////////////////////////////
  38. static const WCHAR c_szIESettings [] = TSZWININETPATH;
  39. static const WCHAR c_szIESettings_Proxy [] = REGSTR_VAL_PROXYSERVER;
  40. static const WCHAR c_szIESettings_ProxyBypass[] = REGSTR_VAL_PROXYOVERRIDE;
  41. static const WCHAR c_szIEConnections [] = TSZWININETPATH L"\\Connections";
  42. static const WCHAR c_szIEConnections_Settings[] = L"DefaultConnectionSettings";
  43. ////////////////////////////////////////////////////////////////////////////////
  44. static HRESULT local_GetDWORD( /*[in/out]*/ BYTE*& pBuf ,
  45. /*[in/out]*/ DWORD& dwSize ,
  46. /*[out ]*/ DWORD& dwValue )
  47. {
  48. if(dwSize < sizeof(DWORD)) return E_FAIL;
  49. ::CopyMemory( &dwValue, pBuf, sizeof(DWORD) );
  50. dwSize -= sizeof(DWORD);
  51. pBuf += sizeof(DWORD);
  52. return S_OK;
  53. }
  54. static HRESULT local_GetSTRING( /*[in/out]*/ BYTE*& pBuf ,
  55. /*[in/out]*/ DWORD& dwSize ,
  56. /*[out ]*/ MPC::string& strValue )
  57. {
  58. DWORD dwLen;
  59. HRESULT hr;
  60. if(FAILED(hr = local_GetDWORD( pBuf, dwSize, dwLen ))) return hr;
  61. if(dwSize < dwLen) return E_FAIL;
  62. strValue.append( (char*)pBuf, (char*)&pBuf[dwLen] );
  63. dwSize -= dwLen;
  64. pBuf += dwLen;
  65. return S_OK;
  66. }
  67. static HRESULT local_GetProxyData( /*[in ]*/ BYTE* pBuf ,
  68. /*[in ]*/ DWORD dwSize ,
  69. /*[out]*/ DWORD& dwCurrentSettingsVersion ,
  70. /*[out]*/ DWORD& dwFlags ,
  71. /*[out]*/ DWORD& dwAccessType ,
  72. /*[out]*/ MPC::string& strProxy ,
  73. /*[out]*/ MPC::string& strProxyBypass )
  74. {
  75. __MPC_FUNC_ENTRY( COMMONID, "MPC::Connectitivy::Proxy GetProxyData" );
  76. HRESULT hr;
  77. DWORD dwStructSize;
  78. __MPC_EXIT_IF_METHOD_FAILS(hr, local_GetDWORD( pBuf, dwSize, dwStructSize )); //if(dwStructSize != 0x3C) __MPC_SET_ERROR_AND_EXIT(hr, E_FAIL);
  79. __MPC_EXIT_IF_METHOD_FAILS(hr, local_GetDWORD( pBuf, dwSize, dwCurrentSettingsVersion ));
  80. __MPC_EXIT_IF_METHOD_FAILS(hr, local_GetDWORD( pBuf, dwSize, dwFlags ));
  81. if(dwFlags & PROXY_TYPE_PROXY)
  82. {
  83. dwAccessType = INTERNET_OPEN_TYPE_PROXY;
  84. __MPC_EXIT_IF_METHOD_FAILS(hr, local_GetSTRING( pBuf, dwSize, strProxy ));
  85. __MPC_EXIT_IF_METHOD_FAILS(hr, local_GetSTRING( pBuf, dwSize, strProxyBypass ));
  86. }
  87. else if(dwFlags & PROXY_TYPE_DIRECT)
  88. {
  89. dwAccessType = INTERNET_OPEN_TYPE_DIRECT;
  90. }
  91. else
  92. {
  93. dwAccessType = INTERNET_OPEN_TYPE_PRECONFIG;
  94. }
  95. hr = S_OK;
  96. __MPC_FUNC_CLEANUP;
  97. if(FAILED(hr))
  98. {
  99. dwAccessType = 0;
  100. strProxy = "";
  101. strProxyBypass = "";
  102. }
  103. __MPC_FUNC_EXIT(hr);
  104. }
  105. ////////////////////////////////////////
  106. MPC::Connectivity::Proxy::Proxy()
  107. {
  108. m_fInitialized = false; // bool m_fInitialized;
  109. //
  110. // MPC::string m_strProxy;
  111. // MPC::string m_strProxyBypass;
  112. // CComHGLOBAL m_hgConnection;
  113. }
  114. MPC::Connectivity::Proxy::~Proxy()
  115. {
  116. }
  117. ////////////////////
  118. HRESULT MPC::Connectivity::Proxy::Initialize( /*[in]*/ bool fImpersonate )
  119. {
  120. __MPC_FUNC_ENTRY( COMMONID, "MPC::Connectivity::Proxy::Initialize" );
  121. HRESULT hr;
  122. MPC::Impersonation imp;
  123. MPC::RegKey rk;
  124. DWORD dwSize;
  125. DWORD dwType;
  126. bool fFound;
  127. if(fImpersonate)
  128. {
  129. __MPC_EXIT_IF_METHOD_FAILS(hr, imp.Initialize ());
  130. __MPC_EXIT_IF_METHOD_FAILS(hr, imp.Impersonate());
  131. }
  132. __MPC_EXIT_IF_METHOD_FAILS(hr, rk.SetRoot( HKEY_CURRENT_USER, KEY_READ ));
  133. __MPC_EXIT_IF_METHOD_FAILS(hr, rk.Attach( c_szIESettings ));
  134. __MPC_EXIT_IF_METHOD_FAILS(hr, rk.Read ( m_strProxy , fFound, c_szIESettings_Proxy ));
  135. __MPC_EXIT_IF_METHOD_FAILS(hr, rk.Read ( m_strProxyBypass, fFound, c_szIESettings_ProxyBypass ));
  136. __MPC_EXIT_IF_METHOD_FAILS(hr, rk.Attach ( c_szIEConnections ));
  137. __MPC_EXIT_IF_METHOD_FAILS(hr, rk.ReadDirect( c_szIEConnections_Settings, m_hgConnection, dwSize, dwType, fFound ));
  138. m_fInitialized = true;
  139. hr = S_OK;
  140. __MPC_FUNC_CLEANUP;
  141. __MPC_FUNC_EXIT(hr);
  142. }
  143. HRESULT MPC::Connectivity::Proxy::Apply( /*[in]*/ HINTERNET hSession )
  144. {
  145. __MPC_FUNC_ENTRY( COMMONID, "MPC::Connectivity::Proxy::Apply" );
  146. HRESULT hr;
  147. if(m_fInitialized)
  148. {
  149. DWORD dwSize = m_hgConnection.Size();
  150. if(m_strProxy.size() == 0 && dwSize)
  151. {
  152. DWORD dwCurrentSettingsVersion;
  153. DWORD dwFlags;
  154. DWORD dwAccessType;
  155. LPVOID ptr = m_hgConnection.Lock();
  156. if(FAILED(local_GetProxyData( (BYTE*)ptr, dwSize, dwCurrentSettingsVersion, dwFlags, dwAccessType, m_strProxy, m_strProxyBypass )))
  157. {
  158. //
  159. // Autoproxy cannot be set using the API, so we copy the whole registry value...
  160. //
  161. MPC::RegKey rk;
  162. __MPC_EXIT_IF_METHOD_FAILS(hr, rk.SetRoot ( HKEY_CURRENT_USER, KEY_ALL_ACCESS ));
  163. __MPC_EXIT_IF_METHOD_FAILS(hr, rk.Attach ( c_szIEConnections ));
  164. __MPC_EXIT_IF_METHOD_FAILS(hr, rk.WriteDirect( c_szIEConnections_Settings, ptr, dwSize, REG_BINARY ));
  165. }
  166. m_hgConnection.Unlock();
  167. }
  168. if(m_strProxy.size())
  169. {
  170. INTERNET_PROXY_INFOA info;
  171. info.dwAccessType = INTERNET_OPEN_TYPE_PROXY;
  172. info.lpszProxy = m_strProxy .c_str();
  173. info.lpszProxyBypass = m_strProxyBypass.c_str(); if(info.lpszProxyBypass[0] == 0) info.lpszProxyBypass = NULL;
  174. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::InternetSetOptionA( hSession, INTERNET_OPTION_PROXY, &info, sizeof(info) ));
  175. }
  176. }
  177. hr = S_OK;
  178. __MPC_FUNC_CLEANUP;
  179. __MPC_FUNC_EXIT(hr);
  180. }
  181. ////////////////////////////////////////
  182. HRESULT MPC::Connectivity::operator>>( /*[in]*/ MPC::Serializer& streamIn, /*[out]*/ MPC::Connectivity::Proxy& val )
  183. {
  184. __MPC_FUNC_ENTRY( COMMONID, "operator>> MPC::Connectivity::Proxy" );
  185. HRESULT hr;
  186. __MPC_EXIT_IF_METHOD_FAILS(hr, streamIn >> val.m_fInitialized );
  187. __MPC_EXIT_IF_METHOD_FAILS(hr, streamIn >> val.m_strProxy );
  188. __MPC_EXIT_IF_METHOD_FAILS(hr, streamIn >> val.m_strProxyBypass);
  189. __MPC_EXIT_IF_METHOD_FAILS(hr, streamIn >> val.m_hgConnection );
  190. hr = S_OK;
  191. __MPC_FUNC_CLEANUP;
  192. __MPC_FUNC_EXIT(hr);
  193. }
  194. HRESULT MPC::Connectivity::operator<<( /*[in]*/ MPC::Serializer& streamOut, /*[in ]*/ const MPC::Connectivity::Proxy& val )
  195. {
  196. __MPC_FUNC_ENTRY( COMMONID, "operator<< MPC::Connectivity::Proxy" );
  197. HRESULT hr;
  198. __MPC_EXIT_IF_METHOD_FAILS(hr, streamOut << val.m_fInitialized );
  199. __MPC_EXIT_IF_METHOD_FAILS(hr, streamOut << val.m_strProxy );
  200. __MPC_EXIT_IF_METHOD_FAILS(hr, streamOut << val.m_strProxyBypass);
  201. __MPC_EXIT_IF_METHOD_FAILS(hr, streamOut << val.m_hgConnection );
  202. hr = S_OK;
  203. __MPC_FUNC_CLEANUP;
  204. __MPC_FUNC_EXIT(hr);
  205. }
  206. ////////////////////////////////////////////////////////////////////////////////
  207. ////////////////////////////////////////////////////////////////////////////////
  208. MPC::Connectivity::WinInetTimeout::WinInetTimeout( /*[in]*/ MPC::CComSafeAutoCriticalSection& cs, /*[in]*/ HINTERNET& hReq ) : m_cs( cs ), m_hReq( hReq )
  209. {
  210. // MPC::CComSafeAutoCriticalSection& m_cs;
  211. // HINTERNET& m_hReq;
  212. m_hTimer = INVALID_HANDLE_VALUE; // HANDLE m_hTimer;
  213. m_dwTimeout = 0; // DWORD m_dwTimeout;
  214. //
  215. // INTERNET_STATUS_CALLBACK m_PreviousCallback;
  216. m_PreviousContext = NULL; // DWORD_PTR m_PreviousContext;
  217. #ifdef _IA64_
  218. m_PreviousCallback = INTERNET_INVALID_STATUS_CALLBACK;
  219. #else
  220. m_PreviousCallback = ::InternetSetStatusCallback( m_hReq, InternetStatusCallback );
  221. if(m_PreviousCallback != INTERNET_INVALID_STATUS_CALLBACK)
  222. {
  223. DWORD_PTR dwContext = (DWORD_PTR)this;
  224. DWORD dwSize = sizeof(m_PreviousContext);
  225. ::InternetQueryOptionW( m_hReq, INTERNET_OPTION_CONTEXT_VALUE, &m_PreviousContext, &dwSize );
  226. ::InternetSetOptionW ( m_hReq, INTERNET_OPTION_CONTEXT_VALUE, &dwContext , sizeof(dwContext) );
  227. }
  228. #endif
  229. }
  230. MPC::Connectivity::WinInetTimeout::~WinInetTimeout()
  231. {
  232. if(m_hReq)
  233. {
  234. if(m_PreviousCallback != INTERNET_INVALID_STATUS_CALLBACK)
  235. {
  236. ::InternetSetOptionW ( m_hReq, INTERNET_OPTION_CONTEXT_VALUE, &m_PreviousContext, sizeof(m_PreviousContext) );
  237. ::InternetSetStatusCallback( m_hReq, m_PreviousCallback );
  238. }
  239. }
  240. (void)Reset();
  241. }
  242. VOID CALLBACK MPC::Connectivity::WinInetTimeout::TimerFunction( PVOID lpParameter, BOOLEAN TimerOrWaitFired )
  243. {
  244. WinInetTimeout* pThis = (WinInetTimeout*)lpParameter;
  245. pThis->m_cs.Lock();
  246. if(pThis->m_hReq)
  247. {
  248. ::InternetCloseHandle( pThis->m_hReq ); pThis->m_hReq = NULL;
  249. }
  250. pThis->m_cs.Unlock();
  251. }
  252. VOID CALLBACK MPC::Connectivity::WinInetTimeout::InternetStatusCallback( HINTERNET hInternet ,
  253. DWORD_PTR dwContext ,
  254. DWORD dwInternetStatus ,
  255. LPVOID lpvStatusInformation ,
  256. DWORD dwStatusInformationLength )
  257. {
  258. WinInetTimeout* pThis = (WinInetTimeout*)dwContext;
  259. pThis->m_cs.Lock();
  260. if(dwInternetStatus == INTERNET_STATUS_DETECTING_PROXY)
  261. {
  262. pThis->InternalReset();
  263. }
  264. else
  265. {
  266. if(pThis->m_hTimer == INVALID_HANDLE_VALUE)
  267. {
  268. (void)pThis->InternalSet();
  269. }
  270. }
  271. pThis->m_cs.Unlock();
  272. }
  273. HRESULT MPC::Connectivity::WinInetTimeout::InternalSet()
  274. {
  275. __MPC_FUNC_ENTRY( COMMONID, "MPC::Connectivity::WinInetTimeout::InternalSet" );
  276. HRESULT hr;
  277. if(m_dwTimeout)
  278. {
  279. if(m_hTimer != INVALID_HANDLE_VALUE)
  280. {
  281. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::ChangeTimerQueueTimer( NULL, m_hTimer, m_dwTimeout, 0 ));
  282. }
  283. else
  284. {
  285. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::CreateTimerQueueTimer( &m_hTimer, NULL, TimerFunction, this, m_dwTimeout, 0, WT_EXECUTEINTIMERTHREAD ));
  286. }
  287. }
  288. hr = S_OK;
  289. __MPC_FUNC_CLEANUP;
  290. __MPC_FUNC_EXIT(hr);
  291. }
  292. HRESULT MPC::Connectivity::WinInetTimeout::InternalReset()
  293. {
  294. __MPC_FUNC_ENTRY( COMMONID, "MPC::Connectivity::WinInetTimeout::InternalReset" );
  295. HRESULT hr;
  296. if(m_hTimer != INVALID_HANDLE_VALUE)
  297. {
  298. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::DeleteTimerQueueTimer( NULL, m_hTimer, INVALID_HANDLE_VALUE ));
  299. m_hTimer = INVALID_HANDLE_VALUE;
  300. }
  301. hr = S_OK;
  302. __MPC_FUNC_CLEANUP;
  303. __MPC_FUNC_EXIT(hr);
  304. }
  305. HRESULT MPC::Connectivity::WinInetTimeout::Set( /*[in]*/ DWORD dwTimeout )
  306. {
  307. HRESULT hr;
  308. m_cs.Lock();
  309. if(SUCCEEDED(hr = InternalReset()))
  310. {
  311. m_dwTimeout = dwTimeout;
  312. hr = InternalSet();
  313. }
  314. m_cs.Unlock();
  315. return hr;
  316. }
  317. HRESULT MPC::Connectivity::WinInetTimeout::Reset()
  318. {
  319. HRESULT hr;
  320. m_cs.Lock();
  321. if(SUCCEEDED(hr = InternalReset()))
  322. {
  323. m_dwTimeout = 0;
  324. }
  325. m_cs.Unlock();
  326. return hr;
  327. }
  328. ////////////////////////////////////////////////////////////////////////////////
  329. ////////////////////////////////////////////////////////////////////////////////
  330. static WCHAR s_DefaultDestination[] = L"http://www.microsoft.com";
  331. static LPCWSTR s_AcceptTypes [] = { L"*/*", NULL }; // */
  332. ////////////////////////////////////////////////////////////////////////////////
  333. HRESULT MPC::Connectivity::NetworkAlive( /*[in]*/ DWORD dwTimeout, /*[in]*/ MPC::Connectivity::Proxy* pProxy )
  334. {
  335. //
  336. // Try to contact Microsoft.
  337. //
  338. return DestinationReachable( s_DefaultDestination, dwTimeout, pProxy );
  339. }
  340. HRESULT MPC::Connectivity::DestinationReachable( /*[in]*/ LPCWSTR szDestination, /*[in]*/ DWORD dwTimeout, /*[in]*/ MPC::Connectivity::Proxy* pProxy )
  341. {
  342. __MPC_FUNC_ENTRY( COMMONID, "MPC::Connectivity::DestinationReachable" );
  343. HRESULT hr;
  344. MPC::URL url;
  345. INTERNET_SCHEME nScheme;
  346. MPC::wstring strScheme;
  347. MPC::wstring strHostName;
  348. DWORD dwPort;
  349. MPC::wstring strUrlPath;
  350. MPC::wstring strExtraInfo;
  351. HINTERNET hInternet = NULL;
  352. HINTERNET hConnect = NULL;
  353. HINTERNET hOpenRequest = NULL;
  354. DWORD dwLength;
  355. DWORD dwStatus;
  356. DWORD dwFlags;
  357. __MPC_PARAMCHECK_BEGIN(hr)
  358. __MPC_PARAMCHECK_STRING_NOT_EMPTY(szDestination);
  359. __MPC_PARAMCHECK_END();
  360. //
  361. // If there's no connection or we are in offline more, abort.
  362. //
  363. {
  364. DWORD dwConnMethod;
  365. if(!::InternetGetConnectedState( &dwConnMethod, 0 ) ||
  366. (dwConnMethod & INTERNET_CONNECTION_OFFLINE) )
  367. {
  368. __MPC_SET_WIN32_ERROR_AND_EXIT(hr, ERROR_INTERNET_DISCONNECTED);
  369. }
  370. }
  371. __MPC_EXIT_IF_METHOD_FAILS(hr, url.put_URL( szDestination ));
  372. __MPC_EXIT_IF_METHOD_FAILS(hr, url.get_Scheme ( nScheme ));
  373. __MPC_EXIT_IF_METHOD_FAILS(hr, url.get_Scheme ( strScheme ));
  374. __MPC_EXIT_IF_METHOD_FAILS(hr, url.get_HostName ( strHostName ));
  375. __MPC_EXIT_IF_METHOD_FAILS(hr, url.get_Port ( dwPort )); if(!dwPort) dwPort = INTERNET_DEFAULT_HTTP_PORT;
  376. __MPC_EXIT_IF_METHOD_FAILS(hr, url.get_Path ( strUrlPath ));
  377. __MPC_EXIT_IF_METHOD_FAILS(hr, url.get_ExtraInfo( strExtraInfo )); strUrlPath += strExtraInfo;
  378. //
  379. // If not a supported URL, just exit.
  380. //
  381. if(strScheme .size() == 0 ||
  382. strHostName.size() == 0 )
  383. {
  384. __MPC_SET_ERROR_AND_EXIT(hr, E_INVALIDARG);
  385. }
  386. if(nScheme != INTERNET_SCHEME_HTTP &&
  387. nScheme != INTERNET_SCHEME_HTTPS )
  388. {
  389. __MPC_SET_ERROR_AND_EXIT(hr, E_INVALIDARG);
  390. }
  391. dwFlags = INTERNET_FLAG_NO_CACHE_WRITE |
  392. INTERNET_FLAG_PRAGMA_NOCACHE |
  393. INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP | // ex: https:// to http://
  394. INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS | // ex: http:// to https://
  395. INTERNET_FLAG_IGNORE_CERT_DATE_INVALID | // expired X509 Cert.
  396. INTERNET_FLAG_IGNORE_CERT_CN_INVALID ; // bad common name in X509 Cert.
  397. if(nScheme == INTERNET_SCHEME_HTTPS)
  398. {
  399. dwFlags |= INTERNET_FLAG_SECURE;
  400. }
  401. ////////////////////////////////////////////////////////////////////////////////
  402. //
  403. // Get handle to a connection
  404. //
  405. __MPC_EXIT_IF_CALL_RETURNS_NULL(hr, (hInternet = ::InternetOpenW( L"HelpSupportServices" ,
  406. INTERNET_OPEN_TYPE_PRECONFIG ,
  407. NULL ,
  408. NULL ,
  409. 0 )));
  410. //
  411. // Optional proxy settings override.
  412. //
  413. if(pProxy)
  414. {
  415. __MPC_EXIT_IF_METHOD_FAILS(hr, pProxy->Apply( hInternet ));
  416. }
  417. //
  418. // Connect
  419. //
  420. __MPC_EXIT_IF_CALL_RETURNS_NULL(hr, (hConnect = ::InternetConnectW( hInternet ,
  421. strHostName.c_str() ,
  422. dwPort ,
  423. NULL ,
  424. NULL ,
  425. INTERNET_SERVICE_HTTP ,
  426. INTERNET_FLAG_NO_UI ,
  427. 0 )));
  428. for(int pass=0; pass<2; pass++)
  429. {
  430. //
  431. // Create a request to get the header for the page.
  432. //
  433. __MPC_EXIT_IF_CALL_RETURNS_NULL(hr, (hOpenRequest = ::HttpOpenRequestW( hConnect ,
  434. pass == 0 ? L"HEAD" : L"GET" ,
  435. strUrlPath.c_str() ,
  436. L"HTTP/1.0" , // 1.0 to get filesize and time
  437. NULL , // referer
  438. s_AcceptTypes ,
  439. dwFlags ,
  440. 0 )));
  441. //
  442. // Because WinINET timeout support has always been broken, we have to use an external timer to close the request object. This effectively will abort the request.
  443. //
  444. {
  445. MPC::CComSafeAutoCriticalSection cs;
  446. MPC::Connectivity::WinInetTimeout to( cs, hOpenRequest );
  447. if(dwTimeout != INFINITE)
  448. {
  449. __MPC_EXIT_IF_METHOD_FAILS(hr, to.Set( dwTimeout ));
  450. }
  451. //
  452. // Send request to get request
  453. //
  454. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::HttpSendRequestW( hOpenRequest, NULL, 0, NULL, 0 ));
  455. }
  456. if(hOpenRequest == NULL)
  457. {
  458. __MPC_SET_WIN32_ERROR_AND_EXIT(hr, ERROR_INTERNET_DISCONNECTED);
  459. }
  460. //
  461. // We have sent the request so now check the status and see if the
  462. // request returned a proper status code as a 32 bit number
  463. //
  464. dwLength = sizeof(dwStatus);
  465. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::HttpQueryInfoW( hOpenRequest ,
  466. HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER ,
  467. (LPVOID)&dwStatus ,
  468. &dwLength ,
  469. NULL ));
  470. //
  471. // Check status and if not OK then fail. If the status is OK this means
  472. // that the object/file is on the server and is reachable to be viewed
  473. // by downloading to the user
  474. //
  475. if(dwStatus < 400) break;
  476. if(pass == 1)
  477. {
  478. switch(dwStatus)
  479. {
  480. case HTTP_STATUS_BAD_REQUEST : break;
  481. case HTTP_STATUS_DENIED : break;
  482. case HTTP_STATUS_PAYMENT_REQ : break;
  483. case HTTP_STATUS_FORBIDDEN : break;
  484. case HTTP_STATUS_NOT_FOUND : __MPC_SET_WIN32_ERROR_AND_EXIT(hr, ERROR_FILE_NOT_FOUND);
  485. case HTTP_STATUS_BAD_METHOD : break;
  486. case HTTP_STATUS_NONE_ACCEPTABLE : break;
  487. case HTTP_STATUS_PROXY_AUTH_REQ : break;
  488. case HTTP_STATUS_REQUEST_TIMEOUT : __MPC_SET_WIN32_ERROR_AND_EXIT(hr, ERROR_INTERNET_DISCONNECTED);
  489. case HTTP_STATUS_CONFLICT : break;
  490. case HTTP_STATUS_GONE : __MPC_SET_WIN32_ERROR_AND_EXIT(hr, ERROR_FILE_NOT_FOUND);
  491. case HTTP_STATUS_LENGTH_REQUIRED : break;
  492. case HTTP_STATUS_PRECOND_FAILED : break;
  493. case HTTP_STATUS_REQUEST_TOO_LARGE: break;
  494. case HTTP_STATUS_URI_TOO_LONG : break;
  495. case HTTP_STATUS_UNSUPPORTED_MEDIA: break;
  496. case HTTP_STATUS_RETRY_WITH : break;
  497. case HTTP_STATUS_SERVER_ERROR : break;
  498. case HTTP_STATUS_NOT_SUPPORTED : break;
  499. case HTTP_STATUS_BAD_GATEWAY : __MPC_SET_WIN32_ERROR_AND_EXIT(hr, ERROR_FILE_NOT_FOUND);
  500. case HTTP_STATUS_SERVICE_UNAVAIL : __MPC_SET_WIN32_ERROR_AND_EXIT(hr, ERROR_FILE_NOT_FOUND);
  501. case HTTP_STATUS_GATEWAY_TIMEOUT : __MPC_SET_WIN32_ERROR_AND_EXIT(hr, ERROR_INTERNET_DISCONNECTED);
  502. case HTTP_STATUS_VERSION_NOT_SUP : break;
  503. }
  504. }
  505. ::InternetCloseHandle( hOpenRequest ); hOpenRequest = NULL;
  506. }
  507. hr = S_OK;
  508. __MPC_FUNC_CLEANUP;
  509. if(hOpenRequest) ::InternetCloseHandle( hOpenRequest );
  510. if(hInternet ) ::InternetCloseHandle( hInternet );
  511. if(hConnect ) ::InternetCloseHandle( hConnect );
  512. __MPC_FUNC_EXIT(hr);
  513. }