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.
825 lines
21 KiB
825 lines
21 KiB
/*++
|
|
|
|
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;
|
|
}
|