void CHttpDownloadDlg::DownloadThread() { ENCODING_INIT; //Create the Internet session handle ASSERT(m_hInternetSession == NULL); m_hInternetSession = ::InternetOpen(AfxGetAppName(), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); if (m_hInternetSession == NULL) { TRACE(_T("Failed in call to InternetOpen, Error:%d\n"), ::GetLastError()); HandleThreadErrorWithLastError(GetResString(IDS_HTTPDOWNLOAD_GENERIC_ERROR)); return; } //Should we exit the thread if (m_bAbort) { PostMessage(WM_HTTPDOWNLOAD_THREAD_FINISHED); return; } //Setup the status callback function if (::InternetSetStatusCallback(m_hInternetSession, _OnStatusCallBack) == INTERNET_INVALID_STATUS_CALLBACK) { TRACE(_T("Failed in call to InternetSetStatusCallback, Error:%d\n"), ::GetLastError()); HandleThreadErrorWithLastError(GetResString(IDS_HTTPDOWNLOAD_GENERIC_ERROR)); return; } //Should we exit the thread if (m_bAbort) { PostMessage(WM_HTTPDOWNLOAD_THREAD_FINISHED); return; } //Make the connection to the HTTP server ASSERT(m_hHttpConnection == NULL); if (m_sUserName.GetLength()) // Elandal: Assumes sizeof(void*) == sizeof(unsigned long) m_hHttpConnection = ::InternetConnect(m_hInternetSession, m_sServer, m_nPort, m_sUserName, m_sPassword, m_dwServiceType, 0, (DWORD) this); else // Elandal: Assumes sizeof(void*) == sizeof(unsigned long) m_hHttpConnection = ::InternetConnect(m_hInternetSession, m_sServer, m_nPort, NULL, NULL, m_dwServiceType, 0, (DWORD) this); if (m_hHttpConnection == NULL) { TRACE(_T("Failed in call to InternetConnect, Error:%d\n"), ::GetLastError()); HandleThreadErrorWithLastError(GetResString(IDS_HTTPDOWNLOAD_FAIL_CONNECT_SERVER)); return; } //Should we exit the thread if (m_bAbort) { PostMessage(WM_HTTPDOWNLOAD_THREAD_FINISHED); return; } //Start the animation to signify that the download is taking place PlayAnimation(); //Issue the request to read the file LPCTSTR ppszAcceptTypes[2]; ppszAcceptTypes[0] = _T("*/*"); //We support accepting any mime file type since this is a simple download of a file ppszAcceptTypes[1] = NULL; ASSERT(m_hHttpFile == NULL); // Elandal: Assumes sizeof(void*) == sizeof(unsigned long) m_hHttpFile = HttpOpenRequest(m_hHttpConnection, NULL, m_sObject, NULL, NULL, ppszAcceptTypes, INTERNET_FLAG_RELOAD | INTERNET_FLAG_DONT_CACHE | INTERNET_FLAG_KEEP_CONNECTION, (DWORD)this); if (m_hHttpFile == NULL) { TRACE(_T("Failed in call to HttpOpenRequest, Error:%d\n"), ::GetLastError()); HandleThreadErrorWithLastError(GetResString(IDS_HTTPDOWNLOAD_FAIL_CONNECT_SERVER)); return; } //Should we exit the thread if (m_bAbort) { PostMessage(WM_HTTPDOWNLOAD_THREAD_FINISHED); return; } //fill in what encoding we support HttpAddRequestHeaders(m_hHttpFile, ACCEPT_ENCODING_HEADER, (DWORD)-1L, HTTP_ADDREQ_FLAG_ADD); //label used to jump to if we need to resend the request resend: //Issue the request BOOL bSend = ::HttpSendRequest(m_hHttpFile, NULL, 0, NULL, 0); if (!bSend) { TRACE(_T("Failed in call to HttpSendRequest, Error:%d\n"), ::GetLastError()); HandleThreadErrorWithLastError(GetResString(IDS_HTTPDOWNLOAD_FAIL_CONNECT_SERVER)); return; } //Check the HTTP status code TCHAR szStatusCode[32]; DWORD dwInfoSize = 32; if (!HttpQueryInfo(m_hHttpFile, HTTP_QUERY_STATUS_CODE, szStatusCode, &dwInfoSize, NULL)) { TRACE(_T("Failed in call to HttpQueryInfo for HTTP query status code, Error:%d\n"), ::GetLastError()); HandleThreadError(GetResString(IDS_HTTPDOWNLOAD_INVALID_SERVER_RESPONSE)); return; } else { long nStatusCode = _ttol(szStatusCode); //Handle any authentication errors if (nStatusCode == HTTP_STATUS_PROXY_AUTH_REQ || nStatusCode == HTTP_STATUS_DENIED) { // We have to read all outstanding data on the Internet handle // before we can resubmit request. Just discard the data. char szData[51]; DWORD dwSize; do { ::InternetReadFile(m_hHttpFile, (LPVOID)szData, 50, &dwSize); } while (dwSize != 0); //Bring up the standard authentication dialog if (::InternetErrorDlg(GetSafeHwnd(), m_hHttpFile, ERROR_INTERNET_INCORRECT_PASSWORD, FLAGS_ERROR_UI_FILTER_FOR_ERRORS | FLAGS_ERROR_UI_FLAGS_GENERATE_DATA | FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS, NULL) == ERROR_INTERNET_FORCE_RETRY) goto resend; } else if (nStatusCode != HTTP_STATUS_OK) { TRACE(_T("Failed to retrieve a HTTP 200 status, Status Code:%d\n"), nStatusCode); HandleThreadErrorWithLastError(GetResString(IDS_HTTPDOWNLOAD_INVALID_HTTP_RESPONSE), nStatusCode); return; } } //Check to see if any encodings are supported // ENCODING_QUERY; TCHAR szContentEncoding[32]; DWORD dwEncodeStringSize = 32; if(::HttpQueryInfo(m_hHttpFile, HTTP_QUERY_CONTENT_ENCODING, szContentEncoding, &dwEncodeStringSize, NULL)) { if(!_tcsicmp(szContentEncoding, _T("gzip")) || !_tcsicmp(szContentEncoding, _T("x-gzip"))) bEncodedWithGZIP = TRUE; } //Update the status control to reflect that we are getting the file information SetStatus(GetResString(IDS_HTTPDOWNLOAD_GETTING_FILE_INFORMATION)); // Get the length of the file. TCHAR szContentLength[32]; dwInfoSize = 32; DWORD dwFileSize = 0; BOOL bGotFileSize = FALSE; if (::HttpQueryInfo(m_hHttpFile, HTTP_QUERY_CONTENT_LENGTH, szContentLength, &dwInfoSize, NULL)) { //Set the progress control range bGotFileSize = TRUE; dwFileSize = (DWORD) _ttol(szContentLength); SetProgressRange(dwFileSize); } //Update the status to say that we are now downloading the file SetStatus(GetResString(IDS_HTTPDOWNLOAD_RETREIVEING_FILE)); //Now do the actual read of the file DWORD dwStartTicks = ::GetTickCount(); DWORD dwCurrentTicks = dwStartTicks; DWORD dwBytesRead = 0; char szReadBuf[1024]; DWORD dwBytesToRead = 1024; DWORD dwTotalBytesRead = 0; DWORD dwLastTotalBytes = 0; DWORD dwLastPercentage = 0; PREPARE_DECODER; do { if (!::InternetReadFile(m_hHttpFile, szReadBuf, dwBytesToRead, &dwBytesRead)) { TRACE(_T("Failed in call to InternetReadFile, Error:%d\n"), ::GetLastError()); HandleThreadErrorWithLastError(GetResString(IDS_HTTPDOWNLOAD_ERROR_READFILE)); return; } else if (dwBytesRead && !m_bAbort) { //Write the data to file TRY { DECODE_DATA(m_FileToWrite, szReadBuf, dwBytesRead); } CATCH(CFileException, e); { TRACE(_T("An exception occured while writing to the download file\n")); HandleThreadErrorWithLastError(GetResString(IDS_HTTPDOWNLOAD_ERROR_READFILE), e->m_lOsError); e->Delete(); //clean up any encoding data before we return ENCODING_CLEAN_UP; return; } END_CATCH //Increment the total number of bytes read dwTotalBytesRead += dwBytesRead; UpdateControlsDuringTransfer(dwStartTicks, dwCurrentTicks, dwTotalBytesRead, dwLastTotalBytes, dwLastPercentage, bGotFileSize, dwFileSize); } } while (dwBytesRead && !m_bAbort); //Delete the file being downloaded to if it is present and the download was aborted m_FileToWrite.Close(); if (m_bAbort) ::DeleteFile(m_sFileToDownloadInto); //clean up any encoding data before we return ENCODING_CLEAN_UP;; //We're finished PostMessage(WM_HTTPDOWNLOAD_THREAD_FINISHED); }
void CFTPTransferDlg::TransferThread() { //Create the Internet session handle (if needed) if (!m_bUsingAttached) { ASSERT(m_hInternetSession == NULL); // m_hInternetSession = ::InternetOpen(AfxGetAppName(), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); m_hInternetSession = InternetOpen("Ftp", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0); if (m_hInternetSession == NULL) { TRACE(_T("Failed in call to InternetOpen, Error:%d\n"), ::GetLastError()); HandleThreadErrorWithLastError(IDS_FTPTRANSFER_GENERIC_ERROR); return; } //Should we exit the thread if (m_bAbort) { PostMessage(WM_FTPTRANSFER_THREAD_FINISHED); return; } } ASSERT(m_hInternetSession); //Setup the status callback function on the Internet session handle INTERNET_STATUS_CALLBACK pOldCallback = ::InternetSetStatusCallback(m_hInternetSession, _OnStatusCallBack); if (pOldCallback == INTERNET_INVALID_STATUS_CALLBACK) { TRACE(_T("Failed in call to InternetSetStatusCallback, Error:%d\n"), ::GetLastError()); HandleThreadErrorWithLastError(IDS_FTPTRANSFER_GENERIC_ERROR); return; } //Should we exit the thread if (m_bAbort) { if (pOldCallback) ::InternetSetStatusCallback(m_hInternetSession, pOldCallback); PostMessage(WM_FTPTRANSFER_THREAD_FINISHED); return; } //Make the connection to the FTP server (if needed) if (!m_bUsingAttached) { ASSERT(m_hFTPConnection == NULL); ASSERT(m_sServer.GetLength()); if (m_sUserName.GetLength()) // m_hFTPConnection = ::InternetConnect(m_hInternetSession, m_sServer, m_nPort, m_sUserName, // m_sPassword, INTERNET_SERVICE_FTP, 0, (DWORD) this); m_hFTPConnection = ::InternetConnect(m_hInternetSession, m_sServer, m_nPort, m_sUserName, m_sPassword, INTERNET_SERVICE_FTP, INTERNET_FLAG_PASSIVE, 0); else m_hFTPConnection = ::InternetConnect(m_hInternetSession, m_sServer, m_nPort, NULL, NULL, INTERNET_SERVICE_FTP, 0, (DWORD) this); if (m_hFTPConnection == NULL) { TRACE(_T("Failed in call to InternetConnect, Error:%d\n"), ::GetLastError()); if (pOldCallback) ::InternetSetStatusCallback(m_hInternetSession, pOldCallback); HandleThreadErrorWithLastError(IDS_FTPTRANSFER_FAIL_CONNECT_SERVER); return; } //Should we exit the thread if (m_bAbort) { if (pOldCallback) ::InternetSetStatusCallback(m_hInternetSession, pOldCallback); PostMessage(WM_FTPTRANSFER_THREAD_FINISHED); return; } } ASSERT(m_hFTPConnection); //Start the animation to signify that the download is taking place PlayAnimation(); //Update the status control to reflect that we are getting the file information SetStatus(IDS_FTPTRANSFER_GETTING_FILE_INFORMATION); // Get the length of the file to transfer DWORD dwFileSize = 0; BOOL bGotFileSize = FALSE; if (m_bDownload) { WIN32_FIND_DATA wfd; HINTERNET hFind = ::FtpFindFirstFile(m_hFTPConnection, m_sRemoteFile, &wfd, INTERNET_FLAG_RELOAD | INTERNET_FLAG_DONT_CACHE, (DWORD) this); if (hFind) { //Set the progress control range bGotFileSize = TRUE; dwFileSize = (DWORD) wfd.nFileSizeLow; // SetProgressRange(dwFileSize); SetProgressRange(0,100); //Destroy the enumeration handle now that we are finished with it InternetCloseHandle(hFind); } } else { bGotFileSize = TRUE; dwFileSize = m_LocalFile.GetLength(); // SetProgressRange(dwFileSize); SetProgressRange(0, 100); } //Should we exit the thread if (m_bAbort) { if (pOldCallback) ::InternetSetStatusCallback(m_hInternetSession, pOldCallback); PostMessage(WM_FTPTRANSFER_THREAD_FINISHED); return; } //check to see if the file already exists on the server if (!m_bDownload) { WIN32_FIND_DATA wfd; HINTERNET hFind = ::FtpFindFirstFile(m_hFTPConnection, m_sRemoteFile, &wfd, INTERNET_FLAG_RELOAD | INTERNET_FLAG_DONT_CACHE, (DWORD) this); BOOL bFound = FALSE; if (hFind) { bFound = TRUE; //Destroy the enumeration handle now that we are finished with it InternetCloseHandle(hFind); } if (bFound && SendMessage(WM_FTPTRANSFER_ASK_OVERWRITE_FILE) == 0) { if (pOldCallback) ::InternetSetStatusCallback(m_hInternetSession, pOldCallback); PostMessage(WM_FTPTRANSFER_THREAD_FINISHED, 1); return; } } //Should we exit the thread if (m_bAbort) { if (pOldCallback) ::InternetSetStatusCallback(m_hInternetSession, pOldCallback); PostMessage(WM_FTPTRANSFER_THREAD_FINISHED); return; } //Open the remote file ASSERT(m_hFTPFile == NULL); if (m_bDownload) { if (m_bBinary) m_hFTPFile = FtpOpenFile(m_hFTPConnection, m_sRemoteFile, GENERIC_READ, FTP_TRANSFER_TYPE_BINARY | INTERNET_FLAG_RELOAD | INTERNET_FLAG_DONT_CACHE, (DWORD) this); else m_hFTPFile = FtpOpenFile(m_hFTPConnection, m_sRemoteFile, GENERIC_READ, FTP_TRANSFER_TYPE_ASCII | INTERNET_FLAG_RELOAD | INTERNET_FLAG_DONT_CACHE, (DWORD) this); } else { if (m_bBinary) m_hFTPFile = FtpOpenFile(m_hFTPConnection, m_sRemoteFile, GENERIC_WRITE, FTP_TRANSFER_TYPE_BINARY | INTERNET_FLAG_RELOAD | INTERNET_FLAG_DONT_CACHE, (DWORD) this); else m_hFTPFile = FtpOpenFile(m_hFTPConnection, m_sRemoteFile, GENERIC_WRITE, FTP_TRANSFER_TYPE_ASCII | INTERNET_FLAG_RELOAD | INTERNET_FLAG_DONT_CACHE, (DWORD) this); } if (m_hFTPFile == NULL) { TRACE(_T("Failed in call to FtpOpenFile, Error:%d\n"), ::GetLastError()); if (pOldCallback) ::InternetSetStatusCallback(m_hInternetSession, pOldCallback); HandleThreadErrorWithLastError(IDS_FTPTRANSFER_FAIL_OPEN_FILE); return; } //Should we exit the thread if (m_bAbort) { if (pOldCallback) ::InternetSetStatusCallback(m_hInternetSession, pOldCallback); PostMessage(WM_FTPTRANSFER_THREAD_FINISHED); return; } //Update the status to say that we are now uploading / downloading the file if (m_bDownload) SetStatus(IDS_FTPTRANSFER_RETREIVEING_FILE); else SetStatus(IDS_FTPTRANSFER_UPLOADING_FILE); //Now do the actual reading / writing of the file DWORD dwStartTicks = ::GetTickCount(); DWORD dwCurrentTicks = dwStartTicks; DWORD dwBytesRead = 0; DWORD dwBytesWritten = 0; char szReadBuf[1024]; DWORD dwBytesToRead = 1024; DWORD dwTotalBytesRead = 0; DWORD dwTotalBytesWritten = 0; DWORD dwLastTotalBytes = 0; DWORD dwLastPercentage = 0; do { if (m_bDownload) { //Read from the remote file if (!::InternetReadFile(m_hFTPFile, szReadBuf, dwBytesToRead, &dwBytesRead)) { TRACE(_T("Failed in call to InternetReadFile, Error:%d\n"), ::GetLastError()); if (pOldCallback) ::InternetSetStatusCallback(m_hInternetSession, pOldCallback); HandleThreadErrorWithLastError(IDS_FTPTRANSFER_ERROR_READFILE); return; } else if (dwBytesRead && !m_bAbort) { //Write the data to file TRY { m_LocalFile.Write(szReadBuf, dwBytesRead); } CATCH(CFileException, e); { TRACE(_T("An exception occured while writing to the download file\n")); if (pOldCallback) ::InternetSetStatusCallback(m_hInternetSession, pOldCallback); HandleThreadErrorWithLastError(IDS_FTPTRANSFER_ERROR_READFILE, e->m_lOsError); e->Delete(); return; } END_CATCH //Increment the total number of bytes read dwTotalBytesRead += dwBytesRead; UpdateControlsDuringTransfer(dwStartTicks, dwCurrentTicks, dwTotalBytesRead, dwLastTotalBytes, dwLastPercentage, bGotFileSize, dwFileSize); } } else { //Read the data from the local file TRY { dwBytesRead = m_LocalFile.Read(szReadBuf, 1024); } CATCH(CFileException, e); { TRACE(_T("An exception occured while reading the local file\n")); if (pOldCallback) ::InternetSetStatusCallback(m_hInternetSession, pOldCallback); HandleThreadErrorWithLastError(IDS_FTPTRANSFER_ERROR_READFILE, e->m_lOsError); e->Delete(); return; } END_CATCH //Write to the remote file if (dwBytesRead) { if (!::InternetWriteFile(m_hFTPFile, szReadBuf, dwBytesRead, &dwBytesWritten)) { TRACE(_T("Failed in call to InternetWriteFile, Error:%d\n"), ::GetLastError()); if (pOldCallback) ::InternetSetStatusCallback(m_hInternetSession, pOldCallback); HandleThreadErrorWithLastError(IDS_FTPTRANSFER_ERROR_WRITEFILE); return; } else if (dwBytesWritten && !m_bAbort) { //Increment the total number of bytes read dwTotalBytesWritten += dwBytesWritten; UpdateControlsDuringTransfer(dwStartTicks, dwCurrentTicks, dwTotalBytesWritten, dwLastTotalBytes, dwLastPercentage, bGotFileSize, dwFileSize); } } } }