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.

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