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.

844 lines
25 KiB

  1. //-----------------------------------------------------------------------------
  2. // Copyright (C) Microsoft Corporation, 1997 - 1999
  3. //
  4. // rpcisapi.cxx
  5. //
  6. // IIS ISAPI extension part of the RPC proxy over HTTP.
  7. //
  8. // Exports:
  9. //
  10. // BOOL WINAPI GetExtensionVersion( HSE_VERSION_INFO *pVer )
  11. //
  12. // Returns the version of the spec that this server was built with.
  13. //
  14. // BOOL WINAPI HttpExtensionProc( EXTENSION_CONTROL_BLOCK *pECB )
  15. //
  16. // This function does all of the work.
  17. //
  18. //-----------------------------------------------------------------------------
  19. //-----------------------------------------------------------------------------
  20. // Includes:
  21. //-----------------------------------------------------------------------------
  22. #include <sysinc.h>
  23. #include <winsock2.h>
  24. #include <rpc.h>
  25. #include <rpcdcep.h>
  26. #include <rpcerrp.h>
  27. #include <httpfilt.h>
  28. #include <httpext.h>
  29. #include <mbstring.h>
  30. #include <ecblist.h>
  31. #include <filter.h>
  32. #include <olist.h>
  33. #include <server.h>
  34. #include <RpcIsapi.h>
  35. #include <registry.h>
  36. #include <StrSafe.h>
  37. //-----------------------------------------------------------------------------
  38. // Globals:
  39. //-----------------------------------------------------------------------------
  40. extern SERVER_INFO *g_pServerInfo;
  41. extern BOOL g_fIsIIS6;
  42. //-----------------------------------------------------------------------------
  43. // GetExtensionVersion()
  44. //
  45. //-----------------------------------------------------------------------------
  46. BOOL WINAPI GetExtensionVersion( HSE_VERSION_INFO *pVer )
  47. {
  48. HRESULT hr;
  49. pVer->dwExtensionVersion = MAKELONG( HSE_VERSION_MINOR, HSE_VERSION_MAJOR );
  50. ASSERT( sizeof(EXTENSION_DESCRIPTION) <= HSE_MAX_EXT_DLL_NAME_LEN );
  51. hr = StringCchCopyNA (pVer->lpszExtensionDesc,
  52. sizeof(pVer->lpszExtensionDesc),
  53. EXTENSION_DESCRIPTION,
  54. sizeof(EXTENSION_DESCRIPTION)
  55. );
  56. // this cannot fail as the strings are constant
  57. ASSERT(SUCCEEDED(hr));
  58. // if the filter data structures are not initialized yet, initialize them
  59. if (g_pServerInfo == NULL)
  60. {
  61. if (InitializeGlobalDataStructures(FALSE /* IsFromFilter */) == FALSE)
  62. {
  63. return FALSE;
  64. }
  65. }
  66. LogEventStartupSuccess (fIsIISInCompatibilityMode ? "5" : "6");
  67. return TRUE;
  68. }
  69. //-----------------------------------------------------------------------------
  70. // ReplyToClient()
  71. //
  72. //-----------------------------------------------------------------------------
  73. BOOL ReplyToClient( EXTENSION_CONTROL_BLOCK *pECB,
  74. const char *pBuffer,
  75. DWORD *pdwSize,
  76. DWORD *pdwStatus )
  77. {
  78. DWORD dwFlags = (HSE_IO_SYNC | HSE_IO_NODELAY);
  79. if (!pECB->WriteClient(pECB->ConnID, (char *)pBuffer, pdwSize, dwFlags))
  80. {
  81. *pdwStatus = GetLastError();
  82. #ifdef DBG_ERROR
  83. DbgPrint("ReplyToClient(): failed: %d\n",*pdwStatus);
  84. #endif
  85. return FALSE;
  86. }
  87. *pdwStatus = HSE_STATUS_SUCCESS;
  88. return TRUE;
  89. }
  90. DWORD
  91. ReplyToClientWithStatus (
  92. IN EXTENSION_CONTROL_BLOCK *pECB,
  93. IN RPC_STATUS RpcStatus
  94. )
  95. /*++
  96. Routine Description:
  97. Sends a reply to the client with the given error code as error.
  98. Arguments:
  99. pECB - extension control block
  100. RpcStatus - error code to be returned to client
  101. Return Value:
  102. Return value appropriate for return to IIS (i.e. HSE_STATUS_*)
  103. --*/
  104. {
  105. // size is the error string + 20 space for the error code
  106. char Buffer[sizeof(ServerErrorString) + 20];
  107. ULONG Size;
  108. ULONG Status;
  109. BOOL Result;
  110. HRESULT hr;
  111. hr = StringCbPrintfA (Buffer,
  112. sizeof(Buffer),
  113. ServerErrorString,
  114. RpcStatus
  115. );
  116. // this should never fail as the strings are constant
  117. ASSERT(SUCCEEDED(hr));
  118. Size = strlen(Buffer);
  119. Result = ReplyToClient (
  120. pECB,
  121. Buffer,
  122. &Size,
  123. &Status
  124. );
  125. return Status;
  126. }
  127. //-----------------------------------------------------------------------------
  128. // ParseQueryString()
  129. //
  130. // The query string is in the format:
  131. //
  132. // <Index_of_pOverlapped>
  133. //
  134. // Where the index is in ASCII Hex. The index is read and converted back
  135. // to a DWORD then used to locate the SERVER_OVERLAPPED. If its found,
  136. // return TRUE, else return FALSE.
  137. //
  138. // NOTE: "&" is the parameter separator if multiple parameters are passed.
  139. //-----------------------------------------------------------------------------
  140. BOOL ParseQueryString( unsigned char *pszQuery,
  141. SERVER_OVERLAPPED **ppOverlapped,
  142. DWORD *pdwStatus )
  143. {
  144. DWORD dwIndex = 0;
  145. pszQuery = AnsiHexToDWORD(pszQuery,&dwIndex,pdwStatus);
  146. if (!pszQuery)
  147. {
  148. return FALSE;
  149. }
  150. *ppOverlapped = GetOverlapped(dwIndex);
  151. if (*ppOverlapped == NULL)
  152. {
  153. return FALSE;
  154. }
  155. return TRUE;
  156. }
  157. BOOL
  158. ParseHTTP2QueryString (
  159. IN char *Query,
  160. IN OUT USHORT *ServerAddressBuffer,
  161. IN ULONG ServerAddressBufferLength,
  162. IN OUT USHORT *ServerPortBuffer,
  163. IN ULONG ServerPortBufferLength
  164. )
  165. /*++
  166. Routine Description:
  167. Parses an HTTP2 format query string into a server address and
  168. server port.
  169. Arguments:
  170. Query - the raw query string as received by the extension
  171. ServerAddressBuffer - the buffer where the server address will be
  172. stored. Undefined upon failure. Upon success it will be 0 terminated.
  173. ServerAddressBufferLengh - the length of ServerAddressBuffer in unicode chars.
  174. ServerPortBuffer - the buffer where the server port will be
  175. stored. Undefined upon failure. Upon success it will be 0 terminated.
  176. ServerPortBufferLengh - the length of ServerAddressBuffer in unicode chars.
  177. Return Value:
  178. non-zero for success and 0 for failure.
  179. --*/
  180. {
  181. char *ColonPosition;
  182. int CharactersConverted;
  183. ColonPosition = _mbschr(Query, ServerAddressAndPortSeparator);
  184. if (ColonPosition == NULL)
  185. return FALSE;
  186. CharactersConverted = MultiByteToWideChar (
  187. CP_ACP,
  188. MB_ERR_INVALID_CHARS,
  189. Query,
  190. ColonPosition - Query,
  191. ServerAddressBuffer,
  192. ServerAddressBufferLength
  193. );
  194. // did we convert successfully?
  195. if (CharactersConverted == 0)
  196. return FALSE;
  197. // do we have space for the terminating null?
  198. if (CharactersConverted + 1 > ServerAddressBufferLength)
  199. return FALSE;
  200. // null terminate the server address string. Since we gave the length
  201. // explicitly to MultiByteToWideChar it will not add null for us
  202. ServerAddressBuffer[CharactersConverted] = 0;
  203. CharactersConverted = MultiByteToWideChar (
  204. CP_ACP,
  205. MB_ERR_INVALID_CHARS,
  206. ColonPosition + 1,
  207. -1, // have MultiByteToWideChar calculate the length
  208. ServerPortBuffer,
  209. ServerPortBufferLength
  210. );
  211. // did we convert successfully?
  212. if (CharactersConverted == 0)
  213. return FALSE;
  214. // since we had MultiByteToWideChar calculate the string length,
  215. // it has null terminated the resulting string. We're all done.
  216. return TRUE;
  217. }
  218. BOOL
  219. GetRemoteUserString (
  220. IN EXTENSION_CONTROL_BLOCK *pECB,
  221. OUT char **FinalRemoteUser
  222. )
  223. /*++
  224. Routine Description:
  225. Gets the remote user name from IIS. If anonymous, an empty
  226. string will be returned.
  227. Arguments:
  228. pECB - the extension control block given to us by IIS.
  229. FinalRemoteUser - on output a pointer to the remote user name allocated by this
  230. routine. Muts be freed by caller using MemFree. Undefined on failure.
  231. Return Value:
  232. non-zero for success or 0 for failure/
  233. --*/
  234. {
  235. ULONG ActualServerVariableLength;
  236. char *TempRemoteUser;
  237. BOOL Result;
  238. ActualServerVariableLength = 0;
  239. TempRemoteUser = NULL;
  240. Result = pECB->GetServerVariable(pECB->ConnID,
  241. "REMOTE_USER",
  242. TempRemoteUser,
  243. &ActualServerVariableLength
  244. );
  245. ASSERT(Result == FALSE);
  246. if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
  247. {
  248. return FALSE;
  249. }
  250. TempRemoteUser = (char *)MemAllocate(ActualServerVariableLength + 1);
  251. if (TempRemoteUser == NULL)
  252. {
  253. return FALSE;
  254. }
  255. Result = pECB->GetServerVariable(pECB->ConnID,
  256. "REMOTE_USER",
  257. TempRemoteUser,
  258. &ActualServerVariableLength
  259. );
  260. if (Result == FALSE)
  261. {
  262. MemFree(TempRemoteUser);
  263. return FALSE;
  264. }
  265. *FinalRemoteUser = TempRemoteUser;
  266. return TRUE;
  267. }
  268. RPC_STATUS
  269. RPC_ENTRY I_RpcProxyIsValidMachine (
  270. IN char *pszMachine,
  271. IN char *pszDotMachine,
  272. IN ULONG dwPortNumber
  273. )
  274. {
  275. BOOL Result;
  276. Result = HttpProxyIsValidMachine(g_pServerInfo,
  277. pszMachine,
  278. pszDotMachine,
  279. dwPortNumber
  280. );
  281. if (Result)
  282. return RPC_S_OK;
  283. else
  284. return RPC_S_ACCESS_DENIED;
  285. }
  286. RPC_STATUS
  287. RPC_ENTRY I_RpcProxyGetClientAddress (
  288. IN void *Context,
  289. OUT char *Buffer,
  290. OUT ULONG *BufferLength
  291. )
  292. {
  293. BOOL Result;
  294. EXTENSION_CONTROL_BLOCK *pECB = (EXTENSION_CONTROL_BLOCK *) Context;
  295. Result = pECB->GetServerVariable(pECB->ConnID,
  296. "REMOTE_ADDR",
  297. Buffer,
  298. BufferLength
  299. );
  300. if (Result)
  301. return RPC_S_OK;
  302. else
  303. return GetLastError();
  304. }
  305. RPC_STATUS
  306. RPC_ENTRY I_RpcProxyGetConnectionTimeout (
  307. OUT ULONG *ConnectionTimeout
  308. )
  309. {
  310. *ConnectionTimeout = IISConnectionTimeout;
  311. return RPC_S_OK;
  312. }
  313. const I_RpcProxyCallbackInterface ProxyCallbackInterface =
  314. {
  315. I_RpcProxyIsValidMachine,
  316. I_RpcProxyGetClientAddress,
  317. I_RpcProxyGetConnectionTimeout
  318. };
  319. // uncomment this to see why connections are being rejected
  320. // by AllowAnonymous
  321. // #define DEBUG_ALLOW_ANONYMOUS
  322. //-----------------------------------------------------------------------------
  323. // HttpExtensionProc()
  324. //
  325. //-----------------------------------------------------------------------------
  326. DWORD WINAPI HttpExtensionProc( EXTENSION_CONTROL_BLOCK *pECB )
  327. {
  328. DWORD dwStatus;
  329. DWORD dwFlags;
  330. DWORD dwSize;
  331. SERVER_INFO *pServerInfo = g_pServerInfo;
  332. SERVER_OVERLAPPED *pOverlapped = NULL;
  333. HSE_SEND_HEADER_EX_INFO HeaderEx;
  334. CHAR *pLegacyVerb;
  335. RPC_STATUS RpcStatus;
  336. ULONG VerbLength;
  337. USHORT ServerAddress[MaxServerAddressLength];
  338. USHORT ServerPort[MaxServerPortLength];
  339. BOOL Result;
  340. ULONG ProxyType;
  341. BOOL ConnectionEstablishmentRequest;
  342. char EchoResponse[sizeof(EchoResponseHeader2) + 2]; // 2 is for
  343. // the size of the Echo RTS which goes instead of ContentLength
  344. int BytesWritten;
  345. ULONG BufferSize;
  346. const BYTE *EchoRTS;
  347. char ServerVariable[20];
  348. ULONG ActualServerVariableLength;
  349. ULONG NumContentLength;
  350. BOOL AnonymousConnection;
  351. char *RemoteUser = NULL;
  352. RPC_CHAR *ActualServerName;
  353. DWORD ExtensionProcResult;
  354. DWORD HttpStatusCode;
  355. char *DestinationEnd;
  356. HRESULT hr;
  357. if (g_pServerInfo->dwEnabled == FALSE)
  358. {
  359. dwSize = sizeof(STATUS_PROXY_DISABLED) - 1; // don't want to count trailing 0.
  360. ReplyToClient(pECB,STATUS_PROXY_DISABLED, &dwSize, &dwStatus);
  361. HttpStatusCode = STATUS_SERVER_ERROR;
  362. ExtensionProcResult = HSE_STATUS_ERROR;
  363. goto AbortAndExit;
  364. }
  365. if (g_pServerInfo->AllowAnonymous == FALSE)
  366. {
  367. // if we are not allowing anonymous connections, check that a secure
  368. // channel and authentication are used
  369. // assume anonymous for now
  370. AnonymousConnection = TRUE;
  371. ActualServerVariableLength = sizeof(ServerVariable);
  372. Result = pECB->GetServerVariable(pECB->ConnID,
  373. "HTTPS",
  374. ServerVariable,
  375. &ActualServerVariableLength
  376. );
  377. if (!Result)
  378. {
  379. HttpStatusCode = STATUS_SERVER_ERROR;
  380. ExtensionProcResult = HSE_STATUS_ERROR;
  381. goto AbortAndExit;
  382. }
  383. if (RpcpStringCompareIntA(ServerVariable, "on") == 0)
  384. {
  385. Result = GetRemoteUserString (pECB,
  386. &RemoteUser
  387. );
  388. if (!Result)
  389. {
  390. #ifdef DEBUG_ALLOW_ANONYMOUS
  391. DbgPrint("Connection rejected getting the remote user failed\n");
  392. #endif // #ifdef DEBUG_ALLOW_ANONYMOUS
  393. HttpStatusCode = STATUS_SERVER_ERROR;
  394. ExtensionProcResult = HSE_STATUS_ERROR;
  395. goto AbortAndExit;
  396. }
  397. // if non-empty string, it is authenticated
  398. if (RemoteUser[0] != 0)
  399. {
  400. AnonymousConnection = FALSE;
  401. #ifdef DEBUG_ALLOW_ANONYMOUS
  402. DbgPrint("Connection rejected because user could not be retrieved\n");
  403. #endif // #ifdef DEBUG_ALLOW_ANONYMOUS
  404. }
  405. else
  406. {
  407. #ifdef DEBUG_ALLOW_ANONYMOUS
  408. DbgPrint("Connection accepted for user %s\n", RemoteUser);
  409. #endif // #ifdef DEBUG_ALLOW_ANONYMOUS
  410. }
  411. }
  412. else
  413. {
  414. #ifdef DEBUG_ALLOW_ANONYMOUS
  415. DbgPrint("Connection rejected because it is not SSL\n");
  416. #endif // #ifdef DEBUG_ALLOW_ANONYMOUS
  417. }
  418. // if empty string, it is not authenticated
  419. if (AnonymousConnection)
  420. {
  421. dwSize = sizeof(AnonymousAccessNotAllowedString) - 1; // don't want to count trailing 0.
  422. ReplyToClient(pECB, AnonymousAccessNotAllowedString, &dwSize, &dwStatus);
  423. HttpStatusCode = STATUS_SERVER_ERROR;
  424. ExtensionProcResult = dwStatus;
  425. goto AbortAndExit;
  426. }
  427. }
  428. pECB->dwHttpStatusCode = STATUS_CONNECTION_OK;
  429. if (g_fIsIIS6)
  430. {
  431. pLegacyVerb = RPC_CONNECT;
  432. }
  433. else
  434. {
  435. pLegacyVerb = POST_STR;
  436. }
  437. VerbLength = strlen(pECB->lpszMethod);
  438. ConnectionEstablishmentRequest = FALSE;
  439. // get the verb and depending on that we will determine our course of
  440. // action
  441. if ((VerbLength == InChannelEstablishmentMethodLength)
  442. && (lstrcmpi(pECB->lpszMethod, InChannelEstablishmentMethod) == 0))
  443. {
  444. ConnectionEstablishmentRequest = TRUE;
  445. ProxyType = RPC_PROXY_CONNECTION_TYPE_IN_PROXY;
  446. }
  447. else if ((VerbLength == OutChannelEstablishmentMethodLength)
  448. && (lstrcmpi(pECB->lpszMethod, OutChannelEstablishmentMethod) == 0))
  449. {
  450. ConnectionEstablishmentRequest = TRUE;
  451. ProxyType = RPC_PROXY_CONNECTION_TYPE_OUT_PROXY;
  452. }
  453. if (ConnectionEstablishmentRequest)
  454. {
  455. // check if this is echo request or a true connection
  456. // establishment
  457. ActualServerVariableLength = sizeof(ServerVariable);
  458. Result = pECB->GetServerVariable(pECB->ConnID,
  459. "CONTENT_LENGTH",
  460. ServerVariable,
  461. &ActualServerVariableLength
  462. );
  463. if (!Result)
  464. {
  465. HttpStatusCode = STATUS_SERVER_ERROR;
  466. ExtensionProcResult = HSE_STATUS_ERROR;
  467. goto AbortAndExit;
  468. }
  469. NumContentLength = atol(ServerVariable);
  470. if (NumContentLength <= MaxEchoRequestSize)
  471. {
  472. // too small for a channel. Must be an echo
  473. EchoRTS = GetEchoRTS(&BufferSize);
  474. // Echo back the RTS packet + headers
  475. hr = StringCbPrintfExA(EchoResponse,
  476. sizeof(EchoResponse),
  477. &DestinationEnd, // ppszDestEnd
  478. NULL, // pcbRemaining
  479. 0, // Flags
  480. EchoResponseHeader2,
  481. BufferSize
  482. );
  483. if (FAILED(hr))
  484. {
  485. HttpStatusCode = STATUS_SERVER_ERROR;
  486. ExtensionProcResult = HSE_STATUS_ERROR;
  487. goto AbortAndExit;
  488. }
  489. // calculate the number of bytes written as the
  490. // distance from the end of the written buffer to the
  491. // beginning
  492. BytesWritten = DestinationEnd - EchoResponse;
  493. // send back headers
  494. dwSize = sizeof(HeaderEx);
  495. dwFlags = 0;
  496. memset(&HeaderEx, 0, dwSize);
  497. HeaderEx.fKeepConn = TRUE;
  498. HeaderEx.pszStatus = EchoResponseHeader1;
  499. HeaderEx.cchStatus = sizeof(EchoResponseHeader1);
  500. HeaderEx.pszHeader = EchoResponse;
  501. HeaderEx.cchHeader = BytesWritten;
  502. Result = pECB->ServerSupportFunction(pECB->ConnID,
  503. HSE_REQ_SEND_RESPONSE_HEADER_EX,
  504. &HeaderEx,
  505. &dwSize,
  506. &dwFlags);
  507. if (!Result)
  508. {
  509. HttpStatusCode = STATUS_SERVER_ERROR;
  510. ExtensionProcResult = HSE_STATUS_ERROR;
  511. goto AbortAndExit;
  512. }
  513. // send back Echo RTS
  514. dwSize = BufferSize;
  515. dwFlags = 0;
  516. Result = pECB->WriteClient(pECB->ConnID, (char *)EchoRTS, &dwSize, dwFlags);
  517. if (!Result)
  518. {
  519. HttpStatusCode = STATUS_SERVER_ERROR;
  520. ExtensionProcResult = HSE_STATUS_ERROR;
  521. goto AbortAndExit;
  522. }
  523. return HSE_STATUS_SUCCESS;
  524. }
  525. else
  526. {
  527. // a channel
  528. Result = ParseHTTP2QueryString (
  529. pECB->lpszQueryString,
  530. ServerAddress,
  531. sizeof(ServerAddress) / sizeof(ServerAddress[0]),
  532. ServerPort,
  533. sizeof(ServerPort) / sizeof(ServerPort[0])
  534. );
  535. if (Result == FALSE)
  536. {
  537. dwSize = sizeof(CannotParseQueryString) - 1; // don't want to count trailing 0.
  538. ReplyToClient(pECB, CannotParseQueryString, &dwSize, &dwStatus);
  539. HttpStatusCode = STATUS_SERVER_ERROR;
  540. ExtensionProcResult = dwStatus;
  541. goto AbortAndExit;
  542. }
  543. if (g_pServerInfo->RpcNewHttpProxyChannel)
  544. {
  545. // get the remote user (if not available yet) and call
  546. // the redirector dll
  547. if (RemoteUser == NULL)
  548. {
  549. Result = GetRemoteUserString (pECB,
  550. &RemoteUser
  551. );
  552. if (Result == FALSE)
  553. {
  554. HttpStatusCode = STATUS_SERVER_ERROR;
  555. ExtensionProcResult = HSE_STATUS_ERROR;
  556. goto AbortAndExit;
  557. }
  558. }
  559. ASSERT(g_pServerInfo->RpcHttpProxyFreeString);
  560. RpcStatus = g_pServerInfo->RpcNewHttpProxyChannel (
  561. ServerAddress,
  562. ServerPort,
  563. RemoteUser,
  564. &ActualServerName
  565. );
  566. if (RpcStatus != RPC_S_OK)
  567. {
  568. HttpStatusCode = STATUS_SERVER_ERROR;
  569. ExtensionProcResult = HSE_STATUS_ERROR;
  570. goto AbortAndExit;
  571. }
  572. }
  573. else
  574. ActualServerName = ServerAddress;
  575. RpcStatus = I_RpcProxyNewConnection (
  576. ProxyType,
  577. ActualServerName,
  578. ServerPort,
  579. pECB,
  580. (I_RpcProxyCallbackInterface *)&ProxyCallbackInterface
  581. );
  582. if (g_pServerInfo->RpcNewHttpProxyChannel
  583. && (ActualServerName != ServerAddress))
  584. {
  585. // get the remote user and call the redirector dll
  586. ASSERT(g_pServerInfo->RpcHttpProxyFreeString);
  587. g_pServerInfo->RpcHttpProxyFreeString(ActualServerName);
  588. }
  589. if (RpcStatus != RPC_S_OK)
  590. {
  591. ReplyToClientWithStatus(pECB, RpcStatus);
  592. HttpStatusCode = STATUS_CONNECTION_OK;
  593. ExtensionProcResult = HSE_STATUS_SUCCESS;
  594. goto AbortAndExit;
  595. }
  596. #if DBG
  597. DbgPrint("RPCPROXY: %d: Connection type %d to %S:%S\n", GetCurrentProcessId(),
  598. ProxyType, ServerAddress, ServerPort);
  599. #endif
  600. HttpStatusCode = STATUS_CONNECTION_OK;
  601. ExtensionProcResult = HSE_STATUS_PENDING;
  602. goto AbortAndExit;
  603. }
  604. }
  605. //
  606. // The RPC request must be a post (or RPC_CONNECT for 6.0):
  607. //
  608. if (_mbsicmp(pECB->lpszMethod,pLegacyVerb))
  609. {
  610. dwSize = sizeof(STATUS_MUST_BE_POST_STR) - 1; // don't want to count trailing 0.
  611. ReplyToClient(pECB,STATUS_MUST_BE_POST_STR,&dwSize,&dwStatus);
  612. HttpStatusCode = STATUS_CONNECTION_OK;
  613. ExtensionProcResult = HSE_STATUS_SUCCESS;
  614. goto AbortAndExit;
  615. }
  616. //
  617. // Make sure there is no data from the initial BIND in the ECB data buffer:
  618. //
  619. // ASSERT(pECB->cbTotalBytes == 0);
  620. //
  621. // Get the connect parameters:
  622. //
  623. if (!ParseQueryString(pECB->lpszQueryString,&pOverlapped,&dwStatus))
  624. {
  625. dwSize = sizeof(STATUS_POST_BAD_FORMAT_STR) - 1; // don't want to count trailing 0.
  626. ReplyToClient(pECB,STATUS_POST_BAD_FORMAT_STR,&dwSize,&dwStatus);
  627. HttpStatusCode = STATUS_CONNECTION_OK;
  628. ExtensionProcResult = HSE_STATUS_SUCCESS;
  629. goto AbortAndExit;
  630. }
  631. pOverlapped->pECB = pECB;
  632. //
  633. // Add the new ECB to the Active ECB List:
  634. //
  635. if (!AddToECBList(g_pServerInfo->pActiveECBList,pECB))
  636. {
  637. #ifdef DBG_ERROR
  638. DbgPrint("HttpExtensionProc(): AddToECBList() failed\n");
  639. #endif
  640. FreeOverlapped(pOverlapped);
  641. HttpStatusCode = STATUS_SERVER_ERROR;
  642. ExtensionProcResult = HSE_STATUS_ERROR;
  643. goto AbortAndExit;
  644. }
  645. //
  646. // Submit the first client async read:
  647. //
  648. if (!StartAsyncClientRead(pECB,pOverlapped->pConn,&dwStatus))
  649. {
  650. #ifdef DBG_ERROR
  651. DbgPrint("HttpExtensionProc(): StartAsyncClientRead() failed %d\n",dwStatus);
  652. #endif
  653. FreeOverlapped(pOverlapped);
  654. CleanupECB(pECB);
  655. HttpStatusCode = STATUS_SERVER_ERROR;
  656. ExtensionProcResult = HSE_STATUS_ERROR;
  657. goto AbortAndExit;
  658. }
  659. //
  660. // Post the first server read on the new socket:
  661. //
  662. IncrementECBRefCount(pServerInfo->pActiveECBList,pECB);
  663. if (!SubmitNewRead(pServerInfo,pOverlapped,&dwStatus))
  664. {
  665. #ifdef DBG_ERROR
  666. DbgPrint("HttpExtensionProc(): SubmitNewRead() failed %d\n",dwStatus);
  667. #endif
  668. FreeOverlapped(pOverlapped);
  669. CleanupECB(pECB);
  670. HttpStatusCode = STATUS_SERVER_ERROR;
  671. ExtensionProcResult = HSE_STATUS_ERROR;
  672. goto AbortAndExit;
  673. }
  674. //
  675. // Make sure the server receive thread is up and running:
  676. //
  677. if (!CheckStartReceiveThread(g_pServerInfo,&dwStatus))
  678. {
  679. #ifdef DBG_ERROR
  680. DbgPrint("HttpExtensionProc(): CheckStartReceiveThread() failed %d\n",dwStatus);
  681. #endif
  682. FreeOverlapped(pOverlapped);
  683. CleanupECB(pECB);
  684. HttpStatusCode = STATUS_SERVER_ERROR;
  685. ExtensionProcResult = HSE_STATUS_ERROR;
  686. goto AbortAndExit;
  687. }
  688. //
  689. // Send back connection Ok to client, and also set fKeepConn to FALSE.
  690. //
  691. dwSize = sizeof(HeaderEx);
  692. dwFlags = 0;
  693. memset(&HeaderEx,0,dwSize);
  694. HeaderEx.fKeepConn = FALSE;
  695. if (!pECB->ServerSupportFunction(pECB->ConnID,
  696. HSE_REQ_SEND_RESPONSE_HEADER_EX,
  697. &HeaderEx,
  698. &dwSize,
  699. &dwFlags))
  700. {
  701. #ifdef DBG_ERROR
  702. DbgPrint("HttpExtensionProc(): SSF(HSE_REQ_SEND_RESPONSE_HEADER_EX) failed %d\n",dwStatus);
  703. #endif
  704. FreeOverlapped(pOverlapped);
  705. CleanupECB(pECB);
  706. HttpStatusCode = STATUS_SERVER_ERROR;
  707. ExtensionProcResult = HSE_STATUS_ERROR;
  708. goto AbortAndExit;
  709. }
  710. HttpStatusCode = STATUS_SERVER_ERROR;
  711. ExtensionProcResult = HSE_STATUS_PENDING;
  712. // fall through
  713. AbortAndExit:
  714. if (RemoteUser)
  715. MemFree(RemoteUser);
  716. pECB->dwHttpStatusCode = HttpStatusCode;
  717. return ExtensionProcResult;
  718. }