Source code of Windows XP (NT5)
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.

254 lines
7.1 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. //-----------------------------------------------------------------------------
  35. // Globals:
  36. //-----------------------------------------------------------------------------
  37. extern SERVER_INFO *g_pServerInfo;
  38. extern BOOL g_fIsIIS6;
  39. //-----------------------------------------------------------------------------
  40. // GetExtensionVersion()
  41. //
  42. //-----------------------------------------------------------------------------
  43. BOOL WINAPI GetExtensionVersion( HSE_VERSION_INFO *pVer )
  44. {
  45. pVer->dwExtensionVersion = MAKELONG( HSE_VERSION_MINOR, HSE_VERSION_MAJOR );
  46. ASSERT( sizeof(EXTENSION_DESCRIPTION) <= HSE_MAX_EXT_DLL_NAME_LEN );
  47. lstrcpy( pVer->lpszExtensionDesc, EXTENSION_DESCRIPTION );
  48. return TRUE;
  49. }
  50. //-----------------------------------------------------------------------------
  51. // ReplyToClient()
  52. //
  53. //-----------------------------------------------------------------------------
  54. BOOL ReplyToClient( EXTENSION_CONTROL_BLOCK *pECB,
  55. char *pBuffer,
  56. DWORD *pdwSize,
  57. DWORD *pdwStatus )
  58. {
  59. DWORD dwFlags = (HSE_IO_SYNC | HSE_IO_NODELAY);
  60. if (!pECB->WriteClient(pECB->ConnID,pBuffer,pdwSize,dwFlags))
  61. {
  62. *pdwStatus = GetLastError();
  63. #ifdef DBG_ERROR
  64. DbgPrint("ReplyToClient(): failed: %d\n",*pdwStatus);
  65. #endif
  66. return FALSE;
  67. }
  68. *pdwStatus = HSE_STATUS_SUCCESS;
  69. return TRUE;
  70. }
  71. //-----------------------------------------------------------------------------
  72. // ParseQueryString()
  73. //
  74. // The query string is in the format:
  75. //
  76. // <Index_of_pOverlapped>
  77. //
  78. // Where the index is in ASCII Hex. The index is read and converted back
  79. // to a DWORD then used to locate the SERVER_OVERLAPPED. If its found,
  80. // return TRUE, else return FALSE.
  81. //
  82. // NOTE: "&" is the parameter separator if multiple parameters are passed.
  83. //-----------------------------------------------------------------------------
  84. BOOL ParseQueryString( unsigned char *pszQuery,
  85. SERVER_OVERLAPPED **ppOverlapped,
  86. DWORD *pdwStatus )
  87. {
  88. DWORD dwIndex = 0;
  89. pszQuery = AnsiHexToDWORD(pszQuery,&dwIndex,pdwStatus);
  90. if (!pszQuery)
  91. {
  92. return FALSE;
  93. }
  94. *ppOverlapped = GetOverlapped(dwIndex);
  95. if (*ppOverlapped == NULL)
  96. {
  97. return FALSE;
  98. }
  99. return TRUE;
  100. }
  101. //-----------------------------------------------------------------------------
  102. // HttpExtensionProc()
  103. //
  104. //-----------------------------------------------------------------------------
  105. DWORD WINAPI HttpExtensionProc( EXTENSION_CONTROL_BLOCK *pECB )
  106. {
  107. DWORD dwStatus;
  108. DWORD dwFlags;
  109. DWORD dwSize;
  110. SERVER_INFO *pServerInfo = g_pServerInfo;
  111. SERVER_OVERLAPPED *pOverlapped = NULL;
  112. HSE_SEND_HEADER_EX_INFO HeaderEx;
  113. CHAR *pVerb;
  114. pECB->dwHttpStatusCode = STATUS_CONNECTION_OK;
  115. if (g_fIsIIS6)
  116. {
  117. pVerb = RPC_CONNECT;
  118. }
  119. else
  120. {
  121. pVerb = POST_STR;
  122. }
  123. //
  124. // The RPC request must be a post (or RPC_CONNECT for 6.0):
  125. //
  126. if (_mbsicmp(pECB->lpszMethod,pVerb))
  127. {
  128. dwSize = sizeof(STATUS_MUST_BE_POST_STR) - 1; // don't want to count trailing 0.
  129. ReplyToClient(pECB,STATUS_MUST_BE_POST_STR,&dwSize,&dwStatus);
  130. return HSE_STATUS_SUCCESS;
  131. }
  132. //
  133. // Make sure there is no data from the initial BIND in the ECB data buffer:
  134. //
  135. // ASSERT(pECB->cbTotalBytes == 0);
  136. //
  137. // Get the connect parameters:
  138. //
  139. if (!ParseQueryString(pECB->lpszQueryString,&pOverlapped,&dwStatus))
  140. {
  141. dwSize = sizeof(STATUS_POST_BAD_FORMAT_STR) - 1; // don't want to count trailing 0.
  142. ReplyToClient(pECB,STATUS_POST_BAD_FORMAT_STR,&dwSize,&dwStatus);
  143. return HSE_STATUS_SUCCESS;
  144. }
  145. pOverlapped->pECB = pECB;
  146. //
  147. // Add the new ECB to the Active ECB List:
  148. //
  149. if (!AddToECBList(g_pServerInfo->pActiveECBList,pECB))
  150. {
  151. #ifdef DBG_ERROR
  152. DbgPrint("HttpExtensionProc(): AddToECBList() failed\n");
  153. #endif
  154. FreeOverlapped(pOverlapped);
  155. pECB->dwHttpStatusCode = STATUS_SERVER_ERROR;
  156. return HSE_STATUS_ERROR;
  157. }
  158. //
  159. // Submit the first client async read:
  160. //
  161. if (!StartAsyncClientRead(pECB,pOverlapped->pConn,&dwStatus))
  162. {
  163. #ifdef DBG_ERROR
  164. DbgPrint("HttpExtensionProc(): StartAsyncClientRead() failed %d\n",dwStatus);
  165. #endif
  166. FreeOverlapped(pOverlapped);
  167. CleanupECB(pECB);
  168. pECB->dwHttpStatusCode = STATUS_SERVER_ERROR;
  169. return HSE_STATUS_ERROR;
  170. }
  171. //
  172. // Post the first server read on the new socket:
  173. //
  174. IncrementECBRefCount(pServerInfo->pActiveECBList,pECB);
  175. if (!SubmitNewRead(pServerInfo,pOverlapped,&dwStatus))
  176. {
  177. #ifdef DBG_ERROR
  178. DbgPrint("HttpExtensionProc(): SubmitNewRead() failed %d\n",dwStatus);
  179. #endif
  180. FreeOverlapped(pOverlapped);
  181. CleanupECB(pECB);
  182. pECB->dwHttpStatusCode = STATUS_SERVER_ERROR;
  183. return HSE_STATUS_ERROR;
  184. }
  185. //
  186. // Make sure the server receive thread is up and running:
  187. //
  188. if (!CheckStartReceiveThread(g_pServerInfo,&dwStatus))
  189. {
  190. #ifdef DBG_ERROR
  191. DbgPrint("HttpExtensionProc(): CheckStartReceiveThread() failed %d\n",dwStatus);
  192. #endif
  193. FreeOverlapped(pOverlapped);
  194. CleanupECB(pECB);
  195. pECB->dwHttpStatusCode = STATUS_SERVER_ERROR;
  196. return HSE_STATUS_ERROR;
  197. }
  198. //
  199. // Send back connection Ok to client, and also set fKeepConn to FALSE.
  200. //
  201. dwSize = sizeof(HeaderEx);
  202. dwFlags = 0;
  203. memset(&HeaderEx,0,dwSize);
  204. HeaderEx.fKeepConn = FALSE;
  205. if (!pECB->ServerSupportFunction(pECB->ConnID,
  206. HSE_REQ_SEND_RESPONSE_HEADER_EX,
  207. &HeaderEx,
  208. &dwSize,
  209. &dwFlags))
  210. {
  211. #ifdef DBG_ERROR
  212. DbgPrint("HttpExtensionProc(): SSF(HSE_REQ_SEND_RESPONSE_HEADER_EX) failed %d\n",dwStatus);
  213. #endif
  214. FreeOverlapped(pOverlapped);
  215. CleanupECB(pECB);
  216. pECB->dwHttpStatusCode = STATUS_SERVER_ERROR;
  217. return HSE_STATUS_ERROR;
  218. }
  219. return HSE_STATUS_PENDING;
  220. }