Leaked source code of windows server 2003
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.

3303 lines
71 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. fsm.hxx
  5. Abstract:
  6. Contains Finite State Machine class definition
  7. Author:
  8. Richard L Firth (rfirth) 11-Apr-1997
  9. Revision History:
  10. 11-Apr-1997 rfirth
  11. Created
  12. --*/
  13. //
  14. // types
  15. //
  16. //
  17. // FSM_STATE - states FSMs can be in. We have some states defined for all FSMs,
  18. // e.g. FSM_STATE_INIT, and other states that are used internally by the FSMs,
  19. // e.g. FSM_STATE_1 through FSM_STATE_10
  20. //
  21. typedef enum {
  22. FSM_STATE_BAD = -1,
  23. FSM_STATE_INIT,
  24. FSM_STATE_WAIT,
  25. FSM_STATE_DONE,
  26. FSM_STATE_ERROR,
  27. FSM_STATE_CONTINUE,
  28. FSM_STATE_FINISH,
  29. FSM_STATE_1,
  30. FSM_STATE_2,
  31. FSM_STATE_3,
  32. FSM_STATE_4,
  33. FSM_STATE_5,
  34. FSM_STATE_6,
  35. FSM_STATE_7,
  36. FSM_STATE_8,
  37. FSM_STATE_9,
  38. FSM_STATE_10
  39. } FSM_STATE;
  40. //
  41. // FSM_HINT - QUICK if next operation is expected to complete quickly
  42. //
  43. typedef enum {
  44. FSM_HINT_SLOW, // default
  45. FSM_HINT_QUICK
  46. } FSM_HINT;
  47. //
  48. // FSM_ACTION - type of (socket) action an FSM is waiting on
  49. //
  50. typedef enum {
  51. FSM_ACTION_NONE = 0,
  52. FSM_ACTION_CONNECT = 1,
  53. FSM_ACTION_SEND,
  54. FSM_ACTION_RECEIVE
  55. } FSM_ACTION;
  56. //
  57. // FSM_TYPE - for debugging purposes
  58. //
  59. typedef enum {
  60. FSM_TYPE_NONE,
  61. FSM_TYPE_WAIT_FOR_COMPLETION,
  62. FSM_TYPE_RESOLVE_HOST,
  63. FSM_TYPE_SOCKET_CONNECT,
  64. FSM_TYPE_SOCKET_SEND,
  65. FSM_TYPE_SOCKET_RECEIVE,
  66. FSM_TYPE_SOCKET_QUERY_AVAILABLE,
  67. FSM_TYPE_SECURE_CONNECT,
  68. FSM_TYPE_SECURE_HANDSHAKE,
  69. FSM_TYPE_SECURE_NEGOTIATE,
  70. FSM_TYPE_NEGOTIATE_LOOP,
  71. FSM_TYPE_SECURE_SEND,
  72. FSM_TYPE_SECURE_RECEIVE,
  73. FSM_TYPE_GET_CONNECTION,
  74. FSM_TYPE_HTTP_SEND_REQUEST,
  75. FSM_TYPE_MAKE_CONNECTION,
  76. FSM_TYPE_OPEN_CONNECTION,
  77. FSM_TYPE_OPEN_PROXY_TUNNEL,
  78. FSM_TYPE_SEND_REQUEST,
  79. FSM_TYPE_RECEIVE_RESPONSE,
  80. FSM_TYPE_HTTP_READ,
  81. FSM_TYPE_HTTP_WRITE,
  82. FSM_TYPE_READ_DATA,
  83. FSM_TYPE_HTTP_QUERY_AVAILABLE,
  84. FSM_TYPE_DRAIN_RESPONSE,
  85. FSM_TYPE_REDIRECT,
  86. FSM_TYPE_READ_LOOP,
  87. FSM_TYPE_PARSE_HTTP_URL,
  88. FSM_TYPE_PARSE_URL_FOR_HTTP,
  89. FSM_TYPE_READ_FILE,
  90. FSM_TYPE_READ_FILE_EX,
  91. FSM_TYPE_WRITE_FILE,
  92. FSM_TYPE_QUERY_DATA_AVAILABLE,
  93. FSM_TYPE_FTP_CONNECT,
  94. FSM_TYPE_FTP_FIND_FIRST_FILE,
  95. FSM_TYPE_FTP_GET_FILE,
  96. FSM_TYPE_FTP_PUT_FILE,
  97. FSM_TYPE_FTP_DELETE_FILE,
  98. FSM_TYPE_FTP_RENAME_FILE,
  99. FSM_TYPE_FTP_GET_FILE_SIZE,
  100. FSM_TYPE_FTP_OPEN_FILE,
  101. FSM_TYPE_FTP_COMMAND,
  102. FSM_TYPE_FTP_CREATE_DIRECTORY,
  103. FSM_TYPE_FTP_REMOVE_DIRECTORY,
  104. FSM_TYPE_FTP_SET_CURRENT_DIRECTORY,
  105. FSM_TYPE_FTP_GET_CURRENT_DIRECTORY,
  106. FSM_TYPE_GOPHER_FIND_FIRST_FILE,
  107. FSM_TYPE_GOPHER_OPEN_FILE,
  108. FSM_TYPE_GOPHER_GET_ATTRIBUTE,
  109. FSM_TYPE_INTERNET_PARSE_URL,
  110. FSM_TYPE_INTERNET_FIND_NEXT_FILE,
  111. FSM_TYPE_INTERNET_QUERY_DATA_AVAILABLE,
  112. FSM_TYPE_INTERNET_WRITE_FILE,
  113. FSM_TYPE_INTERNET_READ_FILE,
  114. FSM_TYPE_BACKGROUND_TASK
  115. } FSM_TYPE;
  116. //
  117. // API_TYPE - what type of parameter API returns. Used in conjunction with
  118. // SetApi()
  119. //
  120. typedef enum {
  121. ApiType_None,
  122. ApiType_Handle,
  123. ApiType_Bool
  124. } API_TYPE;
  125. //
  126. // macros
  127. //
  128. #define COPY_MANDATORY_PARAM(y,x) \
  129. if (x) { \
  130. y = NewString(x); \
  131. if ( y == NULL) { \
  132. SetError(ERROR_NOT_ENOUGH_MEMORY); \
  133. } \
  134. } \
  135. else { \
  136. y = NULL; \
  137. INET_ASSERT(FALSE); \
  138. }
  139. #define COPY_MANDATORY_PARAMW(y,x) \
  140. if (x) { \
  141. y = NewStringW(x); \
  142. if ( y == NULL) { \
  143. SetError(ERROR_NOT_ENOUGH_MEMORY); \
  144. } \
  145. } \
  146. else { \
  147. y = NULL; \
  148. INET_ASSERT(FALSE); \
  149. }
  150. #define COPY_OPTIONAL_PARAM(y,x) \
  151. if (x) { \
  152. y = NewString(x); \
  153. if ( y == NULL) { \
  154. SetError(ERROR_NOT_ENOUGH_MEMORY); \
  155. } \
  156. } \
  157. else { \
  158. y = NULL; \
  159. }
  160. #define DELETE_MANDATORY_PARAM(x) \
  161. if (x) { \
  162. x=(LPSTR)FREE_MEMORY(x); \
  163. } \
  164. else { \
  165. INET_ASSERT(FALSE); \
  166. }
  167. #define DELETE_MANDATORY_PARAMW(x) \
  168. if (x) { \
  169. x=(LPWSTR)FREE_MEMORY(x); \
  170. } \
  171. else { \
  172. INET_ASSERT(FALSE); \
  173. }
  174. #define DELETE_OPTIONAL_PARAM(x) \
  175. if (x) { \
  176. x=(LPSTR)FREE_MEMORY(x); \
  177. }
  178. //
  179. // functions
  180. //
  181. BOOL
  182. wInternetQueryDataAvailable(
  183. IN LPVOID hFileMapped,
  184. OUT LPDWORD lpdwNumberOfBytesAvailable,
  185. IN DWORD dwFlags,
  186. IN DWORD_PTR dwContext
  187. );
  188. VOID
  189. Pop(
  190. CFsm * pNextFsm,
  191. INTERNET_THREAD_INFO * lpThreadInfo,
  192. DWORD dwError
  193. );
  194. //
  195. // classes
  196. //
  197. //
  198. // CFsm - the finite state machine class. Describes the basic work unit,
  199. // assumable by any available thread.
  200. //
  201. // State machines are chainable on a stack: the head of the stack is always the
  202. // currently executing state machine
  203. //
  204. // For non-blocking socket operations, state machines are associated with the
  205. // socket handle blocking the state machine
  206. //
  207. // State machines have a priority which is used in deciding which runnable state
  208. // machine is executed next
  209. //
  210. class CFsm : public CPriorityListEntry {
  211. private:
  212. CFsm * m_Link; // 0x10
  213. DWORD m_dwError; // 0x14
  214. LPINTERNET_THREAD_INFO m_lpThreadInfo; // 0x18
  215. DWORD_PTR m_dwContext; // 0x1C
  216. HINTERNET m_hObject; // 0x20
  217. INTERNET_HANDLE_OBJECT * m_hObjectMapped; // 0x24
  218. DWORD m_dwMappedErrorCode; // 0x28
  219. FSM_STATE m_State; // 0x2C
  220. FSM_STATE m_NextState; // 0x30
  221. FSM_STATE m_FunctionState; // 0x34
  222. DWORD (*m_lpfnHandler)(CFsm *); // 0x38
  223. LPVOID m_lpvContext; // 0x3C
  224. FSM_HINT m_Hint; // 0x40
  225. SOCKET m_Socket; // 0x44
  226. FSM_ACTION m_Action; // 0x48
  227. DWORD_PTR m_dwBlockId; // 0x4C
  228. DWORD m_dwTimeout; // 0x50
  229. BOOL m_fTimeoutWraps;
  230. DWORD m_dwTimer; // 0x54
  231. BOOL m_bTimerStarted; // 0x58
  232. BOOL m_bIsApi; // 0x5C
  233. // indicates a non-yielding fsm, that blocks a full thread while it executes
  234. BOOL m_bIsBlockingFsm; // 0x60
  235. API_TYPE m_ApiType; // 0x64
  236. union {
  237. BOOL Bool;
  238. HINTERNET Handle;
  239. } m_ApiResult; // 0x68
  240. DWORD m_dwApiData; // 0x6C
  241. BOOL m_bHasTimeout;
  242. #ifdef USE_OLD_SENDRECV_SYNC
  243. BOOL m_bOnAsyncList;
  244. #endif
  245. BOOL m_bPop;
  246. //#if INET_DEBUG
  247. #ifdef STRESS_BUG_DEBUG
  248. DWORD m_Signature; // 0x70
  249. public:
  250. DWORD m_ThreadId; // 0x74
  251. #define INET_ASSERT_X(x) if ( !(x) ) { OutputDebugString("WinHttp.DLL: FSM still in use, contact venkatk, x54275 \r\n"); \
  252. DebugBreak(); }
  253. #define FSM_SIGNATURE 0x5f4d5346 // "FSM_"
  254. #define INIT_FSM() m_Signature = FSM_SIGNATURE; \
  255. m_Type = FSM_TYPE_NONE; \
  256. m_ThreadId = 0
  257. #define CHECK_FSM() INET_ASSERT_X(m_Signature == FSM_SIGNATURE)
  258. #define SET_OWNED() m_ThreadId = GetCurrentThreadId()
  259. #define RESET_OWNED() m_ThreadId = 0
  260. #define CHECK_OWNED() INET_ASSERT_X(m_ThreadId == GetCurrentThreadId())
  261. #define CHECK_UNOWNED() INET_ASSERT_X(m_ThreadId == 0)
  262. #define SET_FSM_OWNED(p) if (p) p->m_ThreadId = GetCurrentThreadId()
  263. #define RESET_FSM_OWNED(p) if (p) p->m_ThreadId = 0
  264. #define CHECK_FSM_OWNED(p) if (p) INET_ASSERT_X(p->m_ThreadId == GetCurrentThreadId())
  265. #define CHECK_FSM_UNOWNED(p) if (p) INET_ASSERT_X(p->m_ThreadId == 0)
  266. protected:
  267. FSM_TYPE m_Type; // 0x78
  268. #define SET_FSM_TYPE(type) m_Type = FSM_TYPE_ ## type
  269. #else
  270. #define INIT_FSM() /* NOTHING */
  271. #define CHECK_FSM() /* NOTHING */
  272. #define SET_OWNED() /* NOTHING */
  273. #define RESET_OWNED() /* NOTHING */
  274. #define CHECK_OWNED() /* NOTHING */
  275. #define CHECK_UNOWNED() /* NOTHING */
  276. #define SET_FSM_OWNED(p) /* NOTHING */
  277. #define RESET_FSM_OWNED(p) /* NOTHING */
  278. #define CHECK_FSM_OWNED(p) /* NOTHING */
  279. #define CHECK_FSM_UNOWNED(p) /* NOTHING */
  280. #define SET_FSM_TYPE(type) /* NOTHING */
  281. #endif
  282. public:
  283. CFsm(DWORD (* lpfnHandler)(CFsm *), LPVOID lpvContext);
  284. virtual ~CFsm();
  285. VOID
  286. Push(
  287. VOID
  288. );
  289. VOID
  290. Pop(
  291. VOID
  292. );
  293. VOID
  294. SetPop(BOOL fPushPop) {
  295. m_bPop = fPushPop;
  296. }
  297. BOOL IsPop()
  298. {
  299. return m_bPop;
  300. }
  301. CFsm*
  302. GetParentFsm()
  303. {
  304. return m_Link;
  305. }
  306. DWORD GetError(VOID) const {
  307. return m_dwError;
  308. }
  309. VOID SetError(DWORD Error) {
  310. m_dwError = Error;
  311. }
  312. BOOL IsInvalid(VOID) {
  313. INET_ASSERT(m_hObjectMapped != NULL);
  314. return (m_hObjectMapped != NULL)
  315. ? m_hObjectMapped->IsInvalidated()
  316. : FALSE;
  317. }
  318. DWORD GetMappedError(VOID) const {
  319. return m_dwMappedErrorCode;
  320. }
  321. VOID SetMappedError(DWORD dwError) {
  322. m_dwMappedErrorCode = dwError;
  323. }
  324. LPINTERNET_THREAD_INFO GetThreadInfo(VOID) const {
  325. return m_lpThreadInfo;
  326. }
  327. VOID SetThreadInfo(LPINTERNET_THREAD_INFO lpThreadInfo) {
  328. m_lpThreadInfo = lpThreadInfo;
  329. }
  330. DWORD_PTR GetAppContext(VOID) const {
  331. return m_dwContext;
  332. }
  333. HINTERNET GetAppHandle(VOID) const {
  334. return m_hObject;
  335. }
  336. HINTERNET GetMappedHandle(VOID) const {
  337. return m_hObjectMapped;
  338. }
  339. INTERNET_HANDLE_OBJECT * GetMappedHandleObject(VOID) const {
  340. return (INTERNET_HANDLE_OBJECT *)m_hObjectMapped;
  341. }
  342. FSM_STATE GetState(VOID) const {
  343. return m_State;
  344. }
  345. VOID SetState(FSM_STATE State) {
  346. m_State = State;
  347. }
  348. FSM_STATE GetNextState(VOID) const {
  349. return m_NextState;
  350. }
  351. VOID SetNextState(FSM_STATE State) {
  352. m_NextState = State;
  353. }
  354. FSM_STATE GetFunctionState(VOID) const {
  355. //
  356. // We should never enter into this state, cause the FSMs
  357. // themselves must be correct enough to always set the
  358. // next function state before exiting their state.
  359. //
  360. //INET_ASSERT(m_FunctionState != FSM_STATE_BAD);
  361. return m_FunctionState;
  362. }
  363. VOID SetFunctionState(FSM_STATE State) {
  364. m_FunctionState = State;
  365. }
  366. VOID SetWait(VOID) {
  367. SetState(FSM_STATE_WAIT);
  368. }
  369. BOOL IsWait(VOID) {
  370. return (m_State == FSM_STATE_WAIT) ? TRUE : FALSE;
  371. }
  372. VOID SetErrorState(DWORD Error) {
  373. SetError(Error);
  374. SetState(FSM_STATE_ERROR);
  375. }
  376. VOID SetDone(VOID) {
  377. SetState(FSM_STATE_DONE);
  378. }
  379. VOID SetDone(DWORD Error) {
  380. SetError(Error);
  381. SetState(FSM_STATE_DONE);
  382. }
  383. BOOL IsDone(VOID) {
  384. return (m_State == FSM_STATE_DONE) ? TRUE : FALSE;
  385. }
  386. LPVOID GetContext(VOID) const {
  387. return m_lpvContext;
  388. }
  389. VOID SetContext(LPVOID lpvContext) {
  390. m_lpvContext = lpvContext;
  391. }
  392. LPVOID GetHandler(VOID) const {
  393. return (LPVOID)m_lpfnHandler;
  394. }
  395. VOID SetHandler(LPVOID lpfnHandler) {
  396. m_lpfnHandler = (DWORD (*)(CFsm *))lpfnHandler;
  397. }
  398. VOID SetHandler2(DWORD (* lpfnHandler)(CFsm *)) {
  399. m_lpfnHandler = lpfnHandler;
  400. }
  401. SOCKET GetSocket(VOID) const {
  402. return m_Socket;
  403. }
  404. VOID SetSocket(SOCKET Socket) {
  405. INET_ASSERT(m_Socket == INVALID_SOCKET);
  406. m_Socket = Socket;
  407. }
  408. VOID ResetSocket(VOID) {
  409. m_Socket = INVALID_SOCKET;
  410. }
  411. BOOL IsActive(VOID) {
  412. return (m_Socket == INVALID_SOCKET) ? FALSE : TRUE;
  413. }
  414. FSM_ACTION GetAction(VOID) const {
  415. return m_Action;
  416. }
  417. VOID SetAction(FSM_ACTION Action) {
  418. m_Action = Action;
  419. }
  420. DWORD_PTR GetBlockId(VOID) const {
  421. return m_dwBlockId;
  422. }
  423. VOID SetBlockId(DWORD_PTR dwBlockId) {
  424. m_dwBlockId = dwBlockId;
  425. }
  426. BOOL IsBlockedOn(DWORD_PTR dwBlockId) {
  427. return (m_dwBlockId == dwBlockId) ? TRUE : FALSE;
  428. }
  429. DWORD GetTimeout(VOID) const {
  430. return m_dwTimeout;
  431. }
  432. BOOL GetTimeoutWraps(VOID) const
  433. {
  434. return m_fTimeoutWraps;
  435. }
  436. // This code needs to handle system time roll over.
  437. // SetTimeout is passed the duration, and we calculate the ultimate time
  438. // However, this may result in a rollover -- e.g. if the current time is
  439. // 0xffffff00, the ultimate time could be 0x000000fd
  440. // IsTimedOut is passed the current tick count, however, and in the past
  441. // would return TRUE immediately.
  442. // Thus we set a flag is we need to wait for system time rollover to happen,
  443. VOID SetTimeout(DWORD dwTimeout) {
  444. if (dwTimeout != INFINITE)
  445. m_bHasTimeout = TRUE;
  446. else
  447. m_bHasTimeout = FALSE;
  448. DWORD dw = GetTickCountWrap();
  449. m_dwTimeout = (dwTimeout == INFINITE)
  450. ? dwTimeout
  451. : (dw + dwTimeout);
  452. m_fTimeoutWraps = dw > m_dwTimeout;
  453. }
  454. BOOL HasTimeout()
  455. {
  456. return m_bHasTimeout;
  457. }
  458. #ifdef USE_OLD_SENDRECV_SYNC
  459. VOID SetOnAsyncList(BOOL bOnAsyncList)
  460. {
  461. m_bOnAsyncList = bOnAsyncList;
  462. }
  463. BOOL IsOnAsyncList()
  464. {
  465. return m_bOnAsyncList;
  466. }
  467. #endif //USE_OLD_SENDRECV_SYNC
  468. BOOL IsTimedOut(DWORD dwTime) {
  469. if (m_fTimeoutWraps)
  470. {
  471. m_fTimeoutWraps = ((LONG)dwTime < 0);
  472. }
  473. return ((m_dwTimeout == INFINITE) || m_fTimeoutWraps)
  474. ? FALSE
  475. : (dwTime > m_dwTimeout);
  476. }
  477. VOID StartTimer(VOID) {
  478. m_dwTimer = GetTickCountWrap();
  479. m_bTimerStarted = TRUE;
  480. }
  481. DWORD StopTimer(VOID) {
  482. if (m_bTimerStarted) {
  483. m_dwTimer = GetTickCountWrap() - m_dwTimer;
  484. m_bTimerStarted = FALSE;
  485. }
  486. return m_dwTimer;
  487. }
  488. DWORD GetElapsedTime(VOID) {
  489. return (GetTickCountWrap() - m_dwTimer);
  490. }
  491. DWORD StopAndStartTimer(VOID) {
  492. DWORD tNow = GetTickCountWrap();
  493. DWORD tElapsed = (tNow - m_dwTimer);
  494. m_dwTimer = tNow;
  495. m_bTimerStarted = TRUE;
  496. return tElapsed;
  497. }
  498. DWORD ReadTimer(VOID) {
  499. return m_bTimerStarted ? GetElapsedTime() : m_dwTimer;
  500. }
  501. VOID SetBlocking(BOOL fBlocking = TRUE) {
  502. m_bIsBlockingFsm = fBlocking;
  503. }
  504. BOOL IsBlocking(VOID) const {
  505. return m_bIsBlockingFsm;
  506. }
  507. VOID SetApi(API_TYPE ApiType) {
  508. m_bIsApi = TRUE;
  509. m_ApiType = ApiType;
  510. }
  511. BOOL IsApi(VOID) const {
  512. return m_bIsApi;
  513. }
  514. API_TYPE GetApiType(VOID) const {
  515. return m_ApiType;
  516. }
  517. VOID SetApiResult(BOOL bResult) {
  518. m_ApiResult.Bool = bResult;
  519. }
  520. VOID SetApiResult(HINTERNET hResult) {
  521. m_ApiResult.Handle = hResult;
  522. }
  523. DWORD_PTR GetApiResult(VOID) {
  524. // SUNDOWN: typecast problem
  525. return (m_ApiType == ApiType_Handle)
  526. ? PtrToUlong(GetHandleResult())
  527. : (m_ApiType == ApiType_Bool)
  528. ? (DWORD) GetBoolResult()
  529. : 0;
  530. }
  531. BOOL GetBoolResult(VOID) const {
  532. return m_ApiResult.Bool;
  533. }
  534. HINTERNET GetHandleResult(VOID) const {
  535. return m_ApiResult.Handle;
  536. }
  537. DWORD GetApiData(VOID) const {
  538. return m_dwApiData;
  539. }
  540. VOID SetApiData(DWORD dwApiData) {
  541. m_dwApiData = dwApiData;
  542. }
  543. //This is a must-implement function for any top-level async api fsm.
  544. virtual BOOL GetStatusValues(DWORD *pdwStatus, LPVOID *ppvStatusInformation,
  545. DWORD *pdwStatusInformationLength, WINHTTP_ASYNC_RESULT *pAsyncResult, DWORD *pdwFailureAPI)
  546. {
  547. UNREFERENCED_PARAMETER(pdwStatus);
  548. UNREFERENCED_PARAMETER(ppvStatusInformation);
  549. UNREFERENCED_PARAMETER(pdwStatusInformationLength);
  550. UNREFERENCED_PARAMETER(pAsyncResult);
  551. UNREFERENCED_PARAMETER(pdwFailureAPI);
  552. return FALSE;
  553. }
  554. VOID BaseGetStatusValues(LPVOID *ppvStatusInformation,
  555. DWORD *pdwStatusInformationLength,
  556. WINHTTP_ASYNC_RESULT *pAsyncResult)
  557. {
  558. pAsyncResult->dwResult = (GetError() == ERROR_SUCCESS
  559. ?((GetApiType() == ApiType_Handle)
  560. ? GetApiResult()
  561. : TRUE)
  562. :0);
  563. pAsyncResult->dwError = (GetError() == ERROR_SUCCESS)
  564. ? GetApiData()
  565. : GetError();
  566. *ppvStatusInformation = (LPVOID)pAsyncResult;
  567. *pdwStatusInformationLength = sizeof(*pAsyncResult);
  568. }
  569. DWORD
  570. QueueWorkItem(
  571. DWORD dwCompletionBytes = 0,
  572. LPVOID lpCompletionKey = NULL
  573. );
  574. static
  575. DWORD
  576. RunWorkItem(
  577. IN CFsm * pFsm
  578. );
  579. DWORD
  580. Run(
  581. IN LPINTERNET_THREAD_INFO lpThreadInfo,
  582. OUT DWORD *pdwStatus OPTIONAL = NULL,
  583. OUT LPVOID *ppvStatusInformation OPTIONAL = NULL,
  584. OUT DWORD *pdwStatusInformationLength OPTIONAL = NULL,
  585. OUT WINHTTP_ASYNC_RESULT *pAsyncResult OPTIONAL = NULL,
  586. OUT DWORD *pdwFailureAPI OPTIONAL = NULL
  587. );
  588. // return value = next fsm to "pop" - if NULL, pop already done.
  589. virtual CFsm* Dereference(DWORD* dwError)
  590. {
  591. UNREFERENCED_PARAMETER(dwError);
  592. delete this;
  593. return NULL;
  594. }
  595. #if INET_DEBUG
  596. FSM_TYPE GetType(VOID) const {
  597. return m_Type;
  598. }
  599. DEBUG_FUNCTION
  600. LPSTR
  601. MapType(
  602. VOID
  603. );
  604. DEBUG_FUNCTION
  605. LPSTR
  606. StateName(
  607. IN DWORD State
  608. );
  609. DEBUG_FUNCTION
  610. LPSTR MapState(VOID) {
  611. return StateName(m_State);
  612. }
  613. DEBUG_FUNCTION
  614. LPSTR MapFunctionState(VOID) {
  615. return StateName(m_FunctionState);
  616. }
  617. #else
  618. LPSTR MapType(VOID) {
  619. return "";
  620. }
  621. LPSTR MapState(VOID) {
  622. return "";
  623. }
  624. LPSTR MapFunctionState(VOID) {
  625. return "";
  626. }
  627. #endif
  628. };
  629. /*DWORD
  630. RunSM_Wrapper(
  631. IN*/
  632. //
  633. // Derived State Machines
  634. //
  635. // The following state machines contain the parameters and variables that are
  636. // maintained across machine states and thread switches
  637. //
  638. // In order to make the code more readable, the state machine is friends with
  639. // the object class for which it operates (e.g. ICSocket or ICHttpRequest)
  640. //
  641. //
  642. // CAddressList FSMs
  643. //
  644. class CFsm_ResolveHost : public CFsm {
  645. friend class CAddressList;
  646. private:
  647. //
  648. // parameters
  649. //
  650. LPSTR m_lpszHostName;
  651. LPDWORD m_lpdwResolutionId;
  652. DWORD m_dwFlags;
  653. BOOL m_isScheduled;
  654. LONG m_ReferenceCount;
  655. public:
  656. static
  657. DWORD
  658. RunSM(
  659. IN CFsm * Fsm
  660. );
  661. CFsm_ResolveHost(
  662. IN LPSTR lpszHostName,
  663. IN LPDWORD lpdwResolutionId,
  664. IN DWORD dwFlags,
  665. IN CAddressList * pAddressList
  666. ) : CFsm(RunSM, (LPVOID)pAddressList) {
  667. SET_FSM_TYPE(RESOLVE_HOST);
  668. if (GetError() != ERROR_SUCCESS) {
  669. return;
  670. }
  671. m_lpszHostName = lpszHostName;
  672. m_lpdwResolutionId = lpdwResolutionId;
  673. m_dwFlags = dwFlags;
  674. m_isScheduled = FALSE;
  675. m_ReferenceCount = 1;
  676. }
  677. //returns
  678. // TRUE: to indicate already been scheduled.
  679. // FALSE: to indicate not already been scheduled.
  680. BOOL TestAndSetScheduled()
  681. {
  682. BOOL fPrior;
  683. fPrior = (BOOL)InterlockedExchange((LPLONG)&m_isScheduled, TRUE);
  684. return fPrior;
  685. }
  686. BOOL IsScheduled()
  687. {
  688. return m_isScheduled;
  689. }
  690. virtual CFsm* Dereference(DWORD* dwError)
  691. {
  692. CFsm* pNext;
  693. *dwError = GetError();
  694. if (IsPop())
  695. {
  696. pNext = NULL;
  697. }
  698. else
  699. {
  700. //Timeout fsm needs help with pop.
  701. pNext = GetParentFsm();
  702. }
  703. if (!InterlockedDecrement(&m_ReferenceCount))
  704. {
  705. //0 refcount so delete.
  706. delete this;
  707. }
  708. return pNext;
  709. }
  710. VOID Reference()
  711. {
  712. InterlockedIncrement(&m_ReferenceCount);
  713. }
  714. };
  715. //
  716. // Internet API FSMs
  717. //
  718. class CFsm_InternetParseUrl : public CFsm {
  719. private:
  720. //
  721. // parameters
  722. //
  723. HINTERNET m_hConnectHandle;
  724. DWORD_PTR m_dwContext;
  725. LPCSTR m_lpszUrl;
  726. LPCSTR m_lpszHeaders;
  727. DWORD m_dwHeadersLength;
  728. DWORD m_dwFlags;
  729. public:
  730. static
  731. DWORD
  732. RunSM(
  733. IN CFsm * Fsm
  734. )
  735. {
  736. CFsm_InternetParseUrl *pFsm = (CFsm_InternetParseUrl *)Fsm;
  737. INET_ASSERT(Fsm->GetState() == FSM_STATE_INIT);
  738. pFsm->SetApiResult(InternetOpenUrlA(
  739. pFsm->m_hConnectHandle,
  740. pFsm->m_lpszUrl,
  741. pFsm->m_lpszHeaders,
  742. pFsm->m_dwHeadersLength,
  743. pFsm->m_dwFlags,
  744. pFsm->m_dwContext
  745. ));
  746. pFsm->SetDone();
  747. return ((pFsm->GetHandleResult()) ? ERROR_SUCCESS : GetLastError());
  748. }
  749. CFsm_InternetParseUrl(
  750. IN HINTERNET hConnectHandle,
  751. IN DWORD_PTR dwContext,
  752. IN LPCSTR lpszUrl,
  753. IN LPCSTR lpszHeaders,
  754. IN DWORD dwHeadersLength,
  755. IN DWORD dwFlags
  756. ) : CFsm(RunSM, (LPVOID)hConnectHandle) {
  757. SET_FSM_TYPE(INTERNET_PARSE_URL);
  758. if (GetError() != ERROR_SUCCESS) {
  759. return;
  760. }
  761. SetApi(ApiType_Handle);
  762. SetBlocking();
  763. m_hConnectHandle = hConnectHandle;
  764. m_dwContext = dwContext;
  765. m_lpszUrl = lpszUrl;
  766. m_lpszHeaders = lpszHeaders;
  767. m_dwHeadersLength = dwHeadersLength;
  768. m_dwFlags = dwFlags;
  769. }
  770. };
  771. class CFsm_InternetQueryDataAvailable : public CFsm {
  772. private:
  773. //
  774. // parameters
  775. //
  776. HINTERNET m_hSessionHandle;
  777. LPDWORD m_lpdwNumberOfBytesAvailable;
  778. DWORD m_dwNumberOfBytesAvailable;
  779. DWORD m_dwFlags;
  780. DWORD_PTR m_dwContext;
  781. public:
  782. static
  783. DWORD
  784. RunSM(
  785. IN CFsm * Fsm
  786. )
  787. {
  788. CFsm_InternetQueryDataAvailable *pFsm = (CFsm_InternetQueryDataAvailable *)Fsm;
  789. INET_ASSERT(Fsm->GetState() == FSM_STATE_INIT);
  790. pFsm->SetApiResult(wInternetQueryDataAvailable(
  791. pFsm->m_hSessionHandle,
  792. pFsm->m_lpdwNumberOfBytesAvailable,
  793. pFsm->m_dwFlags,
  794. pFsm->m_dwContext
  795. ));
  796. pFsm->SetApiData(*pFsm->m_lpdwNumberOfBytesAvailable);
  797. pFsm->SetDone();
  798. return ((pFsm->GetBoolResult()) ? ERROR_SUCCESS : GetLastError());
  799. }
  800. CFsm_InternetQueryDataAvailable(
  801. IN HINTERNET hSessionHandle,
  802. OUT LPDWORD lpdwNumberOfBytesAvailable,
  803. IN DWORD dwFlags,
  804. IN DWORD_PTR dwContext
  805. ) : CFsm(RunSM, (LPVOID)hSessionHandle) {
  806. SET_FSM_TYPE(INTERNET_QUERY_DATA_AVAILABLE);
  807. if (GetError() != ERROR_SUCCESS) {
  808. return;
  809. }
  810. SetApi(ApiType_Bool);
  811. SetBlocking();
  812. m_hSessionHandle = hSessionHandle;
  813. m_lpdwNumberOfBytesAvailable = &m_dwNumberOfBytesAvailable;
  814. m_dwNumberOfBytesAvailable = *lpdwNumberOfBytesAvailable;
  815. m_dwFlags = dwFlags;
  816. m_dwContext = dwContext;
  817. }
  818. };
  819. class CFsm_InternetWriteFile : public CFsm {
  820. private:
  821. //
  822. // parameters
  823. //
  824. HINTERNET m_hSessionHandle;
  825. LPCVOID m_lpBuffer;
  826. DWORD m_dwNumberOfBytesToWrite;
  827. LPDWORD m_lpdwNumberOfBytesWritten;
  828. DWORD m_dwNumberOfBytesWritten;
  829. public:
  830. static
  831. DWORD
  832. RunSM(
  833. IN CFsm * Fsm
  834. )
  835. {
  836. CFsm_InternetWriteFile *pFsm = (CFsm_InternetWriteFile *)Fsm;
  837. INET_ASSERT(Fsm->GetState() == FSM_STATE_INIT);
  838. pFsm->SetApiResult(WinHttpWriteData(
  839. pFsm->m_hSessionHandle,
  840. pFsm->m_lpBuffer,
  841. pFsm->m_dwNumberOfBytesToWrite,
  842. pFsm->m_lpdwNumberOfBytesWritten
  843. ));
  844. pFsm->SetApiData(*(pFsm->m_lpdwNumberOfBytesWritten));
  845. pFsm->SetDone();
  846. return ((pFsm->GetBoolResult()) ? ERROR_SUCCESS : GetLastError());
  847. }
  848. CFsm_InternetWriteFile(
  849. IN HINTERNET hSessionHandle,
  850. IN LPCVOID lpBuffer,
  851. IN DWORD dwNumberOfBytesToWrite,
  852. OUT LPDWORD lpdwNumberOfBytesWritten
  853. ) : CFsm(RunSM, (LPVOID)hSessionHandle) {
  854. SET_FSM_TYPE(INTERNET_WRITE_FILE);
  855. if (GetError() != ERROR_SUCCESS) {
  856. return;
  857. }
  858. SetApi(ApiType_Bool);
  859. SetBlocking();
  860. m_hSessionHandle = hSessionHandle;
  861. m_lpBuffer = lpBuffer;
  862. m_dwNumberOfBytesToWrite = dwNumberOfBytesToWrite;
  863. m_dwNumberOfBytesWritten = *lpdwNumberOfBytesWritten;
  864. m_lpdwNumberOfBytesWritten = &m_dwNumberOfBytesWritten;
  865. }
  866. };
  867. class CFsm_InternetReadFile : public CFsm {
  868. private:
  869. //
  870. // parameters
  871. //
  872. HINTERNET m_hSessionHandle;
  873. LPVOID m_lpBuffer;
  874. DWORD m_dwNumberOfBytesToRead;
  875. LPDWORD m_lpdwNumberOfBytesRead;
  876. DWORD m_dwNumberOfBytesRead;
  877. public:
  878. static
  879. DWORD
  880. RunSM(
  881. IN CFsm * Fsm
  882. )
  883. {
  884. CFsm_InternetReadFile *pFsm = (CFsm_InternetReadFile *)Fsm;
  885. INET_ASSERT(Fsm->GetState() == FSM_STATE_INIT);
  886. pFsm->SetApiResult(WinHttpReadData(
  887. pFsm->m_hSessionHandle,
  888. pFsm->m_lpBuffer,
  889. pFsm->m_dwNumberOfBytesToRead,
  890. pFsm->m_lpdwNumberOfBytesRead
  891. ));
  892. pFsm->SetApiData(*(pFsm->m_lpdwNumberOfBytesRead));
  893. pFsm->SetDone();
  894. return ((pFsm->GetBoolResult()) ? ERROR_SUCCESS : GetLastError());
  895. }
  896. CFsm_InternetReadFile(
  897. IN HINTERNET hSessionHandle,
  898. IN LPVOID lpBuffer,
  899. IN DWORD dwNumberOfBytesToRead,
  900. OUT LPDWORD lpdwNumberOfBytesRead
  901. ) : CFsm(RunSM, (LPVOID)hSessionHandle) {
  902. SET_FSM_TYPE(INTERNET_READ_FILE);
  903. if (GetError() != ERROR_SUCCESS) {
  904. return;
  905. }
  906. SetApi(ApiType_Bool);
  907. SetBlocking();
  908. m_hSessionHandle = hSessionHandle;
  909. m_lpBuffer = lpBuffer;
  910. m_dwNumberOfBytesToRead = dwNumberOfBytesToRead;
  911. m_dwNumberOfBytesRead = *lpdwNumberOfBytesRead;
  912. m_lpdwNumberOfBytesRead = &m_dwNumberOfBytesRead;
  913. }
  914. };
  915. //
  916. // ICSocket FSMs
  917. //
  918. //
  919. // CFsm_SocketConnect -
  920. //
  921. class CFsm_SocketConnect : public CFsm {
  922. friend class ICSocket;
  923. private:
  924. //
  925. // parameters
  926. //
  927. LONG m_Timeout;
  928. INT m_Retries;
  929. DWORD m_dwFlags;
  930. //
  931. // local variables
  932. //
  933. BOOL m_bStopOfflineTimer;
  934. LONG m_lPreviousTime;
  935. BOOL m_bResolved;
  936. DWORD m_dwResolutionId;
  937. DWORD m_dwAddressIndex;
  938. char m_AddressBuffer[CSADDR_BUFFER_LENGTH];
  939. LPCSADDR_INFO m_pAddress;
  940. CServerInfo * m_pServerInfo;
  941. CServerInfo * m_pOriginServer;
  942. BOOL m_fTimeout;
  943. public:
  944. static
  945. DWORD
  946. RunSM(
  947. IN CFsm * Fsm
  948. );
  949. CFsm_SocketConnect(
  950. IN LONG Timeout,
  951. IN INT Retries,
  952. IN DWORD dwFlags,
  953. IN ICSocket * pSocket
  954. ) : CFsm(RunSM, (LPVOID)pSocket) {
  955. SET_FSM_TYPE(SOCKET_CONNECT);
  956. if (GetError() != ERROR_SUCCESS) {
  957. return;
  958. }
  959. m_Timeout = Timeout;
  960. m_fTimeout = Timeout ? TRUE : FALSE;
  961. m_Retries = Retries;
  962. m_dwFlags = dwFlags;
  963. m_bStopOfflineTimer = FALSE;
  964. m_lPreviousTime = (LONG)GetTickCountWrap();
  965. m_bResolved = FALSE;
  966. m_dwResolutionId = (DWORD)-1;
  967. m_dwAddressIndex = (DWORD)-1;
  968. m_pAddress = (LPCSADDR_INFO)m_AddressBuffer;
  969. m_pServerInfo = ((HTTP_REQUEST_HANDLE_OBJECT *)
  970. GetThreadInfo()->hObjectMapped)->GetServerInfo();
  971. m_pOriginServer = ((HTTP_REQUEST_HANDLE_OBJECT *)
  972. GetThreadInfo()->hObjectMapped)->GetOriginServer();
  973. }
  974. VOID SetServerInfo(CServerInfo * pServerInfo) {
  975. m_pServerInfo = pServerInfo;
  976. }
  977. BOOL IsCountedOut(VOID) {
  978. return (--m_Retries <= 0) ? TRUE : FALSE;
  979. }
  980. BOOL IsTimedOut(VOID) {
  981. return (m_fTimeout != INFINITE) ? (((m_Timeout -= (LONG)ReadTimer()) <= 0) ? TRUE : FALSE) : FALSE;
  982. }
  983. LONG GetTimeout(VOID) const
  984. {
  985. return m_Timeout;
  986. }
  987. };
  988. //
  989. // CFsm_SocketSend -
  990. //
  991. class CFsm_SocketIOCP : public CFsm
  992. {
  993. public:
  994. BOOL bIOCPSuccess;
  995. DWORD dwBytesTransferred;
  996. DWORD dwIOCPError;
  997. BOOL bIOCPInited;
  998. CFsm_SocketIOCP(DWORD (* lpfnHandler)(CFsm *), LPVOID lpvContext):CFsm(lpfnHandler, lpvContext)
  999. {
  1000. bIOCPSuccess = FALSE;
  1001. dwBytesTransferred = 0;
  1002. dwIOCPError = 0;
  1003. bIOCPInited = FALSE;
  1004. #ifndef USE_OLD_SENDRECV_SYNC
  1005. m_ReferenceCount = 1;
  1006. m_lCookie = 1;
  1007. #endif
  1008. }
  1009. #ifndef USE_OLD_SENDRECV_SYNC
  1010. LONG m_ReferenceCount;
  1011. // m_lCookie == 1 after increment means updated by timeout Q
  1012. LONG m_lCookie;
  1013. BOOL IsValidForTimeoutCheck(LONG lCookie) const
  1014. {
  1015. return (lCookie == m_lCookie);
  1016. }
  1017. BOOL TestAndSetValidForTimeoutEnforce(LONG lCookie)
  1018. {
  1019. return (InterlockedCompareExchange(&m_lCookie, 0, lCookie) == lCookie);
  1020. }
  1021. BOOL TestAndSetValidForIOCPProcessing()
  1022. {
  1023. return (InterlockedIncrement(&m_lCookie) != 1);
  1024. }
  1025. LONG GetCookie() const
  1026. {
  1027. return m_lCookie;
  1028. }
  1029. virtual CFsm* Dereference(DWORD* pdwError)
  1030. {
  1031. CFsm* pNext;
  1032. *pdwError = GetError();
  1033. if (IsPop())
  1034. {
  1035. pNext = NULL;
  1036. }
  1037. else
  1038. {
  1039. pNext = GetParentFsm();
  1040. }
  1041. if (!InterlockedDecrement(&m_ReferenceCount))
  1042. {
  1043. //0 refcount, so delete
  1044. delete this;
  1045. }
  1046. return pNext;
  1047. }
  1048. VOID Reference()
  1049. {
  1050. InterlockedIncrement(&m_ReferenceCount);
  1051. }
  1052. #endif
  1053. };
  1054. class CFsm_SocketSend : public CFsm_SocketIOCP
  1055. {
  1056. friend class ICSocket;
  1057. private:
  1058. //
  1059. // parameters
  1060. //
  1061. LPVOID m_lpBuffer;
  1062. DWORD m_dwBufferLength;
  1063. DWORD m_dwFlags;
  1064. //
  1065. // local variables
  1066. //
  1067. INT m_iTotalSent;
  1068. BOOL m_bStopOfflineTimer;
  1069. CServerInfo * m_pServerInfo;
  1070. CServerInfo * m_pOriginServer;
  1071. public:
  1072. static
  1073. DWORD
  1074. RunSM(
  1075. IN CFsm * Fsm
  1076. );
  1077. CFsm_SocketSend(
  1078. IN LPVOID lpBuffer,
  1079. IN DWORD dwBufferLength,
  1080. IN DWORD dwFlags,
  1081. IN ICSocket * pSocket
  1082. ) : CFsm_SocketIOCP(RunSM, (LPVOID)pSocket) {
  1083. SET_FSM_TYPE(SOCKET_SEND);
  1084. if (GetError() != ERROR_SUCCESS) {
  1085. return;
  1086. }
  1087. INET_ASSERT(lpBuffer != NULL);
  1088. INET_ASSERT((int)dwBufferLength > 0);
  1089. m_lpBuffer = lpBuffer;
  1090. m_dwBufferLength = dwBufferLength;
  1091. m_dwFlags = dwFlags;
  1092. m_iTotalSent = 0;
  1093. m_bStopOfflineTimer = FALSE;
  1094. m_pServerInfo = ((HTTP_REQUEST_HANDLE_OBJECT *)
  1095. GetThreadInfo()->hObjectMapped)->GetServerInfo();
  1096. m_pOriginServer = ((HTTP_REQUEST_HANDLE_OBJECT *)
  1097. GetThreadInfo()->hObjectMapped)->GetOriginServer();
  1098. }
  1099. };
  1100. //
  1101. // CFsm_SocketReceive -
  1102. //
  1103. class CFsm_SocketReceive : public CFsm_SocketIOCP
  1104. {
  1105. friend class ICSocket;
  1106. private:
  1107. //
  1108. // parameters
  1109. //
  1110. LPVOID * m_lplpBuffer;
  1111. LPDWORD m_lpdwBufferLength;
  1112. LPDWORD m_lpdwBufferRemaining;
  1113. LPDWORD m_lpdwBytesReceived;
  1114. DWORD m_dwExtraSpace;
  1115. DWORD m_dwFlags;
  1116. LPBOOL m_lpbEof;
  1117. //
  1118. // local variables
  1119. //
  1120. HLOCAL m_hBuffer;
  1121. LPBYTE m_lpBuffer;
  1122. DWORD m_dwBufferLength;
  1123. DWORD m_dwBufferLeft;
  1124. DWORD m_dwBytesReceived;
  1125. DWORD m_dwBytesRead;
  1126. BOOL m_bEof;
  1127. BOOL m_bAllocated;
  1128. CServerInfo * m_pServerInfo;
  1129. CServerInfo * m_pOriginServer;
  1130. public:
  1131. static
  1132. DWORD
  1133. RunSM(
  1134. IN CFsm * Fsm
  1135. );
  1136. CFsm_SocketReceive(
  1137. IN OUT LPVOID * lplpBuffer,
  1138. IN OUT LPDWORD lpdwBufferLength,
  1139. IN OUT LPDWORD lpdwBufferRemaining,
  1140. IN OUT LPDWORD lpdwBytesReceived,
  1141. IN DWORD dwExtraSpace,
  1142. IN DWORD dwFlags,
  1143. OUT LPBOOL lpbEof,
  1144. IN ICSocket * pSocket
  1145. ) : CFsm_SocketIOCP(RunSM, (LPVOID)pSocket) {
  1146. SET_FSM_TYPE(SOCKET_RECEIVE);
  1147. if (GetError() != ERROR_SUCCESS) {
  1148. return;
  1149. }
  1150. //
  1151. // sanity check
  1152. //
  1153. INET_ASSERT(lplpBuffer != NULL);
  1154. INET_ASSERT(lpdwBufferLength != NULL);
  1155. INET_ASSERT((*lpdwBufferLength == 0) ? (dwFlags & SF_EXPAND) : TRUE);
  1156. m_lplpBuffer = lplpBuffer;
  1157. m_lpdwBufferLength = lpdwBufferLength;
  1158. m_lpdwBufferRemaining = lpdwBufferRemaining;
  1159. m_lpdwBytesReceived = lpdwBytesReceived;
  1160. m_dwExtraSpace = dwExtraSpace;
  1161. m_dwFlags = dwFlags;
  1162. m_lpbEof = lpbEof;
  1163. m_hBuffer = *lplpBuffer;
  1164. m_lpBuffer = (LPBYTE)m_hBuffer;
  1165. m_dwBufferLength = *lpdwBufferLength;
  1166. m_dwBufferLeft = *lpdwBufferRemaining;
  1167. m_dwBytesReceived = *lpdwBytesReceived;
  1168. m_dwBytesRead = 0;
  1169. m_bEof = FALSE;
  1170. m_bAllocated = FALSE;
  1171. m_pServerInfo = ((HTTP_REQUEST_HANDLE_OBJECT *)
  1172. GetThreadInfo()->hObjectMapped)->GetServerInfo();
  1173. m_pOriginServer = ((HTTP_REQUEST_HANDLE_OBJECT *)
  1174. GetThreadInfo()->hObjectMapped)->GetOriginServer();
  1175. }
  1176. };
  1177. //
  1178. // ICSecureSocket FSMs
  1179. //
  1180. //
  1181. // CFsm_SecureConnect -
  1182. //
  1183. class CFsm_SecureConnect : public CFsm {
  1184. friend class ICSecureSocket;
  1185. private:
  1186. //
  1187. // parameters
  1188. //
  1189. LONG m_ConnectTimeout;
  1190. INT m_Retries;
  1191. LONG m_SendTimeout;
  1192. LONG m_RecvTimeout;
  1193. DWORD m_dwFlags;
  1194. //
  1195. // locals
  1196. //
  1197. BOOL m_bAttemptReconnect;
  1198. public:
  1199. static
  1200. DWORD
  1201. RunSM(
  1202. IN CFsm * Fsm
  1203. );
  1204. CFsm_SecureConnect(
  1205. IN LONG ConnectTimeout,
  1206. IN INT Retries,
  1207. IN LONG SendTimeout,
  1208. IN LONG RecvTimeout,
  1209. IN DWORD dwFlags,
  1210. IN ICSecureSocket * pSocket
  1211. ) : CFsm(RunSM, (LPVOID)pSocket) {
  1212. SET_FSM_TYPE(SECURE_CONNECT);
  1213. if (GetError() != ERROR_SUCCESS) {
  1214. return;
  1215. }
  1216. m_ConnectTimeout = ConnectTimeout;
  1217. m_Retries = Retries;
  1218. m_SendTimeout = SendTimeout;
  1219. m_RecvTimeout = RecvTimeout;
  1220. m_dwFlags = dwFlags;
  1221. m_bAttemptReconnect = FALSE;
  1222. }
  1223. };
  1224. //
  1225. // CFsm_SecureHandshake -
  1226. //
  1227. class CFsm_SecureHandshake : public CFsm {
  1228. friend class ICSecureSocket;
  1229. private:
  1230. //
  1231. // parameters
  1232. //
  1233. DWORD m_dwFlags;
  1234. LPBOOL m_lpbAttemptReconnect;
  1235. //
  1236. // locals
  1237. //
  1238. public:
  1239. static
  1240. DWORD
  1241. RunSM(
  1242. IN CFsm * Fsm
  1243. );
  1244. CFsm_SecureHandshake(
  1245. IN DWORD dwFlags,
  1246. OUT LPBOOL lpbAttemptReconnect,
  1247. IN ICSecureSocket * pSocket
  1248. ) : CFsm(RunSM, (LPVOID)pSocket) {
  1249. SET_FSM_TYPE(SECURE_HANDSHAKE);
  1250. if (GetError() != ERROR_SUCCESS) {
  1251. return;
  1252. }
  1253. m_dwFlags = dwFlags;
  1254. m_lpbAttemptReconnect = lpbAttemptReconnect;
  1255. }
  1256. };
  1257. //
  1258. // CFsm_SecureNegotiate -
  1259. //
  1260. class CFsm_SecureNegotiate : public CFsm {
  1261. friend class ICSecureSocket;
  1262. private:
  1263. //
  1264. // parameters
  1265. //
  1266. DWORD m_dwFlags;
  1267. LPBOOL m_lpbAttemptReconnect;
  1268. //
  1269. // locals
  1270. //
  1271. SecBufferDesc m_OutBuffer;
  1272. SecBuffer m_OutBuffers[1];
  1273. CredHandle m_hCreds;
  1274. BOOL m_bDoingClientAuth;
  1275. public:
  1276. static
  1277. DWORD
  1278. RunSM(
  1279. IN CFsm * Fsm
  1280. );
  1281. CFsm_SecureNegotiate(
  1282. IN DWORD dwFlags,
  1283. OUT LPBOOL lpbAttemptReconnect,
  1284. IN ICSecureSocket * pSocket
  1285. ) : CFsm(RunSM, (LPVOID)pSocket) {
  1286. SET_FSM_TYPE(SECURE_NEGOTIATE);
  1287. if (GetError() != ERROR_SUCCESS) {
  1288. return;
  1289. }
  1290. m_dwFlags = dwFlags;
  1291. m_lpbAttemptReconnect = lpbAttemptReconnect;
  1292. ClearCreds(m_hCreds);
  1293. m_bDoingClientAuth = FALSE;
  1294. }
  1295. ~CFsm_SecureNegotiate() {
  1296. //INET_ASSERT(IsCredClear(m_hCreds));
  1297. INET_ASSERT(!m_bDoingClientAuth);
  1298. if ( m_bDoingClientAuth &&
  1299. !IsCredClear(m_hCreds))
  1300. {
  1301. // Look at comments before CliAuthSelectCredentials
  1302. // g_FreeCredentialsHandle(&m_hCreds);
  1303. m_bDoingClientAuth = FALSE;
  1304. }
  1305. }
  1306. };
  1307. //
  1308. // CFsm_NegotiateLoop -
  1309. //
  1310. class CFsm_NegotiateLoop : public CFsm {
  1311. friend class ICSecureSocket;
  1312. private:
  1313. //
  1314. // parameters
  1315. //
  1316. DBLBUFFER * m_pdblbufBuffer;
  1317. DWORD m_dwFlags;
  1318. BOOL m_bDoInitialRead;
  1319. //
  1320. // locals
  1321. //
  1322. SECURITY_STATUS m_scRet;
  1323. DWORD m_dwProviderIndex;
  1324. LPSTR m_lpszBuffer;
  1325. DWORD m_dwBufferLength;
  1326. DWORD m_dwBufferLeft;
  1327. DWORD m_dwBytesReceived;
  1328. BOOL m_bEofReceive;
  1329. BOOL m_bDoingClientAuth;
  1330. BOOL m_bDoRead;
  1331. SecBuffer m_InBuffers[2];
  1332. SecBuffer m_OutBuffers[1];
  1333. SecBufferDesc m_OutBuffer;
  1334. CredHandle m_hCreds;
  1335. DWORD m_dwSSPIFlags;
  1336. public:
  1337. static
  1338. DWORD
  1339. RunSM(
  1340. IN CFsm * Fsm
  1341. );
  1342. CFsm_NegotiateLoop(
  1343. IN DBLBUFFER * pdblbufBuffer,
  1344. IN DWORD dwFlags,
  1345. IN BOOL bDoInitialRead,
  1346. IN BOOL bDoingClientAuth,
  1347. IN CredHandle hCreds,
  1348. IN ICSecureSocket * pSocket
  1349. ) : CFsm(RunSM, (LPVOID)pSocket) {
  1350. SET_FSM_TYPE(NEGOTIATE_LOOP);
  1351. if (GetError() != ERROR_SUCCESS) {
  1352. return;
  1353. }
  1354. m_pdblbufBuffer = pdblbufBuffer;
  1355. m_dwFlags = dwFlags;
  1356. m_bDoInitialRead = bDoInitialRead;
  1357. m_scRet = SEC_E_SECPKG_NOT_FOUND;
  1358. m_lpszBuffer = NULL;
  1359. m_dwBufferLength = 0;
  1360. m_dwBufferLeft = 0;
  1361. m_dwBytesReceived = 0;
  1362. m_bEofReceive = FALSE;
  1363. m_bDoingClientAuth = bDoingClientAuth;
  1364. m_bDoRead = m_bDoInitialRead;
  1365. if (bDoingClientAuth)
  1366. m_hCreds = hCreds;
  1367. else
  1368. ClearCreds(m_hCreds);
  1369. }
  1370. ~CFsm_NegotiateLoop() {
  1371. if (m_bDoingClientAuth)
  1372. {
  1373. INET_ASSERT(!IsCredClear(m_hCreds));
  1374. // Look at comments before CliAuthSelectCredentials
  1375. // g_FreeCredentialsHandle(&m_hCreds);
  1376. m_bDoingClientAuth = FALSE;
  1377. }
  1378. }
  1379. };
  1380. //
  1381. // CFsm_SecureSend -
  1382. //
  1383. class CFsm_SecureSend : public CFsm {
  1384. friend class ICSecureSocket;
  1385. private:
  1386. //
  1387. // parameters
  1388. //
  1389. LPVOID m_lpBuffer;
  1390. DWORD m_dwBufferLength;
  1391. DWORD m_dwFlags;
  1392. //
  1393. // locals
  1394. //
  1395. LPVOID m_lpCryptBuffer;
  1396. DWORD m_dwCryptBufferLength;
  1397. public:
  1398. static
  1399. DWORD
  1400. RunSM(
  1401. IN CFsm * Fsm
  1402. );
  1403. CFsm_SecureSend(
  1404. IN LPVOID lpBuffer,
  1405. IN DWORD dwBufferLength,
  1406. IN DWORD dwFlags,
  1407. IN ICSecureSocket * pSocket
  1408. ) : CFsm(RunSM, (LPVOID)pSocket) {
  1409. SET_FSM_TYPE(SECURE_SEND);
  1410. if (GetError() != ERROR_SUCCESS) {
  1411. return;
  1412. }
  1413. m_lpBuffer = lpBuffer;
  1414. m_dwBufferLength = dwBufferLength;
  1415. m_dwFlags = dwFlags;
  1416. m_lpCryptBuffer = NULL;
  1417. m_dwCryptBufferLength = 0;
  1418. }
  1419. };
  1420. //
  1421. // CFsm_SecureReceive -
  1422. //
  1423. class CFsm_SecureReceive : public CFsm {
  1424. friend class ICSecureSocket;
  1425. private:
  1426. //
  1427. // parameters
  1428. //
  1429. LPVOID * m_lplpBuffer;
  1430. LPDWORD m_lpdwBufferLength;
  1431. LPDWORD m_lpdwBufferRemaining;
  1432. LPDWORD m_lpdwBytesReceived;
  1433. DWORD m_dwExtraSpace;
  1434. DWORD m_dwFlags;
  1435. LPBOOL m_lpbEof;
  1436. //
  1437. // locals
  1438. //
  1439. HLOCAL m_hBuffer;
  1440. DWORD m_dwBufferLength;
  1441. DWORD m_dwBufferLeft;
  1442. DWORD m_dwBytesReceived;
  1443. DWORD m_dwBytesRead;
  1444. LPBYTE m_lpBuffer;
  1445. BOOL m_bEof;
  1446. BOOL m_bAllocated;
  1447. DWORD m_dwDecryptError;
  1448. DWORD m_dwReadFlags;
  1449. LPBYTE m_lpBufferDummy;
  1450. DWORD m_dwBufferLengthDummy;
  1451. DWORD m_dwBufferReceivedDummy;
  1452. DWORD m_dwBufferLeftDummy;
  1453. DWORD m_dwBufferReceivedPre;
  1454. DWORD m_dwInputBytesLeft;
  1455. public:
  1456. static
  1457. DWORD
  1458. RunSM(
  1459. IN CFsm * Fsm
  1460. );
  1461. CFsm_SecureReceive(
  1462. IN OUT LPVOID* lplpBuffer,
  1463. IN OUT LPDWORD lpdwBufferLength,
  1464. IN OUT LPDWORD lpdwBufferRemaining,
  1465. IN OUT LPDWORD lpdwBytesReceived,
  1466. IN DWORD dwExtraSpace,
  1467. IN DWORD dwFlags,
  1468. OUT LPBOOL lpbEof,
  1469. IN ICSecureSocket * pSocket
  1470. ) : CFsm(RunSM, (LPVOID)pSocket) {
  1471. SET_FSM_TYPE(SECURE_RECEIVE);
  1472. if (GetError() != ERROR_SUCCESS) {
  1473. return;
  1474. }
  1475. m_lplpBuffer = lplpBuffer;
  1476. m_lpdwBufferLength = lpdwBufferLength;
  1477. m_lpdwBufferRemaining = lpdwBufferRemaining;
  1478. m_lpdwBytesReceived = lpdwBytesReceived;
  1479. m_dwExtraSpace = dwExtraSpace;
  1480. m_dwFlags = dwFlags;
  1481. m_lpbEof = lpbEof;
  1482. m_hBuffer = (HLOCAL)*lplpBuffer;
  1483. m_dwBufferLength = *lpdwBufferLength;
  1484. m_dwBufferLeft = *lpdwBufferRemaining;
  1485. m_dwBytesReceived = *lpdwBytesReceived;
  1486. m_dwBytesRead = 0;
  1487. m_bEof = FALSE;
  1488. m_bAllocated = FALSE;
  1489. m_dwDecryptError = ERROR_SUCCESS;
  1490. }
  1491. };
  1492. //
  1493. // CServerInfo FSMs
  1494. //
  1495. //
  1496. // CFsm_GetConnection -
  1497. //
  1498. class CFsm_GetConnection : public CFsm {
  1499. friend class CServerInfo;
  1500. private:
  1501. //
  1502. // parameters
  1503. //
  1504. DWORD m_dwSocketFlags;
  1505. INTERNET_PORT m_nPort;
  1506. DWORD m_dwTimeout;
  1507. BOOL m_fTimeoutWraps;
  1508. DWORD m_dwLimitTimeout;
  1509. ICSocket * * m_lplpSocket;
  1510. LPSTR m_lpszSecureTunnelHost;
  1511. DWORD m_dwSecureProtocols;
  1512. //
  1513. // locals
  1514. //
  1515. public:
  1516. static
  1517. DWORD
  1518. RunSM(
  1519. IN CFsm * Fsm
  1520. );
  1521. CFsm_GetConnection(
  1522. IN DWORD dwSocketFlags,
  1523. IN INTERNET_PORT nPort,
  1524. IN DWORD dwTimeout,
  1525. IN DWORD dwLimitTimeout,
  1526. OUT ICSocket * * lplpSocket,
  1527. IN CServerInfo * lpServerInfo,
  1528. IN LPSTR lpszSecureTunnelHost = NULL,
  1529. IN DWORD dwSecureProtocols = 0
  1530. ) : CFsm(RunSM, (LPVOID)lpServerInfo) {
  1531. SET_FSM_TYPE(GET_CONNECTION);
  1532. if (GetError() != ERROR_SUCCESS) {
  1533. return;
  1534. }
  1535. m_dwSocketFlags = dwSocketFlags;
  1536. m_nPort = nPort;
  1537. m_dwTimeout = dwTimeout;
  1538. m_fTimeoutWraps = GetTickCount() > dwTimeout;
  1539. m_dwLimitTimeout = dwLimitTimeout; // This is unused
  1540. m_lplpSocket = lplpSocket;
  1541. if (lpszSecureTunnelHost)
  1542. {
  1543. int ccSecureTunnelHost = (int)strlen(lpszSecureTunnelHost) + 1;
  1544. m_lpszSecureTunnelHost = (LPSTR) ALLOCATE_FIXED_MEMORY(ccSecureTunnelHost);
  1545. if (m_lpszSecureTunnelHost)
  1546. memcpy(m_lpszSecureTunnelHost, lpszSecureTunnelHost, ccSecureTunnelHost);
  1547. }
  1548. else
  1549. {
  1550. m_lpszSecureTunnelHost = NULL;
  1551. }
  1552. m_dwSecureProtocols = dwSecureProtocols;
  1553. }
  1554. ~CFsm_GetConnection() {
  1555. if (m_lpszSecureTunnelHost)
  1556. FREE_MEMORY(m_lpszSecureTunnelHost);
  1557. }
  1558. };
  1559. //
  1560. // HTTP_REQUEST_HANDLE_OBJECT FSMs
  1561. //
  1562. //
  1563. // CFsm_HttpSendRequest -
  1564. //
  1565. class CFsm_HttpSendRequest : public CFsm {
  1566. friend class HTTP_REQUEST_HANDLE_OBJECT;
  1567. public:
  1568. virtual BOOL GetStatusValues(DWORD *pdwStatus, LPVOID *ppvStatusInformation,
  1569. DWORD *pdwStatusInformationLength, WINHTTP_ASYNC_RESULT *pAsyncResult, DWORD *pdwFailureAPI)
  1570. {
  1571. // Delegate to base class first:
  1572. BaseGetStatusValues(ppvStatusInformation, pdwStatusInformationLength, pAsyncResult);
  1573. // Custom stuff:
  1574. if (m_arRequest == AR_HTTP_BEGIN_SEND_REQUEST)
  1575. {
  1576. *pdwStatus = WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE;
  1577. *pdwFailureAPI = API_SEND_REQUEST;
  1578. }
  1579. else
  1580. {
  1581. *pdwStatus = WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE;
  1582. *pdwFailureAPI = API_RECEIVE_RESPONSE;
  1583. }
  1584. //NULL result for success
  1585. if (GetError() == ERROR_SUCCESS)
  1586. {
  1587. *ppvStatusInformation = NULL;
  1588. *pdwStatusInformationLength = NULL;
  1589. }
  1590. return TRUE;
  1591. }
  1592. private:
  1593. //
  1594. // parameters
  1595. //
  1596. LPVOID m_lpOptional;
  1597. DWORD m_dwOptionalLength;
  1598. AR_TYPE m_arRequest;
  1599. //
  1600. // local variables
  1601. //
  1602. HINTERNET m_hRequestMapped;
  1603. HTTP_REQUEST_HANDLE_OBJECT * m_pRequest;
  1604. BOOL m_bFinished;
  1605. BOOL m_bAuthNotFinished;
  1606. BOOL m_bRedirectCountedOut;
  1607. BOOL m_bCancelRedoOfProxy;
  1608. BOOL m_bRedirected;
  1609. BOOL m_bSink;
  1610. DWORD m_dwRedirectCount;
  1611. AUTO_PROXY_ASYNC_MSG *m_pProxyInfoQuery;
  1612. BOOL m_fOwnsProxyInfoQueryObj;
  1613. INTERNET_HANDLE_OBJECT * m_pInternet;
  1614. LPVOID m_pBuffer;
  1615. DWORD m_dwBytesDrained;
  1616. DWORD m_dwTotalBytesDrained;
  1617. DWORD m_iRetries;
  1618. BOOL m_bWasKeepAlive;
  1619. HTTP_METHOD_TYPE m_tMethodRedirect;
  1620. DWORD m_dwCookieIndex;
  1621. public:
  1622. static
  1623. DWORD
  1624. RunSM(
  1625. IN CFsm * Fsm
  1626. );
  1627. CFsm_HttpSendRequest(
  1628. IN LPVOID lpOptional OPTIONAL,
  1629. IN DWORD dwOptionalLength,
  1630. IN HTTP_REQUEST_HANDLE_OBJECT * pRequest,
  1631. IN AR_TYPE arRequest
  1632. ) : CFsm(RunSM, (LPVOID)pRequest) {
  1633. SET_FSM_TYPE(HTTP_SEND_REQUEST);
  1634. if (GetError() != ERROR_SUCCESS) {
  1635. return;
  1636. }
  1637. SetApi(ApiType_Bool);
  1638. m_hRequestMapped = (HINTERNET)pRequest;
  1639. m_lpOptional = lpOptional;
  1640. m_dwOptionalLength = dwOptionalLength;
  1641. m_pRequest = pRequest;
  1642. m_bFinished = FALSE;
  1643. m_bAuthNotFinished = FALSE;
  1644. m_bRedirectCountedOut = FALSE;
  1645. m_bCancelRedoOfProxy = FALSE;
  1646. m_bRedirected = FALSE;
  1647. m_bSink = FALSE;
  1648. m_dwRedirectCount = pRequest->GetDwordOption(WINHTTP_OPTION_MAX_HTTP_AUTOMATIC_REDIRECTS);
  1649. m_pProxyInfoQuery = NULL;
  1650. m_arRequest = arRequest;
  1651. m_fOwnsProxyInfoQueryObj = TRUE;
  1652. m_dwCookieIndex = 0;
  1653. m_pInternet = GetRootHandle(pRequest);
  1654. INET_ASSERT(m_pInternet != NULL);
  1655. INET_ASSERT(m_pInternet->IsValid(TypeInternetHandle) == ERROR_SUCCESS);
  1656. m_pBuffer = NULL;
  1657. m_iRetries = 2;
  1658. m_tMethodRedirect = HTTP_METHOD_TYPE_UNKNOWN;
  1659. }
  1660. ~CFsm_HttpSendRequest(
  1661. VOID
  1662. )
  1663. {
  1664. if ( m_fOwnsProxyInfoQueryObj && m_pProxyInfoQuery && m_pProxyInfoQuery->IsAlloced())
  1665. {
  1666. delete m_pProxyInfoQuery;
  1667. }
  1668. if (m_pBuffer != NULL)
  1669. {
  1670. m_pBuffer = (LPVOID)FREE_MEMORY(m_pBuffer);
  1671. }
  1672. }
  1673. };
  1674. //
  1675. // CFsm_MakeConnection -
  1676. //
  1677. class CFsm_MakeConnection : public CFsm {
  1678. friend class HTTP_REQUEST_HANDLE_OBJECT;
  1679. private:
  1680. //
  1681. // parameters
  1682. //
  1683. //
  1684. // local variables
  1685. //
  1686. HTTP_REQUEST_HANDLE_OBJECT * m_pRequest;
  1687. BOOL m_bAttemptReconnect;
  1688. public:
  1689. static
  1690. DWORD
  1691. RunSM(
  1692. IN CFsm * Fsm
  1693. );
  1694. CFsm_MakeConnection(
  1695. IN HTTP_REQUEST_HANDLE_OBJECT * pRequest
  1696. ) : CFsm(RunSM, (LPVOID)pRequest) {
  1697. SET_FSM_TYPE(MAKE_CONNECTION);
  1698. if (GetError() != ERROR_SUCCESS) {
  1699. return;
  1700. }
  1701. m_pRequest = pRequest;
  1702. }
  1703. };
  1704. //
  1705. // CFsm_OpenConnection -
  1706. //
  1707. class CFsm_OpenConnection : public CFsm {
  1708. friend class HTTP_REQUEST_HANDLE_OBJECT;
  1709. private:
  1710. //
  1711. // parameters
  1712. //
  1713. BOOL m_bNewConnection;
  1714. //
  1715. // local variables
  1716. //
  1717. BOOL m_bCreatedSocket;
  1718. BOOL m_fNoCreate;
  1719. public:
  1720. static
  1721. DWORD
  1722. RunSM(
  1723. IN CFsm * Fsm
  1724. );
  1725. CFsm_OpenConnection(
  1726. IN BOOL bNewConnection,
  1727. IN HTTP_REQUEST_HANDLE_OBJECT * pRequest,
  1728. IN BOOL fNoCreate = FALSE
  1729. ) : CFsm(RunSM, (LPVOID)pRequest) {
  1730. SET_FSM_TYPE(OPEN_CONNECTION);
  1731. if (GetError() != ERROR_SUCCESS) {
  1732. return;
  1733. }
  1734. m_bNewConnection = bNewConnection;
  1735. m_bCreatedSocket = FALSE;
  1736. m_fNoCreate = fNoCreate;
  1737. }
  1738. };
  1739. //
  1740. // CFsm_OpenProxyTunnel -
  1741. //
  1742. class CFsm_OpenProxyTunnel : public CFsm {
  1743. friend class HTTP_REQUEST_HANDLE_OBJECT;
  1744. private:
  1745. //
  1746. // parameters
  1747. //
  1748. //
  1749. // local variables
  1750. //
  1751. HINTERNET m_hConnect;
  1752. HINTERNET m_hRequest;
  1753. HINTERNET m_hRequestMapped;
  1754. HTTP_REQUEST_HANDLE_OBJECT * m_pRequest;
  1755. public:
  1756. static
  1757. DWORD
  1758. RunSM(
  1759. IN CFsm * Fsm
  1760. );
  1761. CFsm_OpenProxyTunnel(
  1762. IN HTTP_REQUEST_HANDLE_OBJECT * pRequest
  1763. ) : CFsm(RunSM, (LPVOID)pRequest) {
  1764. SET_FSM_TYPE(OPEN_PROXY_TUNNEL);
  1765. if (GetError() != ERROR_SUCCESS) {
  1766. return;
  1767. }
  1768. m_hConnect = NULL;
  1769. m_hRequest = NULL;
  1770. m_hRequestMapped = NULL;
  1771. }
  1772. };
  1773. //
  1774. // CFsm_SendRequest -
  1775. //
  1776. class CFsm_SendRequest : public CFsm {
  1777. friend class HTTP_REQUEST_HANDLE_OBJECT;
  1778. private:
  1779. //
  1780. // parameters
  1781. //
  1782. LPVOID m_lpOptional;
  1783. DWORD m_dwOptionalLength;
  1784. //
  1785. // local variables
  1786. //
  1787. LPSTR m_pRequestBuffer;
  1788. DWORD m_dwRequestLength;
  1789. public:
  1790. static
  1791. DWORD
  1792. RunSM(
  1793. IN CFsm * Fsm
  1794. );
  1795. CFsm_SendRequest(
  1796. IN LPVOID lpOptional,
  1797. IN DWORD dwOptionalLength,
  1798. IN HTTP_REQUEST_HANDLE_OBJECT * pRequest
  1799. ) : CFsm(RunSM, (LPVOID)pRequest) {
  1800. SET_FSM_TYPE(SEND_REQUEST);
  1801. if (GetError() != ERROR_SUCCESS) {
  1802. return;
  1803. }
  1804. m_lpOptional = lpOptional;
  1805. m_dwOptionalLength = dwOptionalLength;
  1806. m_pRequestBuffer = NULL;
  1807. }
  1808. ~CFsm_SendRequest() {
  1809. if (m_pRequestBuffer != NULL) {
  1810. m_pRequestBuffer = (LPSTR)FREE_MEMORY(m_pRequestBuffer);
  1811. INET_ASSERT(m_pRequestBuffer == NULL);
  1812. }
  1813. }
  1814. };
  1815. //
  1816. // CFsm_ReceiveResponse -
  1817. //
  1818. class CFsm_ReceiveResponse : public CFsm {
  1819. friend class HTTP_REQUEST_HANDLE_OBJECT;
  1820. private:
  1821. //
  1822. // parameters
  1823. //
  1824. //
  1825. // local variables
  1826. //
  1827. HTTP_REQUEST_HANDLE_OBJECT * m_pRequest;
  1828. DWORD m_dwResponseLeft;
  1829. BOOL m_bEofResponseHeaders;
  1830. BOOL m_bDrained;
  1831. DWORD m_dwHttpStatusContinueCount;
  1832. DWORD m_dwReceiveResponseStartTicks;
  1833. public:
  1834. static
  1835. DWORD
  1836. RunSM(
  1837. IN CFsm * Fsm
  1838. );
  1839. CFsm_ReceiveResponse(
  1840. IN HTTP_REQUEST_HANDLE_OBJECT * pRequest
  1841. ) : CFsm(RunSM, (LPVOID)pRequest) {
  1842. SET_FSM_TYPE(RECEIVE_RESPONSE);
  1843. if (GetError() != ERROR_SUCCESS) {
  1844. return;
  1845. }
  1846. m_pRequest = pRequest;
  1847. m_bDrained = FALSE;
  1848. m_dwHttpStatusContinueCount = pRequest->GetDwordOption(WINHTTP_OPTION_MAX_HTTP_STATUS_CONTINUE);
  1849. }
  1850. };
  1851. //
  1852. // CFsm_HttpReadData -
  1853. //
  1854. class CFsm_HttpReadData : public CFsm {
  1855. friend class HTTP_REQUEST_HANDLE_OBJECT;
  1856. private:
  1857. //
  1858. // parameters
  1859. //
  1860. LPVOID m_lpBuffer;
  1861. DWORD m_dwNumberOfBytesToRead;
  1862. LPDWORD m_lpdwNumberOfBytesRead;
  1863. DWORD m_dwSocketFlags;
  1864. //
  1865. // local variables
  1866. //
  1867. public:
  1868. static
  1869. DWORD
  1870. RunSM(
  1871. IN CFsm * Fsm
  1872. );
  1873. CFsm_HttpReadData(
  1874. IN LPVOID lpBuffer,
  1875. IN DWORD dwNumberOfBytesToRead,
  1876. OUT LPDWORD lpdwNumberOfBytesRead,
  1877. IN DWORD dwSocketFlags,
  1878. IN HTTP_REQUEST_HANDLE_OBJECT * pRequest
  1879. ) : CFsm(RunSM, (LPVOID)pRequest) {
  1880. SET_FSM_TYPE(HTTP_READ);
  1881. if (GetError() != ERROR_SUCCESS) {
  1882. return;
  1883. }
  1884. m_lpBuffer = lpBuffer;
  1885. m_dwNumberOfBytesToRead = dwNumberOfBytesToRead;
  1886. m_lpdwNumberOfBytesRead = lpdwNumberOfBytesRead;
  1887. m_dwSocketFlags = dwSocketFlags;
  1888. }
  1889. };
  1890. //
  1891. // CFsm_HttpWriteData -
  1892. //
  1893. class CFsm_HttpWriteData : public CFsm {
  1894. friend class HTTP_REQUEST_HANDLE_OBJECT;
  1895. public:
  1896. virtual BOOL GetStatusValues(DWORD *pdwStatus, LPVOID *ppvStatusInformation,
  1897. DWORD *pdwStatusInformationLength, WINHTTP_ASYNC_RESULT *pAsyncResult, DWORD *pdwFailureAPI)
  1898. {
  1899. // Delegate to base class first:
  1900. BaseGetStatusValues(ppvStatusInformation, pdwStatusInformationLength, pAsyncResult);
  1901. // Custom stuff:
  1902. *pdwStatus = WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE;
  1903. //# of bytes written for success
  1904. if (GetError() == ERROR_SUCCESS)
  1905. {
  1906. pAsyncResult->dwError = *m_lpdwNumberOfBytesWritten;
  1907. }
  1908. else
  1909. {
  1910. *pdwFailureAPI = API_WRITE_DATA;
  1911. }
  1912. return TRUE;
  1913. }
  1914. private:
  1915. //
  1916. // parameters
  1917. //
  1918. LPVOID m_lpBuffer;
  1919. DWORD m_dwNumberOfBytesToWrite;
  1920. DWORD m_dwNumberOfBytesWritten;
  1921. LPDWORD m_lpdwNumberOfBytesWritten;
  1922. DWORD m_dwSocketFlags;
  1923. //
  1924. // local variables
  1925. //
  1926. public:
  1927. static
  1928. DWORD
  1929. RunSM(
  1930. IN CFsm * Fsm
  1931. );
  1932. CFsm_HttpWriteData(
  1933. IN LPVOID lpBuffer,
  1934. IN DWORD dwNumberOfBytesToWrite,
  1935. OUT LPDWORD lpdwNumberOfBytesWritten, // to ignore
  1936. IN DWORD dwSocketFlags,
  1937. IN HTTP_REQUEST_HANDLE_OBJECT * pRequest
  1938. ) : CFsm(RunSM, (LPVOID)pRequest) {
  1939. UNREFERENCED_PARAMETER(lpdwNumberOfBytesWritten);
  1940. SET_FSM_TYPE(HTTP_WRITE);
  1941. if (GetError() != ERROR_SUCCESS) {
  1942. return;
  1943. }
  1944. INET_ASSERT(lpdwNumberOfBytesWritten == NULL);
  1945. m_lpBuffer = lpBuffer;
  1946. m_dwNumberOfBytesToWrite = dwNumberOfBytesToWrite;
  1947. m_dwNumberOfBytesWritten = 0;
  1948. m_lpdwNumberOfBytesWritten = &m_dwNumberOfBytesWritten;
  1949. m_dwSocketFlags = dwSocketFlags;
  1950. SetApi(ApiType_Bool);
  1951. }
  1952. };
  1953. //
  1954. // CFsm_ReadData -
  1955. //
  1956. class CFsm_ReadData : public CFsm {
  1957. friend class HTTP_REQUEST_HANDLE_OBJECT;
  1958. private:
  1959. //
  1960. // parameters
  1961. //
  1962. LPVOID m_lpBuffer;
  1963. DWORD m_dwNumberOfBytesToRead;
  1964. LPDWORD m_lpdwNumberOfBytesRead;
  1965. BOOL m_fNoAsync;
  1966. DWORD m_dwSocketFlags;
  1967. //
  1968. // local variables
  1969. //
  1970. DWORD m_nBytes;
  1971. DWORD m_nBytesCopied;
  1972. DWORD m_dwBufferLeft;
  1973. DWORD m_dwBytesRead;
  1974. BOOL m_bEof;
  1975. public:
  1976. static
  1977. DWORD
  1978. RunSM(
  1979. IN CFsm * Fsm
  1980. );
  1981. CFsm_ReadData(
  1982. IN LPVOID lpBuffer,
  1983. IN DWORD dwNumberOfBytesToRead,
  1984. OUT LPDWORD lpdwNumberOfBytesRead,
  1985. IN BOOL fNoAsync,
  1986. IN DWORD dwSocketFlags,
  1987. IN HTTP_REQUEST_HANDLE_OBJECT * pRequest
  1988. ) : CFsm(RunSM, (LPVOID)pRequest) {
  1989. SET_FSM_TYPE(READ_DATA);
  1990. if (GetError() != ERROR_SUCCESS) {
  1991. return;
  1992. }
  1993. m_lpBuffer = lpBuffer;
  1994. m_dwNumberOfBytesToRead = dwNumberOfBytesToRead;
  1995. m_lpdwNumberOfBytesRead = lpdwNumberOfBytesRead;
  1996. m_fNoAsync = fNoAsync;
  1997. m_dwSocketFlags = dwSocketFlags;
  1998. m_nBytesCopied = 0;
  1999. }
  2000. };
  2001. //
  2002. // CFsm_HttpQueryAvailable -
  2003. //
  2004. class CFsm_HttpQueryAvailable : public CFsm {
  2005. friend class HTTP_REQUEST_HANDLE_OBJECT;
  2006. private:
  2007. //
  2008. // parameters
  2009. //
  2010. LPDWORD m_lpdwNumberOfBytesAvailable;
  2011. //
  2012. // local variables
  2013. //
  2014. LPVOID m_lpBuffer;
  2015. DWORD m_dwBufferLength;
  2016. DWORD m_dwBufferLeft;
  2017. BOOL m_bEof;
  2018. public:
  2019. static
  2020. DWORD
  2021. RunSM(
  2022. IN CFsm * Fsm
  2023. );
  2024. CFsm_HttpQueryAvailable(
  2025. IN LPDWORD lpdwNumberOfBytesAvailable,
  2026. IN HTTP_REQUEST_HANDLE_OBJECT * pRequest
  2027. ) : CFsm(RunSM, (LPVOID)pRequest) {
  2028. SET_FSM_TYPE(HTTP_QUERY_AVAILABLE);
  2029. if (GetError() != ERROR_SUCCESS) {
  2030. return;
  2031. }
  2032. m_lpdwNumberOfBytesAvailable = lpdwNumberOfBytesAvailable;
  2033. }
  2034. };
  2035. //
  2036. // CFsm_DrainResponse -
  2037. //
  2038. class CFsm_DrainResponse : CFsm {
  2039. friend class HTTP_REQUEST_HANDLE_OBJECT;
  2040. private:
  2041. //
  2042. // parameters
  2043. //
  2044. LPBOOL m_lpbDrained;
  2045. //
  2046. // local variables
  2047. //
  2048. DWORD m_dwAmountToRead;
  2049. DWORD m_dwBufferLeft;
  2050. DWORD m_dwPreviousBytesReceived;
  2051. DWORD m_dwAsyncFlags;
  2052. DWORD m_dwBytesReceived;
  2053. DWORD m_dwBytesReceivedBeforeDrain;
  2054. BOOL m_bEof;
  2055. public:
  2056. static
  2057. DWORD
  2058. RunSM(
  2059. IN CFsm * Fsm
  2060. );
  2061. CFsm_DrainResponse(
  2062. IN LPBOOL lpbDrained,
  2063. IN HTTP_REQUEST_HANDLE_OBJECT * pRequest
  2064. ) : CFsm(RunSM, (LPVOID)pRequest) {
  2065. SET_FSM_TYPE(DRAIN_RESPONSE);
  2066. if (GetError() != ERROR_SUCCESS) {
  2067. return;
  2068. }
  2069. m_lpbDrained = lpbDrained;
  2070. m_bEof = FALSE;
  2071. m_dwBytesReceived = 0;
  2072. m_dwBytesReceivedBeforeDrain = 0;
  2073. }
  2074. };
  2075. //
  2076. // CFsm_Redirect -
  2077. //
  2078. class CFsm_Redirect : public CFsm {
  2079. friend class HTTP_REQUEST_HANDLE_OBJECT;
  2080. private:
  2081. //
  2082. // parameters
  2083. //
  2084. HTTP_METHOD_TYPE m_tMethod;
  2085. //
  2086. // local variables
  2087. //
  2088. BOOL m_bDrained;
  2089. public:
  2090. static
  2091. DWORD
  2092. RunSM(
  2093. IN CFsm * Fsm
  2094. );
  2095. CFsm_Redirect(
  2096. IN HTTP_METHOD_TYPE tMethod,
  2097. IN BOOL fRedirectToProxy,
  2098. IN HTTP_REQUEST_HANDLE_OBJECT * pRequest
  2099. ) : CFsm(RunSM, (LPVOID)pRequest) {
  2100. UNREFERENCED_PARAMETER(fRedirectToProxy);
  2101. SET_FSM_TYPE(REDIRECT);
  2102. if (GetError() != ERROR_SUCCESS) {
  2103. return;
  2104. }
  2105. m_tMethod = tMethod;
  2106. }
  2107. };
  2108. //
  2109. // CFsm_ReadLoop -
  2110. //
  2111. class CFsm_ReadLoop : public CFsm {
  2112. friend class HTTP_REQUEST_HANDLE_OBJECT;
  2113. private:
  2114. //
  2115. // parameters
  2116. //
  2117. DWORD m_dwSocketFlags;
  2118. PBYTE m_pRead;
  2119. DWORD m_cbReadIn;
  2120. DWORD* m_pcbReadOut;
  2121. //
  2122. // local variables
  2123. //
  2124. LPVOID m_pBuf; // read buffer
  2125. DWORD m_cbBuf; // size of read buffer
  2126. DWORD m_dwReadEnd; // read offset goal
  2127. DWORD m_cbRead; // bytes to read
  2128. DWORD m_cbRecv; // bytes received
  2129. public:
  2130. static
  2131. DWORD
  2132. RunSM(
  2133. IN CFsm * Fsm
  2134. );
  2135. CFsm_ReadLoop(
  2136. IN HTTP_REQUEST_HANDLE_OBJECT * pRequest,
  2137. IN DWORD dwSocketFlags,
  2138. IN PBYTE pRead,
  2139. IN DWORD cbReadIn,
  2140. OUT DWORD* pcbReadOut
  2141. ) : CFsm(RunSM, (LPVOID)pRequest) {
  2142. SET_FSM_TYPE(READ_LOOP);
  2143. m_dwSocketFlags = dwSocketFlags;
  2144. m_pRead = pRead;
  2145. m_cbReadIn = cbReadIn;
  2146. m_pcbReadOut = pcbReadOut;
  2147. if (GetError() != ERROR_SUCCESS) {
  2148. return;
  2149. }
  2150. }
  2151. };
  2152. //
  2153. // CFsm_ParseHttpUrl -
  2154. //
  2155. class CFsm_ParseHttpUrl : public CFsm {
  2156. friend
  2157. DWORD
  2158. ParseHttpUrl_Fsm(
  2159. IN CFsm_ParseHttpUrl * Fsm
  2160. );
  2161. private:
  2162. //
  2163. // parameters
  2164. //
  2165. LPHINTERNET m_phInternet;
  2166. LPSTR m_lpszUrl;
  2167. DWORD m_dwSchemeLength;
  2168. LPSTR m_lpszHeaders;
  2169. DWORD m_dwHeadersLength;
  2170. DWORD m_dwFlags;
  2171. DWORD_PTR m_dwContext;
  2172. //
  2173. // locals
  2174. //
  2175. HINTERNET m_hConnect;
  2176. HINTERNET m_hRequest;
  2177. public:
  2178. CFsm_ParseHttpUrl(
  2179. IN OUT LPHINTERNET phInternet,
  2180. IN LPSTR lpszUrl,
  2181. IN DWORD dwSchemeLength,
  2182. IN LPSTR lpszHeaders,
  2183. IN DWORD dwHeadersLength,
  2184. IN DWORD dwFlags,
  2185. IN DWORD_PTR dwContext
  2186. ) : CFsm((DWORD (*)(CFsm *))ParseHttpUrl_Fsm, NULL) {
  2187. SET_FSM_TYPE(PARSE_HTTP_URL);
  2188. if (GetError() != ERROR_SUCCESS) {
  2189. return;
  2190. }
  2191. m_phInternet = phInternet;
  2192. m_lpszUrl = lpszUrl;
  2193. m_dwSchemeLength = dwSchemeLength;
  2194. m_lpszHeaders = lpszHeaders;
  2195. m_dwHeadersLength = dwHeadersLength;
  2196. m_dwFlags = dwFlags;
  2197. m_dwContext = dwContext;
  2198. }
  2199. };
  2200. //
  2201. // CFsm_OpenUrl -
  2202. //
  2203. class CFsm_OpenUrl : public CFsm {
  2204. private:
  2205. //
  2206. // parameters
  2207. //
  2208. //
  2209. // locals
  2210. //
  2211. public:
  2212. CFsm_OpenUrl();
  2213. };
  2214. //
  2215. // CFsm_ParseUrlForHttp -
  2216. //
  2217. class CFsm_ParseUrlForHttp : public CFsm {
  2218. friend
  2219. DWORD
  2220. ParseUrlForHttp_Fsm(
  2221. IN CFsm_ParseUrlForHttp * Fsm
  2222. );
  2223. private:
  2224. //
  2225. // parameters
  2226. //
  2227. LPHINTERNET m_lphInternet; // 0x7C
  2228. HINTERNET m_hInternet; // 0x80
  2229. LPVOID m_hInternetMapped; // 0x84
  2230. LPSTR m_lpcszUrl; // 0x88
  2231. LPSTR m_lpcszHeaders; // 0x8C
  2232. DWORD m_dwHeadersLength; // 0x90
  2233. DWORD m_dwFlags; // 0x94
  2234. DWORD_PTR m_dwContext; // 0x98
  2235. //
  2236. // locals
  2237. //
  2238. PROXY_STATE * m_pProxyState; // 0x9C
  2239. LPSTR m_lpszUrlCopy; // 0xA0
  2240. LPFN_URL_PARSER m_pUrlParser; // 0xA4
  2241. INTERNET_SCHEME m_SchemeType; // 0xA8
  2242. DWORD m_dwSchemeLength; // 0xAC
  2243. AUTO_PROXY_ASYNC_MSG *m_pProxyInfoQuery;// 0xB0
  2244. BOOL m_fFirstCall; // 0xB4
  2245. HINTERNET m_hInternetCopy; // 0xB8
  2246. public:
  2247. static
  2248. DWORD
  2249. RunSM(
  2250. IN CFsm * Fsm
  2251. );
  2252. CFsm_ParseUrlForHttp(
  2253. IN OUT LPHINTERNET lphInternet,
  2254. IN LPVOID hMapped,
  2255. IN LPCSTR lpcszUrl,
  2256. IN LPCSTR lpcszHeaders,
  2257. IN DWORD dwHeadersLength,
  2258. IN DWORD dwFlags,
  2259. IN DWORD_PTR dwContext
  2260. ) : CFsm(RunSM, NULL) {
  2261. SET_FSM_TYPE(PARSE_URL_FOR_HTTP);
  2262. if (GetError() != ERROR_SUCCESS) {
  2263. return;
  2264. }
  2265. //
  2266. // ParseUrlForHttp() is the function that returns the API result for
  2267. // InternetOpenUrl() in the new scheme. Make this FSM return the API
  2268. // result
  2269. //
  2270. SetApi(ApiType_Handle);
  2271. m_lphInternet = lphInternet;
  2272. m_hInternet = *lphInternet;
  2273. m_hInternetMapped = hMapped;
  2274. m_hInternetCopy = *lphInternet;
  2275. m_dwHeadersLength = dwHeadersLength;
  2276. m_dwFlags = dwFlags;
  2277. m_dwContext = dwContext;
  2278. m_pProxyState = NULL;
  2279. m_pUrlParser = NULL;
  2280. m_SchemeType = INTERNET_SCHEME_DEFAULT;
  2281. m_dwSchemeLength = 0;
  2282. m_pProxyInfoQuery = NULL;
  2283. m_fFirstCall = TRUE;
  2284. COPY_MANDATORY_PARAM(m_lpcszUrl, lpcszUrl);
  2285. if (lpcszHeaders)
  2286. {
  2287. m_lpcszHeaders = NewString(lpcszHeaders, dwHeadersLength);
  2288. if (!m_lpcszHeaders)
  2289. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  2290. }
  2291. else
  2292. m_lpcszHeaders = NULL;
  2293. }
  2294. ~CFsm_ParseUrlForHttp() {
  2295. DELETE_MANDATORY_PARAM(m_lpcszUrl);
  2296. DELETE_OPTIONAL_PARAM(m_lpcszHeaders);
  2297. }
  2298. BOOL IsOnApiCall(VOID) {
  2299. return m_fFirstCall;
  2300. }
  2301. VOID ClearOnApiCall(VOID) {
  2302. m_fFirstCall = FALSE;
  2303. }
  2304. DWORD
  2305. QueryProxySettings(
  2306. IN CFsm_ParseUrlForHttp * Fsm,
  2307. IN BOOL fCallback
  2308. );
  2309. DWORD
  2310. BuildProxyMessage(
  2311. IN CFsm_ParseUrlForHttp * Fsm
  2312. );
  2313. DWORD
  2314. ScanProxyUrl(
  2315. IN CFsm_ParseUrlForHttp * Fsm
  2316. );
  2317. DWORD
  2318. CompleteParseUrl(
  2319. IN CFsm_ParseUrlForHttp * Fsm,
  2320. IN LPINTERNET_THREAD_INFO lpThreadInfo,
  2321. IN DWORD error
  2322. );
  2323. };
  2324. //
  2325. // InternetReadFile API
  2326. //
  2327. class CFsm_ReadFile : public CFsm {
  2328. friend
  2329. DWORD
  2330. ReadFile_Fsm(
  2331. IN CFsm_ReadFile * Fsm
  2332. );
  2333. public:
  2334. virtual BOOL GetStatusValues(DWORD *pdwStatus, LPVOID *ppvStatusInformation,
  2335. DWORD *pdwStatusInformationLength, WINHTTP_ASYNC_RESULT *pAsyncResult, DWORD *pdwFailureAPI)
  2336. {
  2337. // Delegate to base class first:
  2338. BaseGetStatusValues(ppvStatusInformation, pdwStatusInformationLength, pAsyncResult);
  2339. // Custom stuff:
  2340. *pdwStatus = WINHTTP_CALLBACK_STATUS_READ_COMPLETE;
  2341. //buffer pointer and bytes read for success
  2342. if(GetError() == ERROR_SUCCESS)
  2343. {
  2344. *ppvStatusInformation = m_lpBuffer;
  2345. *pdwStatusInformationLength = *m_lpdwNumberOfBytesRead;
  2346. }
  2347. else
  2348. {
  2349. *pdwFailureAPI = API_READ_DATA;
  2350. }
  2351. return TRUE;
  2352. }
  2353. private:
  2354. //
  2355. // parameters
  2356. //
  2357. LPVOID m_lpBuffer;
  2358. DWORD m_dwNumberOfBytesToRead;
  2359. LPDWORD m_lpdwNumberOfBytesRead;
  2360. //
  2361. // local variables
  2362. //
  2363. DWORD m_dwBytesRead;
  2364. DWORD m_dwNumberOfBytesRead;
  2365. public:
  2366. static
  2367. DWORD
  2368. RunSM(
  2369. IN CFsm * Fsm
  2370. );
  2371. CFsm_ReadFile(
  2372. IN LPVOID lpBuffer,
  2373. IN DWORD dwNumberOfBytesToRead,
  2374. OUT LPDWORD lpdwNumberOfBytesRead // ignored
  2375. ) : CFsm(RunSM, NULL) {
  2376. UNREFERENCED_PARAMETER(lpdwNumberOfBytesRead);
  2377. SET_FSM_TYPE(READ_FILE);
  2378. if (GetError() != ERROR_SUCCESS) {
  2379. return;
  2380. }
  2381. INET_ASSERT(lpdwNumberOfBytesRead == NULL);
  2382. SetApi(ApiType_Bool);
  2383. m_lpBuffer = lpBuffer;
  2384. m_dwNumberOfBytesToRead = dwNumberOfBytesToRead;
  2385. m_dwNumberOfBytesRead = 0;
  2386. m_lpdwNumberOfBytesRead = &m_dwNumberOfBytesRead;
  2387. }
  2388. };
  2389. //
  2390. // InternetReadFileEx API
  2391. //
  2392. class CFsm_ReadFileEx : public CFsm {
  2393. friend
  2394. DWORD
  2395. ReadFileEx_Fsm(
  2396. IN CFsm_ReadFileEx * Fsm
  2397. );
  2398. private:
  2399. //
  2400. // parameters
  2401. //
  2402. LPINTERNET_BUFFERS m_lpBuffersOut;
  2403. DWORD m_dwFlags;
  2404. DWORD_PTR m_dwContext;
  2405. //
  2406. // local variables
  2407. //
  2408. DWORD m_dwNumberOfBytesToRead;
  2409. DWORD m_dwBytesRead;
  2410. public:
  2411. static
  2412. DWORD
  2413. RunSM(
  2414. IN CFsm * Fsm
  2415. );
  2416. CFsm_ReadFileEx(
  2417. IN LPINTERNET_BUFFERS lpBuffersOut,
  2418. IN DWORD dwFlags,
  2419. IN DWORD_PTR dwContext
  2420. ) : CFsm(RunSM, NULL) {
  2421. SET_FSM_TYPE(READ_FILE);
  2422. if (GetError() != ERROR_SUCCESS) {
  2423. return;
  2424. }
  2425. SetApi(ApiType_Bool);
  2426. m_lpBuffersOut = lpBuffersOut;
  2427. m_dwFlags = dwFlags;
  2428. m_dwContext = dwContext;
  2429. }
  2430. };
  2431. //
  2432. // InternetQueryDataAvailable API
  2433. //
  2434. class CFsm_QueryAvailable : public CFsm {
  2435. friend
  2436. DWORD
  2437. QueryAvailable_Fsm(
  2438. IN CFsm_QueryAvailable * Fsm
  2439. );
  2440. public:
  2441. virtual BOOL GetStatusValues(DWORD *pdwStatus, LPVOID *ppvStatusInformation,
  2442. DWORD *pdwStatusInformationLength, WINHTTP_ASYNC_RESULT *pAsyncResult, DWORD *pdwFailureAPI)
  2443. {
  2444. // Delegate to base class first:
  2445. BaseGetStatusValues(ppvStatusInformation, pdwStatusInformationLength, pAsyncResult);
  2446. // Custom stuff:
  2447. *pdwStatus = WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE;
  2448. //# of bytes available for success
  2449. if(GetError() == ERROR_SUCCESS)
  2450. {
  2451. pAsyncResult->dwError = *m_lpdwNumberOfBytesAvailable;
  2452. }
  2453. else
  2454. {
  2455. *pdwFailureAPI = API_QUERY_DATA_AVAILABLE;
  2456. }
  2457. return TRUE;
  2458. }
  2459. private:
  2460. //
  2461. // parameters
  2462. //
  2463. DWORD m_dwNumberOfBytesAvailable;
  2464. LPDWORD m_lpdwNumberOfBytesAvailable;
  2465. DWORD m_dwFlags;
  2466. DWORD_PTR m_dwContext;
  2467. //
  2468. // local variables
  2469. //
  2470. public:
  2471. static
  2472. DWORD
  2473. RunSM(
  2474. IN CFsm * Fsm
  2475. );
  2476. CFsm_QueryAvailable(
  2477. IN LPDWORD lpdwNumberOfBytesAvailable, // not used
  2478. IN DWORD dwFlags,
  2479. IN DWORD_PTR dwContext
  2480. ) : CFsm(RunSM, NULL) {
  2481. UNREFERENCED_PARAMETER(lpdwNumberOfBytesAvailable);
  2482. INET_ASSERT(lpdwNumberOfBytesAvailable == NULL);
  2483. SET_FSM_TYPE(QUERY_DATA_AVAILABLE);
  2484. if (GetError() != ERROR_SUCCESS) {
  2485. return;
  2486. }
  2487. SetApi(ApiType_Bool);
  2488. m_dwNumberOfBytesAvailable = 0;
  2489. m_lpdwNumberOfBytesAvailable = &m_dwNumberOfBytesAvailable;
  2490. m_dwFlags = dwFlags;
  2491. m_dwContext = dwContext;
  2492. }
  2493. };
  2494. //
  2495. // Fsm to Background tasks
  2496. //
  2497. class BackgroundTaskMgr; // defined in bgtask.hxx
  2498. class CFsm_BackgroundTask : public CFsm {
  2499. friend class BackgroundTaskMgr;
  2500. friend
  2501. DWORD
  2502. BackgroundTask_Fsm(
  2503. IN CFsm_BackgroundTask * Fsm
  2504. );
  2505. private:
  2506. //
  2507. // parameters
  2508. //
  2509. BackgroundTaskMgr* m_pMgr;
  2510. LPCSTR m_lpszUrl;
  2511. //
  2512. // local variables
  2513. //
  2514. //
  2515. // internal methods
  2516. DWORD DoSendReq();
  2517. //
  2518. // this private func can only
  2519. // be called from Mgr
  2520. //
  2521. CFsm_BackgroundTask(
  2522. IN BackgroundTaskMgr* pMgr,
  2523. IN LPCSTR lpszUrl
  2524. ) : CFsm(RunSM, NULL) {
  2525. SET_FSM_TYPE(BACKGROUND_TASK);
  2526. if (GetError() != ERROR_SUCCESS) {
  2527. return;
  2528. }
  2529. m_pMgr = pMgr;
  2530. COPY_MANDATORY_PARAM(m_lpszUrl, lpszUrl);
  2531. }
  2532. public:
  2533. static
  2534. DWORD
  2535. RunSM(
  2536. IN CFsm * Fsm
  2537. );
  2538. ~CFsm_BackgroundTask();
  2539. };
  2540. //
  2541. // prototypes
  2542. //
  2543. CFsm *
  2544. ContainingFsm(
  2545. IN LPVOID lpAddress
  2546. );
  2547. DWORD
  2548. RunAll(
  2549. VOID
  2550. );
  2551. DWORD
  2552. DoFsm(
  2553. IN CFsm * pFsm
  2554. );
  2555. DWORD
  2556. StartFsmChain(
  2557. IN CFsm * pFsm,
  2558. IN HTTP_REQUEST_HANDLE_OBJECT *pRequest,
  2559. IN BOOL bQueue = FALSE,
  2560. IN BOOL bAsync = TRUE
  2561. );