windows-nt/Source/XPSP1/NT/printscan/ui/wiaacmgr/postplug/httpfilepost.cpp

958 lines
25 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
//+-----------------------------------------------------------------------
//
// Microsoft Network
// Copyright (C) Microsoft Corporation, 1998
//
// File: HttpFilePost.cpp
//
// Contents:
// CHttpFilePoster
// RFC 1867 file uploader
//
// Posts files to an http server using HTTP POST
//
// Links:
// RFC 1867 - Form-based File Upload in HTML : http://www.ietf.org/rfc/rfc1867.txt
// RFC 1521 - MIME (Multipurpose Internet Mail Extensions) : http://www.ietf.org/rfc/rfc1521.txt
//
//
// Author: Noah Booth (noahb@microsoft.com)
//
// Revision History:
//
// 2/5/99 noahb created
// 4/25/99 noahb integration with MSN communities
// 3/7/2000 noahb integration with communities File Cabinet
//------------------------------------------------------------------------
#include "precomp.h"
#pragma hdrstop
#include <string>
#include <list>
#include <map>
#include "stdstring.h"
#include "HTTPFilePost.h"
#include "ProgressInfo.h"
using namespace std;
#pragma warning(disable: 4800) //disable warning forcing int to bool
static void ThrowUploaderException(DWORD dwError /* = -1 */)
{
if(dwError == -1)
dwError = GetLastError();
throw( new CUploaderException(dwError) );
}
#define USER_AGENT "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT 5.0) [MSN Communities Active-X Upload Control]"
#define UNKNOWN_MIME "application/octet-stream" //MIME type to use when there is none other available
#define REG_CONTENT_TYPE "Content Type" //name of content type value in HKCR key for a file extension
#define CONTENT_TYPE "Content-Type" //HTTP header content type string
#define MULTI_PART_FORM_DATA "multipart/form-data"
static DWORD g_dwContentLength = 0;
static const char szFileHeaderContentDisp[] = "Content-Disposition: form-data; name=\"Attachment\"; filename=\"";
static const char szFileHeaderContentType[] = "\"\r\nContent-Type: ";
static const char szFileHeaderEnd[] = "\r\n\r\n";
static const char szFormHeaderContentDisp[] = "Content-Disposition: form-data; name=\"";
static const char szFormHeaderEnd[] = "\"\r\n\r\n";
static const char szTitleName[] = "Subject";
static const char szDescName[] = "Message_Body";
#define CHECK_ERROR(cond, err) if (!(cond)) {pszErr=(err); goto done;}
#define SAFERELEASE(p) if (p) {(p)->Release(); p = NULL;} else ;
CHttpFilePoster::CHttpFilePoster()
{
m_iStatus = HFP_UNINITIALIZED;
m_dwFileCount = 0;
m_dwTotalFileBytes = 0;
m_bSinglePost = false;
Initialize("", NULL);
m_hSession = NULL;
m_hConnection = NULL;
m_hFile = NULL;
m_dwContext = reinterpret_cast<DWORD_PTR>(this);
GenBoundaryString();
}
CHttpFilePoster::~CHttpFilePoster()
{
Reset(); //free up memory allocated for the file list
if(m_hFile)
InternetCloseHandle(m_hFile);
if(m_hConnection)
InternetCloseHandle(m_hConnection);
if(m_hSession)
InternetCloseHandle(m_hSession);
}
//generate a boundary string that is statistically likely to be unique
void CHttpFilePoster::GenBoundaryString()
{
GUID guid;
char buff[128];
static const char* szFormat = "-------------%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x-------------";
::CoCreateGuid(&guid);
//TODO: remove sprintf
sprintf(buff, szFormat,
guid.Data1, guid.Data2, guid.Data3,
guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3],
guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
m_strBoundary = buff;
}
void CHttpFilePoster::BuildFilePostHeader(CUploaderFile* pFile)
{
m_strFileHeader = "\r\n" + m_strBoundary + "\r\n";
m_strFileHeader += szFileHeaderContentDisp;
m_strFileHeader += pFile->strName;
m_strFileHeader += szFileHeaderContentType;
m_strFileHeader += pFile->strMime;
m_strFileHeader += szFileHeaderEnd;
}
void CHttpFilePoster::BuildFilePost(CUploaderFile* pFile)
{
m_strFilePost = "\r\n" + m_strBoundary + "\r\n";
m_strFilePost += szFormHeaderContentDisp;
m_strFilePost += szTitleName;
m_strFilePost += szFormHeaderEnd;
m_strFilePost += pFile->strTitle;
m_strFilePost += "\r\n" + m_strBoundary + "\r\n";
m_strFilePost += szFormHeaderContentDisp;
m_strFilePost += szDescName;
m_strFilePost += pFile->strDescription;
m_strFilePost += szFormHeaderEnd;
m_strFilePost += "\r\n";
}
void CHttpFilePoster::BuildCommonPost()
{
WIA_PUSHFUNCTION(TEXT("CHttpFilePoster::BuildCommonPost"));
TFormMapIterator begin = m_mapFormData.begin();
TFormMapIterator end = m_mapFormData.end();
TFormMapIterator it;
m_strCommonPost = "";
if(m_mapFormData.size())
{
for(it = begin; it != end; it++)
{
WIA_TRACE((TEXT("%hs: %hs"), it->first.c_str(), it->second.c_str()));
m_strCommonPost += m_strBoundary + "\r\n";
m_strCommonPost += szFormHeaderContentDisp;
m_strCommonPost += it->first;
m_strCommonPost += szFormHeaderEnd;
m_strCommonPost += it->second;
m_strCommonPost += "\r\n";
}
}
m_strCommonPost += m_strBoundary + "--\r\n";
}
void CHttpFilePoster::CrackPostingURL()
{
BOOL bResult;
char szBuff[INTERNET_MAX_URL_LENGTH];
char* pBuffer = szBuff;
DWORD dwBufLen = INTERNET_MAX_URL_LENGTH;
m_strHttpServer = "";
m_strHttpObject = "";
DWORD dwFlags = ICU_NO_ENCODE | ICU_DECODE | ICU_NO_META | ICU_ENCODE_SPACES_ONLY | ICU_BROWSER_MODE;
bResult = InternetCanonicalizeUrlA(m_strSitePostingURL.c_str(), pBuffer, &dwBufLen, dwFlags);
if(!bResult)
{
pBuffer = new char[dwBufLen];
if(pBuffer)
{
bResult = InternetCanonicalizeUrlA(m_strSitePostingURL.c_str(), pBuffer, &dwBufLen, dwFlags);
}
}
if(bResult)
{
//INTERNET_PORT iPort;
URL_COMPONENTSA urlComponents;
char szServer[INTERNET_MAX_URL_LENGTH + 1];
char szObject[INTERNET_MAX_URL_LENGTH + 1];
dwFlags = 0;
ZeroMemory(&urlComponents, sizeof(urlComponents));
urlComponents.dwStructSize = sizeof(urlComponents);
urlComponents.dwHostNameLength = INTERNET_MAX_URL_LENGTH;
urlComponents.lpszHostName = szServer;
urlComponents.dwUrlPathLength = INTERNET_MAX_URL_LENGTH;
urlComponents.lpszUrlPath = szObject;
bResult = InternetCrackUrlA(pBuffer, 0, dwFlags, &urlComponents);
if(bResult)
{
m_strHttpServer = szServer;
m_strHttpObject = szObject;
}
}
ATLASSERT(bResult);
if(pBuffer != szBuff)
delete pBuffer;
}
bool CHttpFilePoster::Connect()
{
bool bResult = false;
ATLASSERT(m_hSession);
if(!m_hConnection)
{
m_hConnection = InternetConnectA(
m_hSession, //session
m_strHttpServer.c_str(), //server name
INTERNET_INVALID_PORT_NUMBER, //server port
NULL, //user name
NULL, //password
INTERNET_SERVICE_HTTP,
0, //flags
m_dwContext);
if(m_hConnection)
bResult = true;
}
if(!bResult)
ThrowUploaderException();
return bResult;
}
///////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////
bool CHttpFilePoster::Disconnect()
{
if(NULL == m_hConnection || InternetCloseHandle(m_hConnection))
{
m_hConnection = NULL;
return true;
}
else
{
return false;
}
}
bool CHttpFilePoster::Startup()
{
ATLASSERT(m_hSession == NULL);
//CWaitCursor wait;
DWORD dwAccessType = INTERNET_OPEN_TYPE_PRECONFIG;
m_hSession = InternetOpenA(
USER_AGENT,
dwAccessType,
NULL, //proxy name
NULL, //proxy bypass
INTERNET_FLAG_DONT_CACHE
);
InternetSetStatusCallback(m_hSession, CHttpFilePoster::InternetStatusCallback);
if(m_hSession == NULL)
ThrowUploaderException();
return (m_hSession != NULL);
}
///////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////
bool CHttpFilePoster::Shutdown()
{
if(IsConnected())
{
Disconnect();
}
InternetCloseHandle(m_hSession);
m_hSession = NULL;
return true;
}
///////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////
bool CHttpFilePoster::IsConnected()
{
return (m_hConnection != NULL);
}
/*
RequestHead() request posting acceptor headers
Note: It is necessary to call this function before posting files because of the
way HTTP authentication works. When you request an object that requires authentication
the server will first read the entire body of the request. It then determines if
authentication is required. If no authentication is required, it will service the
request and send back the response, otherwise it will send back a response with status 401
(access denied) and some other headers enumerating acceptable authentication schemes.
When client sees these headers, it prompts the user if necessary, and resends the request
with headers containing the requested credentials.
For small posts the user barely notices, but for a large POST this is insane. You
have to send up your entire post just to find out that you need to be authenticated.
Then you have to supply your username/password to your user agent, which will then
resend the POST.
The upshot is that it's necessary to make sure the user is authenticated, if
necessary, BEFORE we attempt to post a bunch of files. One way to do this is to
send a HEAD request to the server, using HttpSendRequest, check the headers and authenticate
if necessary. Then we can continue with the file post.
*/
bool CHttpFilePoster::RequestHead()
{
bool bRet = false;
DWORD dwRet = 0;
return true;
HINTERNET hFile;
hFile = HttpOpenRequestA(m_hConnection, "HEAD", m_strHttpObject.c_str(),
NULL, NULL, NULL, INTERNET_FLAG_EXISTING_CONNECT, m_dwContext);
if(hFile)
{
do
{
HttpSendRequest(hFile, NULL, 0, NULL, 0);
#ifdef _DEBUG
{
//HACK: magic numbers
DWORD dwLen = 1024;
char buffer[1024];
if(HttpQueryInfo(hFile, HTTP_QUERY_RAW_HEADERS_CRLF, buffer, &dwLen, NULL))
{
ATLTRACE("---- HEADERS: \n");
ATLTRACE(buffer);
ATLTRACE("------ DONE --\n");
}
}
#endif
dwRet = InternetErrorDlg(
m_hWndParent,
hFile,
ERROR_INTERNET_INCORRECT_PASSWORD,
FLAGS_ERROR_UI_FLAGS_GENERATE_DATA | FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS,
NULL);
if(dwRet== ERROR_SUCCESS)
bRet = true;
}
while(dwRet == ERROR_INTERNET_FORCE_RETRY);
InternetCloseHandle(hFile);
}
return bRet;
}
bool CHttpFilePoster::DoUpload(CProgressInfo* pProgress)
{
DWORD dwThreadID;
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) UploadThreadProc, (LPVOID) pProgress, 0, &dwThreadID);
return TRUE;
}
//find the MIME type for a file based on the file extension by
// looking in the registry under HKEY_CLASSES_ROOT\.<ext>\Content Type
CStdString CHttpFilePoster::GetMimeType(const CHAR* pszFilename)
{
CHAR* pszExt, *pszRet;
CHAR pszBuff[MAX_PATH];
DWORD dwBuffSize = MAX_PATH;
LONG lResult;
//get file extension
pszExt = strrchr(pszFilename, _T('.'));
if(pszExt == NULL)
{
pszRet = UNKNOWN_MIME;
}
else
{
HKEY hkey = NULL;
lResult = RegOpenKeyExA(HKEY_CLASSES_ROOT, pszExt, 0, KEY_QUERY_VALUE, &hkey);
if(lResult != ERROR_SUCCESS)
pszRet = UNKNOWN_MIME;
lResult = RegQueryValueExA(hkey, REG_CONTENT_TYPE, 0, NULL, (LPBYTE) pszBuff, &dwBuffSize);
if(lResult != ERROR_SUCCESS)
pszRet = UNKNOWN_MIME;
else
pszRet = pszBuff;
if(hkey)
RegCloseKey(hkey);
}
return pszRet;
}
bool CHttpFilePoster::SendString(const CStdString& str)
{
bool bRet = false;
DWORD dwWritten, dwLen;
dwLen = str.length();
if(InternetWriteFile(m_hFile, str.data(), dwLen, &dwWritten) && (dwWritten == dwLen))
{
g_dwContentLength -= dwLen;
ATLTRACE((LPCSTR)str);
bRet = true;
}
if(!bRet)
ThrowUploaderException();
return bRet;
}
DWORD CHttpFilePoster::CalculateContentLength(CUploaderFile* pFile)
{
DWORD dwContentLength = 0;
dwContentLength = m_strFileHeader.length();
dwContentLength += pFile->dwSize;
dwContentLength += m_strFilePost.length();
dwContentLength += m_strCommonPost.length();
g_dwContentLength = dwContentLength;
return dwContentLength;
}
bool CHttpFilePoster::SendHeader()
{
bool bResult = false;
ATLASSERT(m_hFile);
//HACK: magic number
char szBuff[1000];
// boundary string doesn't include the first two '-' characters
sprintf(szBuff, "%s:%s; boundary=%s\r\n", CONTENT_TYPE, MULTI_PART_FORM_DATA, m_strBoundary.c_str() + 2);
bResult = HttpAddRequestHeadersA(m_hFile, szBuff, -1, HTTP_ADDREQ_FLAG_REPLACE | HTTP_ADDREQ_FLAG_ADD);
if(!bResult)
ThrowUploaderException();
return true;
}
bool CHttpFilePoster::BeginUpload(CProgressInfo* pProgressInfo)
{
bool bResult = false;
if(RequestHead())
{
BuildCommonPost();
BuildFilePostHeader(m_pCurrentFile);
BuildFilePost(m_pCurrentFile);
m_hFile = HttpOpenRequestA(
m_hConnection, //connection
"POST", //verb
m_strHttpObject.c_str(),//object
NULL, //http version, use default (1.0)
NULL, //referer, none
NULL, //accept types, use default
INTERNET_FLAG_NO_CACHE_WRITE, //flags, don't write result to cache
m_dwContext);
if(m_hFile)
{
ZeroMemory(&m_internetBuffers, sizeof(m_internetBuffers));
m_internetBuffers.dwBufferTotal = CalculateContentLength(m_pCurrentFile);
m_internetBuffers.dwStructSize = sizeof(m_internetBuffers);
if(SendHeader())
{
bResult = !!HttpSendRequestEx(m_hFile, &m_internetBuffers, NULL, HSR_INITIATE, 0);
}
}
}
if(!bResult)
{
ThrowUploaderException();
//BUGBUG: do we really want to abort the entire upload, or just this file?
//pProgressInfo->dwStatus = TRANSFER_SKIPPING_FILE;
//pProgressInfo->NotifyCaller();
}
return bResult;
}
void CHttpFilePoster::DrainSocket()
{
WIA_PUSHFUNCTION(TEXT("CHttpFilePoster::DrainSocket"));
ATLASSERT(m_hFile);
CHAR buffer[401];
DWORD dwRead = 0;
WIA_TRACE((TEXT("--response body--")));
while(InternetReadFile(m_hFile, buffer, 400, &dwRead) && dwRead > 0)
{
#ifdef DBG
WIA_TRACE((TEXT("dwRead: %d"), dwRead ));
buffer[dwRead] = '\0';
WIA_TRACE((TEXT("%hs"), buffer));
#endif
}
WIA_TRACE((TEXT("--done--")));
ATLASSERT(dwRead == 0);
}
bool CHttpFilePoster::QueryStatusCode(DWORD& dwStatus)
{
ATLASSERT(m_hFile != NULL);
TCHAR szBuffer[80];
DWORD dwLen = 80;
bool bRet;
bRet = HttpQueryInfo(m_hFile, HTTP_QUERY_STATUS_CODE, szBuffer, &dwLen, NULL);
if (bRet)
dwStatus = (DWORD) _ttol(szBuffer);
return bRet;
}
bool CHttpFilePoster::CleanupUpload()
{
BOOL bSuccess = false;
if(m_hFile)
{
bSuccess = HttpEndRequest(m_hFile, NULL, 0, 0);
//drain socket
DrainSocket();
InternetCloseHandle(m_hFile);
m_hFile = NULL;
}
if(!bSuccess)
ThrowUploaderException();
return bSuccess;
}
bool CHttpFilePoster::FinishUpload()
{
return CleanupUpload();
}
bool CHttpFilePoster::CancelUpload()
{
return CleanupUpload();
}
bool CHttpFilePoster::SendFile(CProgressInfo* pProgressInfo)
{
HANDLE hFile = NULL;
BYTE buffer[UPLOAD_BUFFSIZE];
bool bRet = false; // assume failure
try
{
hFile = CreateFileA(
pProgressInfo->strFilename.c_str(),
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
NULL);
if(INVALID_HANDLE_VALUE == hFile)
{
DWORD dwError = GetLastError();
// file either doesn't exist, or is in use by another process, or
// otherwise can't be opened, just skip the file and continue
pProgressInfo->dwStatus = TRANSFER_SKIPPING_FILE;
pProgressInfo->NotifyCaller();
ThrowUploaderException(dwError);
return bRet;
}
ATLASSERT(m_hFile);
DWORD dwBytesTotal = GetFileSize(hFile, NULL);
// this assertion should only fail if the file was modified since
// the upload map was built, if this happens we just skip the file
ATLASSERT(dwBytesTotal == pProgressInfo->dwCurrentBytes);
if(dwBytesTotal != pProgressInfo->dwCurrentBytes)
{
pProgressInfo->dwStatus = TRANSFER_SKIPPING_FILE;
pProgressInfo->NotifyCaller();
CloseHandle(hFile);
ThrowUploaderException();
return bRet;
}
pProgressInfo->dwCurrentDone = 0;
while(pProgressInfo->dwCurrentDone < pProgressInfo->dwCurrentBytes)
{
DWORD dwLeft = pProgressInfo->dwCurrentBytes - pProgressInfo->dwCurrentDone;
DWORD dwToRead = min(UPLOAD_BUFFSIZE, dwLeft);
DWORD dwRead;
DWORD dwWritten;
ReadFile(hFile, buffer, dwToRead, &dwRead, NULL);
if(dwRead != dwToRead)
{
ATLTRACE("Error: enexpected end of file in SendFile\n");
ThrowUploaderException();
}
if(!InternetWriteFile(m_hFile, &buffer, dwRead, &dwWritten))
{
ThrowUploaderException();
}
if(dwWritten != dwRead)
{
ATLTRACE("Error: InternetWriteFile sent less than requested!\n");
ThrowUploaderException();
}
g_dwContentLength -= dwWritten;
ATLTRACE("sent %d, %d left\n", dwWritten, g_dwContentLength);
pProgressInfo->UpdateProgress(dwWritten);
}
if(hFile)
{
CloseHandle(hFile);
hFile = NULL;
}
}
catch(CUploaderException*)
{
if(hFile)
{
CloseHandle(hFile);
hFile = NULL;
}
throw;
}
return bRet;
}
DWORD CHttpFilePoster::AddFile(const CStdString& sFileName, const CStdString& sTitle, DWORD dwFileSize, BOOL bDelete)
{
//getting file size not supported
ATLASSERT(dwFileSize > 0);
CStdString strMime = GetMimeType(sFileName.c_str());
m_dwTotalFileBytes += dwFileSize;
m_listFiles.push_back(new CUploaderFile(sFileName, dwFileSize, bDelete, strMime, sTitle));
return ++m_dwFileCount;
}
void CHttpFilePoster::AddFormData(const CStdString& strName, const CStdString& strValue)
{
m_mapFormData[strName] = strValue;
}
DWORD CHttpFilePoster::RemoveFile(DWORD dwIndex)
{
std::list<CUploaderFile*>::iterator it;
int i;
for(i = 0, it = m_listFiles.begin(); it != m_listFiles.end() && i <= dwIndex; i++ , it++)
;
if(it != m_listFiles.end())
{
m_dwTotalFileBytes -= (*it)->dwSize;
m_dwFileCount--;
delete (*it);
m_listFiles.erase(it);
return i;
}
return -1;
}
DWORD CHttpFilePoster::GetFileCount()
{
m_dwFileCount;
return 0;
}
void CHttpFilePoster::Reset()
{
m_dwTotalFileBytes = 0;
m_dwFileCount = 0;
m_listFiles.clear();
m_mapFormData.clear();
}
///////////////////////////////////////////////////////////////////////////////
// called by WinINet on various connection events
// this function simply passes them to the caller though
// the progress info callback.
// note: this is a static member function, the dwContext parameter
// contains the this pointer
void CALLBACK CHttpFilePoster::InternetStatusCallback(
HINTERNET hInternet,
DWORD_PTR dwContext,
DWORD dwInternetStatus,
LPVOID lpvStatusInformation,
DWORD dwStatusInformationLength
)
{
CHttpFilePoster* pThis = (CHttpFilePoster*) dwContext;
ATLTRACE("InternetStatusCallback dwContext=0x%08x ", dwContext);
switch(dwInternetStatus)
{
case INTERNET_STATUS_RESOLVING_NAME:
ATLTRACE("Looking up the IP address of %s\n", (char*)lpvStatusInformation);
break;
case INTERNET_STATUS_NAME_RESOLVED:
ATLTRACE("IP address is: %s\n", (char*) lpvStatusInformation);
break;
case INTERNET_STATUS_CONNECTING_TO_SERVER:
ATLTRACE("Connecting to server\n");
//pSocketAddress = (SOCKADDR*) lpvStatusInformation;
break;
case INTERNET_STATUS_CONNECTED_TO_SERVER:
ATLTRACE("Connected to the server\n");
//pSocketAddress = (SOCKADDR*) lpvStatusInformation;
break;
case INTERNET_STATUS_SENDING_REQUEST:
ATLTRACE("Sending request\n");
break;
case INTERNET_STATUS_REQUEST_SENT:
ATLTRACE("Request sent\n");
break;
case INTERNET_STATUS_RECEIVING_RESPONSE:
ATLTRACE("Waiting for server response\n");
break;
case INTERNET_STATUS_RESPONSE_RECEIVED:
ATLTRACE("Response received\n");
break;
case INTERNET_STATUS_CLOSING_CONNECTION:
ATLTRACE("Closing connection\n");
break;
case INTERNET_STATUS_CONNECTION_CLOSED:
ATLTRACE("Connection closed\n");
break;
case INTERNET_STATUS_HANDLE_CREATED:
ATLTRACE("Handle created\n");
break;
case INTERNET_STATUS_HANDLE_CLOSING:
ATLTRACE("Handle closed\n");
break;
case INTERNET_STATUS_REQUEST_COMPLETE:
ATLTRACE("Async request complete\n");
break;
default:
ATLTRACE("Some other unknown callback\n");
break;
}
}
HRESULT CHttpFilePoster::ForegroundUpload( CProgressInfo *pProgress )
{
WIA_PUSHFUNCTION(TEXT("CHttpFilePoster::ForegroundUpload"));
DWORD dwError = 0;
try
{
std::list<CHttpFilePoster::CUploaderFile*>::iterator it, begin, end;
Startup();
Connect();
pProgress->StartSession(m_dwFileCount, m_dwTotalFileBytes);
begin = m_listFiles.begin();
end = m_listFiles.end();
for(it = begin; it != end; it++)
{
m_pCurrentFile = *it;
BeginUpload(pProgress);
WIA_TRACE((TEXT("Filename: %hs, Title: %hs, Size: %d"), (*it)->strNameMBCS.c_str(), (*it)->strTitle.c_str(), (*it)->dwSize ));
WIA_TRACE((TEXT("m_strFileHeader: %hs"), m_strFileHeader.c_str()));
WIA_TRACE((TEXT("m_strFilePost: %hs"), m_strFilePost.c_str()));
WIA_TRACE((TEXT("m_strCommonPost: %hs"), m_strCommonPost.c_str()));
SendString(m_strFileHeader);
pProgress->StartFile((*it)->strNameMBCS, (*it)->strTitle, (*it)->dwSize);
SendFile(pProgress);
SendString(m_strFilePost);
SendString(m_strCommonPost);
pProgress->EndFile();
FinishUpload();
}
pProgress->EndSession(!dwError);
Disconnect();
Shutdown();
}
catch(CUploaderException* pE)
{
dwError = pE->m_dwError;
delete pE;
}
return HRESULT_FROM_WIN32(dwError);
}
///////////////////////////////////////////////////////////////////////////////
UINT CHttpFilePoster::UploadThreadProc(LPVOID pVoid)
{
#if 0
CProgressInfo* pProgress = (CProgressInfo*) pVoid;
CUploadProgressDialog* pDialog = (CUploadProgressDialog*) pProgress->lParam;
CHttpFilePoster* pThis = (CHttpFilePoster*) pDialog->m_pHttpFilePoster;
DWORD dwError = 0;
try
{
std::list<CHttpFilePoster::CUploaderFile*>::iterator it, begin, end;
pThis->Startup();
pThis->Connect();
pProgress->StartSession(pThis->m_dwFileCount, pThis->m_dwTotalFileBytes);
begin = pThis->m_listFiles.begin();
end = pThis->m_listFiles.end();
for(it = begin; it != end; it++)
{
pThis->m_pCurrentFile = *it;
pThis->BeginUpload(pProgress);
pThis->SendString(pThis->m_strFileHeader);
pProgress->StartFile((*it)->strNameMBCS, (*it)->strTitle, (*it)->dwSize);
pThis->SendFile(pProgress);
pThis->SendString(pThis->m_strFilePost);
pThis->SendString(pThis->m_strCommonPost);
pProgress->EndFile();
pThis->FinishUpload();
}
pProgress->EndSession(!dwError);
pThis->Disconnect();
pThis->Shutdown();
}
catch(CUploaderException* pE)
{
dwError = pE->m_dwError;
delete pE;
}
::SendMessage(pDialog->m_hWnd, UPLOAD_WM_THREAD_DONE, dwError, 0);
::SendMessage(pThis->m_hWndParent, UPLOAD_WM_THREAD_DONE, dwError, 0);
return dwError;
#else
return 0;
#endif
}