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.

445 lines
12 KiB

  1. /*++
  2. Copyright (c) 1994 Microsoft Corporation
  3. Module Name:
  4. httpext.cxx
  5. Abstract:
  6. This module contains the Microsoft HTTP server extension module
  7. Author:
  8. John Ludeman (johnl) 09-Oct-1994
  9. Revision History:
  10. Murali R. Krishnan (MuraliK) 20-July-1996
  11. Rewrote to enable multiple Extension class forwarding
  12. --*/
  13. /************************************************************
  14. * Include Headers
  15. ************************************************************/
  16. #pragma warning( disable:4509 ) // nonstandard extension: SEH with destructors
  17. #include <w3p.hxx>
  18. #include "wamexec.hxx"
  19. #include "wamreq.hxx"
  20. #include "WamW3.hxx"
  21. #include "ExecDesc.hxx"
  22. /************************************************************
  23. * Prototypes
  24. ************************************************************/
  25. BOOL IsImageRunnableInProcOnly( const STR & strImagePath);
  26. /************************************************************
  27. * Functions
  28. ************************************************************/
  29. /*****************************************************************/
  30. BOOL
  31. HTTP_REQUEST::ProcessBGI(
  32. EXEC_DESCRIPTOR * pExec,
  33. BOOL * pfHandled,
  34. BOOL * pfFinished,
  35. BOOL fTrusted,
  36. BOOL fStarScript
  37. )
  38. /*++
  39. Description:
  40. This method handles the gateway request to server application.
  41. Arguments:
  42. pExec - Execution Descriptor block
  43. pfHandled - Indicates we handled this request
  44. pfFinished - Indicates no further processing is required
  45. fTrusted - Can this app be trusted to process things on a read only
  46. vroot
  47. Return Value:
  48. TRUE if successful, FALSE on error
  49. --*/
  50. {
  51. const STR * pstrBgiPath;
  52. DBG_ASSERT( *(pExec->_pGatewayType) == GATEWAY_BGI);
  53. // UNDONE: Need to decide what to do with this.
  54. if ( !pExec->IsRunningDAV() &&
  55. !VrootAccessCheck( pExec->_pMetaData, FILE_GENERIC_EXECUTE ) )
  56. {
  57. SetDeniedFlags( SF_DENIED_RESOURCE );
  58. return FALSE;
  59. }
  60. if ( pExec->_pstrGatewayImage->IsEmpty()) {
  61. DBG_ASSERT(pExec->_pAppPathURIBlob == NULL);
  62. // obtain the physical path now
  63. //
  64. // Retrieve AppPathURIBlob for other ISAPI DLLs.
  65. // See below for more detail comment about AppPathURIBlob.
  66. //
  67. if ( !LookupVirtualRoot( pExec->_pstrPhysicalPath,
  68. pExec->_pstrURL->QueryStr(),
  69. pExec->_pstrURL->QueryCCH(),
  70. NULL,
  71. NULL,
  72. NULL,
  73. NULL,
  74. FALSE,
  75. NULL,
  76. &(pExec->_pAppPathURIBlob) ))
  77. {
  78. return FALSE;
  79. }
  80. pstrBgiPath = pExec->_pstrPhysicalPath;
  81. }
  82. else
  83. {
  84. //
  85. // Retrieve AppPathURIBlob for each Exec descriptor, such that
  86. // a .STM file and a .ASP file in the same application will have
  87. // two different AppPathURIBlob. The AppPathURIBlob will solve the
  88. // problem that .STM file is loaded under default application(inproc)
  89. // even the request's URL points to an out-proc application.
  90. //
  91. if ( pExec->_pAppPathURIBlob == NULL )
  92. {
  93. if ( !CacheUri( QueryW3Instance(),
  94. &(pExec->_pAppPathURIBlob),
  95. pExec->_pMetaData,
  96. pExec->_pstrURL->QueryStr(),
  97. pExec->_pstrURL->QueryCCH(),
  98. pExec->_pstrPhysicalPath,
  99. pExec->_pstrUnmappedPhysicalPath ) )
  100. {
  101. return FALSE;
  102. }
  103. //
  104. // If the AppPathURIBlob contains a valid MetaData, we need to AddRef it.
  105. // Because this MetaData object is only referenced once if HTTP_REQUEST.pURIInfo
  106. // contains that. AppPathURIBlob is another URIInfo that points to the MetaData
  107. // object, therefore, We need to AddRef the Metadata object here.
  108. // Exec.Reset always CheckIn the _pAppPathURIBlob(), and FreeMetaData reference in
  109. // the Reset.
  110. //
  111. if (pExec->_pAppPathURIBlob->pMetaData)
  112. {
  113. TsReferenceMetaData(pExec->_pAppPathURIBlob->pMetaData->QueryCacheInfo());
  114. }
  115. }
  116. pstrBgiPath = pExec->_pstrGatewayImage;
  117. }
  118. if ( !fStarScript &&
  119. !pExec->IsRunningDAV() &&
  120. !(fTrusted && IS_ACCESS_ALLOWED2(pExec, SCRIPT)) &&
  121. !IS_ACCESS_ALLOWED2(pExec, EXECUTE) )
  122. {
  123. *pfHandled = TRUE;
  124. if ( pExec->IsChild() )
  125. {
  126. SetLastError( ERROR_INVALID_FLAGS );
  127. return FALSE;
  128. }
  129. else
  130. {
  131. Disconnect( HT_FORBIDDEN, IDS_EXECUTE_ACCESS_DENIED, FALSE, pfFinished );
  132. return TRUE;
  133. }
  134. }
  135. return ( DoWamRequest( pExec, *pstrBgiPath, pfHandled, pfFinished));
  136. } // HTTP_REQUEST::ProcessBGI()
  137. BOOL
  138. HTTP_REQUEST::DoWamRequest(
  139. EXEC_DESCRIPTOR * pExec,
  140. const STR & strPath,
  141. BOOL * pfHandled,
  142. BOOL * pfFinished
  143. )
  144. /*++
  145. Routine Description:
  146. This method handles a gateway request to a server extension DLL
  147. Arguments:
  148. pExec - Execution descriptor block
  149. strPath - Fully qualified path to DLL
  150. pfHandled - Indicates we handled this request
  151. pfFinished - Indicates no further processing is required
  152. Return Value:
  153. TRUE if successful, FALSE on error
  154. --*/
  155. {
  156. BOOL fReturn = TRUE;
  157. DBG_ASSERT( *(pExec->_pGatewayType) == GATEWAY_BGI);
  158. //
  159. // 1. Have we already checked if this current request for a legacy
  160. // ISAPI that has to be routed to inproc only AppRoot instance?
  161. //
  162. // _pAppPathURIBlob is associated with each Exec descriptor. Therefore,
  163. // We can use this URIBlob to distiguish a .STM file's application path(always runs
  164. // in proc) or a .ASP file's application path (could be out-proc application)
  165. // This also solves the problem that "#EXEC ISA=/OUTAPP/hello.asp" case in a .STM
  166. // file.(Child Execution).
  167. // The Child execution will get a new EXEC object.
  168. //
  169. if ( !pExec->_pAppPathURIBlob->bUseAppPathChecked) {
  170. //
  171. // This is the first time we are checking the ISAPI application root
  172. // path with respect to current image path
  173. //
  174. BOOL fInProcOnly = IsImageRunnableInProcOnly( strPath);
  175. //
  176. // set the state of the inproc-only vs. anything in the URIInfo record
  177. // so that other callers can use this as well
  178. // UNDONE: For K2/beta3, combine this with the script map lookup
  179. //
  180. InterlockedExchange((LPLONG)&(pExec->_pAppPathURIBlob->bInProcOnly), (LONG)fInProcOnly);
  181. InterlockedExchange((LPLONG)&(pExec->_pAppPathURIBlob->bUseAppPathChecked),(LONG)TRUE);
  182. DBG_ASSERT(pExec->_pAppPathURIBlob->bUseAppPathChecked);
  183. }
  184. g_pWamDictator->Reference();
  185. fReturn = BoolFromHresult( g_pWamDictator->ProcessWamRequest( this, pExec, &strPath, pfHandled, pfFinished ) );
  186. g_pWamDictator->Dereference();
  187. return fReturn;
  188. } // HTTP_REQUEST::DoWamRequest()
  189. BOOL
  190. HTTP_REQUEST::ProcessAsyncGatewayIO(VOID)
  191. /*++
  192. Description:
  193. Calls the ISA (gateway) async i/o completion function
  194. (via this request's wamreq)
  195. Arguments:
  196. None
  197. Returns:
  198. TRUE on success
  199. FALSE on failure
  200. --*/
  201. {
  202. g_pWamDictator->Reference();
  203. DBG_ASSERT( QueryState() == HTR_GATEWAY_ASYNC_IO );
  204. DBG_ASSERT( _pWamRequest );
  205. BOOL fRet = TRUE;
  206. HRESULT hr = NOERROR;
  207. //
  208. // Set state to doverb, since we have completed async i/o. Preserve the error codes.
  209. //
  210. SetState( HTR_DOVERB, QueryLogHttpResponse(), QueryLogWinError());
  211. //
  212. // Ref the wamreq - other threads may access it while we
  213. // wait for ISA async i/o completion function to return
  214. //
  215. //
  216. // Guard against ISAs which call HSE_REQ_DONE_WITH_SESSION or return
  217. // in the mainline (with something other than HSE_STATUS_PENDING) before
  218. // async completion. When this happens the _pWamRequest may be NULLed
  219. // from underneath us.
  220. //
  221. __try
  222. {
  223. _pWamRequest->AddRef();
  224. }
  225. __except( EXCEPTION_EXECUTE_HANDLER )
  226. {
  227. hr = E_FAIL;
  228. }
  229. if ( FAILED(hr) )
  230. {
  231. g_pWamDictator->Dereference();
  232. return FALSE;
  233. }
  234. hr = _pWamRequest->ProcessAsyncGatewayIO( QueryIOStatus(), QueryBytesWritten() );
  235. if( FAILED(hr) ) {
  236. //
  237. // If i/o completion callback failed, log it
  238. //
  239. const CHAR * apsz[1];
  240. // UNDONE is this valid? used to be ...
  241. //apsz[0] = _SeInfo.ecb.lpszQueryString;
  242. apsz[0] = _Exec._pstrURLParams->QueryStr();
  243. DBGPRINTF(( DBG_CONTEXT,
  244. "\n\n[ProcessAsyncGatewayIO] Exception occurred "
  245. " in calling the callback for %s\n",
  246. apsz[0]));
  247. g_pInetSvc->LogEvent( W3_EVENT_EXTENSION_EXCEPTION,
  248. 1,
  249. apsz,
  250. 0 );
  251. fRet = FALSE;
  252. }
  253. //
  254. // Deref the wamreq
  255. //
  256. _pWamRequest->Release();
  257. g_pWamDictator->Dereference();
  258. return fRet;
  259. } // ProcessAsyncGatewayIO()
  260. VOID HTTP_REQUEST::CancelAsyncGatewayIO(VOID)
  261. /*++
  262. Description:
  263. Cancels pending ISA (gateway) async i/o operation
  264. Arguments:
  265. None
  266. Returns:
  267. Nothing
  268. --*/
  269. {
  270. DBG_ASSERT( QueryState() == HTR_GATEWAY_ASYNC_IO );
  271. DBG_ASSERT( _pWamRequest );
  272. SetState( HTR_DONE );
  273. if( _pWamRequest ) {
  274. _pWamRequest->Release();
  275. }
  276. } // CancelAsyncGatewayIO()
  277. BOOL
  278. IsImageRunnableInProcOnly( const STR & strImagePath)
  279. /*++
  280. Description:
  281. This function takes the image path supplied and checks to see if this
  282. matches any present in the InProc-only ISAPI's list. If it does, then
  283. this function returns TRUE else FALSE.
  284. This is used to check for and support legacy ISAPI applications that
  285. can only run inproc
  286. Arguments:
  287. strImagePath - STR object containing the fully qualified image path
  288. (physical path is present)
  289. Returns:
  290. TRUE if this ISAPI Application can only be run inproc
  291. (i.e., image path is present in the InProc-only list)
  292. FALSE, otherwise
  293. --*/
  294. {
  295. LPCSTR pszImagePathStart = strImagePath.QueryStr();
  296. LPCSTR pszDllNameOnly; // points to just the DLL name after last '\\'
  297. IF_DEBUG( BGI )
  298. {
  299. DBGPRINTF(( DBG_CONTEXT,
  300. " IsRunnableInProcOnly([%d] %s\n",
  301. strImagePath.QueryCCH(),
  302. strImagePath.QueryStr()
  303. ));
  304. }
  305. W3_IIS_SERVICE * pSvc = (W3_IIS_SERVICE *) g_pInetSvc;
  306. // Check the full path
  307. if (pSvc->IsInProcISAPI(pszImagePathStart))
  308. return TRUE;
  309. //
  310. // Get the DLL name alone for relative path checks.
  311. // DLL name appears after the last path-separator '\\'
  312. // NYI: How to optimize this relative path check?
  313. //
  314. pszDllNameOnly = strrchr( pszImagePathStart, '\\');
  315. if ( pszDllNameOnly == NULL) {
  316. //
  317. // There were no path-separator '\\' found in the image name
  318. //
  319. //
  320. // Since we get absolute path for image from earlier stages
  321. // This should not happen!
  322. //
  323. DBG_ASSERT( FALSE);
  324. // reset to the start of the name and continue
  325. pszDllNameOnly = pszImagePathStart;
  326. } else {
  327. DBG_ASSERT( *pszDllNameOnly == '\\'); // just paranoid
  328. //
  329. // Skip past the path separator for comparisons to work correctly
  330. //
  331. pszDllNameOnly++;
  332. }
  333. return pSvc->IsInProcISAPI(pszDllNameOnly);
  334. } // IsImageRunnableInProcOnly()