826 lines
21 KiB
C++
826 lines
21 KiB
C++
/*++
|
||
|
||
Copyright (c) 1994 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
sendapi.cxx
|
||
|
||
Abstract:
|
||
|
||
This file contains the implementation of the HttpSendRequestA API.
|
||
|
||
Contents:
|
||
HttpSendRequestA
|
||
HttpSendRequestW
|
||
HttpSendRequestExA
|
||
HttpSendRequestExW
|
||
HttpEndRequestA
|
||
HttpEndRequestW
|
||
HttpWrapSendRequest
|
||
|
||
Author:
|
||
|
||
Keith Moore (keithmo) 16-Nov-1994
|
||
|
||
Revision History:
|
||
|
||
29-Apr-97 rfirth
|
||
Conversion to FSM
|
||
|
||
--*/
|
||
|
||
#include <wininetp.h>
|
||
#include <perfdiag.hxx>
|
||
#include "httpp.h"
|
||
|
||
//
|
||
// private prototypes
|
||
//
|
||
|
||
PRIVATE
|
||
BOOL
|
||
HttpWrapSendRequest(
|
||
IN HINTERNET hRequest,
|
||
IN LPCSTR lpszHeaders OPTIONAL,
|
||
IN DWORD dwHeadersLength,
|
||
IN LPVOID lpOptional OPTIONAL,
|
||
IN DWORD dwOptionalLength,
|
||
IN DWORD dwOptionalLengthTotal,
|
||
IN AR_TYPE arRequest
|
||
);
|
||
|
||
//
|
||
// functions
|
||
//
|
||
|
||
|
||
INTERNETAPI_(BOOL) HttpSendRequestA(
|
||
IN HINTERNET hRequest,
|
||
IN LPCSTR lpszHeaders OPTIONAL,
|
||
IN DWORD dwHeadersLength,
|
||
IN LPVOID lpOptional OPTIONAL,
|
||
IN DWORD dwOptionalLength
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Sends the specified request to the HTTP server.
|
||
|
||
Arguments:
|
||
|
||
hRequest - An open HTTP request handle returned by
|
||
HttpOpenRequest()
|
||
|
||
lpszHeaders - Additional headers to be appended to the request.
|
||
This may be NULL if there are no additional
|
||
headers to append
|
||
|
||
dwHeadersLength - The length (in characters) of the additional
|
||
headers. If this is -1L and lpszAdditional is
|
||
non-NULL, then lpszAdditional is assumed to be
|
||
zero terminated (ASCIIZ)
|
||
|
||
lpOptionalData - Any optional data to send immediately after the
|
||
request headers. This is typically used for POST
|
||
operations. This may be NULL if there is no
|
||
optional data to send
|
||
|
||
dwOptionalDataLength - The length (in BYTEs) of the optional data. This
|
||
may be zero if there is no optional data to send
|
||
|
||
Return Value:
|
||
|
||
BOOL
|
||
Success - TRUE
|
||
|
||
Failure - FALSE. For more information call GetLastError(). If the
|
||
request was async, then GetLastError() will return
|
||
ERROR_IO_PENDING which means that the operation initially
|
||
succeeded, and that the caller should wait for the status
|
||
callback to discover the final success/failure status
|
||
|
||
--*/
|
||
|
||
{
|
||
DEBUG_ENTER_API((DBG_API,
|
||
Bool,
|
||
"HttpSendRequestA",
|
||
"%#x, %.80q, %d, %#x, %d",
|
||
hRequest,
|
||
lpszHeaders,
|
||
dwHeadersLength,
|
||
lpOptional,
|
||
dwOptionalLength
|
||
));
|
||
|
||
|
||
BOOL fRet= HttpWrapSendRequest(
|
||
hRequest,
|
||
lpszHeaders,
|
||
dwHeadersLength,
|
||
lpOptional,
|
||
dwOptionalLength,
|
||
0,
|
||
AR_HTTP_SEND_REQUEST
|
||
);
|
||
|
||
|
||
DEBUG_LEAVE_API(fRet);
|
||
|
||
return fRet;
|
||
}
|
||
|
||
|
||
INTERNETAPI_(BOOL) HttpSendRequestW(
|
||
IN HINTERNET hRequest,
|
||
IN LPCWSTR lpszHeaders OPTIONAL,
|
||
IN DWORD dwHeadersLength,
|
||
IN LPVOID lpOptional OPTIONAL,
|
||
IN DWORD dwOptionalLength
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Sends the specified request to the HTTP server.
|
||
|
||
Arguments:
|
||
|
||
hRequest - An open HTTP request handle returned by
|
||
HttpOpenRequest()
|
||
|
||
lpszHeaders - Additional headers to be appended to the request.
|
||
This may be NULL if there are no additional
|
||
headers to append
|
||
|
||
dwHeadersLength - The length (in characters) of the additional
|
||
headers. If this is -1L and lpszAdditional is
|
||
non-NULL, then lpszAdditional is assumed to be
|
||
zero terminated (ASCIIZ)
|
||
|
||
lpOptionalData - Any optional data to send immediately after the
|
||
request headers. This is typically used for POST
|
||
operations. This may be NULL if there is no
|
||
optional data to send
|
||
|
||
dwOptionalDataLength - The length (in BYTEs) of the optional data. This
|
||
may be zero if there is no optional data to send
|
||
|
||
Return Value:
|
||
|
||
BOOL
|
||
Success - TRUE
|
||
|
||
Failure - FALSE. For more information call GetLastError(). If the
|
||
request was async, then GetLastError() will return
|
||
ERROR_IO_PENDING which means that the operation initially
|
||
succeeded, and that the caller should wait for the status
|
||
callback to discover the final success/failure status
|
||
|
||
--*/
|
||
|
||
{
|
||
DEBUG_ENTER_API((DBG_API,
|
||
Bool,
|
||
"HttpSendRequestW",
|
||
"%#x, %.80wq, %d, %#x, %d",
|
||
hRequest,
|
||
lpszHeaders,
|
||
dwHeadersLength,
|
||
lpOptional,
|
||
dwOptionalLength
|
||
));
|
||
|
||
DWORD dwErr = ERROR_SUCCESS;
|
||
BOOL fResult = FALSE;
|
||
MEMORYPACKET mpHeaders;
|
||
|
||
if (!hRequest)
|
||
{
|
||
dwErr = ERROR_INVALID_HANDLE;
|
||
goto cleanup;
|
||
}
|
||
if (lpszHeaders)
|
||
{
|
||
ALLOC_MB(lpszHeaders, dwHeadersLength, mpHeaders);
|
||
if (!mpHeaders.psStr)
|
||
{
|
||
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
||
goto cleanup;
|
||
}
|
||
UNICODE_TO_ANSI(lpszHeaders, mpHeaders);
|
||
}
|
||
fResult = HttpWrapSendRequest(hRequest, mpHeaders.psStr, mpHeaders.dwSize,
|
||
lpOptional, dwOptionalLength, 0, AR_HTTP_SEND_REQUEST);
|
||
|
||
cleanup:
|
||
if (dwErr!=ERROR_SUCCESS)
|
||
{
|
||
SetLastError(dwErr);
|
||
DEBUG_ERROR(HTTP, dwErr);
|
||
}
|
||
DEBUG_LEAVE_API(fResult);
|
||
return fResult;
|
||
}
|
||
|
||
|
||
INTERNETAPI_(BOOL) HttpSendRequestExA(
|
||
IN HINTERNET hRequest,
|
||
IN LPINTERNET_BUFFERSA lpBuffersIn OPTIONAL,
|
||
OUT LPINTERNET_BUFFERSA lpBuffersOut OPTIONAL,
|
||
IN DWORD dwFlags,
|
||
IN DWORD_PTR dwContext
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
description-of-function.
|
||
|
||
Arguments:
|
||
|
||
hRequest -
|
||
lpBuffersIn -
|
||
lpBuffersOut -
|
||
dwFlags -
|
||
dwContext -
|
||
|
||
Return Value:
|
||
|
||
WINAPI
|
||
|
||
--*/
|
||
|
||
{
|
||
DEBUG_ENTER_API((DBG_API,
|
||
Bool,
|
||
"HttpSendRequestExA",
|
||
"%#x, %#x, %#x, %#x, %#x",
|
||
hRequest,
|
||
lpBuffersIn,
|
||
lpBuffersOut,
|
||
dwFlags,
|
||
dwContext
|
||
));
|
||
|
||
DWORD error = ERROR_SUCCESS;
|
||
LPCSTR lpszHeaders = NULL;
|
||
DWORD dwHeadersLength = 0;
|
||
LPVOID lpOptional = NULL;
|
||
DWORD dwOptionalLength = 0;
|
||
DWORD dwOptionalLengthTotal = 0;
|
||
BOOL fRet = FALSE;
|
||
|
||
if ( lpBuffersOut )
|
||
{
|
||
error = ERROR_INVALID_PARAMETER;
|
||
goto quit;
|
||
}
|
||
|
||
if ( lpBuffersIn )
|
||
{
|
||
if ( IsBadReadPtr(lpBuffersIn, sizeof(INTERNET_BUFFERSA)) ||
|
||
lpBuffersIn->dwStructSize != sizeof(INTERNET_BUFFERSA) )
|
||
{
|
||
error = ERROR_INVALID_PARAMETER;
|
||
goto quit;
|
||
}
|
||
|
||
lpszHeaders = lpBuffersIn->lpcszHeader;
|
||
dwHeadersLength = lpBuffersIn->dwHeadersLength;
|
||
lpOptional = lpBuffersIn->lpvBuffer;
|
||
dwOptionalLength = lpBuffersIn->dwBufferLength;
|
||
dwOptionalLengthTotal = lpBuffersIn->dwBufferTotal;
|
||
}
|
||
|
||
fRet= HttpWrapSendRequest(
|
||
hRequest,
|
||
lpszHeaders,
|
||
dwHeadersLength,
|
||
lpOptional,
|
||
dwOptionalLength,
|
||
dwOptionalLengthTotal,
|
||
AR_HTTP_BEGIN_SEND_REQUEST
|
||
);
|
||
|
||
quit:
|
||
|
||
if ( error != ERROR_SUCCESS )
|
||
{
|
||
SetLastError(error);
|
||
DEBUG_ERROR(HTTP, error);
|
||
fRet = FALSE;
|
||
}
|
||
|
||
DEBUG_LEAVE_API(fRet);
|
||
|
||
return fRet;
|
||
}
|
||
|
||
|
||
INTERNETAPI_(BOOL) HttpSendRequestExW(
|
||
IN HINTERNET hRequest,
|
||
IN LPINTERNET_BUFFERSW lpBuffersIn OPTIONAL,
|
||
OUT LPINTERNET_BUFFERSW lpBuffersOut OPTIONAL,
|
||
IN DWORD dwFlags,
|
||
IN DWORD_PTR dwContext
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
description-of-function.
|
||
|
||
Arguments:
|
||
|
||
hRequest -
|
||
lpBuffersIn -
|
||
lpBuffersOut -
|
||
dwFlags -
|
||
dwContext -
|
||
|
||
Return Value:
|
||
|
||
BOOL
|
||
|
||
--*/
|
||
|
||
{
|
||
DEBUG_ENTER_API((DBG_API,
|
||
Bool,
|
||
"HttpSendRequestExW",
|
||
"%#x, %#x, %#x, %#x, %#x",
|
||
hRequest,
|
||
lpBuffersIn,
|
||
lpBuffersOut,
|
||
dwFlags,
|
||
dwContext
|
||
));
|
||
|
||
DWORD dwErr = ERROR_SUCCESS;
|
||
BOOL fResult = FALSE;
|
||
MEMORYPACKET mpHeaders;
|
||
LPVOID pOptional = NULL;
|
||
DWORD dwOptionalLength = 0;
|
||
DWORD dwOptionalLengthTotal = 0;
|
||
|
||
if (!hRequest)
|
||
{
|
||
dwErr = ERROR_INVALID_HANDLE;
|
||
}
|
||
else if (lpBuffersOut)
|
||
{
|
||
dwErr = ERROR_INVALID_PARAMETER;
|
||
}
|
||
else
|
||
{
|
||
if ( lpBuffersIn )
|
||
{
|
||
if (IsBadReadPtr(lpBuffersIn, sizeof(INTERNET_BUFFERS))
|
||
||
|
||
(lpBuffersIn->dwStructSize != sizeof(INTERNET_BUFFERSW)))
|
||
{
|
||
dwErr = ERROR_INVALID_PARAMETER;
|
||
goto cleanup;
|
||
}
|
||
|
||
if (lpBuffersIn->lpcszHeader)
|
||
{
|
||
ALLOC_MB(lpBuffersIn->lpcszHeader, lpBuffersIn->dwHeadersLength, mpHeaders);
|
||
if (!mpHeaders.psStr)
|
||
{
|
||
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
||
goto cleanup;
|
||
}
|
||
UNICODE_TO_ANSI(lpBuffersIn->lpcszHeader, mpHeaders);
|
||
}
|
||
pOptional = lpBuffersIn->lpvBuffer;
|
||
dwOptionalLength = lpBuffersIn->dwBufferLength;
|
||
dwOptionalLengthTotal = lpBuffersIn->dwBufferTotal;
|
||
}
|
||
|
||
fResult = HttpWrapSendRequest(
|
||
hRequest,
|
||
mpHeaders.psStr,
|
||
mpHeaders.dwSize,
|
||
pOptional,
|
||
dwOptionalLength,
|
||
dwOptionalLengthTotal,
|
||
AR_HTTP_BEGIN_SEND_REQUEST
|
||
);
|
||
}
|
||
|
||
cleanup:
|
||
if (dwErr!=ERROR_SUCCESS)
|
||
{
|
||
SetLastError(dwErr);
|
||
DEBUG_ERROR(HTTP, dwErr);
|
||
}
|
||
DEBUG_LEAVE_API(fResult);
|
||
return fResult;
|
||
}
|
||
|
||
|
||
INTERNETAPI_(BOOL) HttpEndRequestA(
|
||
IN HINTERNET hRequest,
|
||
OUT LPINTERNET_BUFFERSA lpBuffersOut OPTIONAL,
|
||
IN DWORD dwFlags,
|
||
IN DWORD_PTR dwContext
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
description-of-function.
|
||
|
||
Arguments:
|
||
|
||
hRequest -
|
||
lpBuffersOut -
|
||
dwFlags -
|
||
dwContext -
|
||
|
||
Return Value:
|
||
|
||
WINAPI
|
||
|
||
--*/
|
||
|
||
{
|
||
DEBUG_ENTER_API((DBG_API,
|
||
Bool,
|
||
"HttpEndRequestA",
|
||
"%#x, %#x, %#x, %#x",
|
||
hRequest,
|
||
lpBuffersOut,
|
||
dwFlags,
|
||
dwContext
|
||
));
|
||
|
||
DWORD error = ERROR_SUCCESS;
|
||
IN LPCSTR lpszHeaders = NULL;
|
||
IN DWORD dwHeadersLength = 0;
|
||
IN LPVOID lpOptional = NULL;
|
||
IN DWORD dwOptionalLength = 0;
|
||
BOOL fRet = FALSE;
|
||
|
||
if ( lpBuffersOut )
|
||
{
|
||
error = ERROR_INVALID_PARAMETER;
|
||
goto quit;
|
||
}
|
||
|
||
|
||
fRet= HttpWrapSendRequest(
|
||
hRequest,
|
||
NULL,
|
||
0,
|
||
NULL,
|
||
0,
|
||
0,
|
||
AR_HTTP_END_SEND_REQUEST
|
||
);
|
||
|
||
quit:
|
||
|
||
if ( error != ERROR_SUCCESS )
|
||
{
|
||
SetLastError(error);
|
||
DEBUG_ERROR(HTTP, error);
|
||
fRet = FALSE;
|
||
}
|
||
|
||
DEBUG_LEAVE_API(fRet);
|
||
|
||
return fRet;
|
||
}
|
||
|
||
|
||
INTERNETAPI_(BOOL) HttpEndRequestW(
|
||
IN HINTERNET hRequest,
|
||
OUT LPINTERNET_BUFFERSW lpBuffersOut OPTIONAL,
|
||
IN DWORD dwFlags,
|
||
IN DWORD_PTR dwContext
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
description-of-function.
|
||
|
||
Arguments:
|
||
|
||
hRequest -
|
||
lpBuffersOut -
|
||
dwFlags -
|
||
dwContext -
|
||
|
||
Return Value:
|
||
|
||
BOOL
|
||
|
||
--*/
|
||
|
||
{
|
||
DEBUG_ENTER_API((DBG_API,
|
||
Bool,
|
||
"HttpEndRequestW",
|
||
"%#x, %#x, %#x, %#x",
|
||
hRequest,
|
||
lpBuffersOut,
|
||
dwFlags,
|
||
dwContext
|
||
));
|
||
|
||
DWORD dwErr = ERROR_SUCCESS;
|
||
BOOL fResult = FALSE;
|
||
|
||
if (!hRequest)
|
||
{
|
||
dwErr = ERROR_INVALID_HANDLE;
|
||
}
|
||
else if (lpBuffersOut)
|
||
{
|
||
dwErr = ERROR_INVALID_PARAMETER;
|
||
}
|
||
else
|
||
{
|
||
fResult = HttpWrapSendRequest(hRequest, NULL, 0, NULL, 0, 0, AR_HTTP_END_SEND_REQUEST);
|
||
}
|
||
|
||
if (dwErr!=ERROR_SUCCESS)
|
||
{
|
||
SetLastError(dwErr);
|
||
DEBUG_ERROR(HTTP, dwErr);
|
||
}
|
||
DEBUG_LEAVE_API(fResult);
|
||
return fResult;
|
||
}
|
||
|
||
|
||
PRIVATE
|
||
BOOL
|
||
HttpWrapSendRequest(
|
||
IN HINTERNET hRequest,
|
||
IN LPCSTR lpszHeaders OPTIONAL,
|
||
IN DWORD dwHeadersLength,
|
||
IN LPVOID lpOptional OPTIONAL,
|
||
IN DWORD dwOptionalLength,
|
||
IN DWORD dwOptionalLengthTotal,
|
||
IN AR_TYPE arRequest
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Sends the specified request to the HTTP server.
|
||
|
||
Arguments:
|
||
|
||
hRequest - An open HTTP request handle returned by
|
||
HttpOpenRequest()
|
||
|
||
lpszHeaders - Additional headers to be appended to the request.
|
||
This may be NULL if there are no additional
|
||
headers to append
|
||
|
||
dwHeadersLength - The length (in characters) of the additional
|
||
headers. If this is -1L and lpszAdditional is
|
||
non-NULL, then lpszAdditional is assumed to be
|
||
zero terminated (ASCIIZ)
|
||
|
||
lpOptionalData - Any optional data to send immediately after the
|
||
request headers. This is typically used for POST
|
||
operations. This may be NULL if there is no
|
||
optional data to send
|
||
|
||
dwOptionalDataLength - The length (in BYTEs) of the optional data. This
|
||
may be zero if there is no optional data to send
|
||
|
||
dwOptionalLengthTotal - Total length need to be sent for File Upload.
|
||
|
||
arRequest - Which API the caller is making,
|
||
assumed to be HttpEndRequestA, HttpSendRequestExA, or
|
||
HttpSendRequestA
|
||
|
||
Return Value:
|
||
|
||
BOOL
|
||
Success - TRUE
|
||
|
||
Failure - FALSE. For more information call GetLastError(). If the
|
||
request was async, then GetLastError() will return
|
||
ERROR_IO_PENDING which means that the operation initially
|
||
succeeded, and that the caller should wait for the status
|
||
callback to discover the final success/failure status
|
||
|
||
Comments:
|
||
|
||
--*/
|
||
|
||
{
|
||
DEBUG_ENTER((DBG_HTTP,
|
||
Bool,
|
||
"HttpWrapSendRequest",
|
||
"%#x, %.80q, %d, %#x, %d, %d",
|
||
hRequest,
|
||
lpszHeaders,
|
||
dwHeadersLength,
|
||
lpOptional,
|
||
dwOptionalLength,
|
||
dwOptionalLengthTotal
|
||
));
|
||
|
||
PERF_ENTER(HttpWrapSendRequest);
|
||
|
||
DWORD error = ERROR_SUCCESS;
|
||
HINTERNET hRequestMapped = NULL;
|
||
BOOL bDeref = TRUE;
|
||
|
||
if (!GlobalDataInitialized) {
|
||
error = ERROR_INTERNET_NOT_INITIALIZED;
|
||
goto done;
|
||
}
|
||
|
||
//
|
||
// we will need the thread info for several items
|
||
//
|
||
|
||
LPINTERNET_THREAD_INFO lpThreadInfo;
|
||
|
||
lpThreadInfo = InternetGetThreadInfo();
|
||
if (lpThreadInfo == NULL) {
|
||
error = ERROR_INTERNET_INTERNAL_ERROR;
|
||
goto done;
|
||
}
|
||
|
||
//
|
||
// the only FSMs that can come before this one are InternetOpenUrl() or
|
||
// HttpSendRequest() when we are performing nested send for https://
|
||
// tunnelling through proxy
|
||
//
|
||
|
||
INET_ASSERT((lpThreadInfo->Fsm == NULL)
|
||
|| (lpThreadInfo->Fsm->GetType() == FSM_TYPE_PARSE_HTTP_URL)
|
||
|| (lpThreadInfo->Fsm->GetType() == FSM_TYPE_OPEN_PROXY_TUNNEL)
|
||
);
|
||
|
||
INET_ASSERT( arRequest == AR_HTTP_SEND_REQUEST ||
|
||
arRequest == AR_HTTP_BEGIN_SEND_REQUEST ||
|
||
arRequest == AR_HTTP_END_SEND_REQUEST );
|
||
|
||
|
||
//
|
||
// map the handle
|
||
//
|
||
error = MapHandleToAddress(hRequest, (LPVOID *)&hRequestMapped, FALSE);
|
||
|
||
|
||
if ((error != ERROR_SUCCESS) && (hRequestMapped == NULL)) {
|
||
goto quit;
|
||
}
|
||
|
||
//
|
||
// Cast it to the object that we know. We are going to do caching
|
||
// semantics with this
|
||
//
|
||
|
||
HTTP_REQUEST_HANDLE_OBJECT * pRequest;
|
||
|
||
pRequest = (HTTP_REQUEST_HANDLE_OBJECT *)hRequestMapped;
|
||
|
||
//
|
||
// set the context and handle info & reset the error variables
|
||
//
|
||
|
||
|
||
_InternetSetContext(lpThreadInfo,
|
||
((INTERNET_HANDLE_OBJECT *)hRequestMapped)->GetContext()
|
||
);
|
||
_InternetSetObjectHandle(lpThreadInfo, hRequest, hRequestMapped);
|
||
_InternetClearLastError(lpThreadInfo);
|
||
|
||
//
|
||
// quit now if the handle was invalid
|
||
//
|
||
|
||
if (error != ERROR_SUCCESS) {
|
||
goto quit;
|
||
}
|
||
|
||
//
|
||
// use RIsHandleLocal() to discover 4 things:
|
||
//
|
||
// 1. Handle is valid
|
||
// 2. Handle is of expected type (HTTP Request in this case)
|
||
// 3. Handle is local or remote
|
||
// 4. Handle supports async I/O
|
||
//
|
||
|
||
BOOL isLocal;
|
||
BOOL isAsync;
|
||
|
||
error = RIsHandleLocal(hRequestMapped,
|
||
&isLocal,
|
||
&isAsync,
|
||
TypeHttpRequestHandle
|
||
);
|
||
|
||
if (error != ERROR_SUCCESS) {
|
||
goto quit;
|
||
}
|
||
|
||
//
|
||
// For SEND_REQUEST, and BEGIN_SEND_REQUEST, we need
|
||
// to do some basic initalization
|
||
//
|
||
|
||
if ( arRequest == AR_HTTP_SEND_REQUEST ||
|
||
arRequest == AR_HTTP_BEGIN_SEND_REQUEST)
|
||
{
|
||
BOOL fGoneOffline = FALSE;
|
||
|
||
|
||
error = pRequest->InitBeginSendRequest(lpszHeaders,
|
||
dwHeadersLength,
|
||
&lpOptional,
|
||
&dwOptionalLength,
|
||
dwOptionalLengthTotal,
|
||
&fGoneOffline
|
||
);
|
||
|
||
if ( error != ERROR_SUCCESS || fGoneOffline )
|
||
{
|
||
if ( error == ERROR_INTERNET_CACHE_SUCCESS )
|
||
{
|
||
error = ERROR_SUCCESS;
|
||
}
|
||
|
||
goto quit;
|
||
}
|
||
}
|
||
|
||
|
||
//
|
||
// send the request to the server. This may involve redirections and user
|
||
// authentication
|
||
//
|
||
|
||
//error = DoFsm(new CFsm_HttpSendRequest(lpOptional, dwOptionalLength, pRequest, arRequest));
|
||
//if (error == ERROR_IO_PENDING) {
|
||
// bDeref = FALSE;
|
||
//}
|
||
CFsm_HttpSendRequest * pFsm;
|
||
|
||
pFsm = new CFsm_HttpSendRequest(lpOptional, dwOptionalLength, pRequest, arRequest);
|
||
|
||
if (pFsm != NULL) {
|
||
if (isAsync && !lpThreadInfo->IsAsyncWorkerThread) {
|
||
error = pFsm->QueueWorkItem();
|
||
} else {
|
||
error = DoFsm(pFsm);
|
||
}
|
||
if (error == ERROR_IO_PENDING) {
|
||
bDeref = FALSE;
|
||
}
|
||
} else {
|
||
error = ERROR_NOT_ENOUGH_MEMORY;
|
||
}
|
||
|
||
quit:
|
||
|
||
//
|
||
// if we went async don't deref the handle
|
||
//
|
||
|
||
if (bDeref && (hRequestMapped != NULL)) {
|
||
DereferenceObject((LPVOID)hRequestMapped);
|
||
}
|
||
|
||
done:
|
||
|
||
BOOL success = TRUE;
|
||
|
||
// SetLastError must be called after PERF_LEAVE !!!
|
||
PERF_LEAVE(HttpWrapSendRequest);
|
||
|
||
if (error != ERROR_SUCCESS) {
|
||
|
||
SetLastError(error);
|
||
DEBUG_ERROR(HTTP, error);
|
||
success = FALSE;
|
||
}
|
||
|
||
DEBUG_LEAVE(success);
|
||
return success;
|
||
}
|