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.
2988 lines
62 KiB
2988 lines
62 KiB
/*++
|
|
|
|
Copyright (c) 1997 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
fsm.hxx
|
|
|
|
Abstract:
|
|
|
|
Contains Finite State Machine class definition
|
|
|
|
Author:
|
|
|
|
Richard L Firth (rfirth) 11-Apr-1997
|
|
|
|
Revision History:
|
|
|
|
11-Apr-1997 rfirth
|
|
Created
|
|
|
|
--*/
|
|
|
|
//
|
|
// types
|
|
//
|
|
|
|
//
|
|
// FSM_STATE - states FSMs can be in. We have some states defined for all FSMs,
|
|
// e.g. FSM_STATE_INIT, and other states that are used internally by the FSMs,
|
|
// e.g. FSM_STATE_1 through FSM_STATE_10
|
|
//
|
|
|
|
typedef enum {
|
|
FSM_STATE_BAD = -1,
|
|
FSM_STATE_INIT,
|
|
FSM_STATE_WAIT,
|
|
FSM_STATE_DONE,
|
|
FSM_STATE_ERROR,
|
|
FSM_STATE_CONTINUE,
|
|
FSM_STATE_FINISH,
|
|
FSM_STATE_1,
|
|
FSM_STATE_2,
|
|
FSM_STATE_3,
|
|
FSM_STATE_4,
|
|
FSM_STATE_5,
|
|
FSM_STATE_6,
|
|
FSM_STATE_7,
|
|
FSM_STATE_8,
|
|
FSM_STATE_9,
|
|
FSM_STATE_10
|
|
} FSM_STATE;
|
|
|
|
//
|
|
// FSM_HINT - QUICK if next operation is expected to complete quickly
|
|
//
|
|
|
|
typedef enum {
|
|
FSM_HINT_SLOW, // default
|
|
FSM_HINT_QUICK
|
|
} FSM_HINT;
|
|
|
|
//
|
|
// FSM_ACTION - type of (socket) action an FSM is waiting on
|
|
//
|
|
|
|
typedef enum {
|
|
FSM_ACTION_NONE = 0,
|
|
FSM_ACTION_CONNECT = 1,
|
|
FSM_ACTION_SEND,
|
|
FSM_ACTION_RECEIVE
|
|
} FSM_ACTION;
|
|
|
|
//
|
|
// FSM_TYPE - for debugging purposes
|
|
//
|
|
|
|
typedef enum {
|
|
FSM_TYPE_NONE,
|
|
FSM_TYPE_WAIT_FOR_COMPLETION,
|
|
FSM_TYPE_RESOLVE_HOST,
|
|
FSM_TYPE_SOCKET_CONNECT,
|
|
FSM_TYPE_SOCKET_SEND,
|
|
FSM_TYPE_SOCKET_RECEIVE,
|
|
FSM_TYPE_SOCKET_QUERY_AVAILABLE,
|
|
FSM_TYPE_SECURE_CONNECT,
|
|
FSM_TYPE_SECURE_HANDSHAKE,
|
|
FSM_TYPE_SECURE_NEGOTIATE,
|
|
FSM_TYPE_NEGOTIATE_LOOP,
|
|
FSM_TYPE_SECURE_SEND,
|
|
FSM_TYPE_SECURE_RECEIVE,
|
|
FSM_TYPE_GET_CONNECTION,
|
|
FSM_TYPE_HTTP_SEND_REQUEST,
|
|
FSM_TYPE_MAKE_CONNECTION,
|
|
FSM_TYPE_OPEN_CONNECTION,
|
|
FSM_TYPE_OPEN_PROXY_TUNNEL,
|
|
FSM_TYPE_SEND_REQUEST,
|
|
FSM_TYPE_RECEIVE_RESPONSE,
|
|
FSM_TYPE_HTTP_READ,
|
|
FSM_TYPE_HTTP_WRITE,
|
|
FSM_TYPE_READ_DATA,
|
|
FSM_TYPE_HTTP_QUERY_AVAILABLE,
|
|
FSM_TYPE_DRAIN_RESPONSE,
|
|
FSM_TYPE_REDIRECT,
|
|
FSM_TYPE_READ_LOOP,
|
|
FSM_TYPE_PARSE_HTTP_URL,
|
|
FSM_TYPE_PARSE_URL_FOR_HTTP,
|
|
FSM_TYPE_READ_FILE,
|
|
FSM_TYPE_READ_FILE_EX,
|
|
FSM_TYPE_WRITE_FILE,
|
|
FSM_TYPE_QUERY_DATA_AVAILABLE,
|
|
FSM_TYPE_FTP_CONNECT,
|
|
FSM_TYPE_FTP_FIND_FIRST_FILE,
|
|
FSM_TYPE_FTP_GET_FILE,
|
|
FSM_TYPE_FTP_PUT_FILE,
|
|
FSM_TYPE_FTP_DELETE_FILE,
|
|
FSM_TYPE_FTP_RENAME_FILE,
|
|
FSM_TYPE_FTP_GET_FILE_SIZE,
|
|
FSM_TYPE_FTP_OPEN_FILE,
|
|
FSM_TYPE_FTP_COMMAND,
|
|
FSM_TYPE_FTP_CREATE_DIRECTORY,
|
|
FSM_TYPE_FTP_REMOVE_DIRECTORY,
|
|
FSM_TYPE_FTP_SET_CURRENT_DIRECTORY,
|
|
FSM_TYPE_FTP_GET_CURRENT_DIRECTORY,
|
|
FSM_TYPE_GOPHER_FIND_FIRST_FILE,
|
|
FSM_TYPE_GOPHER_OPEN_FILE,
|
|
FSM_TYPE_GOPHER_GET_ATTRIBUTE,
|
|
FSM_TYPE_INTERNET_PARSE_URL,
|
|
FSM_TYPE_INTERNET_FIND_NEXT_FILE,
|
|
FSM_TYPE_INTERNET_QUERY_DATA_AVAILABLE,
|
|
FSM_TYPE_INTERNET_WRITE_FILE,
|
|
FSM_TYPE_INTERNET_READ_FILE,
|
|
FSM_TYPE_BACKGROUND_TASK
|
|
} FSM_TYPE;
|
|
|
|
//
|
|
// API_TYPE - what type of parameter API returns. Used in conjunction with
|
|
// SetApi()
|
|
//
|
|
|
|
typedef enum {
|
|
ApiType_None,
|
|
ApiType_Handle,
|
|
ApiType_Bool
|
|
} API_TYPE;
|
|
|
|
//
|
|
// macros
|
|
//
|
|
|
|
#define COPY_MANDATORY_PARAM(y,x) \
|
|
if (x) { \
|
|
y = NewString(x); \
|
|
if ( y == NULL) { \
|
|
SetError(ERROR_NOT_ENOUGH_MEMORY); \
|
|
} \
|
|
} \
|
|
else { \
|
|
y = NULL; \
|
|
INET_ASSERT(FALSE); \
|
|
}
|
|
|
|
#define COPY_MANDATORY_PARAMW(y,x) \
|
|
if (x) { \
|
|
y = NewStringW(x); \
|
|
if ( y == NULL) { \
|
|
SetError(ERROR_NOT_ENOUGH_MEMORY); \
|
|
} \
|
|
} \
|
|
else { \
|
|
y = NULL; \
|
|
INET_ASSERT(FALSE); \
|
|
}
|
|
|
|
|
|
#define COPY_OPTIONAL_PARAM(y,x) \
|
|
if (x) { \
|
|
y = NewString(x); \
|
|
if ( y == NULL) { \
|
|
SetError(ERROR_NOT_ENOUGH_MEMORY); \
|
|
} \
|
|
} \
|
|
else { \
|
|
y = NULL; \
|
|
}
|
|
|
|
#define DELETE_MANDATORY_PARAM(x) \
|
|
if (x) { \
|
|
x=(LPSTR)FREE_MEMORY(x); \
|
|
} \
|
|
else { \
|
|
INET_ASSERT(FALSE); \
|
|
}
|
|
|
|
#define DELETE_MANDATORY_PARAMW(x) \
|
|
if (x) { \
|
|
x=(LPWSTR)FREE_MEMORY(x); \
|
|
} \
|
|
else { \
|
|
INET_ASSERT(FALSE); \
|
|
}
|
|
|
|
|
|
#define DELETE_OPTIONAL_PARAM(x) \
|
|
if (x) { \
|
|
x=(LPSTR)FREE_MEMORY(x); \
|
|
}
|
|
|
|
//
|
|
// functions
|
|
//
|
|
|
|
BOOL
|
|
wInternetQueryDataAvailable(
|
|
IN LPVOID hFileMapped,
|
|
OUT LPDWORD lpdwNumberOfBytesAvailable,
|
|
IN DWORD dwFlags,
|
|
IN DWORD_PTR dwContext
|
|
);
|
|
|
|
|
|
//
|
|
// classes
|
|
//
|
|
|
|
//
|
|
// CFsm - the finite state machine class. Describes the basic work unit,
|
|
// assumable by any available thread.
|
|
//
|
|
// State machines are chainable on a stack: the head of the stack is always the
|
|
// currently executing state machine
|
|
//
|
|
// For non-blocking socket operations, state machines are associated with the
|
|
// socket handle blocking the state machine
|
|
//
|
|
// State machines have a priority which is used in deciding which runnable state
|
|
// machine is executed next
|
|
//
|
|
|
|
class CFsm : public CPriorityListEntry {
|
|
|
|
private:
|
|
|
|
CFsm * m_Link; // 0x10
|
|
DWORD m_dwError; // 0x14
|
|
LPINTERNET_THREAD_INFO m_lpThreadInfo; // 0x18
|
|
DWORD_PTR m_dwContext; // 0x1C
|
|
HINTERNET m_hObject; // 0x20
|
|
INTERNET_HANDLE_OBJECT * m_hObjectMapped; // 0x24
|
|
DWORD m_dwMappedErrorCode; // 0x28
|
|
FSM_STATE m_State; // 0x2C
|
|
FSM_STATE m_NextState; // 0x30
|
|
FSM_STATE m_FunctionState; // 0x34
|
|
DWORD (*m_lpfnHandler)(CFsm *); // 0x38
|
|
LPVOID m_lpvContext; // 0x3C
|
|
FSM_HINT m_Hint; // 0x40
|
|
SOCKET m_Socket; // 0x44
|
|
FSM_ACTION m_Action; // 0x48
|
|
DWORD_PTR m_dwBlockId; // 0x4C
|
|
DWORD m_dwTimeout; // 0x50
|
|
BOOL m_fTimeoutWraps;
|
|
DWORD m_dwTimer; // 0x54
|
|
BOOL m_bTimerStarted; // 0x58
|
|
BOOL m_bIsApi; // 0x5C
|
|
// indicates a non-yielding fsm, that blocks a full thread while it executes
|
|
BOOL m_bIsBlockingFsm; // 0x60
|
|
API_TYPE m_ApiType; // 0x64
|
|
union {
|
|
BOOL Bool;
|
|
HINTERNET Handle;
|
|
} m_ApiResult; // 0x68
|
|
DWORD m_dwApiData; // 0x6C
|
|
|
|
BOOL m_bHasTimeout;
|
|
BOOL m_bOnAsyncList;
|
|
BOOL m_bPushPop;
|
|
|
|
//#if INET_DEBUG
|
|
#ifdef STRESS_BUG_DEBUG
|
|
|
|
DWORD m_Signature; // 0x70
|
|
|
|
public:
|
|
|
|
DWORD m_ThreadId; // 0x74
|
|
|
|
#define INET_ASSERT_X(x) if ( !(x) ) { OutputDebugString("WinHttp5.DLL: FSM still in use, contact venkatk, x54275 \r\n"); \
|
|
DebugBreak(); }
|
|
|
|
#define FSM_SIGNATURE 0x5f4d5346 // "FSM_"
|
|
#define INIT_FSM() m_Signature = FSM_SIGNATURE; \
|
|
m_Type = FSM_TYPE_NONE; \
|
|
m_ThreadId = 0
|
|
#define CHECK_FSM() INET_ASSERT_X(m_Signature == FSM_SIGNATURE)
|
|
#define SET_OWNED() m_ThreadId = GetCurrentThreadId()
|
|
#define RESET_OWNED() m_ThreadId = 0
|
|
#define CHECK_OWNED() INET_ASSERT_X(m_ThreadId == GetCurrentThreadId())
|
|
#define CHECK_UNOWNED() INET_ASSERT_X(m_ThreadId == 0)
|
|
#define SET_FSM_OWNED(p) if (p) p->m_ThreadId = GetCurrentThreadId()
|
|
#define RESET_FSM_OWNED(p) if (p) p->m_ThreadId = 0
|
|
#define CHECK_FSM_OWNED(p) if (p) INET_ASSERT_X(p->m_ThreadId == GetCurrentThreadId())
|
|
#define CHECK_FSM_UNOWNED(p) if (p) INET_ASSERT_X(p->m_ThreadId == 0)
|
|
|
|
#else
|
|
|
|
#define INIT_FSM() /* NOTHING */
|
|
#define CHECK_FSM() /* NOTHING */
|
|
#define SET_OWNED() /* NOTHING */
|
|
#define RESET_OWNED() /* NOTHING */
|
|
#define CHECK_OWNED() /* NOTHING */
|
|
#define CHECK_UNOWNED() /* NOTHING */
|
|
#define SET_FSM_OWNED(p) /* NOTHING */
|
|
#define RESET_FSM_OWNED(p) /* NOTHING */
|
|
#define CHECK_FSM_OWNED(p) /* NOTHING */
|
|
#define CHECK_FSM_UNOWNED(p) /* NOTHING */
|
|
|
|
#endif
|
|
|
|
protected:
|
|
|
|
FSM_TYPE m_Type; // 0x78
|
|
|
|
#define SET_FSM_TYPE(type) m_Type = FSM_TYPE_ ## type
|
|
|
|
public:
|
|
|
|
CFsm(DWORD (* lpfnHandler)(CFsm *), LPVOID lpvContext, BOOL fPushPop = TRUE);
|
|
virtual ~CFsm();
|
|
|
|
VOID
|
|
Push(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
Pop(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
SetPushPop(BOOL fPushPop) {
|
|
m_bPushPop = fPushPop;
|
|
}
|
|
|
|
DWORD GetError(VOID) const {
|
|
return m_dwError;
|
|
}
|
|
|
|
VOID SetError(DWORD Error) {
|
|
m_dwError = Error;
|
|
}
|
|
|
|
BOOL IsInvalid(VOID) {
|
|
|
|
INET_ASSERT(m_hObjectMapped != NULL);
|
|
|
|
return (m_hObjectMapped != NULL)
|
|
? m_hObjectMapped->IsInvalidated()
|
|
: FALSE;
|
|
}
|
|
|
|
DWORD GetMappedError(VOID) const {
|
|
return m_dwMappedErrorCode;
|
|
}
|
|
|
|
VOID SetMappedError(DWORD dwError) {
|
|
m_dwMappedErrorCode = dwError;
|
|
}
|
|
|
|
LPINTERNET_THREAD_INFO GetThreadInfo(VOID) const {
|
|
return m_lpThreadInfo;
|
|
}
|
|
|
|
VOID SetThreadInfo(LPINTERNET_THREAD_INFO lpThreadInfo) {
|
|
m_lpThreadInfo = lpThreadInfo;
|
|
}
|
|
|
|
DWORD_PTR GetAppContext(VOID) const {
|
|
return m_dwContext;
|
|
}
|
|
|
|
HINTERNET GetAppHandle(VOID) const {
|
|
return m_hObject;
|
|
}
|
|
|
|
HINTERNET GetMappedHandle(VOID) const {
|
|
return m_hObjectMapped;
|
|
}
|
|
|
|
INTERNET_HANDLE_OBJECT * GetMappedHandleObject(VOID) const {
|
|
return (INTERNET_HANDLE_OBJECT *)m_hObjectMapped;
|
|
}
|
|
|
|
FSM_STATE GetState(VOID) const {
|
|
return m_State;
|
|
}
|
|
|
|
VOID SetState(FSM_STATE State) {
|
|
m_State = State;
|
|
}
|
|
|
|
FSM_STATE GetNextState(VOID) const {
|
|
return m_NextState;
|
|
}
|
|
|
|
VOID SetNextState(FSM_STATE State) {
|
|
m_NextState = State;
|
|
}
|
|
|
|
FSM_STATE GetFunctionState(VOID) const {
|
|
|
|
//
|
|
// We should never enter into this state, cause the FSMs
|
|
// themselves must be correct enough to always set the
|
|
// next function state before exiting their state.
|
|
//
|
|
|
|
//INET_ASSERT(m_FunctionState != FSM_STATE_BAD);
|
|
|
|
return m_FunctionState;
|
|
}
|
|
|
|
VOID SetFunctionState(FSM_STATE State) {
|
|
m_FunctionState = State;
|
|
}
|
|
|
|
VOID SetWait(VOID) {
|
|
SetState(FSM_STATE_WAIT);
|
|
}
|
|
|
|
BOOL IsWait(VOID) {
|
|
return (m_State == FSM_STATE_WAIT) ? TRUE : FALSE;
|
|
}
|
|
|
|
VOID SetErrorState(DWORD Error) {
|
|
SetError(Error);
|
|
SetState(FSM_STATE_ERROR);
|
|
}
|
|
|
|
VOID SetDone(VOID) {
|
|
SetState(FSM_STATE_DONE);
|
|
}
|
|
|
|
VOID SetDone(DWORD Error) {
|
|
SetError(Error);
|
|
SetState(FSM_STATE_DONE);
|
|
}
|
|
|
|
BOOL IsDone(VOID) {
|
|
return (m_State == FSM_STATE_DONE) ? TRUE : FALSE;
|
|
}
|
|
|
|
LPVOID GetContext(VOID) const {
|
|
return m_lpvContext;
|
|
}
|
|
|
|
VOID SetContext(LPVOID lpvContext) {
|
|
m_lpvContext = lpvContext;
|
|
}
|
|
|
|
LPVOID GetHandler(VOID) const {
|
|
return (LPVOID)m_lpfnHandler;
|
|
}
|
|
|
|
VOID SetHandler(LPVOID lpfnHandler) {
|
|
m_lpfnHandler = (DWORD (*)(CFsm *))lpfnHandler;
|
|
}
|
|
|
|
VOID SetHandler2(DWORD (* lpfnHandler)(CFsm *)) {
|
|
m_lpfnHandler = lpfnHandler;
|
|
}
|
|
|
|
SOCKET GetSocket(VOID) const {
|
|
return m_Socket;
|
|
}
|
|
|
|
VOID SetSocket(SOCKET Socket) {
|
|
|
|
INET_ASSERT(m_Socket == INVALID_SOCKET);
|
|
|
|
m_Socket = Socket;
|
|
}
|
|
|
|
VOID ResetSocket(VOID) {
|
|
m_Socket = INVALID_SOCKET;
|
|
}
|
|
|
|
BOOL IsActive(VOID) {
|
|
return (m_Socket == INVALID_SOCKET) ? FALSE : TRUE;
|
|
}
|
|
|
|
FSM_ACTION GetAction(VOID) const {
|
|
return m_Action;
|
|
}
|
|
|
|
VOID SetAction(FSM_ACTION Action) {
|
|
m_Action = Action;
|
|
}
|
|
|
|
DWORD_PTR GetBlockId(VOID) const {
|
|
return m_dwBlockId;
|
|
}
|
|
|
|
VOID SetBlockId(DWORD_PTR dwBlockId) {
|
|
m_dwBlockId = dwBlockId;
|
|
}
|
|
|
|
BOOL IsBlockedOn(DWORD_PTR dwBlockId) {
|
|
return (m_dwBlockId == dwBlockId) ? TRUE : FALSE;
|
|
}
|
|
|
|
DWORD GetTimeout(VOID) const {
|
|
return m_dwTimeout;
|
|
}
|
|
|
|
// This code needs to handle system time roll over.
|
|
// SetTimeout is passed the duration, and we calculate the ultimate time
|
|
// However, this may result in a rollover -- e.g. if the current time is
|
|
// 0xffffff00, the ultimate time could be 0x000000fd
|
|
|
|
// IsTimedOut is passed the current tick count, however, and in the past
|
|
// would return TRUE immediately.
|
|
// Thus we set a flag is we need to wait for system time rollover to happen,
|
|
|
|
VOID SetTimeout(DWORD dwTimeout) {
|
|
|
|
if (dwTimeout != INFINITE)
|
|
m_bHasTimeout = TRUE;
|
|
else
|
|
m_bHasTimeout = FALSE;
|
|
DWORD dw = GetTickCountWrap();
|
|
m_dwTimeout = (dwTimeout == INFINITE)
|
|
? dwTimeout
|
|
: (dw + dwTimeout);
|
|
m_fTimeoutWraps = dw > m_dwTimeout;
|
|
}
|
|
|
|
BOOL HasTimeout()
|
|
{
|
|
return m_bHasTimeout;
|
|
}
|
|
|
|
VOID SetOnAsyncList(BOOL bOnAsyncList)
|
|
{
|
|
m_bOnAsyncList = bOnAsyncList;
|
|
}
|
|
|
|
BOOL IsOnAsyncList()
|
|
{
|
|
return m_bOnAsyncList;
|
|
}
|
|
|
|
BOOL IsTimedOut(DWORD dwTime) {
|
|
if (m_fTimeoutWraps)
|
|
{
|
|
m_fTimeoutWraps = ((LONG)dwTime < 0);
|
|
}
|
|
return ((m_dwTimeout == INFINITE) || m_fTimeoutWraps)
|
|
? FALSE
|
|
: (dwTime > m_dwTimeout);
|
|
}
|
|
|
|
VOID StartTimer(VOID) {
|
|
m_dwTimer = GetTickCountWrap();
|
|
m_bTimerStarted = TRUE;
|
|
}
|
|
|
|
DWORD StopTimer(VOID) {
|
|
if (m_bTimerStarted) {
|
|
m_dwTimer = GetTickCountWrap() - m_dwTimer;
|
|
m_bTimerStarted = FALSE;
|
|
}
|
|
return m_dwTimer;
|
|
}
|
|
|
|
DWORD GetElapsedTime(VOID) {
|
|
return (GetTickCountWrap() - m_dwTimer);
|
|
}
|
|
|
|
DWORD StopAndStartTimer(VOID) {
|
|
|
|
DWORD tNow = GetTickCountWrap();
|
|
DWORD tElapsed = (tNow - m_dwTimer);
|
|
|
|
m_dwTimer = tNow;
|
|
m_bTimerStarted = TRUE;
|
|
return tElapsed;
|
|
}
|
|
|
|
DWORD ReadTimer(VOID) {
|
|
return m_bTimerStarted ? GetElapsedTime() : m_dwTimer;
|
|
}
|
|
|
|
VOID SetBlocking(BOOL fBlocking = TRUE) {
|
|
m_bIsBlockingFsm = fBlocking;
|
|
}
|
|
|
|
BOOL IsBlocking(VOID) const {
|
|
return m_bIsBlockingFsm;
|
|
}
|
|
|
|
VOID SetApi(API_TYPE ApiType) {
|
|
m_bIsApi = TRUE;
|
|
m_ApiType = ApiType;
|
|
}
|
|
|
|
BOOL IsApi(VOID) const {
|
|
return m_bIsApi;
|
|
}
|
|
|
|
API_TYPE GetApiType(VOID) const {
|
|
return m_ApiType;
|
|
}
|
|
|
|
VOID SetApiResult(BOOL bResult) {
|
|
m_ApiResult.Bool = bResult;
|
|
}
|
|
|
|
VOID SetApiResult(HINTERNET hResult) {
|
|
m_ApiResult.Handle = hResult;
|
|
}
|
|
|
|
DWORD GetApiResult(VOID) {
|
|
// SUNDOWN: typecast problem
|
|
return (m_ApiType == ApiType_Handle)
|
|
? PtrToUlong(GetHandleResult())
|
|
: (m_ApiType == ApiType_Bool)
|
|
? (DWORD) GetBoolResult()
|
|
: 0;
|
|
}
|
|
|
|
BOOL GetBoolResult(VOID) const {
|
|
return m_ApiResult.Bool;
|
|
}
|
|
|
|
HINTERNET GetHandleResult(VOID) const {
|
|
return m_ApiResult.Handle;
|
|
}
|
|
|
|
DWORD GetApiData(VOID) const {
|
|
return m_dwApiData;
|
|
}
|
|
|
|
VOID SetApiData(DWORD dwApiData) {
|
|
m_dwApiData = dwApiData;
|
|
}
|
|
|
|
DWORD
|
|
QueueWorkItem(
|
|
VOID
|
|
);
|
|
|
|
static
|
|
DWORD
|
|
RunWorkItem(
|
|
IN CFsm * pFsm
|
|
);
|
|
|
|
DWORD
|
|
Run(
|
|
IN LPINTERNET_THREAD_INFO lpThreadInfo,
|
|
OUT DWORD *lpdwApiResult OPTIONAL,
|
|
OUT DWORD *lpdwApiData OPTIONAL
|
|
);
|
|
|
|
FSM_TYPE GetType(VOID) const {
|
|
return m_Type;
|
|
}
|
|
|
|
#if INET_DEBUG
|
|
|
|
DEBUG_FUNCTION
|
|
LPSTR
|
|
MapType(
|
|
VOID
|
|
);
|
|
|
|
DEBUG_FUNCTION
|
|
LPSTR
|
|
StateName(
|
|
IN DWORD State
|
|
);
|
|
|
|
DEBUG_FUNCTION
|
|
LPSTR MapState(VOID) {
|
|
return StateName(m_State);
|
|
}
|
|
|
|
DEBUG_FUNCTION
|
|
LPSTR MapFunctionState(VOID) {
|
|
return StateName(m_FunctionState);
|
|
}
|
|
|
|
#else
|
|
|
|
LPSTR MapType(VOID) {
|
|
return "";
|
|
}
|
|
|
|
LPSTR MapState(VOID) {
|
|
return "";
|
|
}
|
|
|
|
LPSTR MapFunctionState(VOID) {
|
|
return "";
|
|
}
|
|
|
|
#endif
|
|
|
|
};
|
|
|
|
/*DWORD
|
|
RunSM_Wrapper(
|
|
IN*/
|
|
|
|
|
|
//
|
|
// Derived State Machines
|
|
//
|
|
// The following state machines contain the parameters and variables that are
|
|
// maintained across machine states and thread switches
|
|
//
|
|
// In order to make the code more readable, the state machine is friends with
|
|
// the object class for which it operates (e.g. ICSocket or ICHttpRequest)
|
|
//
|
|
|
|
//
|
|
// CAddressList FSMs
|
|
//
|
|
|
|
class CFsm_ResolveHost : public CFsm {
|
|
|
|
friend class CAddressList;
|
|
|
|
private:
|
|
|
|
//
|
|
// parameters
|
|
//
|
|
|
|
LPSTR m_lpszHostName;
|
|
LPDWORD m_lpdwResolutionId;
|
|
DWORD m_dwFlags;
|
|
|
|
public:
|
|
|
|
static
|
|
DWORD
|
|
RunSM(
|
|
IN CFsm * Fsm
|
|
);
|
|
|
|
CFsm_ResolveHost(
|
|
IN LPSTR lpszHostName,
|
|
IN LPDWORD lpdwResolutionId,
|
|
IN DWORD dwFlags,
|
|
IN CAddressList * pAddressList
|
|
) : CFsm(RunSM, (LPVOID)pAddressList) {
|
|
|
|
SET_FSM_TYPE(RESOLVE_HOST);
|
|
|
|
if (GetError() != ERROR_SUCCESS) {
|
|
return;
|
|
}
|
|
m_lpszHostName = lpszHostName;
|
|
m_lpdwResolutionId = lpdwResolutionId;
|
|
m_dwFlags = dwFlags;
|
|
}
|
|
};
|
|
|
|
|
|
|
|
//
|
|
// Internet API FSMs
|
|
//
|
|
|
|
class CFsm_InternetParseUrl : public CFsm {
|
|
|
|
private:
|
|
|
|
//
|
|
// parameters
|
|
//
|
|
|
|
HINTERNET m_hConnectHandle;
|
|
DWORD_PTR m_dwContext;
|
|
LPCSTR m_lpszUrl;
|
|
LPCSTR m_lpszHeaders;
|
|
DWORD m_dwHeadersLength;
|
|
DWORD m_dwFlags;
|
|
|
|
public:
|
|
|
|
static
|
|
DWORD
|
|
RunSM(
|
|
IN CFsm * Fsm
|
|
)
|
|
{
|
|
CFsm_InternetParseUrl *pFsm = (CFsm_InternetParseUrl *)Fsm;
|
|
|
|
INET_ASSERT(Fsm->GetState() == FSM_STATE_INIT);
|
|
|
|
pFsm->SetApiResult(InternetOpenUrlA(
|
|
pFsm->m_hConnectHandle,
|
|
pFsm->m_lpszUrl,
|
|
pFsm->m_lpszHeaders,
|
|
pFsm->m_dwHeadersLength,
|
|
pFsm->m_dwFlags,
|
|
pFsm->m_dwContext
|
|
));
|
|
|
|
pFsm->SetDone();
|
|
|
|
return ((pFsm->GetHandleResult()) ? ERROR_SUCCESS : GetLastError());
|
|
}
|
|
|
|
CFsm_InternetParseUrl(
|
|
IN HINTERNET hConnectHandle,
|
|
IN DWORD_PTR dwContext,
|
|
IN LPCSTR lpszUrl,
|
|
IN LPCSTR lpszHeaders,
|
|
IN DWORD dwHeadersLength,
|
|
IN DWORD dwFlags
|
|
) : CFsm(RunSM, (LPVOID)hConnectHandle) {
|
|
|
|
SET_FSM_TYPE(INTERNET_PARSE_URL);
|
|
|
|
if (GetError() != ERROR_SUCCESS) {
|
|
return;
|
|
}
|
|
|
|
SetApi(ApiType_Handle);
|
|
SetBlocking();
|
|
|
|
m_hConnectHandle = hConnectHandle;
|
|
m_dwContext = dwContext;
|
|
m_lpszUrl = lpszUrl;
|
|
m_lpszHeaders = lpszHeaders;
|
|
m_dwHeadersLength = dwHeadersLength;
|
|
m_dwFlags = dwFlags;
|
|
}
|
|
};
|
|
|
|
|
|
class CFsm_InternetQueryDataAvailable : public CFsm {
|
|
|
|
private:
|
|
|
|
//
|
|
// parameters
|
|
//
|
|
|
|
HINTERNET m_hSessionHandle;
|
|
LPDWORD m_lpdwNumberOfBytesAvailable;
|
|
DWORD m_dwNumberOfBytesAvailable;
|
|
DWORD m_dwFlags;
|
|
DWORD_PTR m_dwContext;
|
|
|
|
public:
|
|
|
|
static
|
|
DWORD
|
|
RunSM(
|
|
IN CFsm * Fsm
|
|
)
|
|
{
|
|
CFsm_InternetQueryDataAvailable *pFsm = (CFsm_InternetQueryDataAvailable *)Fsm;
|
|
|
|
INET_ASSERT(Fsm->GetState() == FSM_STATE_INIT);
|
|
|
|
pFsm->SetApiResult(wInternetQueryDataAvailable(
|
|
pFsm->m_hSessionHandle,
|
|
pFsm->m_lpdwNumberOfBytesAvailable,
|
|
pFsm->m_dwFlags,
|
|
pFsm->m_dwContext
|
|
));
|
|
|
|
pFsm->SetApiData(*pFsm->m_lpdwNumberOfBytesAvailable);
|
|
|
|
pFsm->SetDone();
|
|
|
|
return ((pFsm->GetBoolResult()) ? ERROR_SUCCESS : GetLastError());
|
|
}
|
|
|
|
CFsm_InternetQueryDataAvailable(
|
|
IN HINTERNET hSessionHandle,
|
|
OUT LPDWORD lpdwNumberOfBytesAvailable,
|
|
IN DWORD dwFlags,
|
|
IN DWORD_PTR dwContext
|
|
) : CFsm(RunSM, (LPVOID)hSessionHandle) {
|
|
|
|
SET_FSM_TYPE(INTERNET_QUERY_DATA_AVAILABLE);
|
|
|
|
if (GetError() != ERROR_SUCCESS) {
|
|
return;
|
|
}
|
|
|
|
SetApi(ApiType_Bool);
|
|
SetBlocking();
|
|
|
|
m_hSessionHandle = hSessionHandle;
|
|
m_lpdwNumberOfBytesAvailable = &m_dwNumberOfBytesAvailable;
|
|
m_dwNumberOfBytesAvailable = *lpdwNumberOfBytesAvailable;
|
|
m_dwFlags = dwFlags;
|
|
m_dwContext = dwContext;
|
|
}
|
|
};
|
|
|
|
|
|
|
|
class CFsm_InternetWriteFile : public CFsm {
|
|
|
|
private:
|
|
|
|
//
|
|
// parameters
|
|
//
|
|
|
|
HINTERNET m_hSessionHandle;
|
|
LPCVOID m_lpBuffer;
|
|
DWORD m_dwNumberOfBytesToWrite;
|
|
LPDWORD m_lpdwNumberOfBytesWritten;
|
|
DWORD m_dwNumberOfBytesWritten;
|
|
|
|
public:
|
|
|
|
static
|
|
DWORD
|
|
RunSM(
|
|
IN CFsm * Fsm
|
|
)
|
|
{
|
|
CFsm_InternetWriteFile *pFsm = (CFsm_InternetWriteFile *)Fsm;
|
|
|
|
INET_ASSERT(Fsm->GetState() == FSM_STATE_INIT);
|
|
|
|
pFsm->SetApiResult(WinHttpWriteData(
|
|
pFsm->m_hSessionHandle,
|
|
pFsm->m_lpBuffer,
|
|
pFsm->m_dwNumberOfBytesToWrite,
|
|
pFsm->m_lpdwNumberOfBytesWritten
|
|
));
|
|
|
|
pFsm->SetApiData(*(pFsm->m_lpdwNumberOfBytesWritten));
|
|
|
|
pFsm->SetDone();
|
|
|
|
return ((pFsm->GetBoolResult()) ? ERROR_SUCCESS : GetLastError());
|
|
}
|
|
|
|
CFsm_InternetWriteFile(
|
|
IN HINTERNET hSessionHandle,
|
|
IN LPCVOID lpBuffer,
|
|
IN DWORD dwNumberOfBytesToWrite,
|
|
OUT LPDWORD lpdwNumberOfBytesWritten
|
|
) : CFsm(RunSM, (LPVOID)hSessionHandle) {
|
|
|
|
SET_FSM_TYPE(INTERNET_WRITE_FILE);
|
|
|
|
if (GetError() != ERROR_SUCCESS) {
|
|
return;
|
|
}
|
|
|
|
SetApi(ApiType_Bool);
|
|
SetBlocking();
|
|
|
|
m_hSessionHandle = hSessionHandle;
|
|
m_lpBuffer = lpBuffer;
|
|
m_dwNumberOfBytesToWrite = dwNumberOfBytesToWrite;
|
|
m_dwNumberOfBytesWritten = *lpdwNumberOfBytesWritten;
|
|
m_lpdwNumberOfBytesWritten = &m_dwNumberOfBytesWritten;
|
|
}
|
|
};
|
|
|
|
class CFsm_InternetReadFile : public CFsm {
|
|
|
|
private:
|
|
|
|
//
|
|
// parameters
|
|
//
|
|
|
|
HINTERNET m_hSessionHandle;
|
|
LPVOID m_lpBuffer;
|
|
DWORD m_dwNumberOfBytesToRead;
|
|
LPDWORD m_lpdwNumberOfBytesRead;
|
|
DWORD m_dwNumberOfBytesRead;
|
|
|
|
public:
|
|
|
|
static
|
|
DWORD
|
|
RunSM(
|
|
IN CFsm * Fsm
|
|
)
|
|
{
|
|
CFsm_InternetReadFile *pFsm = (CFsm_InternetReadFile *)Fsm;
|
|
|
|
INET_ASSERT(Fsm->GetState() == FSM_STATE_INIT);
|
|
|
|
pFsm->SetApiResult(WinHttpReadData(
|
|
pFsm->m_hSessionHandle,
|
|
pFsm->m_lpBuffer,
|
|
pFsm->m_dwNumberOfBytesToRead,
|
|
pFsm->m_lpdwNumberOfBytesRead
|
|
));
|
|
|
|
pFsm->SetApiData(*(pFsm->m_lpdwNumberOfBytesRead));
|
|
|
|
pFsm->SetDone();
|
|
|
|
return ((pFsm->GetBoolResult()) ? ERROR_SUCCESS : GetLastError());
|
|
}
|
|
|
|
CFsm_InternetReadFile(
|
|
IN HINTERNET hSessionHandle,
|
|
IN LPVOID lpBuffer,
|
|
IN DWORD dwNumberOfBytesToRead,
|
|
OUT LPDWORD lpdwNumberOfBytesRead
|
|
) : CFsm(RunSM, (LPVOID)hSessionHandle) {
|
|
|
|
SET_FSM_TYPE(INTERNET_READ_FILE);
|
|
|
|
if (GetError() != ERROR_SUCCESS) {
|
|
return;
|
|
}
|
|
|
|
SetApi(ApiType_Bool);
|
|
SetBlocking();
|
|
|
|
m_hSessionHandle = hSessionHandle;
|
|
m_lpBuffer = lpBuffer;
|
|
m_dwNumberOfBytesToRead = dwNumberOfBytesToRead;
|
|
m_dwNumberOfBytesRead = *lpdwNumberOfBytesRead;
|
|
m_lpdwNumberOfBytesRead = &m_dwNumberOfBytesRead;
|
|
}
|
|
};
|
|
|
|
//
|
|
// ICSocket FSMs
|
|
//
|
|
|
|
|
|
//
|
|
// CFsm_SocketConnect -
|
|
//
|
|
|
|
class CFsm_SocketConnect : public CFsm {
|
|
|
|
friend class ICSocket;
|
|
|
|
private:
|
|
|
|
//
|
|
// parameters
|
|
//
|
|
|
|
LONG m_Timeout;
|
|
INT m_Retries;
|
|
DWORD m_dwFlags;
|
|
|
|
//
|
|
// local variables
|
|
//
|
|
|
|
BOOL m_bStopOfflineTimer;
|
|
LONG m_lPreviousTime;
|
|
BOOL m_bResolved;
|
|
DWORD m_dwResolutionId;
|
|
DWORD m_dwAddressIndex;
|
|
char m_AddressBuffer[CSADDR_BUFFER_LENGTH];
|
|
LPCSADDR_INFO m_pAddress;
|
|
CServerInfo * m_pServerInfo;
|
|
CServerInfo * m_pOriginServer;
|
|
BOOL m_fTimeout;
|
|
|
|
public:
|
|
|
|
static
|
|
DWORD
|
|
RunSM(
|
|
IN CFsm * Fsm
|
|
);
|
|
|
|
CFsm_SocketConnect(
|
|
IN LONG Timeout,
|
|
IN INT Retries,
|
|
IN DWORD dwFlags,
|
|
IN ICSocket * pSocket
|
|
) : CFsm(RunSM, (LPVOID)pSocket) {
|
|
|
|
SET_FSM_TYPE(SOCKET_CONNECT);
|
|
|
|
if (GetError() != ERROR_SUCCESS) {
|
|
return;
|
|
}
|
|
m_Timeout = Timeout;
|
|
m_fTimeout = Timeout ? TRUE : FALSE;
|
|
m_Retries = Retries;
|
|
m_dwFlags = dwFlags;
|
|
m_bStopOfflineTimer = FALSE;
|
|
m_lPreviousTime = (LONG)GetTickCountWrap();
|
|
m_bResolved = FALSE;
|
|
m_dwResolutionId = (DWORD)-1;
|
|
m_dwAddressIndex = (DWORD)-1;
|
|
m_pAddress = (LPCSADDR_INFO)m_AddressBuffer;
|
|
m_pServerInfo = ((HTTP_REQUEST_HANDLE_OBJECT *)
|
|
GetThreadInfo()->hObjectMapped)->GetServerInfo();
|
|
m_pOriginServer = ((HTTP_REQUEST_HANDLE_OBJECT *)
|
|
GetThreadInfo()->hObjectMapped)->GetOriginServer();
|
|
}
|
|
|
|
VOID SetServerInfo(CServerInfo * pServerInfo) {
|
|
m_pServerInfo = pServerInfo;
|
|
}
|
|
|
|
BOOL IsCountedOut(VOID) {
|
|
return (--m_Retries <= 0) ? TRUE : FALSE;
|
|
}
|
|
|
|
BOOL IsTimedOut(VOID) {
|
|
return (m_fTimeout != INFINITE) ? (((m_Timeout -= (LONG)ReadTimer()) <= 0) ? TRUE : FALSE) : FALSE;
|
|
}
|
|
|
|
LONG GetTimeout(VOID) const
|
|
{
|
|
return m_Timeout;
|
|
}
|
|
};
|
|
|
|
//
|
|
// CFsm_SocketSend -
|
|
//
|
|
|
|
class CFsm_SocketIOCP : public CFsm
|
|
{
|
|
public:
|
|
BOOL bIOCPSuccess;
|
|
DWORD dwBytesTransferred;
|
|
DWORD dwIOCPError;
|
|
BOOL bIOCPInited;
|
|
|
|
CFsm_SocketIOCP(DWORD (* lpfnHandler)(CFsm *), LPVOID lpvContext):CFsm(lpfnHandler, lpvContext)
|
|
{
|
|
bIOCPSuccess = FALSE;
|
|
dwBytesTransferred = 0;
|
|
dwIOCPError = 0;
|
|
bIOCPInited = FALSE;
|
|
}
|
|
};
|
|
|
|
class CFsm_SocketSend : public CFsm_SocketIOCP
|
|
{
|
|
friend class ICSocket;
|
|
|
|
private:
|
|
|
|
//
|
|
// parameters
|
|
//
|
|
|
|
LPVOID m_lpBuffer;
|
|
DWORD m_dwBufferLength;
|
|
DWORD m_dwFlags;
|
|
|
|
//
|
|
// local variables
|
|
//
|
|
|
|
INT m_iTotalSent;
|
|
BOOL m_bStopOfflineTimer;
|
|
CServerInfo * m_pServerInfo;
|
|
CServerInfo * m_pOriginServer;
|
|
|
|
public:
|
|
|
|
static
|
|
DWORD
|
|
RunSM(
|
|
IN CFsm * Fsm
|
|
);
|
|
|
|
CFsm_SocketSend(
|
|
IN LPVOID lpBuffer,
|
|
IN DWORD dwBufferLength,
|
|
IN DWORD dwFlags,
|
|
IN ICSocket * pSocket
|
|
) : CFsm_SocketIOCP(RunSM, (LPVOID)pSocket) {
|
|
|
|
SET_FSM_TYPE(SOCKET_SEND);
|
|
|
|
if (GetError() != ERROR_SUCCESS) {
|
|
return;
|
|
}
|
|
|
|
INET_ASSERT(lpBuffer != NULL);
|
|
INET_ASSERT((int)dwBufferLength > 0);
|
|
|
|
m_lpBuffer = lpBuffer;
|
|
m_dwBufferLength = dwBufferLength;
|
|
m_dwFlags = dwFlags;
|
|
m_iTotalSent = 0;
|
|
m_bStopOfflineTimer = FALSE;
|
|
m_pServerInfo = ((HTTP_REQUEST_HANDLE_OBJECT *)
|
|
GetThreadInfo()->hObjectMapped)->GetServerInfo();
|
|
m_pOriginServer = ((HTTP_REQUEST_HANDLE_OBJECT *)
|
|
GetThreadInfo()->hObjectMapped)->GetOriginServer();
|
|
}
|
|
};
|
|
|
|
//
|
|
// CFsm_SocketReceive -
|
|
//
|
|
|
|
class CFsm_SocketReceive : public CFsm_SocketIOCP
|
|
{
|
|
friend class ICSocket;
|
|
|
|
private:
|
|
|
|
//
|
|
// parameters
|
|
//
|
|
|
|
LPVOID * m_lplpBuffer;
|
|
LPDWORD m_lpdwBufferLength;
|
|
LPDWORD m_lpdwBufferRemaining;
|
|
LPDWORD m_lpdwBytesReceived;
|
|
DWORD m_dwExtraSpace;
|
|
DWORD m_dwFlags;
|
|
LPBOOL m_lpbEof;
|
|
|
|
//
|
|
// local variables
|
|
//
|
|
|
|
HLOCAL m_hBuffer;
|
|
LPBYTE m_lpBuffer;
|
|
DWORD m_dwBufferLength;
|
|
DWORD m_dwBufferLeft;
|
|
DWORD m_dwBytesReceived;
|
|
DWORD m_dwBytesRead;
|
|
BOOL m_bEof;
|
|
BOOL m_bAllocated;
|
|
CServerInfo * m_pServerInfo;
|
|
CServerInfo * m_pOriginServer;
|
|
|
|
public:
|
|
|
|
static
|
|
DWORD
|
|
RunSM(
|
|
IN CFsm * Fsm
|
|
);
|
|
|
|
CFsm_SocketReceive(
|
|
IN OUT LPVOID * lplpBuffer,
|
|
IN OUT LPDWORD lpdwBufferLength,
|
|
IN OUT LPDWORD lpdwBufferRemaining,
|
|
IN OUT LPDWORD lpdwBytesReceived,
|
|
IN DWORD dwExtraSpace,
|
|
IN DWORD dwFlags,
|
|
OUT LPBOOL lpbEof,
|
|
IN ICSocket * pSocket
|
|
) : CFsm_SocketIOCP(RunSM, (LPVOID)pSocket) {
|
|
|
|
SET_FSM_TYPE(SOCKET_RECEIVE);
|
|
|
|
if (GetError() != ERROR_SUCCESS) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
// sanity check
|
|
//
|
|
|
|
INET_ASSERT(lplpBuffer != NULL);
|
|
INET_ASSERT(lpdwBufferLength != NULL);
|
|
INET_ASSERT((*lpdwBufferLength == 0) ? (dwFlags & SF_EXPAND) : TRUE);
|
|
|
|
m_lplpBuffer = lplpBuffer;
|
|
m_lpdwBufferLength = lpdwBufferLength;
|
|
m_lpdwBufferRemaining = lpdwBufferRemaining;
|
|
m_lpdwBytesReceived = lpdwBytesReceived;
|
|
m_dwExtraSpace = dwExtraSpace;
|
|
m_dwFlags = dwFlags;
|
|
m_lpbEof = lpbEof;
|
|
m_hBuffer = *lplpBuffer;
|
|
m_lpBuffer = (LPBYTE)m_hBuffer;
|
|
m_dwBufferLength = *lpdwBufferLength;
|
|
m_dwBufferLeft = *lpdwBufferRemaining;
|
|
m_dwBytesReceived = *lpdwBytesReceived;
|
|
m_dwBytesRead = 0;
|
|
m_bEof = FALSE;
|
|
m_bAllocated = FALSE;
|
|
m_pServerInfo = ((HTTP_REQUEST_HANDLE_OBJECT *)
|
|
GetThreadInfo()->hObjectMapped)->GetServerInfo();
|
|
m_pOriginServer = ((HTTP_REQUEST_HANDLE_OBJECT *)
|
|
GetThreadInfo()->hObjectMapped)->GetOriginServer();
|
|
}
|
|
};
|
|
|
|
//
|
|
// ICSecureSocket FSMs
|
|
//
|
|
|
|
//
|
|
// CFsm_SecureConnect -
|
|
//
|
|
|
|
class CFsm_SecureConnect : public CFsm {
|
|
|
|
friend class ICSecureSocket;
|
|
|
|
private:
|
|
|
|
//
|
|
// parameters
|
|
//
|
|
|
|
LONG m_Timeout;
|
|
INT m_Retries;
|
|
DWORD m_dwFlags;
|
|
|
|
//
|
|
// locals
|
|
//
|
|
|
|
BOOL m_bAttemptReconnect;
|
|
|
|
public:
|
|
|
|
static
|
|
DWORD
|
|
RunSM(
|
|
IN CFsm * Fsm
|
|
);
|
|
|
|
CFsm_SecureConnect(
|
|
IN LONG Timeout,
|
|
IN INT Retries,
|
|
IN DWORD dwFlags,
|
|
IN ICSecureSocket * pSocket
|
|
) : CFsm(RunSM, (LPVOID)pSocket) {
|
|
|
|
SET_FSM_TYPE(SECURE_CONNECT);
|
|
|
|
if (GetError() != ERROR_SUCCESS) {
|
|
return;
|
|
}
|
|
|
|
m_Timeout = Timeout;
|
|
m_Retries = Retries;
|
|
m_dwFlags = dwFlags;
|
|
m_bAttemptReconnect = FALSE;
|
|
}
|
|
};
|
|
|
|
//
|
|
// CFsm_SecureHandshake -
|
|
//
|
|
|
|
class CFsm_SecureHandshake : public CFsm {
|
|
|
|
friend class ICSecureSocket;
|
|
|
|
private:
|
|
|
|
//
|
|
// parameters
|
|
//
|
|
|
|
DWORD m_dwFlags;
|
|
LPBOOL m_lpbAttemptReconnect;
|
|
|
|
//
|
|
// locals
|
|
//
|
|
|
|
public:
|
|
|
|
static
|
|
DWORD
|
|
RunSM(
|
|
IN CFsm * Fsm
|
|
);
|
|
|
|
CFsm_SecureHandshake(
|
|
IN DWORD dwFlags,
|
|
OUT LPBOOL lpbAttemptReconnect,
|
|
IN ICSecureSocket * pSocket
|
|
) : CFsm(RunSM, (LPVOID)pSocket) {
|
|
|
|
SET_FSM_TYPE(SECURE_HANDSHAKE);
|
|
|
|
if (GetError() != ERROR_SUCCESS) {
|
|
return;
|
|
}
|
|
|
|
m_dwFlags = dwFlags;
|
|
m_lpbAttemptReconnect = lpbAttemptReconnect;
|
|
}
|
|
};
|
|
|
|
//
|
|
// CFsm_SecureNegotiate -
|
|
//
|
|
|
|
class CFsm_SecureNegotiate : public CFsm {
|
|
|
|
friend class ICSecureSocket;
|
|
|
|
private:
|
|
|
|
//
|
|
// parameters
|
|
//
|
|
|
|
DWORD m_dwFlags;
|
|
LPBOOL m_lpbAttemptReconnect;
|
|
|
|
//
|
|
// locals
|
|
//
|
|
|
|
SecBufferDesc m_OutBuffer;
|
|
SecBuffer m_OutBuffers[1];
|
|
CredHandle m_hCreds;
|
|
BOOL m_bDoingClientAuth;
|
|
|
|
public:
|
|
|
|
static
|
|
DWORD
|
|
RunSM(
|
|
IN CFsm * Fsm
|
|
);
|
|
|
|
CFsm_SecureNegotiate(
|
|
IN DWORD dwFlags,
|
|
OUT LPBOOL lpbAttemptReconnect,
|
|
IN ICSecureSocket * pSocket
|
|
) : CFsm(RunSM, (LPVOID)pSocket) {
|
|
|
|
SET_FSM_TYPE(SECURE_NEGOTIATE);
|
|
|
|
if (GetError() != ERROR_SUCCESS) {
|
|
return;
|
|
}
|
|
|
|
m_dwFlags = dwFlags;
|
|
m_lpbAttemptReconnect = lpbAttemptReconnect;
|
|
ClearCreds(m_hCreds);
|
|
m_bDoingClientAuth = FALSE;
|
|
}
|
|
|
|
|
|
~CFsm_SecureNegotiate() {
|
|
//INET_ASSERT(IsCredClear(m_hCreds));
|
|
INET_ASSERT(!m_bDoingClientAuth);
|
|
|
|
if ( m_bDoingClientAuth &&
|
|
!IsCredClear(m_hCreds))
|
|
{
|
|
// Look at comments before CliAuthSelectCredentials
|
|
// g_FreeCredentialsHandle(&m_hCreds);
|
|
m_bDoingClientAuth = FALSE;
|
|
|
|
}
|
|
}
|
|
|
|
};
|
|
|
|
//
|
|
// CFsm_NegotiateLoop -
|
|
//
|
|
|
|
class CFsm_NegotiateLoop : public CFsm {
|
|
|
|
friend class ICSecureSocket;
|
|
|
|
private:
|
|
|
|
//
|
|
// parameters
|
|
//
|
|
|
|
DBLBUFFER * m_pdblbufBuffer;
|
|
DWORD m_dwFlags;
|
|
BOOL m_bDoInitialRead;
|
|
|
|
//
|
|
// locals
|
|
//
|
|
|
|
SECURITY_STATUS m_scRet;
|
|
DWORD m_dwProviderIndex;
|
|
LPSTR m_lpszBuffer;
|
|
DWORD m_dwBufferLength;
|
|
DWORD m_dwBufferLeft;
|
|
DWORD m_dwBytesReceived;
|
|
BOOL m_bEofReceive;
|
|
BOOL m_bDoingClientAuth;
|
|
BOOL m_bDoRead;
|
|
SecBuffer m_InBuffers[2];
|
|
SecBuffer m_OutBuffers[1];
|
|
SecBufferDesc m_OutBuffer;
|
|
CredHandle m_hCreds;
|
|
DWORD m_dwSSPIFlags;
|
|
|
|
public:
|
|
|
|
static
|
|
DWORD
|
|
RunSM(
|
|
IN CFsm * Fsm
|
|
);
|
|
|
|
CFsm_NegotiateLoop(
|
|
IN DBLBUFFER * pdblbufBuffer,
|
|
IN DWORD dwFlags,
|
|
IN BOOL bDoInitialRead,
|
|
IN BOOL bDoingClientAuth,
|
|
IN CredHandle hCreds,
|
|
IN ICSecureSocket * pSocket
|
|
) : CFsm(RunSM, (LPVOID)pSocket) {
|
|
|
|
SET_FSM_TYPE(NEGOTIATE_LOOP);
|
|
|
|
if (GetError() != ERROR_SUCCESS) {
|
|
return;
|
|
}
|
|
|
|
m_pdblbufBuffer = pdblbufBuffer;
|
|
m_dwFlags = dwFlags;
|
|
m_bDoInitialRead = bDoInitialRead;
|
|
m_scRet = SEC_E_SECPKG_NOT_FOUND;
|
|
m_lpszBuffer = NULL;
|
|
m_dwBufferLength = 0;
|
|
m_dwBufferLeft = 0;
|
|
m_dwBytesReceived = 0;
|
|
m_bEofReceive = FALSE;
|
|
m_bDoingClientAuth = bDoingClientAuth;
|
|
m_bDoRead = m_bDoInitialRead;
|
|
|
|
if (bDoingClientAuth)
|
|
m_hCreds = hCreds;
|
|
else
|
|
ClearCreds(m_hCreds);
|
|
}
|
|
|
|
~CFsm_NegotiateLoop() {
|
|
|
|
if (m_bDoingClientAuth)
|
|
{
|
|
INET_ASSERT(!IsCredClear(m_hCreds));
|
|
// Look at comments before CliAuthSelectCredentials
|
|
// g_FreeCredentialsHandle(&m_hCreds);
|
|
m_bDoingClientAuth = FALSE;
|
|
}
|
|
}
|
|
};
|
|
|
|
//
|
|
// CFsm_SecureSend -
|
|
//
|
|
|
|
class CFsm_SecureSend : public CFsm {
|
|
|
|
friend class ICSecureSocket;
|
|
|
|
private:
|
|
|
|
//
|
|
// parameters
|
|
//
|
|
|
|
LPVOID m_lpBuffer;
|
|
DWORD m_dwBufferLength;
|
|
DWORD m_dwFlags;
|
|
|
|
//
|
|
// locals
|
|
//
|
|
|
|
LPVOID m_lpCryptBuffer;
|
|
DWORD m_dwCryptBufferLength;
|
|
|
|
public:
|
|
|
|
static
|
|
DWORD
|
|
RunSM(
|
|
IN CFsm * Fsm
|
|
);
|
|
|
|
CFsm_SecureSend(
|
|
IN LPVOID lpBuffer,
|
|
IN DWORD dwBufferLength,
|
|
IN DWORD dwFlags,
|
|
IN ICSecureSocket * pSocket
|
|
) : CFsm(RunSM, (LPVOID)pSocket) {
|
|
|
|
SET_FSM_TYPE(SECURE_SEND);
|
|
|
|
if (GetError() != ERROR_SUCCESS) {
|
|
return;
|
|
}
|
|
|
|
m_lpBuffer = lpBuffer;
|
|
m_dwBufferLength = dwBufferLength;
|
|
m_dwFlags = dwFlags;
|
|
m_lpCryptBuffer = NULL;
|
|
m_dwCryptBufferLength = 0;
|
|
}
|
|
};
|
|
|
|
//
|
|
// CFsm_SecureReceive -
|
|
//
|
|
|
|
class CFsm_SecureReceive : public CFsm {
|
|
|
|
friend class ICSecureSocket;
|
|
|
|
private:
|
|
|
|
//
|
|
// parameters
|
|
//
|
|
|
|
LPVOID * m_lplpBuffer;
|
|
LPDWORD m_lpdwBufferLength;
|
|
LPDWORD m_lpdwBufferRemaining;
|
|
LPDWORD m_lpdwBytesReceived;
|
|
DWORD m_dwExtraSpace;
|
|
DWORD m_dwFlags;
|
|
LPBOOL m_lpbEof;
|
|
|
|
//
|
|
// locals
|
|
//
|
|
|
|
HLOCAL m_hBuffer;
|
|
DWORD m_dwBufferLength;
|
|
DWORD m_dwBufferLeft;
|
|
DWORD m_dwBytesReceived;
|
|
DWORD m_dwBytesRead;
|
|
LPBYTE m_lpBuffer;
|
|
BOOL m_bEof;
|
|
BOOL m_bAllocated;
|
|
DWORD m_dwDecryptError;
|
|
DWORD m_dwReadFlags;
|
|
LPBYTE m_lpBufferDummy;
|
|
DWORD m_dwBufferLengthDummy;
|
|
DWORD m_dwBufferReceivedDummy;
|
|
DWORD m_dwBufferLeftDummy;
|
|
DWORD m_dwBufferReceivedPre;
|
|
DWORD m_dwInputBytesLeft;
|
|
|
|
public:
|
|
|
|
static
|
|
DWORD
|
|
RunSM(
|
|
IN CFsm * Fsm
|
|
);
|
|
|
|
CFsm_SecureReceive(
|
|
IN OUT LPVOID* lplpBuffer,
|
|
IN OUT LPDWORD lpdwBufferLength,
|
|
IN OUT LPDWORD lpdwBufferRemaining,
|
|
IN OUT LPDWORD lpdwBytesReceived,
|
|
IN DWORD dwExtraSpace,
|
|
IN DWORD dwFlags,
|
|
OUT LPBOOL lpbEof,
|
|
IN ICSecureSocket * pSocket
|
|
) : CFsm(RunSM, (LPVOID)pSocket) {
|
|
|
|
SET_FSM_TYPE(SECURE_RECEIVE);
|
|
|
|
if (GetError() != ERROR_SUCCESS) {
|
|
return;
|
|
}
|
|
|
|
m_lplpBuffer = lplpBuffer;
|
|
m_lpdwBufferLength = lpdwBufferLength;
|
|
m_lpdwBufferRemaining = lpdwBufferRemaining;
|
|
m_lpdwBytesReceived = lpdwBytesReceived;
|
|
m_dwExtraSpace = dwExtraSpace;
|
|
m_dwFlags = dwFlags;
|
|
m_lpbEof = lpbEof;
|
|
m_hBuffer = (HLOCAL)*lplpBuffer;
|
|
m_dwBufferLength = *lpdwBufferLength;
|
|
m_dwBufferLeft = *lpdwBufferRemaining;
|
|
m_dwBytesReceived = *lpdwBytesReceived;
|
|
m_dwBytesRead = 0;
|
|
m_bEof = FALSE;
|
|
m_bAllocated = FALSE;
|
|
m_dwDecryptError = ERROR_SUCCESS;
|
|
}
|
|
};
|
|
|
|
//
|
|
// CServerInfo FSMs
|
|
//
|
|
|
|
//
|
|
// CFsm_GetConnection -
|
|
//
|
|
|
|
class CFsm_GetConnection : public CFsm {
|
|
|
|
friend class CServerInfo;
|
|
|
|
private:
|
|
|
|
//
|
|
// parameters
|
|
//
|
|
|
|
DWORD m_dwSocketFlags;
|
|
INTERNET_PORT m_nPort;
|
|
DWORD m_dwTimeout;
|
|
BOOL m_fTimeoutWraps;
|
|
DWORD m_dwLimitTimeout;
|
|
ICSocket * * m_lplpSocket;
|
|
LPSTR m_lpszSecureTunnelHost;
|
|
|
|
//
|
|
// locals
|
|
//
|
|
|
|
public:
|
|
|
|
static
|
|
DWORD
|
|
RunSM(
|
|
IN CFsm * Fsm
|
|
);
|
|
|
|
CFsm_GetConnection(
|
|
IN DWORD dwSocketFlags,
|
|
IN INTERNET_PORT nPort,
|
|
IN DWORD dwTimeout,
|
|
IN DWORD dwLimitTimeout,
|
|
OUT ICSocket * * lplpSocket,
|
|
IN CServerInfo * lpServerInfo,
|
|
IN LPSTR lpszSecureTunnelHost = NULL
|
|
) : CFsm(RunSM, (LPVOID)lpServerInfo) {
|
|
|
|
SET_FSM_TYPE(GET_CONNECTION);
|
|
|
|
if (GetError() != ERROR_SUCCESS) {
|
|
return;
|
|
}
|
|
|
|
m_dwSocketFlags = dwSocketFlags;
|
|
m_nPort = nPort;
|
|
m_dwTimeout = dwTimeout;
|
|
m_fTimeoutWraps = GetTickCount() > dwTimeout;
|
|
m_dwLimitTimeout = dwLimitTimeout; // This is unused
|
|
m_lplpSocket = lplpSocket;
|
|
if (lpszSecureTunnelHost)
|
|
{
|
|
int ccSecureTunnelHost = strlen(lpszSecureTunnelHost) + 1;
|
|
m_lpszSecureTunnelHost = (LPSTR) ALLOCATE_FIXED_MEMORY(ccSecureTunnelHost);
|
|
if (m_lpszSecureTunnelHost)
|
|
memcpy(m_lpszSecureTunnelHost, lpszSecureTunnelHost, ccSecureTunnelHost);
|
|
}
|
|
else
|
|
{
|
|
m_lpszSecureTunnelHost = NULL;
|
|
}
|
|
}
|
|
|
|
~CFsm_GetConnection() {
|
|
if (m_lpszSecureTunnelHost)
|
|
FREE_MEMORY(m_lpszSecureTunnelHost);
|
|
}
|
|
};
|
|
|
|
//
|
|
// HTTP_REQUEST_HANDLE_OBJECT FSMs
|
|
//
|
|
|
|
//
|
|
// CFsm_HttpSendRequest -
|
|
//
|
|
|
|
class CFsm_HttpSendRequest : public CFsm {
|
|
|
|
friend class HTTP_REQUEST_HANDLE_OBJECT;
|
|
|
|
public:
|
|
AR_TYPE m_arRequest;
|
|
|
|
private:
|
|
|
|
//
|
|
// parameters
|
|
//
|
|
|
|
LPVOID m_lpOptional;
|
|
DWORD m_dwOptionalLength;
|
|
|
|
//
|
|
// local variables
|
|
//
|
|
|
|
HINTERNET m_hRequestMapped;
|
|
HTTP_REQUEST_HANDLE_OBJECT * m_pRequest;
|
|
BOOL m_bFinished;
|
|
BOOL m_bAuthNotFinished;
|
|
BOOL m_bRedirectCountedOut;
|
|
BOOL m_bCancelRedoOfProxy;
|
|
BOOL m_bRedirected;
|
|
BOOL m_bSink;
|
|
DWORD m_dwRedirectCount;
|
|
AUTO_PROXY_ASYNC_MSG *m_pProxyInfoQuery;
|
|
BOOL m_fOwnsProxyInfoQueryObj;
|
|
INTERNET_HANDLE_OBJECT * m_pInternet;
|
|
LPVOID m_pBuffer;
|
|
DWORD m_dwBytesDrained;
|
|
DWORD m_iRetries;
|
|
BOOL m_bWasKeepAlive;
|
|
HTTP_METHOD_TYPE m_tMethodRedirect;
|
|
DWORD m_dwCookieIndex;
|
|
|
|
public:
|
|
|
|
static
|
|
DWORD
|
|
RunSM(
|
|
IN CFsm * Fsm
|
|
);
|
|
|
|
CFsm_HttpSendRequest(
|
|
IN LPVOID lpOptional OPTIONAL,
|
|
IN DWORD dwOptionalLength,
|
|
IN HTTP_REQUEST_HANDLE_OBJECT * pRequest,
|
|
IN AR_TYPE arRequest
|
|
) : CFsm(RunSM, (LPVOID)pRequest, FALSE) {
|
|
|
|
SET_FSM_TYPE(HTTP_SEND_REQUEST);
|
|
|
|
if (GetError() != ERROR_SUCCESS) {
|
|
return;
|
|
}
|
|
|
|
SetApi(ApiType_Bool);
|
|
m_hRequestMapped = (HINTERNET)pRequest;
|
|
m_lpOptional = lpOptional;
|
|
m_dwOptionalLength = dwOptionalLength;
|
|
m_pRequest = pRequest;
|
|
m_bFinished = FALSE;
|
|
m_bAuthNotFinished = FALSE;
|
|
m_bRedirectCountedOut = FALSE;
|
|
m_bCancelRedoOfProxy = FALSE;
|
|
m_bRedirected = FALSE;
|
|
m_bSink = FALSE;
|
|
m_dwRedirectCount = GlobalMaxHttpRedirects;
|
|
m_pProxyInfoQuery = NULL;
|
|
m_arRequest = arRequest;
|
|
m_fOwnsProxyInfoQueryObj = TRUE;
|
|
m_dwCookieIndex = 0;
|
|
|
|
m_pInternet = GetRootHandle(pRequest);
|
|
|
|
INET_ASSERT(m_pInternet != NULL);
|
|
INET_ASSERT(m_pInternet->IsValid(TypeInternetHandle) == ERROR_SUCCESS);
|
|
|
|
m_pBuffer = NULL;
|
|
m_iRetries = 2;
|
|
m_tMethodRedirect = HTTP_METHOD_TYPE_UNKNOWN;
|
|
}
|
|
|
|
~CFsm_HttpSendRequest(
|
|
VOID
|
|
)
|
|
{
|
|
if ( m_fOwnsProxyInfoQueryObj && m_pProxyInfoQuery && m_pProxyInfoQuery->IsAlloced())
|
|
{
|
|
delete m_pProxyInfoQuery;
|
|
}
|
|
|
|
if (m_pBuffer != NULL)
|
|
{
|
|
m_pBuffer = (LPVOID)FREE_MEMORY(m_pBuffer);
|
|
}
|
|
}
|
|
|
|
};
|
|
|
|
//
|
|
// CFsm_MakeConnection -
|
|
//
|
|
|
|
class CFsm_MakeConnection : public CFsm {
|
|
|
|
friend class HTTP_REQUEST_HANDLE_OBJECT;
|
|
|
|
private:
|
|
|
|
//
|
|
// parameters
|
|
//
|
|
|
|
//
|
|
// local variables
|
|
//
|
|
|
|
HTTP_REQUEST_HANDLE_OBJECT * m_pRequest;
|
|
BOOL m_bAttemptReconnect;
|
|
|
|
public:
|
|
|
|
static
|
|
DWORD
|
|
RunSM(
|
|
IN CFsm * Fsm
|
|
);
|
|
|
|
CFsm_MakeConnection(
|
|
IN HTTP_REQUEST_HANDLE_OBJECT * pRequest
|
|
) : CFsm(RunSM, (LPVOID)pRequest) {
|
|
|
|
SET_FSM_TYPE(MAKE_CONNECTION);
|
|
|
|
if (GetError() != ERROR_SUCCESS) {
|
|
return;
|
|
}
|
|
|
|
m_pRequest = pRequest;
|
|
}
|
|
};
|
|
|
|
//
|
|
// CFsm_OpenConnection -
|
|
//
|
|
|
|
class CFsm_OpenConnection : public CFsm {
|
|
|
|
friend class HTTP_REQUEST_HANDLE_OBJECT;
|
|
|
|
private:
|
|
|
|
//
|
|
// parameters
|
|
//
|
|
|
|
BOOL m_bNewConnection;
|
|
|
|
//
|
|
// local variables
|
|
//
|
|
|
|
BOOL m_bCreatedSocket;
|
|
BOOL m_fNoCreate;
|
|
|
|
public:
|
|
|
|
static
|
|
DWORD
|
|
RunSM(
|
|
IN CFsm * Fsm
|
|
);
|
|
|
|
CFsm_OpenConnection(
|
|
IN BOOL bNewConnection,
|
|
IN HTTP_REQUEST_HANDLE_OBJECT * pRequest,
|
|
IN BOOL fNoCreate = FALSE
|
|
) : CFsm(RunSM, (LPVOID)pRequest) {
|
|
|
|
SET_FSM_TYPE(OPEN_CONNECTION);
|
|
|
|
if (GetError() != ERROR_SUCCESS) {
|
|
return;
|
|
}
|
|
|
|
m_bNewConnection = bNewConnection;
|
|
m_bCreatedSocket = FALSE;
|
|
m_fNoCreate = fNoCreate;
|
|
}
|
|
};
|
|
|
|
//
|
|
// CFsm_OpenProxyTunnel -
|
|
//
|
|
|
|
class CFsm_OpenProxyTunnel : public CFsm {
|
|
|
|
friend class HTTP_REQUEST_HANDLE_OBJECT;
|
|
|
|
private:
|
|
|
|
//
|
|
// parameters
|
|
//
|
|
|
|
//
|
|
// local variables
|
|
//
|
|
|
|
HINTERNET m_hConnect;
|
|
HINTERNET m_hRequest;
|
|
HINTERNET m_hRequestMapped;
|
|
HTTP_REQUEST_HANDLE_OBJECT * m_pRequest;
|
|
|
|
public:
|
|
|
|
static
|
|
DWORD
|
|
RunSM(
|
|
IN CFsm * Fsm
|
|
);
|
|
|
|
CFsm_OpenProxyTunnel(
|
|
IN HTTP_REQUEST_HANDLE_OBJECT * pRequest
|
|
) : CFsm(RunSM, (LPVOID)pRequest) {
|
|
|
|
SET_FSM_TYPE(OPEN_PROXY_TUNNEL);
|
|
|
|
if (GetError() != ERROR_SUCCESS) {
|
|
return;
|
|
}
|
|
|
|
m_hConnect = NULL;
|
|
m_hRequest = NULL;
|
|
m_hRequestMapped = NULL;
|
|
}
|
|
};
|
|
|
|
//
|
|
// CFsm_SendRequest -
|
|
//
|
|
|
|
class CFsm_SendRequest : public CFsm {
|
|
|
|
friend class HTTP_REQUEST_HANDLE_OBJECT;
|
|
|
|
private:
|
|
|
|
//
|
|
// parameters
|
|
//
|
|
|
|
LPVOID m_lpOptional;
|
|
DWORD m_dwOptionalLength;
|
|
|
|
|
|
//
|
|
// local variables
|
|
//
|
|
|
|
LPSTR m_pRequestBuffer;
|
|
DWORD m_dwRequestLength;
|
|
BOOL m_bExtraCrLf;
|
|
|
|
public:
|
|
|
|
static
|
|
DWORD
|
|
RunSM(
|
|
IN CFsm * Fsm
|
|
);
|
|
|
|
CFsm_SendRequest(
|
|
IN LPVOID lpOptional,
|
|
IN DWORD dwOptionalLength,
|
|
IN HTTP_REQUEST_HANDLE_OBJECT * pRequest
|
|
) : CFsm(RunSM, (LPVOID)pRequest) {
|
|
|
|
SET_FSM_TYPE(SEND_REQUEST);
|
|
|
|
if (GetError() != ERROR_SUCCESS) {
|
|
return;
|
|
}
|
|
|
|
m_lpOptional = lpOptional;
|
|
m_dwOptionalLength = dwOptionalLength;
|
|
m_pRequestBuffer = NULL;
|
|
m_bExtraCrLf = FALSE;
|
|
}
|
|
|
|
~CFsm_SendRequest() {
|
|
if (m_pRequestBuffer != NULL) {
|
|
m_pRequestBuffer = (LPSTR)FREE_MEMORY(m_pRequestBuffer);
|
|
|
|
INET_ASSERT(m_pRequestBuffer == NULL);
|
|
|
|
}
|
|
}
|
|
};
|
|
|
|
//
|
|
// CFsm_ReceiveResponse -
|
|
//
|
|
|
|
class CFsm_ReceiveResponse : public CFsm {
|
|
|
|
friend class HTTP_REQUEST_HANDLE_OBJECT;
|
|
|
|
private:
|
|
|
|
//
|
|
// parameters
|
|
//
|
|
|
|
//
|
|
// local variables
|
|
//
|
|
|
|
HTTP_REQUEST_HANDLE_OBJECT * m_pRequest;
|
|
DWORD m_dwResponseLeft;
|
|
BOOL m_bEofResponseHeaders;
|
|
BOOL m_bDrained;
|
|
|
|
public:
|
|
|
|
static
|
|
DWORD
|
|
RunSM(
|
|
IN CFsm * Fsm
|
|
);
|
|
|
|
CFsm_ReceiveResponse(
|
|
IN HTTP_REQUEST_HANDLE_OBJECT * pRequest
|
|
) : CFsm(RunSM, (LPVOID)pRequest) {
|
|
|
|
SET_FSM_TYPE(RECEIVE_RESPONSE);
|
|
|
|
if (GetError() != ERROR_SUCCESS) {
|
|
return;
|
|
}
|
|
|
|
m_pRequest = pRequest;
|
|
m_bDrained = FALSE;
|
|
}
|
|
};
|
|
|
|
//
|
|
// CFsm_HttpReadData -
|
|
//
|
|
|
|
class CFsm_HttpReadData : public CFsm {
|
|
|
|
friend class HTTP_REQUEST_HANDLE_OBJECT;
|
|
|
|
private:
|
|
|
|
//
|
|
// parameters
|
|
//
|
|
|
|
LPVOID m_lpBuffer;
|
|
DWORD m_dwNumberOfBytesToRead;
|
|
LPDWORD m_lpdwNumberOfBytesRead;
|
|
DWORD m_dwSocketFlags;
|
|
|
|
//
|
|
// local variables
|
|
//
|
|
|
|
public:
|
|
|
|
static
|
|
DWORD
|
|
RunSM(
|
|
IN CFsm * Fsm
|
|
);
|
|
|
|
CFsm_HttpReadData(
|
|
IN LPVOID lpBuffer,
|
|
IN DWORD dwNumberOfBytesToRead,
|
|
OUT LPDWORD lpdwNumberOfBytesRead,
|
|
IN DWORD dwSocketFlags,
|
|
IN HTTP_REQUEST_HANDLE_OBJECT * pRequest
|
|
) : CFsm(RunSM, (LPVOID)pRequest) {
|
|
|
|
SET_FSM_TYPE(HTTP_READ);
|
|
|
|
if (GetError() != ERROR_SUCCESS) {
|
|
return;
|
|
}
|
|
|
|
m_lpBuffer = lpBuffer;
|
|
m_dwNumberOfBytesToRead = dwNumberOfBytesToRead;
|
|
m_lpdwNumberOfBytesRead = lpdwNumberOfBytesRead;
|
|
m_dwSocketFlags = dwSocketFlags;
|
|
}
|
|
};
|
|
|
|
//
|
|
// CFsm_HttpWriteData -
|
|
//
|
|
|
|
class CFsm_HttpWriteData : public CFsm {
|
|
|
|
friend class HTTP_REQUEST_HANDLE_OBJECT;
|
|
|
|
private:
|
|
|
|
//
|
|
// parameters
|
|
//
|
|
|
|
LPVOID m_lpBuffer;
|
|
DWORD m_dwNumberOfBytesToWrite;
|
|
LPDWORD m_lpdwNumberOfBytesWritten;
|
|
DWORD m_dwSocketFlags;
|
|
|
|
//
|
|
// local variables
|
|
//
|
|
|
|
public:
|
|
|
|
static
|
|
DWORD
|
|
RunSM(
|
|
IN CFsm * Fsm
|
|
);
|
|
|
|
CFsm_HttpWriteData(
|
|
IN LPVOID lpBuffer,
|
|
IN DWORD dwNumberOfBytesToWrite,
|
|
OUT LPDWORD lpdwNumberOfBytesWritten,
|
|
IN DWORD dwSocketFlags,
|
|
IN HTTP_REQUEST_HANDLE_OBJECT * pRequest
|
|
) : CFsm(RunSM, (LPVOID)pRequest, FALSE) {
|
|
|
|
SET_FSM_TYPE(HTTP_WRITE);
|
|
|
|
if (GetError() != ERROR_SUCCESS) {
|
|
return;
|
|
}
|
|
|
|
m_lpBuffer = lpBuffer;
|
|
m_dwNumberOfBytesToWrite = dwNumberOfBytesToWrite;
|
|
m_lpdwNumberOfBytesWritten = lpdwNumberOfBytesWritten;
|
|
m_dwSocketFlags = dwSocketFlags;
|
|
SetApi(ApiType_Bool);
|
|
}
|
|
};
|
|
|
|
|
|
//
|
|
// CFsm_ReadData -
|
|
//
|
|
|
|
class CFsm_ReadData : public CFsm {
|
|
|
|
friend class HTTP_REQUEST_HANDLE_OBJECT;
|
|
|
|
private:
|
|
|
|
//
|
|
// parameters
|
|
//
|
|
|
|
LPVOID m_lpBuffer;
|
|
DWORD m_dwNumberOfBytesToRead;
|
|
LPDWORD m_lpdwNumberOfBytesRead;
|
|
BOOL m_fNoAsync;
|
|
DWORD m_dwSocketFlags;
|
|
|
|
//
|
|
// local variables
|
|
//
|
|
|
|
DWORD m_nBytes;
|
|
DWORD m_nBytesCopied;
|
|
DWORD m_dwBufferLeft;
|
|
DWORD m_dwBytesRead;
|
|
BOOL m_bEof;
|
|
|
|
public:
|
|
|
|
static
|
|
DWORD
|
|
RunSM(
|
|
IN CFsm * Fsm
|
|
);
|
|
|
|
CFsm_ReadData(
|
|
IN LPVOID lpBuffer,
|
|
IN DWORD dwNumberOfBytesToRead,
|
|
OUT LPDWORD lpdwNumberOfBytesRead,
|
|
IN BOOL fNoAsync,
|
|
IN DWORD dwSocketFlags,
|
|
IN HTTP_REQUEST_HANDLE_OBJECT * pRequest
|
|
) : CFsm(RunSM, (LPVOID)pRequest) {
|
|
|
|
SET_FSM_TYPE(READ_DATA);
|
|
|
|
if (GetError() != ERROR_SUCCESS) {
|
|
return;
|
|
}
|
|
|
|
m_lpBuffer = lpBuffer;
|
|
m_dwNumberOfBytesToRead = dwNumberOfBytesToRead;
|
|
m_lpdwNumberOfBytesRead = lpdwNumberOfBytesRead;
|
|
m_fNoAsync = fNoAsync;
|
|
m_dwSocketFlags = dwSocketFlags;
|
|
m_nBytesCopied = 0;
|
|
}
|
|
};
|
|
|
|
//
|
|
// CFsm_HttpQueryAvailable -
|
|
//
|
|
|
|
class CFsm_HttpQueryAvailable : public CFsm {
|
|
|
|
friend class HTTP_REQUEST_HANDLE_OBJECT;
|
|
|
|
private:
|
|
|
|
//
|
|
// parameters
|
|
//
|
|
|
|
LPDWORD m_lpdwNumberOfBytesAvailable;
|
|
|
|
//
|
|
// local variables
|
|
//
|
|
|
|
LPVOID m_lpBuffer;
|
|
DWORD m_dwBufferLength;
|
|
DWORD m_dwBufferLeft;
|
|
BOOL m_bEof;
|
|
|
|
public:
|
|
|
|
static
|
|
DWORD
|
|
RunSM(
|
|
IN CFsm * Fsm
|
|
);
|
|
|
|
CFsm_HttpQueryAvailable(
|
|
IN LPDWORD lpdwNumberOfBytesAvailable,
|
|
IN HTTP_REQUEST_HANDLE_OBJECT * pRequest
|
|
) : CFsm(RunSM, (LPVOID)pRequest) {
|
|
|
|
SET_FSM_TYPE(HTTP_QUERY_AVAILABLE);
|
|
|
|
if (GetError() != ERROR_SUCCESS) {
|
|
return;
|
|
}
|
|
|
|
m_lpdwNumberOfBytesAvailable = lpdwNumberOfBytesAvailable;
|
|
}
|
|
};
|
|
|
|
//
|
|
// CFsm_DrainResponse -
|
|
//
|
|
|
|
class CFsm_DrainResponse : CFsm {
|
|
|
|
friend class HTTP_REQUEST_HANDLE_OBJECT;
|
|
|
|
private:
|
|
|
|
//
|
|
// parameters
|
|
//
|
|
|
|
LPBOOL m_lpbDrained;
|
|
|
|
//
|
|
// local variables
|
|
//
|
|
|
|
DWORD m_dwAmountToRead;
|
|
DWORD m_dwBufferLeft;
|
|
DWORD m_dwPreviousBytesReceived;
|
|
DWORD m_dwAsyncFlags;
|
|
DWORD m_dwBytesReceived;
|
|
BOOL m_bEof;
|
|
|
|
public:
|
|
|
|
static
|
|
DWORD
|
|
RunSM(
|
|
IN CFsm * Fsm
|
|
);
|
|
|
|
CFsm_DrainResponse(
|
|
IN LPBOOL lpbDrained,
|
|
IN HTTP_REQUEST_HANDLE_OBJECT * pRequest
|
|
) : CFsm(RunSM, (LPVOID)pRequest) {
|
|
|
|
SET_FSM_TYPE(DRAIN_RESPONSE);
|
|
|
|
if (GetError() != ERROR_SUCCESS) {
|
|
return;
|
|
}
|
|
|
|
m_lpbDrained = lpbDrained;
|
|
m_bEof = FALSE;
|
|
m_dwBytesReceived = 0;
|
|
}
|
|
};
|
|
|
|
//
|
|
// CFsm_Redirect -
|
|
//
|
|
|
|
class CFsm_Redirect : public CFsm {
|
|
|
|
friend class HTTP_REQUEST_HANDLE_OBJECT;
|
|
|
|
private:
|
|
|
|
//
|
|
// parameters
|
|
//
|
|
|
|
HTTP_METHOD_TYPE m_tMethod;
|
|
|
|
//
|
|
// local variables
|
|
//
|
|
|
|
BOOL m_bDrained;
|
|
|
|
public:
|
|
|
|
static
|
|
DWORD
|
|
RunSM(
|
|
IN CFsm * Fsm
|
|
);
|
|
|
|
CFsm_Redirect(
|
|
IN HTTP_METHOD_TYPE tMethod,
|
|
IN BOOL fRedirectToProxy,
|
|
IN HTTP_REQUEST_HANDLE_OBJECT * pRequest
|
|
) : CFsm(RunSM, (LPVOID)pRequest) {
|
|
|
|
SET_FSM_TYPE(REDIRECT);
|
|
|
|
if (GetError() != ERROR_SUCCESS) {
|
|
return;
|
|
}
|
|
|
|
m_tMethod = tMethod;
|
|
|
|
}
|
|
};
|
|
|
|
//
|
|
// CFsm_ReadLoop -
|
|
//
|
|
|
|
class CFsm_ReadLoop : public CFsm {
|
|
|
|
friend class HTTP_REQUEST_HANDLE_OBJECT;
|
|
|
|
private:
|
|
|
|
//
|
|
// parameters
|
|
//
|
|
|
|
DWORD m_dwSocketFlags;
|
|
PBYTE m_pRead;
|
|
DWORD m_cbReadIn;
|
|
DWORD* m_pcbReadOut;
|
|
|
|
//
|
|
// local variables
|
|
//
|
|
|
|
LPVOID m_pBuf; // read buffer
|
|
DWORD m_cbBuf; // size of read buffer
|
|
DWORD m_dwReadEnd; // read offset goal
|
|
DWORD m_cbRead; // bytes to read
|
|
DWORD m_cbRecv; // bytes received
|
|
|
|
public:
|
|
|
|
static
|
|
DWORD
|
|
RunSM(
|
|
IN CFsm * Fsm
|
|
);
|
|
|
|
CFsm_ReadLoop(
|
|
IN HTTP_REQUEST_HANDLE_OBJECT * pRequest,
|
|
IN DWORD dwSocketFlags,
|
|
IN PBYTE pRead,
|
|
IN DWORD cbReadIn,
|
|
OUT DWORD* pcbReadOut
|
|
) : CFsm(RunSM, (LPVOID)pRequest) {
|
|
|
|
SET_FSM_TYPE(READ_LOOP);
|
|
|
|
m_dwSocketFlags = dwSocketFlags;
|
|
m_pRead = pRead;
|
|
m_cbReadIn = cbReadIn;
|
|
m_pcbReadOut = pcbReadOut;
|
|
|
|
if (GetError() != ERROR_SUCCESS) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
};
|
|
|
|
//
|
|
// CFsm_ParseHttpUrl -
|
|
//
|
|
|
|
class CFsm_ParseHttpUrl : public CFsm {
|
|
|
|
friend
|
|
DWORD
|
|
ParseHttpUrl_Fsm(
|
|
IN CFsm_ParseHttpUrl * Fsm
|
|
);
|
|
|
|
private:
|
|
|
|
//
|
|
// parameters
|
|
//
|
|
|
|
LPHINTERNET m_phInternet;
|
|
LPSTR m_lpszUrl;
|
|
DWORD m_dwSchemeLength;
|
|
LPSTR m_lpszHeaders;
|
|
DWORD m_dwHeadersLength;
|
|
DWORD m_dwFlags;
|
|
DWORD_PTR m_dwContext;
|
|
|
|
//
|
|
// locals
|
|
//
|
|
|
|
HINTERNET m_hConnect;
|
|
HINTERNET m_hRequest;
|
|
|
|
public:
|
|
|
|
CFsm_ParseHttpUrl(
|
|
IN OUT LPHINTERNET phInternet,
|
|
IN LPSTR lpszUrl,
|
|
IN DWORD dwSchemeLength,
|
|
IN LPSTR lpszHeaders,
|
|
IN DWORD dwHeadersLength,
|
|
IN DWORD dwFlags,
|
|
IN DWORD_PTR dwContext
|
|
) : CFsm((DWORD (*)(CFsm *))ParseHttpUrl_Fsm, NULL) {
|
|
|
|
SET_FSM_TYPE(PARSE_HTTP_URL);
|
|
|
|
if (GetError() != ERROR_SUCCESS) {
|
|
return;
|
|
}
|
|
|
|
m_phInternet = phInternet;
|
|
m_lpszUrl = lpszUrl;
|
|
m_dwSchemeLength = dwSchemeLength;
|
|
m_lpszHeaders = lpszHeaders;
|
|
m_dwHeadersLength = dwHeadersLength;
|
|
m_dwFlags = dwFlags;
|
|
m_dwContext = dwContext;
|
|
}
|
|
};
|
|
|
|
//
|
|
// CFsm_OpenUrl -
|
|
//
|
|
|
|
class CFsm_OpenUrl : public CFsm {
|
|
|
|
private:
|
|
|
|
//
|
|
// parameters
|
|
//
|
|
|
|
//
|
|
// locals
|
|
//
|
|
|
|
public:
|
|
|
|
CFsm_OpenUrl();
|
|
};
|
|
|
|
//
|
|
// CFsm_ParseUrlForHttp -
|
|
//
|
|
|
|
class CFsm_ParseUrlForHttp : public CFsm {
|
|
|
|
friend
|
|
DWORD
|
|
ParseUrlForHttp_Fsm(
|
|
IN CFsm_ParseUrlForHttp * Fsm
|
|
);
|
|
|
|
private:
|
|
|
|
//
|
|
// parameters
|
|
//
|
|
|
|
LPHINTERNET m_lphInternet; // 0x7C
|
|
HINTERNET m_hInternet; // 0x80
|
|
LPVOID m_hInternetMapped; // 0x84
|
|
LPSTR m_lpcszUrl; // 0x88
|
|
LPSTR m_lpcszHeaders; // 0x8C
|
|
DWORD m_dwHeadersLength; // 0x90
|
|
DWORD m_dwFlags; // 0x94
|
|
DWORD_PTR m_dwContext; // 0x98
|
|
|
|
//
|
|
// locals
|
|
//
|
|
|
|
PROXY_STATE * m_pProxyState; // 0x9C
|
|
LPSTR m_lpszUrlCopy; // 0xA0
|
|
LPFN_URL_PARSER m_pUrlParser; // 0xA4
|
|
INTERNET_SCHEME m_SchemeType; // 0xA8
|
|
DWORD m_dwSchemeLength; // 0xAC
|
|
AUTO_PROXY_ASYNC_MSG *m_pProxyInfoQuery;// 0xB0
|
|
BOOL m_fFirstCall; // 0xB4
|
|
HINTERNET m_hInternetCopy; // 0xB8
|
|
|
|
public:
|
|
|
|
static
|
|
DWORD
|
|
RunSM(
|
|
IN CFsm * Fsm
|
|
);
|
|
|
|
CFsm_ParseUrlForHttp(
|
|
IN OUT LPHINTERNET lphInternet,
|
|
IN LPVOID hMapped,
|
|
IN LPCSTR lpcszUrl,
|
|
IN LPCSTR lpcszHeaders,
|
|
IN DWORD dwHeadersLength,
|
|
IN DWORD dwFlags,
|
|
IN DWORD_PTR dwContext
|
|
) : CFsm(RunSM, NULL) {
|
|
|
|
SET_FSM_TYPE(PARSE_URL_FOR_HTTP);
|
|
|
|
if (GetError() != ERROR_SUCCESS) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
// ParseUrlForHttp() is the function that returns the API result for
|
|
// InternetOpenUrl() in the new scheme. Make this FSM return the API
|
|
// result
|
|
//
|
|
|
|
SetApi(ApiType_Handle);
|
|
m_lphInternet = lphInternet;
|
|
m_hInternet = *lphInternet;
|
|
m_hInternetMapped = hMapped;
|
|
m_hInternetCopy = *lphInternet;
|
|
m_dwHeadersLength = dwHeadersLength;
|
|
m_dwFlags = dwFlags;
|
|
m_dwContext = dwContext;
|
|
m_pProxyState = NULL;
|
|
m_pUrlParser = NULL;
|
|
m_SchemeType = INTERNET_SCHEME_DEFAULT;
|
|
m_dwSchemeLength = 0;
|
|
m_pProxyInfoQuery = NULL;
|
|
m_fFirstCall = TRUE;
|
|
|
|
COPY_MANDATORY_PARAM(m_lpcszUrl, lpcszUrl);
|
|
|
|
if (lpcszHeaders)
|
|
{
|
|
m_lpcszHeaders = NewString(lpcszHeaders, dwHeadersLength);
|
|
if (!m_lpcszHeaders)
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
}
|
|
else
|
|
m_lpcszHeaders = NULL;
|
|
}
|
|
|
|
~CFsm_ParseUrlForHttp() {
|
|
DELETE_MANDATORY_PARAM(m_lpcszUrl);
|
|
DELETE_OPTIONAL_PARAM(m_lpcszHeaders);
|
|
}
|
|
|
|
BOOL IsOnApiCall(VOID) {
|
|
return m_fFirstCall;
|
|
}
|
|
|
|
VOID ClearOnApiCall(VOID) {
|
|
m_fFirstCall = FALSE;
|
|
}
|
|
|
|
DWORD
|
|
QueryProxySettings(
|
|
IN CFsm_ParseUrlForHttp * Fsm,
|
|
IN BOOL fCallback
|
|
);
|
|
|
|
DWORD
|
|
BuildProxyMessage(
|
|
IN CFsm_ParseUrlForHttp * Fsm
|
|
);
|
|
|
|
DWORD
|
|
ScanProxyUrl(
|
|
IN CFsm_ParseUrlForHttp * Fsm
|
|
);
|
|
|
|
DWORD
|
|
CompleteParseUrl(
|
|
IN CFsm_ParseUrlForHttp * Fsm,
|
|
IN LPINTERNET_THREAD_INFO lpThreadInfo,
|
|
IN DWORD error
|
|
);
|
|
};
|
|
|
|
//
|
|
// InternetReadFile API
|
|
//
|
|
|
|
class CFsm_ReadFile : public CFsm {
|
|
|
|
friend
|
|
DWORD
|
|
ReadFile_Fsm(
|
|
IN CFsm_ReadFile * Fsm
|
|
);
|
|
|
|
public:
|
|
LPVOID m_lpBuffer;
|
|
LPDWORD m_lpdwNumberOfBytesRead;
|
|
|
|
|
|
private:
|
|
|
|
//
|
|
// parameters
|
|
//
|
|
|
|
DWORD m_dwNumberOfBytesToRead;
|
|
|
|
//
|
|
// local variables
|
|
//
|
|
|
|
DWORD m_dwBytesRead;
|
|
|
|
public:
|
|
|
|
static
|
|
DWORD
|
|
RunSM(
|
|
IN CFsm * Fsm
|
|
);
|
|
|
|
CFsm_ReadFile(
|
|
IN LPVOID lpBuffer,
|
|
IN DWORD dwNumberOfBytesToRead,
|
|
OUT LPDWORD lpdwNumberOfBytesRead
|
|
) : CFsm(RunSM, NULL, FALSE) {
|
|
|
|
SET_FSM_TYPE(READ_FILE);
|
|
|
|
if (GetError() != ERROR_SUCCESS) {
|
|
return;
|
|
}
|
|
|
|
SetApi(ApiType_Bool);
|
|
m_lpBuffer = lpBuffer;
|
|
m_dwNumberOfBytesToRead = dwNumberOfBytesToRead;
|
|
m_lpdwNumberOfBytesRead = lpdwNumberOfBytesRead;
|
|
}
|
|
};
|
|
|
|
//
|
|
// InternetReadFileEx API
|
|
//
|
|
|
|
class CFsm_ReadFileEx : public CFsm {
|
|
|
|
friend
|
|
DWORD
|
|
ReadFileEx_Fsm(
|
|
IN CFsm_ReadFileEx * Fsm
|
|
);
|
|
|
|
private:
|
|
|
|
//
|
|
// parameters
|
|
//
|
|
|
|
LPINTERNET_BUFFERS m_lpBuffersOut;
|
|
DWORD m_dwFlags;
|
|
DWORD_PTR m_dwContext;
|
|
|
|
//
|
|
// local variables
|
|
//
|
|
|
|
DWORD m_dwNumberOfBytesToRead;
|
|
DWORD m_dwBytesRead;
|
|
|
|
public:
|
|
|
|
static
|
|
DWORD
|
|
RunSM(
|
|
IN CFsm * Fsm
|
|
);
|
|
|
|
CFsm_ReadFileEx(
|
|
IN LPINTERNET_BUFFERS lpBuffersOut,
|
|
IN DWORD dwFlags,
|
|
IN DWORD_PTR dwContext
|
|
) : CFsm(RunSM, NULL) {
|
|
|
|
SET_FSM_TYPE(READ_FILE);
|
|
|
|
if (GetError() != ERROR_SUCCESS) {
|
|
return;
|
|
}
|
|
|
|
SetApi(ApiType_Bool);
|
|
m_lpBuffersOut = lpBuffersOut;
|
|
m_dwFlags = dwFlags;
|
|
m_dwContext = dwContext;
|
|
}
|
|
};
|
|
|
|
//
|
|
// InternetQueryDataAvailable API
|
|
//
|
|
|
|
class CFsm_QueryAvailable : public CFsm {
|
|
|
|
friend
|
|
DWORD
|
|
QueryAvailable_Fsm(
|
|
IN CFsm_QueryAvailable * Fsm
|
|
);
|
|
|
|
public:
|
|
LPDWORD m_lpdwNumberOfBytesAvailable;
|
|
|
|
private:
|
|
|
|
//
|
|
// parameters
|
|
//
|
|
|
|
DWORD m_dwFlags;
|
|
DWORD_PTR m_dwContext;
|
|
|
|
//
|
|
// local variables
|
|
//
|
|
|
|
public:
|
|
|
|
static
|
|
DWORD
|
|
RunSM(
|
|
IN CFsm * Fsm
|
|
);
|
|
|
|
CFsm_QueryAvailable(
|
|
IN LPDWORD lpdwNumberOfBytesAvailable,
|
|
IN DWORD dwFlags,
|
|
IN DWORD_PTR dwContext
|
|
) : CFsm(RunSM, NULL, FALSE) {
|
|
|
|
SET_FSM_TYPE(QUERY_DATA_AVAILABLE);
|
|
|
|
if (GetError() != ERROR_SUCCESS) {
|
|
return;
|
|
}
|
|
|
|
SetApi(ApiType_Bool);
|
|
m_lpdwNumberOfBytesAvailable = lpdwNumberOfBytesAvailable;
|
|
m_dwFlags = dwFlags;
|
|
m_dwContext = dwContext;
|
|
}
|
|
};
|
|
|
|
//
|
|
// Fsm to Background tasks
|
|
//
|
|
|
|
class BackgroundTaskMgr; // defined in bgtask.hxx
|
|
class CFsm_BackgroundTask : public CFsm {
|
|
friend class BackgroundTaskMgr;
|
|
|
|
friend
|
|
DWORD
|
|
BackgroundTask_Fsm(
|
|
IN CFsm_BackgroundTask * Fsm
|
|
);
|
|
|
|
private:
|
|
|
|
//
|
|
// parameters
|
|
//
|
|
BackgroundTaskMgr* m_pMgr;
|
|
LPCSTR m_lpszUrl;
|
|
|
|
//
|
|
// local variables
|
|
//
|
|
|
|
//
|
|
// internal methods
|
|
|
|
DWORD DoSendReq();
|
|
|
|
//
|
|
// this private func can only
|
|
// be called from Mgr
|
|
//
|
|
CFsm_BackgroundTask(
|
|
IN BackgroundTaskMgr* pMgr,
|
|
IN LPCSTR lpszUrl
|
|
) : CFsm(RunSM, NULL) {
|
|
|
|
SET_FSM_TYPE(BACKGROUND_TASK);
|
|
|
|
if (GetError() != ERROR_SUCCESS) {
|
|
return;
|
|
}
|
|
|
|
m_pMgr = pMgr;
|
|
COPY_MANDATORY_PARAM(m_lpszUrl, lpszUrl);
|
|
}
|
|
|
|
public:
|
|
|
|
static
|
|
DWORD
|
|
RunSM(
|
|
IN CFsm * Fsm
|
|
);
|
|
|
|
|
|
~CFsm_BackgroundTask();
|
|
};
|
|
|
|
|
|
//
|
|
// prototypes
|
|
//
|
|
|
|
CFsm *
|
|
ContainingFsm(
|
|
IN LPVOID lpAddress
|
|
);
|
|
|
|
DWORD
|
|
RunAll(
|
|
VOID
|
|
);
|
|
|
|
DWORD
|
|
DoFsm(
|
|
IN CFsm * pFsm
|
|
);
|
|
|
|
DWORD
|
|
DoAsyncFsm(
|
|
IN CFsm * pFsm,
|
|
IN HTTP_REQUEST_HANDLE_OBJECT *pRequest
|
|
);
|