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.

2228 lines
58 KiB

  1. /*++
  2. Copyright (c) 1995-1996 Microsoft Corporation
  3. Module Name :
  4. isplocal.cxx
  5. Abstract:
  6. This module declares the functions for Local ISAPI handler
  7. as well as the global table of all ISAPI applications loaded
  8. Author:
  9. Murali R. Krishnan ( MuraliK ) 17-July-1996
  10. Environment:
  11. User Mode - Win32
  12. Project:
  13. W3 Services DLL
  14. --*/
  15. /************************************************************
  16. * Include Headers
  17. ************************************************************/
  18. # include <isapip.hxx>
  19. # include <irtlmisc.h>
  20. # include "isapidll.hxx"
  21. # include "setable.hxx"
  22. # include "gip.h"
  23. # include "iwr.h"
  24. # include "WamW3.hxx"
  25. /************************************************************
  26. * Global Data
  27. ************************************************************/
  28. //
  29. // Generic mapping for Application access check
  30. //
  31. GENERIC_MAPPING sg_FileGenericMapping =
  32. {
  33. FILE_GENERIC_READ,
  34. FILE_GENERIC_WRITE,
  35. FILE_GENERIC_EXECUTE,
  36. FILE_ALL_ACCESS
  37. };
  38. /************************************************************
  39. * Functions
  40. ************************************************************/
  41. BOOL
  42. CallChildCompletionProc(
  43. IN WAM_EXEC_INFO * pWamExecInfo,
  44. DWORD dwBytes,
  45. DWORD dwLastError
  46. )
  47. /*++
  48. Routine Description:
  49. Call the async IO completion routine of the child ISA.
  50. Arguments:
  51. pWamExecInfo - WAM_EXEC_INFO of the child
  52. dwBytes - Bytes for read/write
  53. dwLastError - Last error (used for status of IO request)
  54. Return Value:
  55. TRUE on success, FALSE on failure
  56. --*/
  57. {
  58. BOOL fRet = TRUE;
  59. DBG_ASSERT( pWamExecInfo->_AsyncIoInfo._pfnHseIO != NULL);
  60. __try
  61. {
  62. (*pWamExecInfo->_AsyncIoInfo._pfnHseIO)( &(pWamExecInfo->ecb),
  63. pWamExecInfo->_AsyncIoInfo._pvHseIOContext,
  64. dwBytes,
  65. dwLastError );
  66. }
  67. __except ( g_fEnableTryExcept ?
  68. WAMExceptionFilter( GetExceptionInformation(),
  69. WAM_EVENT_EXTENSION_EXCEPTION,
  70. pWamExecInfo ) :
  71. EXCEPTION_CONTINUE_SEARCH )
  72. {
  73. fRet = FALSE;
  74. }
  75. return fRet;
  76. }
  77. /**************************************************
  78. * Member functions of HSE_APPDLL
  79. **************************************************/
  80. /* class static */
  81. PHSE
  82. HSE_APPDLL::LoadModule( IN const char * pchModuleName,
  83. IN HANDLE hImpersonation,
  84. IN BOOL fCache )
  85. {
  86. PFN_HTTPEXTENSIONPROC pfnSEProc;
  87. HMODULE hMod;
  88. PFN_GETEXTENSIONVERSION pfnGetExtVer;
  89. PFN_TERMINATEEXTENSION pfnTerminate;
  90. HSE_VERSION_INFO ExtensionVersion;
  91. HSE_APPDLL * pExtension = NULL;
  92. hMod = LoadLibraryEx( pchModuleName,
  93. NULL,
  94. LOAD_WITH_ALTERED_SEARCH_PATH );
  95. if ( hMod == NULL ) {
  96. DBGPRINTF(( DBG_CONTEXT,
  97. "[SEGetEntryPoint] LoadLibrary %s failed with error %d\n",
  98. pchModuleName, GetLastError()));
  99. return NULL;
  100. }
  101. //
  102. // check machine type from header
  103. //
  104. LPBYTE pImg = (LPBYTE)hMod;
  105. //
  106. // skip possible DOS header
  107. //
  108. if ( ((IMAGE_DOS_HEADER*)pImg)->e_magic == IMAGE_DOS_SIGNATURE )
  109. {
  110. pImg += ((IMAGE_DOS_HEADER*)pImg)->e_lfanew;
  111. }
  112. //
  113. // test only if NT header detected
  114. //
  115. if ( !TsIsWindows95() ) {
  116. if ( *(DWORD*)pImg == IMAGE_NT_SIGNATURE
  117. && ( ((IMAGE_FILE_HEADER*)(pImg+sizeof(DWORD)))->Machine
  118. < USER_SHARED_DATA->ImageNumberLow
  119. || ((IMAGE_FILE_HEADER*)(pImg+sizeof(DWORD)))->Machine
  120. > USER_SHARED_DATA->ImageNumberHigh ) )
  121. {
  122. DBGPRINTF(( DBG_CONTEXT,
  123. "[SEGetEntryPoint] LoadLibrary loaded bad "
  124. " format exe type %d, valid range %d-%d\n",
  125. ((IMAGE_FILE_HEADER*)(pImg+sizeof(DWORD)))->Machine,
  126. USER_SHARED_DATA->ImageNumberLow,
  127. USER_SHARED_DATA->ImageNumberHigh
  128. ));
  129. SetLastError( ERROR_BAD_EXE_FORMAT );
  130. FreeLibrary( hMod );
  131. return NULL;
  132. }
  133. }
  134. //
  135. // Retrieve the entry points
  136. //
  137. pfnSEProc = (PFN_HTTPEXTENSIONPROC) GetProcAddress(
  138. hMod,
  139. SE_DEFAULT_ENTRY );
  140. pfnGetExtVer = (PFN_GETEXTENSIONVERSION) GetProcAddress(
  141. hMod,
  142. SE_INIT_ENTRY );
  143. //
  144. // Note that there is no harm done
  145. // even if ISAPI is old and does not have TerminateExtension
  146. //
  147. pfnTerminate =
  148. (PFN_TERMINATEEXTENSION) GetProcAddress( hMod, SE_TERM_ENTRY );
  149. //
  150. // Revert our security context, so that GetExtensionVersion()
  151. // can be called in the system context
  152. //
  153. RevertToSelf();
  154. if ( !pfnSEProc ||
  155. !pfnGetExtVer ||
  156. !pfnGetExtVer( &ExtensionVersion )) {
  157. DBGPRINTF(( DBG_CONTEXT,
  158. "SE_TABLE::LoadModule() GetExtVer failed, Error %d\n",
  159. GetLastError() ));
  160. FreeLibrary( hMod );
  161. return NULL;
  162. }
  163. //
  164. // Re-impersonate before for Loading ACLs which is called in
  165. // the constructor of HSE_APPDLL
  166. //
  167. if ( !ImpersonateLoggedOnUser( hImpersonation )) {
  168. DWORD dwError = GetLastError();
  169. //
  170. // since this call is not implemented on win95, ignore it.
  171. //
  172. if ( !TsIsWindows95() ) {
  173. DBGPRINTF(( DBG_CONTEXT,
  174. "SE_TABLE::LoadModule() Re-impersonation failed,"
  175. " Error %d\n",
  176. GetLastError() ));
  177. //
  178. // tell the extension that we are shutting down :(
  179. //
  180. if ( pfnTerminate ) {
  181. pfnTerminate( HSE_TERM_MUST_UNLOAD );
  182. }
  183. FreeLibrary( hMod);
  184. SetLastError( dwError);
  185. return ( NULL);
  186. }
  187. }
  188. pExtension = new HSE_APPDLL( pchModuleName,
  189. hMod,
  190. pfnSEProc,
  191. pfnTerminate,
  192. fCache );
  193. if ( !pExtension || !pExtension->IsValid()) {
  194. if ( pfnTerminate ) {
  195. pfnTerminate( HSE_TERM_MUST_UNLOAD );
  196. }
  197. if ( pExtension != NULL) {
  198. delete pExtension;
  199. pExtension = NULL;
  200. }
  201. FreeLibrary( hMod );
  202. return NULL;
  203. }
  204. DBGPRINTF(( DBG_CONTEXT,
  205. "SE_TABLE::LoadModule() Loaded extension %s, "
  206. " description \"%s\"\n",
  207. pchModuleName,
  208. ExtensionVersion.lpszExtensionDesc ));
  209. return ( (HSE_BASE * ) pExtension);
  210. } // HSE_APPDLL::LoadModule()
  211. HSE_APPDLL::~HSE_APPDLL(VOID)
  212. {
  213. Unload();
  214. if ( _hMod) {
  215. DBG_REQUIRE( FreeLibrary( _hMod ) );
  216. _hMod = NULL;
  217. }
  218. } // HSE_APPDLL::~HSE_APPDLL()
  219. BOOL
  220. HSE_APPDLL::LoadAcl(VOID)
  221. {
  222. DWORD cbSecDesc = _buffSD.QuerySize();
  223. DBG_ASSERT( IsValid());
  224. //
  225. // Force an access check on the next request
  226. //
  227. SetLastSuccessfulUser( NULL );
  228. //
  229. // Chicago does not have GetFileSecurity call
  230. //
  231. if ( TsIsWindows95() ) {
  232. return(TRUE);
  233. }
  234. if ( GetFileSecurity( QueryModuleName(),
  235. (OWNER_SECURITY_INFORMATION |
  236. GROUP_SECURITY_INFORMATION |
  237. DACL_SECURITY_INFORMATION),
  238. NULL,
  239. 0,
  240. &cbSecDesc ))
  241. {
  242. return TRUE;
  243. }
  244. if ( GetLastError() != ERROR_INSUFFICIENT_BUFFER )
  245. {
  246. return FALSE;
  247. }
  248. TryAgain:
  249. if ( !_buffSD.Resize( cbSecDesc ) ||
  250. !GetFileSecurity( QueryModuleName(),
  251. (OWNER_SECURITY_INFORMATION |
  252. GROUP_SECURITY_INFORMATION |
  253. DACL_SECURITY_INFORMATION),
  254. _buffSD.QueryPtr(),
  255. cbSecDesc,
  256. &cbSecDesc ))
  257. {
  258. //
  259. // A new ACL may have been written since we checked the old
  260. // one, so try it again
  261. //
  262. if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER )
  263. {
  264. goto TryAgain;
  265. }
  266. return FALSE;
  267. }
  268. return TRUE;
  269. } // HSE_APPDLL::LoadAcl()
  270. BOOL
  271. HSE_APPDLL::AccessCheck( IN HANDLE hImpersonation,
  272. IN BOOL fCacheImpersonation
  273. )
  274. {
  275. BOOL fRet = TRUE;
  276. // NOTE we call IsKindaValid() because caller may dereference before calling us
  277. // (causing IsValid() to return false).
  278. DBG_ASSERT( IsKindaValid() );
  279. //
  280. // Optimize for the anonymous user and only do the access
  281. // check if this is a different user then the last successful
  282. // user
  283. //
  284. if ( !TsIsWindows95() ) {
  285. if ( !fCacheImpersonation ||
  286. (hImpersonation != QueryLastSuccessfulUser()) ) {
  287. DWORD dwGrantedAccess;
  288. BYTE PrivSet[400];
  289. DWORD cbPrivilegeSet = sizeof(PrivSet);
  290. BOOL fAccessGranted;
  291. fRet = ( ::AccessCheck( QuerySecDesc(),
  292. hImpersonation,
  293. FILE_GENERIC_EXECUTE,
  294. &sg_FileGenericMapping,
  295. (PRIVILEGE_SET *) &PrivSet,
  296. &cbPrivilegeSet,
  297. &dwGrantedAccess,
  298. &fAccessGranted )
  299. && fAccessGranted);
  300. if ( fRet && fCacheImpersonation ) {
  301. SetLastSuccessfulUser( hImpersonation );
  302. }
  303. }
  304. }
  305. return ( fRet);
  306. } // HSE_APPDLL::AccessCheck()
  307. DWORD
  308. HSE_APPDLL::ExecuteRequest(
  309. WAM_EXEC_INFO * pWamExecInfo
  310. )
  311. {
  312. DWORD dwIsaRet; // return value from ISA
  313. DBG_ASSERT( pWamExecInfo );
  314. EXTENSION_CONTROL_BLOCK * pecb = &(pWamExecInfo->ecb);
  315. pecb->GetServerVariable= GetServerVariable;
  316. pecb->WriteClient = WriteClient;
  317. pecb->ReadClient = ReadClient;
  318. pecb->ServerSupportFunction = ServerSupportFunction;
  319. DBG_ASSERT( IsValid());
  320. // addref the context before we hand it to ISA
  321. pWamExecInfo->AddRef();
  322. IF_DEBUG( WAM_FILENAMES ) {
  323. DBGPRINTF(( DBG_CONTEXT, "Dll: %s\tScript: %s\n",
  324. WRC_GET_SZ( WRC_I_ISADLLPATH ),
  325. WRC_GET_SZ( WRC_I_PATHINFO ) ));
  326. }
  327. DBG_WAMREQ_REFCOUNTS(( "HSE_APPDLL::ExecuteRequest before ISA call ...", pWamExecInfo ));
  328. // call the extension proc ...
  329. dwIsaRet = ( _pfnEntryPoint( pecb ) );
  330. // release the context upon return from ISA
  331. pWamExecInfo->Release( );
  332. DBG_WAMREQ_REFCOUNTS(( "HSE_APPDLL::ExecuteRequest after ISA call ...", pWamExecInfo ));
  333. return dwIsaRet;
  334. } // HSE_APPDLL::ExecuteRequest()
  335. BOOL
  336. HSE_APPDLL::Cleanup(VOID)
  337. {
  338. return (TRUE);
  339. } // HSE_APPDLL::Cleanup()
  340. DWORD
  341. HSE_APPDLL::Unload(VOID)
  342. {
  343. // Unload can be called before the ref count hits zero
  344. // This will force all the requests inside ISAPI DLL to exit
  345. // DBG_ASSERT( RefCount() == 0);
  346. DBG_REQUIRE( Cleanup());
  347. if ( _pfnTerminate ) {
  348. //
  349. // From the old code :(
  350. // The return value from Terminate() is ignored!
  351. //
  352. _pfnTerminate( HSE_TERM_MUST_UNLOAD );
  353. _pfnTerminate = NULL;
  354. }
  355. SetValid( FALSE);
  356. return (NO_ERROR);
  357. } // HSE_APPDLL::Unload()
  358. /*-----------------------------------------------------------------------------*
  359. Support for ISAPI Callback Functions
  360. */
  361. /*-----------------------------------------------------------------------------*
  362. GetISAContext
  363. Gets the ISA context from the ISA-supplied connection handle.
  364. NOTE caller must balance calls to GetISAContext and ReleaseISAContext
  365. Arguments:
  366. See below
  367. Returns:
  368. BOOL
  369. */
  370. BOOL
  371. GetISAContext(
  372. IN HCONN hConn,
  373. OUT EXTENSION_CONTROL_BLOCK ** ppecb,
  374. OUT WAM_EXEC_INFO ** ppWamExecInfo,
  375. OUT IWamRequest ** ppIWamRequest
  376. )
  377. {
  378. IF_DEBUG( MISC ) {
  379. DBGPRINTF(( DBG_CONTEXT, "GetISAContext(%08x)\n", hConn ));
  380. }
  381. *ppecb = (EXTENSION_CONTROL_BLOCK *) hConn;
  382. *ppWamExecInfo = (WAM_EXEC_INFO *) hConn;
  383. DBG_ASSERT( *ppecb );
  384. DBG_ASSERT( *ppWamExecInfo );
  385. if ( !*ppecb || (*ppecb)->cbSize != sizeof(EXTENSION_CONTROL_BLOCK) ) {
  386. DBGPRINTF(( DBG_CONTEXT,
  387. "[GetISAContext]: Invalid ECB\r\n"));
  388. SetLastError( ERROR_INVALID_PARAMETER );
  389. return FALSE;
  390. }
  391. if ( !( (*ppWamExecInfo)->IsValid() ) ) {
  392. DBGPRINTF(( DBG_CONTEXT,
  393. "[GetISAContext]: Invalid WAM_EXEC_INFO.\r\n"));
  394. SetLastError( ERROR_INVALID_PARAMETER );
  395. return FALSE;
  396. }
  397. //
  398. // Get iwamreq
  399. //
  400. if ( FAILED( (*ppWamExecInfo)->GetIWamRequest( ppIWamRequest ) ) ) {
  401. DBGPRINTF(( DBG_CONTEXT,
  402. "[GetISAContext]: GetIWamRequest failed.\r\n"));
  403. SetLastError( ERROR_INVALID_PARAMETER );
  404. return FALSE;
  405. }
  406. //
  407. // Addref wamexec-info
  408. //
  409. (*ppWamExecInfo)->AddRef();
  410. DBG_ASSERT( *ppIWamRequest );
  411. return TRUE;
  412. } // GetISAContext
  413. /*-----------------------------------------------------------------------------*
  414. ReleaseISAContext
  415. Releases the ISA context.
  416. NOTE caller must balance calls to GetISAContext and ReleaseISAContext
  417. Arguments:
  418. See below
  419. Returns:
  420. Nothing
  421. */
  422. VOID
  423. ReleaseISAContext(
  424. OUT EXTENSION_CONTROL_BLOCK ** ppecb,
  425. OUT WAM_EXEC_INFO ** ppWamExecInfo,
  426. OUT IWamRequest ** ppIWamRequest
  427. )
  428. {
  429. IF_DEBUG( MISC ) {
  430. DBGPRINTF((
  431. DBG_CONTEXT
  432. , "ReleaseISAContext(%08x)\n"
  433. , *ppecb
  434. ));
  435. }
  436. DBG_ASSERT( *ppecb );
  437. DBG_ASSERT( *ppWamExecInfo );
  438. DBG_ASSERT( *ppIWamRequest );
  439. //
  440. // Release iwamreq - balances Get in GetISAContext
  441. //
  442. (*ppWamExecInfo)->ReleaseIWamRequest( *ppIWamRequest );
  443. //
  444. // Release wamexec-info - balances Addref in GetISAContext
  445. //
  446. (*ppWamExecInfo)->Release();
  447. *ppIWamRequest = NULL;
  448. *ppWamExecInfo = NULL;
  449. *ppecb = NULL;
  450. return;
  451. } // ReleaseISAContext
  452. /************************************************************
  453. * ISAPI Callback Functions
  454. ************************************************************/
  455. /*-----------------------------------------------------------------------------*
  456. ServerSupportFunction
  457. Routine Description:
  458. This method handles a gateway request to a server extension DLL
  459. Arguments:
  460. hConn - Connection context (pointer to WAM_EXEC_INFO)
  461. dwHSERequest - Request type
  462. lpvBuffer - Buffer for request
  463. lpdwSize -
  464. lpdwDataType
  465. Return Value:
  466. TRUE on success, FALSE on failure
  467. */
  468. BOOL
  469. WINAPI
  470. ServerSupportFunction(
  471. HCONN hConn,
  472. DWORD dwHSERequest,
  473. LPVOID lpvBuffer,
  474. LPDWORD lpdwSize,
  475. LPDWORD lpdwDataType
  476. )
  477. {
  478. BOOL fReturn = FALSE; // this function's return value
  479. BOOL fNotSupportedOOP = FALSE; // is the hse request supported OOP?
  480. EXTENSION_CONTROL_BLOCK * pecb = NULL;
  481. WAM_EXEC_INFO * pWamExecInfo = NULL;
  482. IWamRequest * pIWamRequest = NULL;
  483. HANDLE hCurrentUser = NULL;
  484. IF_DEBUG( WAM_ISA_CALLS ) {
  485. DBGPRINTF(( DBG_CONTEXT,
  486. "ServerSupportFunction:\n\t"
  487. "hConn = (%p)\t"
  488. "dwHSERequest = (%p)\t"
  489. "lpvBuffer = (%p)\t"
  490. "lpdwSize = (%p)\t"
  491. "lpdwDataType = (%p)\t"
  492. "\n"
  493. ,
  494. hConn,
  495. dwHSERequest,
  496. lpvBuffer,
  497. lpdwSize,
  498. lpdwDataType
  499. ));
  500. }
  501. //
  502. // Get ISA context from connection handle - bail if bogus
  503. // - if this succeeds, we have usable WAM_EXEC_INFO and IWamRequest ptrs
  504. // - if this fails, GetISAContext calls SetLastError so we don't need to
  505. //
  506. if( !GetISAContext( hConn,
  507. &pecb,
  508. &pWamExecInfo,
  509. &pIWamRequest ) ) {
  510. return FALSE;
  511. }
  512. if ( !pWamExecInfo->QueryPWam()->FInProcess() )
  513. {
  514. hCurrentUser = INVALID_HANDLE_VALUE;
  515. }
  516. //
  517. // Fast path send response headers - will be called on almost every
  518. // request
  519. //
  520. //
  521. // New send-header api. Fixes send-header/keep-alive bug.
  522. // Also recommended for best performance.
  523. //
  524. if ( dwHSERequest == HSE_REQ_SEND_RESPONSE_HEADER_EX ) {
  525. if ( lpvBuffer == NULL ) {
  526. SetLastError( ERROR_INVALID_PARAMETER );
  527. fReturn = FALSE;
  528. goto LExit;
  529. }
  530. if ( pWamExecInfo->NoHeaders() ) {
  531. fReturn = TRUE;
  532. goto LExit;
  533. }
  534. HSE_SEND_HEADER_EX_INFO * pSendHeaderExInfo =
  535. reinterpret_cast<HSE_SEND_HEADER_EX_INFO *>( lpvBuffer );
  536. //
  537. // null strings are permitted
  538. // (preserves semantics of old send-header api)
  539. //
  540. DWORD cchStatus = (
  541. pSendHeaderExInfo->cchStatus
  542. ? pSendHeaderExInfo->cchStatus + 1
  543. : pSendHeaderExInfo->pszStatus
  544. ? lstrlen( pSendHeaderExInfo->pszStatus ) + 1
  545. : 0
  546. );
  547. DWORD cchHeader = (
  548. pSendHeaderExInfo->cchHeader
  549. ? pSendHeaderExInfo->cchHeader + 1
  550. : pSendHeaderExInfo->pszHeader
  551. ? lstrlen( pSendHeaderExInfo->pszHeader ) + 1
  552. : 0
  553. );
  554. //
  555. // set keep-conn state explicitly based on caller's boolean
  556. // (since boolean itself is explicit)
  557. //
  558. if ( pSendHeaderExInfo->fKeepConn == FALSE ) {
  559. pWamExecInfo->_dwIsaKeepConn = KEEPCONN_FALSE;
  560. } else {
  561. pWamExecInfo->_dwIsaKeepConn = KEEPCONN_TRUE;
  562. }
  563. DoRevertHack( &hCurrentUser );
  564. fReturn =
  565. BoolFromHresult( pIWamRequest->SendHeader(
  566. (unsigned char *) pSendHeaderExInfo->pszStatus
  567. , cchStatus
  568. , (unsigned char *) pSendHeaderExInfo->pszHeader
  569. , cchHeader
  570. , pWamExecInfo->_dwIsaKeepConn
  571. ));
  572. UndoRevertHack( &hCurrentUser );
  573. goto LExit;
  574. }
  575. //
  576. // Old send-header api, exists purely for back-compatibility
  577. //
  578. // Not recommended because ISA has no way to communicate
  579. // its keep-conn strategy to us before we send headers.
  580. // We infer it from header string, which is slow.
  581. //
  582. if ( dwHSERequest == HSE_REQ_SEND_RESPONSE_HEADER ) {
  583. if ( pWamExecInfo->NoHeaders() ) {
  584. fReturn = TRUE;
  585. goto LExit;
  586. }
  587. //
  588. // lpvBuffer points to status string
  589. // status string is optional (null is permitted)
  590. //
  591. DWORD cchStatus = (
  592. lpvBuffer
  593. ? lstrlen( (char *) lpvBuffer ) + 1
  594. : 0
  595. );
  596. //
  597. // lpdwDataType points to header string
  598. // header string is optional (null is permitted)
  599. //
  600. DWORD cchHeader = (
  601. lpdwDataType
  602. ? lstrlen( (char *) lpdwDataType ) + 1
  603. : 0
  604. );
  605. //
  606. // if status or header string contains "Content-Length:",
  607. // we assume ISA wants connection kept alive.
  608. //
  609. // NOTE we don't set keep-conn state false in opposite case,
  610. // since old caller may not intend to close connection.
  611. //
  612. //
  613. if ( (lpvBuffer && stristr((const char *)lpvBuffer, "Content-Length:"))
  614. ||
  615. (lpdwDataType
  616. && stristr((const char *)lpdwDataType, "Content-Length:"))
  617. ) {
  618. pWamExecInfo->_dwIsaKeepConn = KEEPCONN_TRUE;
  619. } else {
  620. pWamExecInfo->_dwIsaKeepConn = KEEPCONN_FALSE;
  621. }
  622. IF_DEBUG( WAM_ISA_CALLS ) {
  623. DBGPRINTF(( DBG_CONTEXT,
  624. "SSF SendHeader: "
  625. "Status = %s "
  626. "Header = %s "
  627. "Keep-conn = %d "
  628. "\n"
  629. , (unsigned char *) lpvBuffer
  630. , (unsigned char *) lpdwDataType
  631. , pWamExecInfo->_dwIsaKeepConn
  632. ));
  633. }
  634. DoRevertHack( &hCurrentUser );
  635. fReturn =
  636. BoolFromHresult( pIWamRequest->SendHeader(
  637. (unsigned char *) lpvBuffer
  638. , cchStatus
  639. , (unsigned char *) lpdwDataType
  640. , cchHeader
  641. , pWamExecInfo->_dwIsaKeepConn
  642. ));
  643. UndoRevertHack( &hCurrentUser );
  644. goto LExit;
  645. }
  646. //
  647. // Handle the server extension's request
  648. //
  649. switch ( dwHSERequest ) {
  650. //
  651. // IO Completion routine is provided.
  652. //
  653. case HSE_REQ_IO_COMPLETION:
  654. //
  655. // We don't check the pointer because we dont' want to mask
  656. // application coding errors
  657. //
  658. if ( lpvBuffer != NULL) {
  659. //
  660. // Set the callback function and its ecb ptr argument
  661. // NOTE setting the ptr seems a bit cheesy, but is probably the quickest way
  662. // to make new out-of-proc wam suport our old code path
  663. //
  664. pWamExecInfo->_AsyncIoInfo._pfnHseIO = (PFN_HSE_IO_COMPLETION ) lpvBuffer;
  665. }
  666. pWamExecInfo->_AsyncIoInfo._pvHseIOContext = (PVOID ) lpdwDataType;
  667. fReturn = TRUE;
  668. break;
  669. case HSE_REQ_TRANSMIT_FILE:
  670. if ( lpvBuffer == NULL ) {
  671. SetLastError( ERROR_INVALID_PARAMETER );
  672. fReturn = FALSE;
  673. break;
  674. }
  675. // NOTE lpvBuffer == pHseTfInfo
  676. fReturn = pWamExecInfo->TransmitFile((LPHSE_TF_INFO ) lpvBuffer);
  677. break;
  678. case HSE_REQ_ASYNC_READ_CLIENT: {
  679. DWORD dwFlags;
  680. if ( lpvBuffer == NULL || lpdwSize == NULL ) {
  681. SetLastError( ERROR_INVALID_PARAMETER );
  682. fReturn = FALSE;
  683. break;
  684. }
  685. dwFlags = lpdwDataType ? *lpdwDataType : HSE_IO_ASYNC;
  686. fReturn = pWamExecInfo->AsyncReadClient( lpvBuffer,
  687. lpdwSize,
  688. dwFlags );
  689. break;
  690. }
  691. case HSE_REQ_SEND_URL_REDIRECT_RESP: {
  692. //
  693. // Descrption:
  694. // Send an URL redirect message to the browser client
  695. //
  696. // Input:
  697. // lpvBuffer - pointer to buffer that contains the location to
  698. // redirect the client to.
  699. // lpdwSize - pointer to DWORD containing size (UnUsed)
  700. // lpdwDataType - Unused
  701. //
  702. // Return:
  703. // None
  704. //
  705. // Notes:
  706. // Works In-Process and Out-Of-Process
  707. if ( lpvBuffer == NULL ) {
  708. SetLastError( ERROR_INVALID_PARAMETER );
  709. fReturn = FALSE;
  710. break;
  711. }
  712. //
  713. // bug 117107: don't change keep-conn setting
  714. // on redirected responses.
  715. //
  716. // NOTE old behavior had been that we closed
  717. // the connection by default
  718. //
  719. pWamExecInfo->_dwIsaKeepConn = KEEPCONN_DONT_CHANGE;
  720. DoRevertHack( &hCurrentUser );
  721. fReturn = BoolFromHresult(
  722. pIWamRequest->SendURLRedirectResponse(
  723. (unsigned char *) lpvBuffer
  724. ) );
  725. UndoRevertHack( &hCurrentUser );
  726. break;
  727. } // case HSE_REQ_SEND_URL_REDIRECT_RESP:
  728. //
  729. // HSE_REQ_SEND_URL functionality is broken (especially if the URL
  730. // to be sent is another ISA. In this case, we are overwriting state of
  731. // the parent ISA by the child )
  732. //
  733. // For now, just treat HSE_REQ_SEND_URL as a redirect. If enough people
  734. // complain, then a new HTTP_REQUEST object must be created in order to
  735. // handle the new request.
  736. //
  737. case HSE_REQ_SEND_URL: {
  738. if ( lpvBuffer == NULL ) {
  739. SetLastError( ERROR_INVALID_PARAMETER );
  740. fReturn = FALSE;
  741. break;
  742. }
  743. //
  744. // bug 117107: don't change keep-conn setting
  745. // on redirected responses.
  746. //
  747. // NOTE old behavior had been that we closed
  748. // the connection by default
  749. //
  750. pWamExecInfo->_dwIsaKeepConn = KEEPCONN_DONT_CHANGE;
  751. DoRevertHack( &hCurrentUser );
  752. fReturn = BoolFromHresult( pIWamRequest->SendRedirectMessage( (unsigned char *) lpvBuffer ) );
  753. UndoRevertHack( &hCurrentUser );
  754. break;
  755. } // case HSE_REQ_SEND_URL:
  756. //
  757. // This is an async callback from the extension dll indicating
  758. // they are done with the socket
  759. //
  760. case HSE_REQ_DONE_WITH_SESSION: {
  761. DBG_WAMREQ_REFCOUNTS(( "ServerSupportFunction DONE_WITH_SESSION",
  762. pWamExecInfo));
  763. // DBG_ASSERT( pWamExecInfo->_AsyncIoInfo._dwOutstandingIO == FALSE);
  764. //
  765. // A multi-threaded extension may indicate they
  766. // are done before returning pending.
  767. // Thus, we always return success.
  768. //
  769. fReturn = TRUE;
  770. //
  771. // Remember if the ISA wanted to keep the session open
  772. //
  773. if ( lpvBuffer &&
  774. *((DWORD *) lpvBuffer) == HSE_STATUS_SUCCESS_AND_KEEP_CONN ) {
  775. pWamExecInfo->_dwIsaKeepConn = KEEPCONN_TRUE;
  776. }
  777. //
  778. // FDisconnected is only true for ASP when it is sending a buffered
  779. // oop response. That call has already been made when we
  780. // get here and the flag is either set (cleanup has already
  781. // happened) or not (cleanup needs to happen here)
  782. //
  783. if( !pWamExecInfo->FDisconnected() )
  784. {
  785. //
  786. // Figure out whether mainline thread or this callback thread
  787. // hit its cleanup code first.
  788. //
  789. // This protects somewhat against isapis that disobey the async
  790. // rules. The isapi should be in one of two modes:
  791. //
  792. // 1. It return HSE_STATUS_PENDING in the mainline thread and
  793. // always calls HSE_DONE_WITH_SESSION.
  794. //
  795. // 2. It returns any other status code from the mainline and
  796. // NEVER calls HSE_DONE_WITH_SESSION.
  797. //
  798. // Unfortunately isapi writers frequently do bad things to good
  799. // servers. This code will prevent an AV (accessing a deleted
  800. // ecb when the isapi calls HSE_DONE_WITH_SESSION from the
  801. // the mainline thread. If the call occurs on another thread
  802. // then all bets are off and only thread scheduling can save
  803. // us.
  804. //
  805. // This protection was disabled for a while, but some internal
  806. // ISAPI writers were having problems.
  807. //
  808. // NOTE return value is initial value of the destination
  809. //
  810. LONG FirstThread = INTERLOCKED_COMPARE_EXCHANGE(
  811. (LONG *) &pWamExecInfo->_FirstThread
  812. , (LONG) FT_CALLBACK
  813. , (LONG) FT_NULL
  814. );
  815. if( FirstThread == (LONG) FT_NULL )
  816. {
  817. // Do nothing. Save the final release for the
  818. // mainline thread.
  819. ;
  820. }
  821. else
  822. {
  823. //
  824. // Mainline thread executed first, so this callback thread
  825. // now must cleanup the wamreq and release wamexecinfo.
  826. //
  827. DoRevertHack( &hCurrentUser );
  828. pIWamRequest->CleanupWamRequest(
  829. (unsigned char*) pecb->lpszLogData
  830. , lstrlen( pecb->lpszLogData ) + 1
  831. , pecb->dwHttpStatusCode
  832. , pWamExecInfo->_dwIsaKeepConn
  833. );
  834. UndoRevertHack( &hCurrentUser );
  835. pWamExecInfo->Release( );
  836. }
  837. }
  838. else
  839. {
  840. // we do need to release even if asp is disconnected
  841. pWamExecInfo->Release( );
  842. }
  843. break;
  844. } // case HSE_REQ_DONE_WITH_SESSION:
  845. case HSE_REQ_EXECUTE_CHILD: {
  846. //
  847. // Descrption:
  848. // SSI Execute functions
  849. //
  850. // Input:
  851. // lpvBuffer - pointer to the URL (or Command string)
  852. // to be executed.
  853. // lpdwSize - NULL or points to verb to do request under
  854. // lpdwDataType - Points to DWORD containing flags
  855. //
  856. // Flags (OR'd) and their meanings:
  857. //
  858. // HSE_EXEC_NO_HEADERS - When set, suppresses sending of the
  859. // child request's headers. Needed to
  860. // be set if the parent request sends
  861. // its own headers.
  862. //
  863. // HSE_EXEC_COMMAND - When set, lpvBuffer contains command
  864. // string to execute, as opposed to URL.
  865. // SSINC uses it for <!--#EXEC CMD=...
  866. //
  867. // HSE_EXEC_NO_ISA_WILDCARDS
  868. // - When set, disables wildcard ISAPI
  869. // file extension mapping during the
  870. // child execution. DAVFS sets this flag
  871. // to avoid recursions.
  872. //
  873. // HSE_EXEC_CUSTOM_ERROR
  874. // - Set to indicate that this is a custom
  875. // error URL. DAV code uses this junk.
  876. //
  877. // Return:
  878. // TRUE = SUCCESS
  879. //
  880. // Notes:
  881. // Works In-Process and Out-Of-Process
  882. //
  883. if ( lpvBuffer == NULL || lpdwDataType == NULL ) {
  884. SetLastError( ERROR_INVALID_PARAMETER );
  885. fReturn = FALSE;
  886. break;
  887. }
  888. DWORD dwExecFlags = *lpdwDataType;
  889. DoRevertHack( &hCurrentUser );
  890. fReturn = BoolFromHresult( pIWamRequest->SSIncExec(
  891. (unsigned char *)lpvBuffer,
  892. dwExecFlags,
  893. lpdwSize ?
  894. (unsigned char *)lpdwSize : NULL ) );
  895. UndoRevertHack( &hCurrentUser );
  896. break;
  897. } // case HSE_REQ_EXECUTE_CHILD
  898. //
  899. // These are Microsoft specific extensions
  900. //
  901. case HSE_REQ_MAP_URL_TO_PATH: {
  902. //
  903. // Descrption:
  904. // Simple api for looking up path-translated for a vroot
  905. //
  906. // Input:
  907. // lpvBuffer - ptr to buffer which contains URL
  908. // (will contain path-translated on return)
  909. // lpdwDataType - ignored
  910. // lpdwSize - ptr to buffer size
  911. //
  912. // Return:
  913. // lpvBuffer - contains path-translated on return
  914. // lpdwDataType - ignored, unchanged
  915. // lpdwSize - unchanged
  916. //
  917. DWORD cchRequired = 0;
  918. if ( lpvBuffer == NULL || lpdwSize == NULL ) {
  919. SetLastError( ERROR_INVALID_PARAMETER );
  920. fReturn = FALSE;
  921. break;
  922. }
  923. DoRevertHack( &hCurrentUser );
  924. fReturn = BoolFromHresult( pIWamRequest->LookupVirtualRoot(
  925. (unsigned char *) lpvBuffer,
  926. (*lpdwSize),
  927. &cchRequired ) );
  928. UndoRevertHack( &hCurrentUser );
  929. *lpdwSize = cchRequired;
  930. break;
  931. } // case HSE_REQ_MAP_URL_TO_PATH:
  932. case HSE_REQ_MAP_URL_TO_PATH_EX: {
  933. //
  934. // Descrption:
  935. // Extended api for looking up path-translated for a vroot
  936. //
  937. // Input:
  938. // lpvBuffer - ptr to buffer which contains URL
  939. // lpdwDataType - ptr to HSE_URL_MAPEX_INFO struct (see iisext.x)
  940. // lpdwSize - (optional) ptr to buffer size
  941. //
  942. // Return:
  943. // lpvBuffer - unchanged
  944. // lpdwDataType - ptr to HSE_URL_MAPEX_INFO struct, which now has
  945. // its parameters filled in
  946. // lpdwSize - if supplied, ptr to size of returned buffer
  947. // within HSE_URL_MAPEX_INFO struct
  948. //
  949. DWORD cchRequired = 0;
  950. HSE_URL_MAPEX_INFO * purlmap = (HSE_URL_MAPEX_INFO *) lpdwDataType;
  951. if ( lpvBuffer == NULL || lpdwDataType == NULL ) {
  952. SetLastError( ERROR_INVALID_PARAMETER );
  953. fReturn = FALSE;
  954. break;
  955. }
  956. DoRevertHack( &hCurrentUser );
  957. fReturn = BoolFromHresult( pIWamRequest->LookupVirtualRootEx(
  958. (unsigned char *) lpvBuffer, // [in] szURL
  959. (unsigned char *)purlmap->lpszPath, // [out] pchBuffer
  960. sizeof( purlmap->lpszPath ),
  961. &cchRequired,
  962. &purlmap->cchMatchingPath,
  963. &purlmap->cchMatchingURL,
  964. &purlmap->dwFlags ) );
  965. UndoRevertHack( &hCurrentUser );
  966. if ( lpdwSize != NULL )
  967. {
  968. *lpdwSize = cchRequired;
  969. }
  970. if ( fReturn )
  971. {
  972. //
  973. // Bug38264 - Don't reflect a trailing backslash
  974. // in the URL in the cchMatchingURL value. This
  975. // check must be done against the original URL in
  976. // lpvBuffer because the string doesn't exist in
  977. // any of the HSE_URL_MAPEX_INFO members.
  978. //
  979. DWORD cchOriginalURL = lstrlen( (LPSTR)lpvBuffer );
  980. if ( cchOriginalURL < purlmap->cchMatchingURL )
  981. {
  982. purlmap->cchMatchingURL = cchOriginalURL;
  983. }
  984. purlmap->dwFlags &= HSE_URL_FLAGS_MASK;
  985. purlmap->dwReserved1 = 0;
  986. purlmap->dwReserved2 = 0;
  987. }
  988. break;
  989. } // case HSE_REQ_MAP_URL_TO_PATH_EX:
  990. case HSE_REQ_ABORTIVE_CLOSE: {
  991. //
  992. // Descrption:
  993. // request an abortive close on disconnect for this connection
  994. //
  995. DoRevertHack( &hCurrentUser );
  996. fReturn = BoolFromHresult( pIWamRequest->RequestAbortiveClose() );
  997. UndoRevertHack( &hCurrentUser );
  998. break;
  999. } // case HSE_REQ_ABORTIVE_CLOSE
  1000. case HSE_REQ_CLOSE_CONNECTION: {
  1001. //
  1002. // Descrption:
  1003. // close the connection socket
  1004. //
  1005. DoRevertHack( &hCurrentUser );
  1006. fReturn = BoolFromHresult( pIWamRequest->CloseConnection() );
  1007. UndoRevertHack( &hCurrentUser );
  1008. break;
  1009. } // case HSE_REQ_CLOSE_CONNECTION
  1010. case HSE_REQ_GET_CERT_INFO: {
  1011. //
  1012. // this call is obsolete - use HSE_REQ_GET_CERT_INFO_EX instead
  1013. //
  1014. SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
  1015. fReturn = FALSE;
  1016. break;
  1017. } // case HSE_REQ_GET_CERT_INFO:
  1018. case HSE_REQ_GET_CERT_INFO_EX: {
  1019. //
  1020. // Descrption:
  1021. // Returns the first cert in the request's cert-chain,
  1022. // only used if using an SSPI package
  1023. //
  1024. // Input:
  1025. // lpvBuffer - ISA-provided struct
  1026. // NOTE ISA must allocate buffer within struct
  1027. //
  1028. // Notes:
  1029. // Works in-proc or out-of-proc
  1030. //
  1031. //
  1032. // cast ISA-provided ptr to our cert struct
  1033. //
  1034. CERT_CONTEXT_EX * pCertContextEx = reinterpret_cast
  1035. <CERT_CONTEXT_EX *>
  1036. ( lpvBuffer );
  1037. if ( lpvBuffer == NULL ) {
  1038. DBG_ASSERT( FALSE );
  1039. SetLastError( ERROR_INVALID_PARAMETER );
  1040. fReturn = FALSE;
  1041. break;
  1042. }
  1043. //
  1044. // pass struct members as individual parameters
  1045. //
  1046. DoRevertHack( &hCurrentUser );
  1047. fReturn = BoolFromHresult( pIWamRequest->GetClientCertInfoEx(
  1048. pCertContextEx->cbAllocated,
  1049. &( pCertContextEx->CertContext.dwCertEncodingType ),
  1050. pCertContextEx->CertContext.pbCertEncoded,
  1051. &( pCertContextEx->CertContext.cbCertEncoded ),
  1052. &( pCertContextEx->dwCertificateFlags ) ) );
  1053. UndoRevertHack( &hCurrentUser );
  1054. break;
  1055. } // case HSE_REQ_GET_CERT_INFO_EX:
  1056. case HSE_REQ_GET_SSPI_INFO: {
  1057. //
  1058. // Descrption:
  1059. // Retrieves the SSPI context and credential handles, only used if
  1060. // using an SSPI package
  1061. //
  1062. // Input:
  1063. // lpvBuffer - pointer to buffer that will contain the CtxtHandle
  1064. // on return
  1065. // lpdwSize - pointer to DWORD containing size (UnUsed)
  1066. // lpdwDataType - pointer to buffer that will contain the
  1067. // CredHandle on return
  1068. //
  1069. // Return:
  1070. // CtxtHandle - in *lpvBuffer
  1071. // CredHandle - in *lpdwDataType
  1072. //
  1073. // Notes:
  1074. // Works In-Process
  1075. // Fails out-of-process, by design
  1076. // (security 'handles' won't duplicate cross-process)
  1077. //
  1078. //
  1079. // NOTE: ISA must ensure that lpvBuffer & lpdwDataType point to buffers
  1080. // of appropriate sizes sizeof(CtxtHandle) & sizeof(CredHandle)
  1081. //
  1082. if( !pWamExecInfo->QueryPWam()->FInProcess() ) {
  1083. fNotSupportedOOP = TRUE;
  1084. break;
  1085. }
  1086. if ( lpvBuffer == NULL || lpdwDataType == NULL ) {
  1087. DBG_ASSERT( FALSE );
  1088. SetLastError( ERROR_INVALID_PARAMETER );
  1089. fReturn = FALSE;
  1090. break;
  1091. }
  1092. DoRevertHack( &hCurrentUser );
  1093. fReturn = BoolFromHresult(
  1094. pIWamRequest->GetSspiInfo(
  1095. 8 /* UNDONE sizeof( CtxtHandle) */
  1096. , (PBYTE ) lpvBuffer
  1097. , 8 /* UNDONE sizeof( CredHandle) */
  1098. , (PBYTE ) lpdwDataType
  1099. ));
  1100. UndoRevertHack( &hCurrentUser );
  1101. break;
  1102. } // case HSE_REQ_GET_SSPI_INFO:
  1103. case HSE_APPEND_LOG_PARAMETER: {
  1104. //
  1105. // Descrption:
  1106. // Appends a certain string to the log record written out.
  1107. //
  1108. // Input:
  1109. // lpvBuffer - string containing the log data to be appended
  1110. // lpdwSize - pointer to DWORD containing size (UnUsed)
  1111. // lpdwDataType - pointer to Data type value (Unused)
  1112. //
  1113. // Return:
  1114. // None
  1115. //
  1116. // Notes:
  1117. // Works Out-Of-Process & In-Process
  1118. // Good candidate for being marshalled into calling process.
  1119. if ( lpvBuffer == NULL ) {
  1120. SetLastError( ERROR_INVALID_PARAMETER );
  1121. fReturn = FALSE;
  1122. break;
  1123. }
  1124. DoRevertHack( &hCurrentUser );
  1125. fReturn = BoolFromHresult( pIWamRequest->AppendLogParameter( (unsigned char *) lpvBuffer ) );
  1126. UndoRevertHack( &hCurrentUser );
  1127. break;
  1128. } // case HSE_APPEND_LOG_PARAMETER:
  1129. case HSE_REQ_REFRESH_ISAPI_ACL: {
  1130. //
  1131. // Descrption:
  1132. // Refreshes the ACLs for the ISAPI dll specified
  1133. // It forces the server to re-read the ACL for the ISAPI dll
  1134. //
  1135. // Input:
  1136. // lpvBuffer - string containing the name of the ISAPI dll
  1137. // lpdwSize - pointer to DWORD containing size (UnUsed)
  1138. // lpdwDataType - pointer to Data type value (Unused)
  1139. //
  1140. // Return:
  1141. // None
  1142. //
  1143. // Notes:
  1144. // This is local to the WAM process
  1145. if ( lpvBuffer == NULL ) {
  1146. SetLastError( ERROR_INVALID_PARAMETER );
  1147. fReturn = FALSE;
  1148. break;
  1149. }
  1150. fReturn = (g_psextensions->RefreshAcl( (LPSTR) lpvBuffer ));
  1151. break;
  1152. } // case HSE_REQ_REFRESH_ISAPI_ACL:
  1153. case HSE_REQ_IS_KEEP_CONN: {
  1154. //
  1155. // Descrption:
  1156. // Obtains the state if this connection is keep-alive or not.
  1157. //
  1158. // Input:
  1159. // lpvBuffer - pointer to BOOL which will contain the state on return
  1160. // lpdwSize - pointer to DWORD containing size (UnUsed)
  1161. // lpdwDataType - pointer to Data type value (Unused)
  1162. //
  1163. // Return:
  1164. // *lpvBuffer contains the value (TRUE=>keep-alive, FALSE=>non-KA)
  1165. //
  1166. // Notes:
  1167. // Works Out-Of-Process & In-Process
  1168. // Good candidate for being marshalled into calling process.
  1169. //
  1170. // We need this function here in ServerSupportFunction
  1171. // (vs. fetching the BOOL up front) because a script, for example,
  1172. // could change the state of keep-conn then later query it.
  1173. //
  1174. if ( lpvBuffer == NULL ) {
  1175. SetLastError( ERROR_INVALID_PARAMETER );
  1176. fReturn = FALSE;
  1177. break;
  1178. }
  1179. DBG_ASSERT( NULL != lpvBuffer );
  1180. DoRevertHack( &hCurrentUser );
  1181. fReturn = BoolFromHresult( pIWamRequest->IsKeepConnSet( (LPBOOL)lpvBuffer ) );
  1182. UndoRevertHack( &hCurrentUser );
  1183. break;
  1184. } // case HSE_REQ_IS_KEEP_CONN:
  1185. case HSE_REQ_GET_IMPERSONATION_TOKEN: {
  1186. //
  1187. // Descrption:
  1188. // Obtains the impersonation token for the current user
  1189. //
  1190. // Input:
  1191. // lpvBuffer - pointer to HANDLE that will contain the impersonation
  1192. // token on return
  1193. // lpdwSize - pointer to DWORD containing size (UnUsed)
  1194. // lpdwDataType - pointer to Data type value (Unused)
  1195. //
  1196. // Return:
  1197. // *lpvBuffer contains the value
  1198. //
  1199. if ( lpvBuffer == NULL ) {
  1200. DBG_ASSERT( FALSE );
  1201. SetLastError( ERROR_INVALID_PARAMETER );
  1202. fReturn = FALSE;
  1203. break;
  1204. }
  1205. *((HANDLE *)lpvBuffer) = WRC_GET_FIX.m_hUserToken;
  1206. fReturn = TRUE;
  1207. break;
  1208. } // case HSE_REQ_GET_IMPERSONATION_TOKEN:
  1209. case HSE_REQ_GET_VIRTUAL_PATH_TOKEN:
  1210. //
  1211. // Descrption:
  1212. // Obtains the impersonation token for the specified virtual path
  1213. //
  1214. // Input:
  1215. // lpvBuffer - points to virtual path for which UNC impersonation
  1216. // token is sought
  1217. // lpdwSize - points to a HANDLE which will be set on return
  1218. // lpdwDataType - pointer to Data type value (Unused)
  1219. //
  1220. // Return:
  1221. // *lpdwSize contains the token
  1222. //
  1223. if( lpvBuffer == NULL || lpdwSize == NULL ) {
  1224. DBG_ASSERT( FALSE );
  1225. SetLastError( ERROR_INVALID_PARAMETER );
  1226. fReturn = FALSE;
  1227. }
  1228. DoRevertHack( &hCurrentUser );
  1229. fReturn = BoolFromHresult( pIWamRequest->GetVirtualPathToken(
  1230. (unsigned char *) lpvBuffer,
  1231. #ifdef _WIN64
  1232. (UINT64 *)lpdwSize ) );
  1233. #else
  1234. (ULONG_PTR *)lpdwSize ) );
  1235. #endif
  1236. UndoRevertHack( &hCurrentUser );
  1237. break;
  1238. case HSE_REQ_IS_CONNECTED:
  1239. //
  1240. // Description:
  1241. // Attempts to determine if the if the client is still connected.
  1242. // Works by doing a "peek" on the socket.
  1243. //
  1244. // Input:
  1245. // lpvBuffer - pointer to BOOL which will contain the state on return
  1246. // lpdwSize - pointer to DWORD containing size (UnUsed)
  1247. // lpdwDataType - pointer to Data type value (Unused)
  1248. //
  1249. // Return:
  1250. // *lpvBuffer contains the value
  1251. // TRUE connected
  1252. // FALSE socket closed or unreadable
  1253. //
  1254. if ( lpvBuffer == NULL ) {
  1255. SetLastError( ERROR_INVALID_PARAMETER );
  1256. fReturn = FALSE;
  1257. break;
  1258. }
  1259. DBG_ASSERT( NULL != lpvBuffer );
  1260. DoRevertHack( &hCurrentUser );
  1261. fReturn = BoolFromHresult( pIWamRequest->TestConnection( (LPBOOL)lpvBuffer ) );
  1262. UndoRevertHack( &hCurrentUser );
  1263. break;
  1264. case HSE_REQ_GET_EXECUTE_FLAGS:
  1265. //
  1266. // Descrption:
  1267. // Gets the execute descriptor flags used for this request
  1268. //
  1269. // Input:
  1270. // None
  1271. //
  1272. // Return:
  1273. // *lpdwDataType contains the flags
  1274. //
  1275. if ( lpdwDataType == NULL )
  1276. {
  1277. DBG_ASSERT( FALSE );
  1278. SetLastError( ERROR_INVALID_PARAMETER );
  1279. fReturn = FALSE;
  1280. break;
  1281. }
  1282. *lpdwDataType = pWamExecInfo->_dwChildExecFlags;
  1283. fReturn = TRUE;
  1284. break;
  1285. case HSE_REQ_EXTENSION_TRIGGER:
  1286. //
  1287. // Description:
  1288. // Notify any filters waiting on SF_NOTIFY_EXTENSION_TRIGGER
  1289. //
  1290. // Input:
  1291. // lpvBuffer - Context pointer
  1292. // lpdwDataType - Points to trigger type
  1293. //
  1294. //
  1295. // Only works in-proc.
  1296. //
  1297. if ( !lpdwDataType )
  1298. {
  1299. SetLastError( ERROR_INVALID_PARAMETER );
  1300. fReturn = FALSE;
  1301. break;
  1302. }
  1303. if ( !pWamExecInfo->QueryPWam()->FInProcess() )
  1304. {
  1305. SetLastError( ERROR_NOT_SUPPORTED );
  1306. fReturn = FALSE;
  1307. break;
  1308. }
  1309. fReturn = BoolFromHresult( pIWamRequest->ExtensionTrigger(
  1310. (unsigned char*) lpvBuffer,
  1311. *lpdwDataType ) );
  1312. break;
  1313. //
  1314. // These are private services
  1315. //
  1316. //
  1317. // Descrption:
  1318. // Following is a list of options that only work in-process
  1319. // and are mostly backdoor hand-off of pointers to ill-behaved
  1320. // applications! A big hack!
  1321. //
  1322. // Input:
  1323. // lpvBuffer - pointer to location that will contain the returned value
  1324. // lpdwSize - pointer to DWORD containing size (UnUsed)
  1325. // lpdwDataType - pointer to Data type value (Unused)
  1326. //
  1327. // Return:
  1328. // *lpvBuffer contains the value
  1329. //
  1330. // Notes:
  1331. // Works In-Process
  1332. // Fails gracefully Out-Of-Process
  1333. case HSE_PRIV_REQ_TSVCINFO:
  1334. case HSE_PRIV_REQ_HTTP_REQUEST:
  1335. case HSE_PRIV_REQ_VROOT_TABLE:
  1336. case HSE_PRIV_REQ_TSVC_CACHE: {
  1337. if( !pWamExecInfo->QueryPWam()->FInProcess() ) {
  1338. fNotSupportedOOP = TRUE;
  1339. break;
  1340. }
  1341. if ( lpvBuffer == NULL ) {
  1342. DBG_ASSERT( FALSE );
  1343. SetLastError( ERROR_INVALID_PARAMETER );
  1344. fReturn = FALSE;
  1345. break;
  1346. }
  1347. DoRevertHack( &hCurrentUser );
  1348. fReturn = BoolFromHresult( pIWamRequest->GetPrivatePtr( dwHSERequest, (unsigned char **) &lpvBuffer ) );
  1349. UndoRevertHack( &hCurrentUser );
  1350. break;
  1351. } // case HSE_PRIV_REQ_TSVCINFO: et al
  1352. default: {
  1353. SetLastError( ERROR_INVALID_PARAMETER );
  1354. fReturn = FALSE;
  1355. break;
  1356. } // case default:
  1357. } // switch ( dwHSERequest )
  1358. if (fNotSupportedOOP) {
  1359. SetLastError( ERROR_INVALID_FUNCTION );
  1360. fReturn = FALSE;
  1361. }
  1362. LExit:
  1363. //
  1364. // Release isa context
  1365. // Balances GetISAContext at top of this function
  1366. //
  1367. ReleaseISAContext(
  1368. &pecb
  1369. , &pWamExecInfo
  1370. , &pIWamRequest
  1371. );
  1372. return ( fReturn );
  1373. } // ServerSupportFunction()
  1374. BOOL
  1375. WINAPI
  1376. GetServerVariable(
  1377. HCONN hConn,
  1378. LPSTR szVarName,
  1379. LPVOID lpvBuffer,
  1380. LPDWORD lpdwSize
  1381. )
  1382. {
  1383. BOOL fReturn = FALSE;
  1384. EXTENSION_CONTROL_BLOCK * pecb = NULL;
  1385. WAM_EXEC_INFO * pWamExecInfo = NULL;
  1386. IWamRequest * pIWamRequest = NULL;
  1387. IF_DEBUG( WAM_ISA_CALLS ) {
  1388. DBGPRINTF(( DBG_CONTEXT,
  1389. "GetServerVariable:\n\t"
  1390. "hConn = (%08x)\t"
  1391. "szVarName = %s\t"
  1392. "lpvBuffer = (%08x)\t"
  1393. "*lpdwSize = %d\t"
  1394. "\n"
  1395. ,
  1396. hConn,
  1397. szVarName,
  1398. lpvBuffer,
  1399. lpdwSize ? *lpdwSize : -1
  1400. ));
  1401. }
  1402. //
  1403. // Validate ISA-supplied input parameters
  1404. //
  1405. if ( szVarName == NULL || lpdwSize == NULL ) {
  1406. DBG_ASSERT( FALSE );
  1407. SetLastError( ERROR_INVALID_PARAMETER );
  1408. return FALSE;
  1409. }
  1410. //
  1411. // Get ISA context from connection handle - bail if bogus
  1412. // - if this succeeds, we have usable WAM_EXEC_INFO and IWamRequest ptrs
  1413. // - if this fails, GetISAContext calls SetLastError so we don't need to
  1414. //
  1415. if( !GetISAContext( hConn,
  1416. &pecb,
  1417. &pWamExecInfo,
  1418. &pIWamRequest ) ) {
  1419. return FALSE;
  1420. }
  1421. fReturn = BoolFromHresult( pWamExecInfo->GetInfoForName(
  1422. pIWamRequest,
  1423. (unsigned char *) szVarName,
  1424. (unsigned char *) lpvBuffer,
  1425. *lpdwSize,
  1426. lpdwSize ) );
  1427. //
  1428. // Release isa context
  1429. // Balances GetISAContext at top of this function
  1430. //
  1431. ReleaseISAContext(
  1432. &pecb
  1433. , &pWamExecInfo
  1434. , &pIWamRequest
  1435. );
  1436. return ( fReturn );
  1437. } // GetServerVariable()
  1438. /*-----------------------------------------------------------------------------*
  1439. WriteClient
  1440. Routine Description:
  1441. Writes to the http client on behalf of the ISA
  1442. Arguments:
  1443. hConn - Connection context (pointer to WAM_EXEC_INFO)
  1444. Buffer - pointer to the buffer containing the data to be sent to the client
  1445. lpdwBytes - pointer to DWORD that contains the size of data to be
  1446. sent out to client when this function is called.
  1447. On return, if this is a synchronous write, then this location
  1448. will contain the number of bytes actually sent out.
  1449. dwReserved - Reserved set of flags
  1450. For now,
  1451. HSE_IO_ASYNC - indicates that Async Write should be done
  1452. HSE_IO_SYNC - (default) indicates that Sync. Write should be done.
  1453. Return Value:
  1454. TRUE on success, FALSE on failure
  1455. See GetLastError() for error code
  1456. Note:
  1457. Atmost one async IO operation is permitted at a given time.
  1458. Atmost one sync IO operation should be made. Multiple sync IO operations
  1459. may result in unpredictable result.
  1460. Enforcing one sync IO operation would make every single ISAPI to pay a
  1461. penalty for a very few insane ones. So we don't do it.
  1462. */
  1463. BOOL
  1464. WINAPI
  1465. WriteClient(
  1466. HCONN hConn,
  1467. LPVOID Buffer,
  1468. LPDWORD lpdwBytes,
  1469. DWORD dwReserved
  1470. )
  1471. {
  1472. BOOL fReturn = FALSE;
  1473. EXTENSION_CONTROL_BLOCK * pecb = NULL;
  1474. WAM_EXEC_INFO * pWamExecInfo = NULL;
  1475. IWamRequest * pIWamRequest = NULL;
  1476. HANDLE hCurrentUser = NULL;
  1477. IF_DEBUG( WAM_ISA_CALLS ) {
  1478. DBGPRINTF(( DBG_CONTEXT,
  1479. "WriteClient:\n\t"
  1480. "hConn = (%08x)\t"
  1481. "Buffer = (%08x)\t"
  1482. "*lpdwBytes = %d\t"
  1483. "\n"
  1484. ,
  1485. hConn,
  1486. Buffer,
  1487. lpdwBytes ? *lpdwBytes : -1
  1488. ));
  1489. }
  1490. //
  1491. // Return failure when invalid Buffer is supplied
  1492. //
  1493. // NOTE we do this before validating ecb
  1494. //
  1495. if ( (NULL == Buffer) || (NULL == lpdwBytes) ) {
  1496. SetLastError( ERROR_INVALID_PARAMETER);
  1497. return ( FALSE);
  1498. }
  1499. //
  1500. // Ignore zero length sends
  1501. //
  1502. // NOTE we do this before validating ecb
  1503. // so we don't need to release iwamreq ptr
  1504. //
  1505. if ( *lpdwBytes == 0 ) {
  1506. return TRUE;
  1507. }
  1508. //
  1509. // Get ISA context from connection handle - bail if bogus
  1510. // - if this succeeds, we have usable WAM_EXEC_INFO and IWamRequest ptrs
  1511. // - if this fails, GetISAContext calls SetLastError so we don't need to
  1512. //
  1513. if( !GetISAContext( hConn,
  1514. &pecb,
  1515. &pWamExecInfo,
  1516. &pIWamRequest ) ) {
  1517. return FALSE;
  1518. }
  1519. if ( !pWamExecInfo->QueryPWam()->FInProcess() )
  1520. {
  1521. hCurrentUser = INVALID_HANDLE_VALUE;
  1522. }
  1523. //
  1524. // Branch based on Async IO or Synchronous IO operation
  1525. //
  1526. if ( (dwReserved & HSE_IO_ASYNC) ) {
  1527. //
  1528. // Check for error condition in the AsyncIO callback path
  1529. //
  1530. if ((pWamExecInfo->_AsyncIoInfo._pfnHseIO == NULL) ||
  1531. (pWamExecInfo->_AsyncIoInfo._dwOutstandingIO)
  1532. ) {
  1533. DBGPRINTF(( DBG_CONTEXT,
  1534. "%08x::Async WriteClient() requested when IO in progress"
  1535. " or when Context not supplied.\n",
  1536. pWamExecInfo));
  1537. //
  1538. // Set error code and fall-through
  1539. // - so that we will properly release pWamExecInfo
  1540. // and WamRequest pointers
  1541. //
  1542. SetLastError( ERROR_INVALID_PARAMETER);
  1543. fReturn = (FALSE);
  1544. } else {
  1545. //
  1546. // 1. Set Request state to be async IO from ISAPI client
  1547. // 2. Submit Async IOP
  1548. // 3. Return to the ISAPI application
  1549. //
  1550. pWamExecInfo->InitAsyncIO( ASYNC_IO_TYPE_WRITE );
  1551. pWamExecInfo->_AsyncIoInfo._cbLastAsyncIO = *lpdwBytes;
  1552. DoRevertHack( &hCurrentUser );
  1553. fReturn = BoolFromHresult(
  1554. pIWamRequest->AsyncWriteClient(
  1555. #ifdef _WIN64
  1556. (UINT64) pWamExecInfo,
  1557. #else
  1558. (ULONG_PTR) pWamExecInfo,
  1559. #endif
  1560. (unsigned char *) Buffer,
  1561. *lpdwBytes,
  1562. dwReserved
  1563. ) );
  1564. UndoRevertHack( &hCurrentUser );
  1565. if ( !fReturn ) {
  1566. pWamExecInfo->UninitAsyncIO();
  1567. }
  1568. }
  1569. } else {
  1570. //
  1571. // Submit synchronous IO operation
  1572. //
  1573. DWORD cbToWrite = *lpdwBytes;
  1574. DoRevertHack( &hCurrentUser );
  1575. fReturn = BoolFromHresult( pIWamRequest->
  1576. SyncWriteClient( cbToWrite,
  1577. (unsigned char *) Buffer,
  1578. lpdwBytes,
  1579. dwReserved ) );
  1580. UndoRevertHack( &hCurrentUser );
  1581. }
  1582. //
  1583. // Release isa context
  1584. // Balances GetISAContext at top of this function
  1585. //
  1586. ReleaseISAContext(
  1587. &pecb
  1588. , &pWamExecInfo
  1589. , &pIWamRequest
  1590. );
  1591. return ( fReturn );
  1592. } // WriteClient()
  1593. BOOL
  1594. WINAPI
  1595. ReadClient(
  1596. HCONN hConn,
  1597. LPVOID Buffer,
  1598. LPDWORD lpdwBytes
  1599. )
  1600. {
  1601. BOOL fReturn = FALSE;
  1602. EXTENSION_CONTROL_BLOCK * pecb = NULL;
  1603. WAM_EXEC_INFO * pWamExecInfo = NULL;
  1604. IWamRequest * pIWamRequest = NULL;
  1605. HANDLE hCurrentUser = NULL;
  1606. IF_DEBUG( WAM_ISA_CALLS ) {
  1607. DBGPRINTF(( DBG_CONTEXT,
  1608. "ReadClient:\n\t"
  1609. "hConn = (%08x)\t"
  1610. "Buffer = (%08x)\t"
  1611. "*lpdwBytes = %d\t"
  1612. "\n"
  1613. ,
  1614. hConn,
  1615. Buffer,
  1616. lpdwBytes ? *lpdwBytes : -1
  1617. ));
  1618. }
  1619. //
  1620. // Return failure when invalid Buffer is supplied
  1621. //
  1622. // NOTE we do this before validating ecb
  1623. //
  1624. if ( (NULL == Buffer) || (NULL == lpdwBytes) ) {
  1625. SetLastError( ERROR_INVALID_PARAMETER);
  1626. return ( FALSE);
  1627. }
  1628. //
  1629. // Get ISA context from connection handle - bail if bogus
  1630. // - if this succeeds, we have usable WAM_EXEC_INFO and IWamRequest ptrs
  1631. // - if this fails, GetISAContext calls SetLastError so we don't need to
  1632. //
  1633. if( !GetISAContext( hConn,
  1634. &pecb,
  1635. &pWamExecInfo,
  1636. &pIWamRequest ) ) {
  1637. return FALSE;
  1638. }
  1639. if ( !pWamExecInfo->QueryPWam()->FInProcess() )
  1640. {
  1641. hCurrentUser = INVALID_HANDLE_VALUE;
  1642. }
  1643. DoRevertHack( &hCurrentUser );
  1644. fReturn = BoolFromHresult( pIWamRequest->SyncReadClient(
  1645. (unsigned char *) Buffer,
  1646. *lpdwBytes,
  1647. lpdwBytes) );
  1648. UndoRevertHack( &hCurrentUser );
  1649. //
  1650. // Release isa context
  1651. // Balances GetISAContext at top of this function
  1652. //
  1653. ReleaseISAContext(
  1654. &pecb
  1655. , &pWamExecInfo
  1656. , &pIWamRequest
  1657. );
  1658. return ( fReturn );
  1659. } // ReadClient()