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.

706 lines
20 KiB

  1. /******************************************************************************
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. HttpContext.cpp
  5. Abstract:
  6. This file contains the implementation of the MPCHttpContext class,
  7. which handles the interface with IIS.
  8. Revision History:
  9. Davide Massarenti (Dmassare) 04/20/99
  10. created
  11. ******************************************************************************/
  12. #include "stdafx.h"
  13. #define BUFFER_SIZE_TMP (64)
  14. static const char szStatus [] = "200 OK";
  15. static const char szNewLine[] = "\r\n";
  16. /////////////////////////////////////////////////////////////////////////////
  17. /////////////////////////////////////////////////////////////////////////////
  18. //
  19. // Static functions.
  20. //
  21. /////////////////////////////////////////////////////////////////////////////
  22. /////////////////////////////////////////////////////////////////////////////
  23. static void SupportAddHeader( /*[in/out]*/ MPC::string& szHeaders ,
  24. /*[in] */ const char* szHeaderName ,
  25. /*[in] */ const char* szHeaderValue )
  26. {
  27. __ULT_FUNC_ENTRY("SupportAddHeader");
  28. szHeaders.append( szHeaderName );
  29. szHeaders.append( ": " );
  30. szHeaders.append( szHeaderValue );
  31. szHeaders.append( szNewLine );
  32. }
  33. static void SupportAddHeader( /*[in/out]*/ MPC::string& szHeaders ,
  34. /*[in] */ const char* szHeaderName ,
  35. /*[in] */ DWORD dwHeaderValue )
  36. {
  37. __ULT_FUNC_ENTRY("SupportAddHeader");
  38. char rgBuf[BUFFER_SIZE_TMP];
  39. sprintf( rgBuf, "%lu", dwHeaderValue );
  40. SupportAddHeader( szHeaders, szHeaderName, rgBuf );
  41. }
  42. static void SupportEndHeaders( /*[in/out]*/ MPC::string& szHeaders )
  43. {
  44. __ULT_FUNC_ENTRY("SupportEndHeaders");
  45. szHeaders.append( szNewLine );
  46. }
  47. //////////////////////////////////////////////////////////////////////
  48. //////////////////////////////////////////////////////////////////////
  49. //
  50. // Construction/Destruction
  51. //
  52. //////////////////////////////////////////////////////////////////////
  53. //////////////////////////////////////////////////////////////////////
  54. MPCHttpContext::MPCHttpContext() : m_hsInput (g_Heap),
  55. m_hsOutput(g_Heap)
  56. {
  57. __ULT_FUNC_ENTRY("MPCHttpContext::MPCHttpContext");
  58. m_pECB = NULL;
  59. m_mpcsServer = NULL;
  60. m_dwSkippedInput = 0;
  61. m_fRequestProcessed = FALSE;
  62. m_fKeepConnection = TRUE;
  63. m_fAsync = FALSE;
  64. m_FSMstate = FSM_REGISTER;
  65. m_IOstate = IO_IDLE;
  66. #ifdef DEBUG
  67. m_Debug_NO_RESPONSE_TO_OPEN = false;
  68. m_Debug_NO_RESPONSE_TO_WRITE = false;
  69. m_Debug_RESPONSE_TO_OPEN = false;
  70. m_Debug_RESPONSE_TO_OPEN_response = 0;
  71. m_Debug_RESPONSE_TO_OPEN_position = -1;
  72. m_Debug_RESPONSE_TO_OPEN_protocol = UPLOAD_LIBRARY_PROTOCOL_VERSION_SRV;
  73. m_Debug_RESPONSE_TO_WRITE = false;
  74. m_Debug_RESPONSE_TO_WRITE_response = 0;
  75. m_Debug_RESPONSE_TO_WRITE_position = -1;
  76. m_Debug_RESPONSE_TO_WRITE_protocol = UPLOAD_LIBRARY_PROTOCOL_VERSION_SRV;
  77. m_Debug_RANDOM_POINTER_ERROR = false;
  78. m_Debug_RANDOM_POINTER_ERROR_pos_low = 0;
  79. m_Debug_RANDOM_POINTER_ERROR_pos_high = -1;
  80. m_Debug_FIXED_POINTER_ERROR = false;
  81. m_Debug_FIXED_POINTER_ERROR_pos = 0;
  82. #endif
  83. }
  84. MPCHttpContext::~MPCHttpContext()
  85. {
  86. __ULT_FUNC_ENTRY("MPCHttpContext::~MPCHttpContext");
  87. if(m_mpcsServer) delete m_mpcsServer;
  88. if(m_fAsync && m_pECB)
  89. {
  90. //
  91. // Close session.
  92. //
  93. m_pECB->ServerSupportFunction( m_pECB->ConnID ,
  94. HSE_REQ_DONE_WITH_SESSION ,
  95. NULL ,
  96. NULL ,
  97. NULL );
  98. }
  99. }
  100. //////////////////////////////////////////////////////////////////////
  101. //////////////////////////////////////////////////////////////////////
  102. //
  103. // Callbacks
  104. //
  105. //////////////////////////////////////////////////////////////////////
  106. //////////////////////////////////////////////////////////////////////
  107. VOID WINAPI MPCHttpContext::IOCompletion( /*[in]*/ EXTENSION_CONTROL_BLOCK* pECB ,
  108. /*[in]*/ PVOID pContext ,
  109. /*[in]*/ DWORD cbIO ,
  110. /*[in]*/ DWORD dwError )
  111. {
  112. __ULT_FUNC_ENTRY("MPCHttpContext::IOCompletion");
  113. MPCHttpContext* ptr = NULL;
  114. try
  115. {
  116. ptr = reinterpret_cast<MPCHttpContext*>(pContext);
  117. ptr->m_pECB = pECB;
  118. if(dwError != ERROR_SUCCESS)
  119. {
  120. delete ptr; ptr = NULL;
  121. }
  122. else
  123. {
  124. switch( ptr->m_IOstate )
  125. {
  126. case IO_IDLE:
  127. break;
  128. case IO_READING:
  129. //
  130. // If the request has already been processed, simply count the number of bytes received.
  131. //
  132. if(ptr->m_fRequestProcessed)
  133. {
  134. ptr->m_dwSkippedInput += cbIO;
  135. }
  136. else
  137. {
  138. ptr->m_hsInput.write( ptr->m_rgBuffer, cbIO );
  139. }
  140. //
  141. // If this is the last request (cbIO==0) or the number of bytes skipped is equal to the number of missing bytes,
  142. // proceed to the next phase.
  143. //
  144. if(cbIO == 0 || ptr->m_dwSkippedInput == ptr->m_hsInput.GetAvailableForWrite())
  145. {
  146. ptr->m_IOstate = IO_IDLE;
  147. }
  148. else
  149. {
  150. if(ptr->Fsm_Process() == HSE_STATUS_ERROR)
  151. {
  152. delete ptr; ptr = NULL;
  153. }
  154. else
  155. {
  156. ptr->AsyncRead();
  157. }
  158. }
  159. break;
  160. case IO_WRITING:
  161. if(cbIO == 0 || ptr->m_hsOutput.IsEOR())
  162. {
  163. ptr->m_IOstate = IO_IDLE;
  164. }
  165. else
  166. {
  167. ptr->AsyncWrite();
  168. }
  169. break;
  170. }
  171. if(ptr->m_IOstate == IO_IDLE)
  172. {
  173. ptr->AdvanceFSM();
  174. }
  175. }
  176. }
  177. catch(...)
  178. {
  179. __ULT_TRACE_ERROR( UPLOADLIBID, "Upload Server raised an exception. Gracefully exiting..." );
  180. (void)g_NTEvents.LogEvent( EVENTLOG_ERROR_TYPE, PCHUL_ERR_EXCEPTION,
  181. L"" , // %1 = SERVER
  182. L"IOCompletion", // %2 = CLIENT
  183. NULL );
  184. if(ptr)
  185. {
  186. delete ptr; ptr = NULL;
  187. }
  188. }
  189. }
  190. //////////////////////////////////////////////////////////////////////
  191. //////////////////////////////////////////////////////////////////////
  192. //
  193. // Protected Methods.
  194. //
  195. //////////////////////////////////////////////////////////////////////
  196. //////////////////////////////////////////////////////////////////////
  197. DWORD MPCHttpContext::AsyncRead()
  198. {
  199. __ULT_FUNC_ENTRY("MPCHttpContext::AsyncRead");
  200. DWORD dwRes = HSE_STATUS_SUCCESS;
  201. DWORD dwSize = m_hsInput.GetAvailableForWrite();
  202. //
  203. // If not all the data has been read, ask for async I/O operation.
  204. //
  205. if(dwSize)
  206. {
  207. DWORD dwTmp = HSE_IO_ASYNC;
  208. m_fAsync = TRUE;
  209. m_IOstate = IO_READING;
  210. dwSize = min( dwSize, sizeof(m_rgBuffer) );
  211. if(!m_pECB->ServerSupportFunction( m_pECB->ConnID ,
  212. HSE_REQ_ASYNC_READ_CLIENT,
  213. m_rgBuffer ,
  214. &dwSize ,
  215. &dwTmp ))
  216. {
  217. dwRes = HSE_STATUS_ERROR; __ULT_FUNC_LEAVE;
  218. }
  219. else
  220. {
  221. dwRes = HSE_STATUS_PENDING; __ULT_FUNC_LEAVE;
  222. }
  223. }
  224. __ULT_FUNC_CLEANUP;
  225. __ULT_FUNC_EXIT(dwRes);
  226. }
  227. DWORD MPCHttpContext::AsyncWrite()
  228. {
  229. __ULT_FUNC_ENTRY("MPCHttpContext::AsyncWrite");
  230. DWORD dwRes = HSE_STATUS_SUCCESS;
  231. DWORD dwSize = m_hsOutput.GetAvailableForRead();
  232. //
  233. // If not all the data has been read, ask for async I/O operation.
  234. //
  235. if(dwSize)
  236. {
  237. m_fAsync = TRUE;
  238. m_IOstate = IO_WRITING;
  239. dwSize = min( dwSize, sizeof(m_rgBuffer) );
  240. if(FAILED(m_hsOutput.read( m_rgBuffer, dwSize )))
  241. {
  242. dwRes = HSE_STATUS_ERROR; __ULT_FUNC_LEAVE;
  243. }
  244. if(m_pECB->WriteClient( m_pECB->ConnID, m_rgBuffer, &dwSize, HSE_IO_ASYNC ) == FALSE)
  245. {
  246. dwRes = HSE_STATUS_ERROR; __ULT_FUNC_LEAVE;
  247. }
  248. dwRes = HSE_STATUS_PENDING; __ULT_FUNC_LEAVE;
  249. }
  250. __ULT_FUNC_CLEANUP;
  251. __ULT_FUNC_EXIT(dwRes);
  252. }
  253. DWORD MPCHttpContext::AdvanceFSM()
  254. {
  255. __ULT_FUNC_ENTRY("MPCHttpContext::AdvanceFSM");
  256. DWORD dwRes = HSE_STATUS_SUCCESS;
  257. bool fClean = false;
  258. while(dwRes == HSE_STATUS_SUCCESS)
  259. {
  260. switch(m_FSMstate)
  261. {
  262. case FSM_REGISTER: m_FSMstate = FSM_INPUT ; dwRes = Fsm_Register (); break; // Register IO callback.
  263. case FSM_INPUT : m_FSMstate = FSM_PROCESS; dwRes = Fsm_ReceiveInput(); break; // Read all the input.
  264. case FSM_PROCESS : m_FSMstate = FSM_OUTPUT ; dwRes = Fsm_Process (); break; // Process request.
  265. case FSM_OUTPUT : m_FSMstate = FSM_DELETE ; dwRes = Fsm_SendOutput (); break; // Send output.
  266. case FSM_DELETE : fClean = true; __ULT_FUNC_LEAVE; // Delete the request object.
  267. }
  268. }
  269. if(dwRes != HSE_STATUS_SUCCESS &&
  270. dwRes != HSE_STATUS_PENDING )
  271. {
  272. fClean = true;
  273. }
  274. __ULT_FUNC_CLEANUP;
  275. if(fClean) delete this;
  276. __ULT_FUNC_EXIT(dwRes);
  277. }
  278. DWORD MPCHttpContext::Fsm_Register()
  279. {
  280. __ULT_FUNC_ENTRY("MPCHttpContext::Fsm_Register");
  281. DWORD dwRes = HSE_STATUS_SUCCESS;
  282. if(!m_pECB->ServerSupportFunction( m_pECB->ConnID ,
  283. HSE_REQ_IO_COMPLETION,
  284. IOCompletion ,
  285. NULL ,
  286. (LPDWORD)this ))
  287. {
  288. dwRes = HSE_STATUS_ERROR; __ULT_FUNC_LEAVE;
  289. }
  290. __ULT_FUNC_CLEANUP;
  291. __ULT_FUNC_EXIT(dwRes);
  292. }
  293. DWORD MPCHttpContext::Fsm_ReceiveInput()
  294. {
  295. __ULT_FUNC_ENTRY("MPCHttpContext::Fsm_ReceiveInput");
  296. DWORD dwRes = HSE_STATUS_SUCCESS;
  297. //
  298. // Alloc a buffer large enough to hold the request data.
  299. //
  300. if(FAILED(m_hsInput.SetSize( m_pECB->cbTotalBytes ))) { dwRes = HSE_STATUS_ERROR; __ULT_FUNC_LEAVE; }
  301. if(FAILED(m_hsInput.write ( m_pECB->lpbData, m_pECB->cbAvailable ))) { dwRes = HSE_STATUS_ERROR; __ULT_FUNC_LEAVE; }
  302. dwRes = AsyncRead();
  303. __ULT_FUNC_CLEANUP;
  304. __ULT_FUNC_EXIT(dwRes);
  305. }
  306. DWORD MPCHttpContext::Fsm_Process()
  307. {
  308. __ULT_FUNC_ENTRY("MPCHttpContext::Fsm_Process");
  309. HRESULT hr;
  310. DWORD dwRes = HSE_STATUS_SUCCESS;
  311. if(m_fRequestProcessed == TRUE) __ULT_FUNC_LEAVE;
  312. m_hsInput .Rewind();
  313. m_hsOutput.Reset ();
  314. if(FAILED(hr = m_mpcsServer->Process( m_fKeepConnection )))
  315. {
  316. if(hr == E_PENDING)
  317. {
  318. dwRes = HSE_STATUS_PENDING; __ULT_FUNC_LEAVE;
  319. }
  320. m_fRequestProcessed = TRUE;
  321. dwRes = HSE_STATUS_ERROR; __ULT_FUNC_LEAVE;
  322. }
  323. m_fRequestProcessed = TRUE;
  324. __ULT_FUNC_CLEANUP;
  325. __ULT_FUNC_EXIT(dwRes);
  326. }
  327. DWORD MPCHttpContext::Fsm_SendOutput()
  328. {
  329. __ULT_FUNC_ENTRY("MPCHttpContext::Fsm_SendOutput");
  330. HSE_SEND_HEADER_EX_INFO headerInfo;
  331. MPC::string szHeaders;
  332. DWORD dwRes;
  333. //
  334. // Built headers.
  335. //
  336. SupportAddHeader( szHeaders, "Content-Length", m_hsOutput.GetSize() );
  337. SupportAddHeader( szHeaders, "Content-Type" , "application/uploadlibrary" );
  338. SupportEndHeaders( szHeaders );
  339. //
  340. // Populate HSE_SEND_HEADER_EX_INFO struct.
  341. //
  342. headerInfo.pszStatus = szStatus;
  343. headerInfo.cchStatus = strlen( szStatus );
  344. headerInfo.pszHeader = szHeaders.c_str();
  345. headerInfo.cchHeader = szHeaders.length();
  346. headerInfo.fKeepConn = TRUE;
  347. //
  348. // Send response.
  349. //
  350. if(!m_pECB->ServerSupportFunction( m_pECB->ConnID ,
  351. HSE_REQ_SEND_RESPONSE_HEADER_EX ,
  352. &headerInfo ,
  353. NULL ,
  354. NULL ))
  355. {
  356. dwRes = HSE_STATUS_ERROR; __ULT_FUNC_LEAVE;
  357. }
  358. //
  359. // Send data, if present.
  360. //
  361. dwRes = AsyncWrite();
  362. __ULT_FUNC_CLEANUP;
  363. __ULT_FUNC_EXIT(dwRes);
  364. }
  365. //////////////////////////////////////////////////////////////////////
  366. //////////////////////////////////////////////////////////////////////
  367. //
  368. // Methods.
  369. //
  370. //////////////////////////////////////////////////////////////////////
  371. //////////////////////////////////////////////////////////////////////
  372. DWORD MPCHttpContext::Init( /*[in]*/ LPEXTENSION_CONTROL_BLOCK pECB )
  373. {
  374. __ULT_FUNC_ENTRY("MPCHttpContext::Init");
  375. DWORD dwRes;
  376. MPC::wstring szURL;
  377. MPC::wstring szUser;
  378. m_pECB = pECB;
  379. if(FAILED(GetServerVariable( "URL", szURL )))
  380. {
  381. szURL = L"DEFAULT";
  382. }
  383. if(FAILED(GetServerVariable( "REMOTE_USER", szUser )))
  384. {
  385. szUser = L"";
  386. }
  387. #ifdef DEBUG
  388. if(pECB->lpszQueryString)
  389. {
  390. static MPC::string constNO_RESPONSE_TO_OPEN ( "NO_RESPONSE_TO_OPEN" );
  391. static MPC::string constNO_RESPONSE_TO_WRITE( "NO_RESPONSE_TO_WRITE" );
  392. static MPC::string constRESPONSE_TO_OPEN ( "RESPONSE_TO_OPEN" );
  393. static MPC::string constRESPONSE_TO_WRITE ( "RESPONSE_TO_WRITE" );
  394. static MPC::string constRANDOM_POINTER_ERROR( "RANDOM_POINTER_ERROR" );
  395. static MPC::string constFIXED_POINTER_ERROR ( "FIXED_POINTER_ERROR" );
  396. std::vector<MPC::string> vec;
  397. std::vector<MPC::string> vec2;
  398. std::vector<MPC::string> vec3;
  399. MPC::NocaseCompare cmp;
  400. int i;
  401. MPC::SplitAtDelimiter( vec, pECB->lpszQueryString, "&" );
  402. for(i=0; i<vec.size(); i++)
  403. {
  404. MPC::SplitAtDelimiter( vec2, vec[i].c_str(), "=" );
  405. switch( vec2.size() )
  406. {
  407. default:
  408. case 2 : MPC::SplitAtDelimiter( vec3, vec2[1].c_str(), "," );
  409. case 1 : break;
  410. case 0 : continue;
  411. }
  412. MPC::string& name = vec2[0];
  413. if(cmp( name, constNO_RESPONSE_TO_OPEN ))
  414. {
  415. m_Debug_NO_RESPONSE_TO_OPEN = true;
  416. }
  417. else if(cmp( name, constNO_RESPONSE_TO_WRITE ))
  418. {
  419. m_Debug_NO_RESPONSE_TO_WRITE = true;
  420. }
  421. else if(cmp( name, constRESPONSE_TO_OPEN ))
  422. {
  423. switch( vec3.size() )
  424. {
  425. case 3 : m_Debug_RESPONSE_TO_OPEN_protocol = atol( vec3[2].c_str() );
  426. case 2 : m_Debug_RESPONSE_TO_OPEN_position = atol( vec3[1].c_str() );
  427. case 1 : m_Debug_RESPONSE_TO_OPEN_response = atol( vec3[0].c_str() );
  428. m_Debug_RESPONSE_TO_OPEN = true;
  429. }
  430. }
  431. else if(cmp( name, constRESPONSE_TO_WRITE ))
  432. {
  433. switch( vec3.size() )
  434. {
  435. case 3 : m_Debug_RESPONSE_TO_WRITE_protocol = atol( vec3[2].c_str() );
  436. case 2 : m_Debug_RESPONSE_TO_WRITE_position = atol( vec3[1].c_str() );
  437. case 1 : m_Debug_RESPONSE_TO_WRITE_response = atol( vec3[0].c_str() );
  438. m_Debug_RESPONSE_TO_WRITE = true;
  439. }
  440. }
  441. else if(cmp( name, constRANDOM_POINTER_ERROR ))
  442. {
  443. switch( vec3.size() )
  444. {
  445. case 2: m_Debug_RANDOM_POINTER_ERROR_pos_high = atol( vec3[1].c_str() );
  446. m_Debug_RANDOM_POINTER_ERROR_pos_low = atol( vec3[0].c_str() );
  447. m_Debug_RANDOM_POINTER_ERROR = true;
  448. }
  449. }
  450. else if(cmp( name, constFIXED_POINTER_ERROR ))
  451. {
  452. switch( vec3.size() )
  453. {
  454. case 1 : m_Debug_FIXED_POINTER_ERROR_pos = atol( vec3[0].c_str() );
  455. m_Debug_FIXED_POINTER_ERROR = true;
  456. }
  457. }
  458. }
  459. }
  460. #endif
  461. m_mpcsServer = new MPCServer( this, szURL.c_str(), szUser.c_str() );
  462. if(m_mpcsServer == NULL)
  463. {
  464. dwRes = HSE_STATUS_ERROR; __ULT_FUNC_LEAVE;
  465. }
  466. dwRes = AdvanceFSM();
  467. __ULT_FUNC_CLEANUP;
  468. __ULT_FUNC_EXIT(dwRes);
  469. }
  470. HRESULT MPCHttpContext::GetServerVariable( /*[in]*/ LPCSTR szVar, /*[out]*/ MPC::wstring& szValue )
  471. {
  472. __ULT_FUNC_ENTRY("MPCHttpContext::GetServerVariable");
  473. USES_CONVERSION;
  474. HRESULT hr;
  475. DWORD dwRes;
  476. LPSTR szData = NULL;
  477. DWORD dwSize = 0;
  478. m_pECB->GetServerVariable( m_pECB->ConnID, (LPSTR)szVar, NULL, &dwSize );
  479. dwRes = ::GetLastError();
  480. if(dwRes != ERROR_INSUFFICIENT_BUFFER)
  481. {
  482. __MPC_SET_WIN32_ERROR_AND_EXIT(hr, dwRes);
  483. }
  484. __MPC_EXIT_IF_ALLOC_FAILS(hr, szData, new CHAR[dwSize+1]);
  485. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, m_pECB->GetServerVariable( m_pECB->ConnID, (LPSTR)szVar, szData, &dwSize ));
  486. szValue = A2W( szData );
  487. hr = S_OK;
  488. __ULT_FUNC_CLEANUP;
  489. if(szData) delete [] szData;
  490. __ULT_FUNC_EXIT(hr);
  491. }
  492. HRESULT MPCHttpContext::GetRequestSize( /*[out]*/ DWORD& dwCount )
  493. {
  494. __ULT_FUNC_ENTRY("MPCHttpContext::GetRequestSize");
  495. HRESULT hr;
  496. dwCount = m_hsInput.GetSize();
  497. hr = S_OK;
  498. __ULT_FUNC_EXIT(hr);
  499. }
  500. HRESULT MPCHttpContext::CheckDataAvailable( /*[in] */ DWORD dwCount ,
  501. /*[out]*/ bool& fAvailable )
  502. {
  503. __ULT_FUNC_ENTRY("MPCHttpContext::CheckDataAvailable");
  504. HRESULT hr;
  505. fAvailable = (m_hsInput.GetAvailableForRead() >= dwCount);
  506. hr = S_OK;
  507. __ULT_FUNC_EXIT(hr);
  508. }
  509. HRESULT MPCHttpContext::Read( /*[in]*/ void* pBuffer ,
  510. /*[in]*/ DWORD dwCount )
  511. {
  512. __ULT_FUNC_ENTRY("MPCHttpContext::Read");
  513. HRESULT hr = m_hsInput.read( pBuffer, dwCount );
  514. __ULT_FUNC_EXIT(hr);
  515. }
  516. HRESULT MPCHttpContext::Write( /*[in]*/ const void* pBuffer ,
  517. /*[in]*/ DWORD dwCount )
  518. {
  519. __ULT_FUNC_ENTRY("MPCHttpContext::Write");
  520. HRESULT hr = m_hsOutput.write( pBuffer, dwCount );
  521. __ULT_FUNC_EXIT(hr);
  522. }