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.

750 lines
25 KiB

  1. /*****************************************************************************\
  2. * MODULE: anycon.cxx
  3. *
  4. * The module contains the base class for connections
  5. *
  6. * Copyright (C) 1997-1998 Microsoft Corporation
  7. *
  8. * History:
  9. * 07/31/98 Weihaic Created
  10. *
  11. \*****************************************************************************/
  12. #include "precomp.h"
  13. #include "priv.h"
  14. /******************************************************************************
  15. * Class Data Static Members
  16. *****************************************************************************/
  17. const DWORD CAnyConnection::gm_dwConnectTimeout = 30000; // Thirty second timeout on connect
  18. const DWORD CAnyConnection::gm_dwSendTimeout = 30000; // Thirty timeout on send timeout
  19. const DWORD CAnyConnection::gm_dwReceiveTimeout = 60000; // Thirty seconds on receive timeout
  20. const DWORD CAnyConnection::gm_dwSendSize = 0x10000; // We use a 16K sections when sending
  21. // data through WININET
  22. extern BOOL Ping (LPTSTR pszServerName);
  23. CAnyConnection::CAnyConnection (
  24. BOOL bSecure,
  25. INTERNET_PORT nServerPort,
  26. BOOL bIgnoreSecurityDlg,
  27. DWORD dwAuthMethod):
  28. m_lpszPassword (NULL),
  29. m_lpszUserName (NULL),
  30. m_hSession (NULL),
  31. m_hConnect (NULL),
  32. m_dwAccessFlag (INTERNET_OPEN_TYPE_PRECONFIG),
  33. m_bSecure (bSecure),
  34. m_bShowSecDlg (FALSE),
  35. m_dwAuthMethod (dwAuthMethod),
  36. m_bIgnoreSecurityDlg (bIgnoreSecurityDlg),
  37. m_bValid (FALSE)
  38. {
  39. if (!nServerPort) {
  40. if (bSecure) {
  41. m_nServerPort = INTERNET_DEFAULT_HTTPS_PORT;
  42. }
  43. else {
  44. m_nServerPort = INTERNET_DEFAULT_HTTP_PORT;
  45. }
  46. }
  47. else
  48. m_nServerPort = nServerPort;
  49. m_bValid = TRUE;
  50. }
  51. CAnyConnection::~CAnyConnection ()
  52. {
  53. if (m_hConnect) {
  54. (void) CAnyConnection::Disconnect ();
  55. }
  56. if (m_hSession) {
  57. (void) CAnyConnection::CloseSession ();
  58. }
  59. LocalFree (m_lpszPassword);
  60. m_lpszPassword = NULL;
  61. LocalFree (m_lpszUserName);
  62. m_lpszUserName = NULL;
  63. }
  64. HINTERNET
  65. CAnyConnection::OpenSession ()
  66. {
  67. m_hSession = InetInternetOpen(g_szUserAgent,
  68. m_dwAccessFlag,
  69. NULL,
  70. NULL,
  71. #ifndef WINNT32
  72. INTERNET_FLAG_ASYNC);
  73. #else
  74. 0);
  75. #endif
  76. if (m_hSession) { // Set up the callback function if successful
  77. #ifndef WINNT32
  78. INTERNET_STATUS_CALLBACK dwISC;
  79. dwISC = InternetSetStatusCallback( m_hSession, CAsyncContext::InternetCallback );
  80. if (dwISC != NULL) {
  81. // We do not support chaining down to a previous callback, there should not
  82. // be one and if it fails it will also be non NULL, Set last error to invalid handle and
  83. // Clean Up
  84. SetLastError (ERROR_INVALID_HANDLE);
  85. goto Cleanup;
  86. }
  87. #endif
  88. // Also set an internet connection timeout for the session for when we try the
  89. // connection, should we do this instead of a ping?
  90. DWORD dwTimeout = gm_dwConnectTimeout;
  91. if (!InetInternetSetOption( m_hSession,
  92. INTERNET_OPTION_CONNECT_TIMEOUT,
  93. (LPVOID)&dwTimeout,
  94. sizeof(dwTimeout)
  95. ))
  96. goto Cleanup;
  97. // Now set the Send and Receive Timeout values
  98. dwTimeout = gm_dwSendTimeout;
  99. if (!InetInternetSetOption( m_hSession,
  100. INTERNET_OPTION_SEND_TIMEOUT,
  101. (LPVOID)&dwTimeout,
  102. sizeof(dwTimeout)
  103. ))
  104. goto Cleanup;
  105. dwTimeout = gm_dwReceiveTimeout;
  106. if (!InetInternetSetOption( m_hSession,
  107. INTERNET_OPTION_RECEIVE_TIMEOUT,
  108. (LPVOID)&dwTimeout,
  109. sizeof(dwTimeout)
  110. ))
  111. goto Cleanup;
  112. }
  113. return m_hSession;
  114. Cleanup:
  115. if (m_hSession) {
  116. InetInternetCloseHandle (m_hSession);
  117. m_hSession = NULL;
  118. }
  119. return m_hSession;
  120. }
  121. BOOL CAnyConnection::CloseSession ()
  122. {
  123. BOOL bRet = InetInternetCloseHandle (m_hSession);
  124. m_hSession = NULL;
  125. return bRet;
  126. }
  127. HINTERNET
  128. CAnyConnection::Connect(
  129. LPTSTR lpszServerName)
  130. {
  131. if (m_hSession) {
  132. // Ping the server if it is in the intranet to make sure that the server is online
  133. if (lpszServerName &&
  134. (_tcschr ( lpszServerName, TEXT ('.')) || Ping (lpszServerName) )) {
  135. m_hConnect = InetInternetConnect(m_hSession,
  136. lpszServerName,
  137. m_nServerPort,
  138. NULL,//m_lpszUserName,
  139. NULL, //m_lpszPassword,
  140. INTERNET_SERVICE_HTTP,
  141. 0,
  142. 0);
  143. }
  144. }
  145. return m_hConnect;
  146. }
  147. BOOL
  148. CAnyConnection::Disconnect ()
  149. {
  150. BOOL bRet = InetInternetCloseHandle (m_hConnect);
  151. m_hConnect = NULL;
  152. return bRet;
  153. }
  154. HINTERNET
  155. CAnyConnection::OpenRequest (
  156. LPTSTR lpszUrl)
  157. {
  158. HINTERNET hReq = NULL;
  159. DWORD dwFlags;
  160. if (m_hConnect) {
  161. // We need to create an Asynchronous Context for the Rest of the operations to use,
  162. // passing this in of course makes this request also asynchronous
  163. WIN9X_NEW_ASYNC( pacSync );
  164. WIN9X_IF_ASYNC( pacSync )
  165. WIN9X_IF_ASYNC( pacSync->bValid() ) {
  166. hReq = InetHttpOpenRequest(m_hConnect,
  167. g_szPOST,
  168. lpszUrl,
  169. g_szHttpVersion,
  170. NULL,
  171. NULL,
  172. INETPP_REQ_FLAGS | (m_bSecure? INTERNET_FLAG_SECURE:0),
  173. WIN9X_CONTEXT_ASYNC(pacSync));
  174. } WIN9X_ELSE_ASYNC( delete pacSync );
  175. }
  176. return hReq;
  177. }
  178. BOOL
  179. CAnyConnection::CloseRequest (HINTERNET hReq)
  180. { // BUG: We have to close the handle manually, since WININET seems not to be giving us
  181. // an INTERNET_STATUS_HANDLE_CLOSING message
  182. BOOL bSuccess;
  183. WIN9X_GET_ASYNC( pacSync, hReq );
  184. bSuccess = InetInternetCloseHandle (hReq); // When this handle is closed, the context will be closed
  185. WIN9X_IF_ASYNC(pacSync) WIN9X_OP_ASYNC(delete pacSync;)
  186. return bSuccess;
  187. }
  188. BOOL
  189. CAnyConnection::SendRequest(
  190. HINTERNET hReq,
  191. LPCTSTR lpszHdr,
  192. DWORD cbData,
  193. LPBYTE pidi)
  194. {
  195. BOOL bRet = FALSE;
  196. CMemStream *pStream;
  197. pStream = new CMemStream (pidi, cbData);
  198. if (pStream && pStream->bValid ()){
  199. bRet = SendRequest (hReq, lpszHdr, pStream);
  200. }
  201. if (pStream) {
  202. delete pStream;
  203. }
  204. return bRet;
  205. }
  206. BOOL CAnyConnection::SendRequest(
  207. HINTERNET hReq,
  208. LPCTSTR lpszHdr,
  209. CStream *pStream)
  210. {
  211. BOOL bRet = FALSE;
  212. DWORD dwStatus;
  213. DWORD cbStatus = sizeof(dwStatus);
  214. BOOL bRetry = FALSE;
  215. DWORD dwRetryCount = 0;
  216. BOOL bShowUI = FALSE;
  217. DWORD cbData;
  218. PBYTE pBuf = NULL;
  219. DWORD cbRead;
  220. if (!pStream->GetTotalSize (&cbData))
  221. return FALSE;
  222. pBuf = new BYTE[gm_dwSendSize];
  223. if (!pBuf)
  224. return FALSE;
  225. #define MAX_RETRY 3
  226. do {
  227. BOOL bSuccess = FALSE;
  228. BOOL bLeave;
  229. WIN9X_GET_ASYNC( pacSync, hReq );
  230. WIN9X_IF_ASYNC (!pacSync) WIN9X_BREAK_ASYNC(FALSE);
  231. if (cbData < gm_dwSendSize) {
  232. if (pStream->Reset() &&
  233. pStream->Read (pBuf, cbData, &cbRead) && cbRead == cbData) {
  234. // If what we want to send is small, we send it with HttpSendRequest and not
  235. // HttpSendRequestEx, this is to wotk around a problem where we get timeouts on
  236. // receive on very small data transactions
  237. bSuccess = InetHttpSendRequest(hReq,
  238. lpszHdr,
  239. (lpszHdr ? (DWORD)-1 : 0),
  240. pBuf,
  241. cbData);
  242. (void) WIN9X_TIMEOUT_ASYNC(pacSync, bSuccess);
  243. }
  244. } else {
  245. do {
  246. BOOL bSuccessSend;
  247. // The timeout value for the packets applies for an entire session, so, instead of sending in
  248. // one chuck, we have to send in smaller chunks
  249. INTERNET_BUFFERS BufferIn;
  250. bLeave = TRUE;
  251. BufferIn.dwStructSize = sizeof( INTERNET_BUFFERS );
  252. BufferIn.Next = NULL;
  253. BufferIn.lpcszHeader = lpszHdr;
  254. if (lpszHdr)
  255. BufferIn.dwHeadersLength = sizeof(TCHAR)*lstrlen(lpszHdr);
  256. else
  257. BufferIn.dwHeadersLength = 0;
  258. BufferIn.dwHeadersTotal = 1; // There is one header to send
  259. BufferIn.lpvBuffer = NULL; // We defer this to the multiple write side
  260. BufferIn.dwBufferLength = 0; // The total buffer length
  261. BufferIn.dwBufferTotal = cbData; // This is the size of the data we are about to send
  262. BufferIn.dwOffsetLow = 0; // No offset into the buffers
  263. BufferIn.dwOffsetHigh = 0;
  264. // Since we will only ever be sending one request per hReq handle, we can associate
  265. // the context with all of these operations
  266. bSuccess = InetHttpSendRequestEx (hReq,
  267. &BufferIn,
  268. NULL,
  269. 0,
  270. WIN9X_CONTEXT_ASYNC(pacSync));
  271. (void) WIN9X_TIMEOUT_ASYNC(pacSync, bSuccess );
  272. if (bSuccess) {
  273. bSuccess = pStream->Reset();
  274. }
  275. DWORD dwBufPos = 0; // This is our current point in the buffer
  276. DWORD dwRemaining = cbData; // These are the number of bytes left to send
  277. bSuccessSend = bSuccess;
  278. while (bSuccess && dwRemaining) { // While we have data to send and the operations are
  279. // successful
  280. DWORD dwWrite = min( dwRemaining, gm_dwSendSize); // The amount to write
  281. DWORD dwWritten; // The amount actually written
  282. if (pStream->Read (pBuf, dwWrite, &cbRead) && cbRead == dwWrite) {
  283. bSuccess = InetInternetWriteFile (hReq, pBuf, dwWrite, &dwWritten);
  284. (void) WIN9X_TIMEOUT_ASYNC(pacSync, bSuccess ); // Wait for the operation to actually happen
  285. if (bSuccess) {
  286. bSuccess = dwWritten ? TRUE : FALSE;
  287. dwRemaining -= dwWritten; // Remaining amount decreases by this
  288. dwBufPos += dwWritten; // Advance through the buffer
  289. if (dwWritten != dwWrite) {
  290. // We need to adjust the pointer, since not all the bytes are
  291. // successfully sent to the server
  292. //
  293. bSuccess = pStream->SetPtr (dwBufPos);
  294. }
  295. }
  296. }
  297. else
  298. bSuccess = FALSE;
  299. }
  300. BOOL bEndSuccess = FALSE;
  301. if (bSuccessSend) { // We started the request successfully, so we can end it successfully
  302. bEndSuccess = InetHttpEndRequest (hReq,
  303. NULL,
  304. 0,
  305. WIN9X_CONTEXT_ASYNC(pacSync));
  306. (void) WIN9X_TIMEOUT_ASYNC(pacSync, bEndSuccess );
  307. }
  308. if (!bEndSuccess && GetLastError() == ERROR_INTERNET_FORCE_RETRY)
  309. bLeave = FALSE;
  310. bSuccess = bSuccess && bEndSuccess && bSuccessSend;
  311. } while (!bLeave);
  312. }
  313. if (bSuccess) {
  314. if ( InetHttpQueryInfo(hReq,
  315. HTTP_QUERY_FLAG_NUMBER | HTTP_QUERY_STATUS_CODE,
  316. &dwStatus,
  317. &cbStatus,
  318. NULL) ) {
  319. switch (dwStatus) {
  320. case HTTP_STATUS_DENIED:
  321. case HTTP_STATUS_PROXY_AUTH_REQ:
  322. SetLastError (ERROR_ACCESS_DENIED);
  323. break;
  324. case HTTP_STATUS_FORBIDDEN:
  325. SetLastError (HTTP_STATUS_FORBIDDEN);
  326. break;
  327. case HTTP_STATUS_OK:
  328. bRet = TRUE;
  329. break;
  330. case HTTP_STATUS_SERVER_ERROR:
  331. DBG_MSG(DBG_LEV_ERROR, (TEXT("CAnyConnection::SendRequest : HTTP_STATUS_SERVER_ERROR")));
  332. SetLastError (ERROR_INVALID_PRINTER_NAME);
  333. break;
  334. default:
  335. if ((dwStatus >= HTTP_STATUS_BAD_REQUEST) &&
  336. (dwStatus < HTTP_STATUS_SERVER_ERROR)) {
  337. SetLastError(ERROR_INVALID_PRINTER_NAME);
  338. } else {
  339. // We get some other errors, but don't know how to handle it
  340. //
  341. DBG_MSG(DBG_LEV_ERROR, (TEXT("CAnyConnection::SendRequest : Unknown Error (%d)"), dwStatus));
  342. SetLastError (ERROR_INVALID_HANDLE);
  343. }
  344. break;
  345. }
  346. }
  347. }
  348. else {
  349. if (m_bSecure) {
  350. #if NEVER
  351. //
  352. // In the future, we need to change this part to call InternetQueryOption on
  353. // INTERNET_OPTION_SECURITY_CERTIFICATE_STRUCT
  354. // and pass it back to the client
  355. //
  356. LPTSTR szBuf[1024];
  357. DWORD dwSize = 1024;
  358. switch (GetLastError ()) {
  359. case ERROR_INTERNET_INVALID_CA:
  360. case ERROR_INTERNET_SEC_CERT_DATE_INVALID:
  361. case ERROR_INTERNET_SEC_CERT_CN_INVALID:
  362. if (InternetQueryOption(hReq,
  363. INTERNET_OPTION_SECURITY_CERTIFICATE,
  364. szBuf, &dwSize)) {
  365. DBG_MSG(DBG_LEV_WARN, (TEXT("Cert: %ws\n"), szBuf));
  366. break;
  367. }
  368. }
  369. #endif
  370. DWORD dwFlags = 0;
  371. DWORD dwRet;
  372. if (m_bShowSecDlg) {
  373. bShowUI = TRUE;
  374. dwRet = InetInternetErrorDlg (GetTopWindow (NULL),
  375. hReq,
  376. GetLastError(),
  377. FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS, NULL);
  378. if (dwRet == ERROR_SUCCESS || dwRet == ERROR_INTERNET_FORCE_RETRY) {
  379. bRetry = TRUE;
  380. }
  381. }
  382. else {
  383. switch (GetLastError ()) {
  384. case ERROR_INTERNET_INVALID_CA:
  385. dwFlags = SECURITY_FLAG_IGNORE_UNKNOWN_CA;
  386. break;
  387. default:
  388. // All other failure, try to ignore everything and retry
  389. dwFlags = SECURITY_FLAG_IGNORE_REVOCATION |
  390. SECURITY_FLAG_IGNORE_UNKNOWN_CA |
  391. SECURITY_FLAG_IGNORE_WRONG_USAGE |
  392. SECURITY_FLAG_IGNORE_CERT_CN_INVALID |
  393. SECURITY_FLAG_IGNORE_CERT_DATE_INVALID|
  394. SECURITY_FLAG_IGNORE_REDIRECT_TO_HTTPS |
  395. SECURITY_FLAG_IGNORE_REDIRECT_TO_HTTP ;
  396. break;
  397. }
  398. if (InetInternetSetOption(hReq,
  399. INTERNET_OPTION_SECURITY_FLAGS,
  400. &dwFlags,
  401. sizeof (DWORD))) {
  402. bRetry = TRUE;
  403. }
  404. }
  405. }
  406. }
  407. }
  408. while (bRetry && ++dwRetryCount < MAX_RETRY);
  409. if (!bRet && GetLastError () == ERROR_INTERNET_LOGIN_FAILURE)
  410. {
  411. SetLastError (ERROR_ACCESS_DENIED);
  412. }
  413. if (bShowUI) {
  414. // We only show the dialog once.
  415. m_bShowSecDlg = FALSE;
  416. }
  417. if (pBuf) {
  418. delete [] pBuf;
  419. }
  420. return bRet;
  421. }
  422. BOOL CAnyConnection::ReadFile (
  423. HINTERNET hReq,
  424. LPVOID lpvBuffer,
  425. DWORD cbBuffer,
  426. LPDWORD lpcbRd)
  427. {
  428. BOOL bSuccess;
  429. bSuccess = InetInternetReadFile(hReq, lpvBuffer, cbBuffer, lpcbRd);
  430. return WIN9X_WAIT_ASYNC( hReq, bSuccess );
  431. }
  432. BOOL CAnyConnection::SetPassword (
  433. HINTERNET hReq,
  434. LPTSTR lpszUserName,
  435. LPTSTR lpszPassword)
  436. {
  437. BOOL bRet = FALSE;
  438. TCHAR szNULL[] = TEXT ("");
  439. if (!lpszUserName) {
  440. lpszUserName = szNULL;
  441. }
  442. if (!lpszPassword) {
  443. lpszPassword = szNULL;
  444. }
  445. if ( InetInternetSetOption (hReq,
  446. INTERNET_OPTION_USERNAME,
  447. lpszUserName,
  448. (DWORD) (lstrlen(lpszUserName) + 1)) &&
  449. InetInternetSetOption (hReq,
  450. INTERNET_OPTION_PASSWORD,
  451. lpszPassword,
  452. (DWORD) (lstrlen(lpszPassword) + 1)) ) {
  453. bRet = TRUE;
  454. }
  455. return bRet;
  456. }
  457. BOOL CAnyConnection::GetAuthSchem (
  458. HINTERNET hReq,
  459. LPSTR lpszScheme,
  460. DWORD dwSize)
  461. {
  462. DWORD dwIndex = 0;
  463. return InetHttpQueryInfo(hReq, HTTP_QUERY_WWW_AUTHENTICATE, (LPVOID)lpszScheme, &dwSize, &dwIndex);
  464. }
  465. void CAnyConnection::SetShowSecurityDlg (
  466. BOOL bShowSecDlg)
  467. {
  468. m_bShowSecDlg = bShowSecDlg;
  469. }
  470. #ifndef WINNT32 // We use asynchronous code in this case
  471. /**********************************************************************************************
  472. ** Method - GetAsyncContext
  473. ** Description - Get the async context from the handle
  474. **********************************************************************************************/
  475. CAnyConnection::CAsyncContext *CAnyConnection::GetAsyncContext( IN HINTERNET hInternet ) {
  476. CAsyncContext *pacContext; // This is the context we wish to retrieve
  477. DWORD dwContextSize = sizeof(pacContext);
  478. if (InternetQueryOption( hInternet,
  479. INTERNET_OPTION_CONTEXT_VALUE,
  480. (LPBYTE)&pacContext,
  481. &dwContextSize ))
  482. return pacContext;
  483. else
  484. return NULL;
  485. }
  486. /**********************************************************************************************
  487. ** Method - AsynchronousWait
  488. ** Description - This is really a wrapper for the object asynchronous wait, we simply first
  489. ** get the object out of the context before we continue doing anything
  490. **********************************************************************************************/
  491. BOOL CAnyConnection::AsynchronousWait( IN HINTERNET hInternet, IN OUT BOOL &bSuccess) {
  492. // We get the context value from the internet handle
  493. CAsyncContext *pacContext; // This is the context we wish to retrieve
  494. if (bSuccess) return TRUE; // Saves having to get the context
  495. DWORD dwContextSize = sizeof(pacContext);
  496. if (InternetQueryOption( hInternet,
  497. INTERNET_OPTION_CONTEXT_VALUE,
  498. (LPBYTE)&pacContext,
  499. &dwContextSize ))
  500. return pacContext->TimeoutWait (bSuccess);
  501. else
  502. return bSuccess = FALSE;
  503. }
  504. #endif // #ifndef WINNT32
  505. #ifndef WINNT32
  506. /**********************************************************************************************
  507. ** Class Implementation - CAnyConnection::CAsyncContext
  508. **********************************************************************************************/
  509. /**********************************************************************************************
  510. ** Constructor - CAsyncContext
  511. ** Description - Create the Event Handle, set the point to the CAnyConnection and ensure
  512. ** that the two return values are correctly set
  513. ***********************************************************************************************/
  514. CAnyConnection::CAsyncContext::CAsyncContext(void) :
  515. m_dwRet (0),
  516. m_dwError (ERROR_SUCCESS),
  517. m_hEvent (NULL) {
  518. // Create an event with no inheritable security, automatic reset semantics, a non-signalled
  519. // initial state and no name
  520. m_hEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
  521. }
  522. /************************************************************************************************
  523. ** Destructor - CAsyncContext
  524. ** Description - Deallocate the event handle
  525. ************************************************************************************************/
  526. CAnyConnection::CAsyncContext::~CAsyncContext() {
  527. if (m_hEvent) CloseHandle(m_hEvent);
  528. }
  529. /************************************************************************************************
  530. ** Method - TimeoutWait
  531. ** Description - Wait on an event callback if the call was asynchronous, clear the event, the
  532. ** callback routine does the hard work, this one is for a bool
  533. ************************************************************************************************/
  534. BOOL CAnyConnection::CAsyncContext::TimeoutWait(IN OUT BOOL &bSuccess) {
  535. if (!bSuccess && GetLastError() == ERROR_IO_PENDING) { // The call was asynchronously deferred
  536. DWORD dwRet;
  537. dwRet = WaitForSingleObject( m_hEvent , INFINITE );
  538. // This is not a real infinite wait since the timeout has been set in WININET
  539. // The callback will signal us back when it is all done
  540. // The object was signalled
  541. // The m_dwRet value will have been set to indicate success or failure
  542. // if the synchronisation was wrong it will be set to 0, so also a failure
  543. bSuccess = (BOOL)m_dwRet;
  544. if (!bSuccess) SetLastError (m_dwError);
  545. else SetLastError(ERROR_SUCCESS);
  546. } else ResetEvent(m_hEvent);
  547. // Some events are synchronous, but still generate a callback, in this case the callback
  548. // will be in the same thread and set event, leaving the event open for next time,
  549. // In either case it is safe to do this, since if there is no callback, there will
  550. // be no data to pass back and no set event.
  551. return bSuccess;
  552. }
  553. /************************************************************************************************
  554. ** Callback - InternetCallback
  555. ** Description - This handles the callback from the Wininet API, it is responsible for asyncronous
  556. ** handle returns as well as other call returns, it also destructs the context
  557. ** when it is eventually deleted
  558. ************************************************************************************************/
  559. void CALLBACK CAnyConnection::CAsyncContext::InternetCallback(
  560. IN HINTERNET hInternet,
  561. IN DWORD_PTR dwContext,
  562. IN DWORD dwInternetStatus,
  563. IN LPVOID lpvStatusInformation,
  564. IN DWORD dwStatusInformationLength) {
  565. CAsyncContext *pThis = (CAsyncContext *)dwContext;
  566. // Regardless of whether we are in a critical failure state or not, we want to delete the
  567. // context of this handle is closing
  568. switch(dwInternetStatus) {
  569. #if 0
  570. // BUG: We do not get this notification from WININET, so we have to do this from outside
  571. // When this is resolved, this code is much neater
  572. case INTERNET_STATUS_HANDLE_CLOSING:
  573. delete pThis;
  574. break;
  575. #endif // #if 0
  576. case INTERNET_STATUS_REQUEST_COMPLETE: // The request we sent was successful (or timed
  577. // out)
  578. pThis->m_dwRet = ((LPINTERNET_ASYNC_RESULT)lpvStatusInformation)->dwResult;
  579. pThis->m_dwError = ((LPINTERNET_ASYNC_RESULT)lpvStatusInformation)->dwError;
  580. SetEvent (pThis->m_hEvent);
  581. break;
  582. }
  583. }
  584. #endif // #ifndef WINNT32
  585. /************************************************************************************************
  586. ** End of File (anycon.cxx)
  587. ************************************************************************************************/