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.

1309 lines
30 KiB

  1. /*++
  2. Copyright (c) 1999-2001 Microsoft Corporation
  3. Module Name :
  4. w3isapi.cxx
  5. Abstract:
  6. IIS Plus ISAPI Handler
  7. Author:
  8. Wade Hilmo (WadeH) 03-Feb-2000
  9. Project:
  10. w3isapi.dll
  11. --*/
  12. /************************************************************
  13. * Include Headers
  14. ************************************************************/
  15. #include "precomp.hxx"
  16. #include "isapi_context.hxx"
  17. #include "server_support.hxx"
  18. /************************************************************
  19. * Globals
  20. ************************************************************/
  21. CHAR g_szClsid[SIZE_CLSID_STRING];
  22. CHAR g_szIsapiHandlerInstance[SIZE_CLSID_STRING];
  23. DWORD g_dwPidW3Core;
  24. /************************************************************
  25. * Declarations
  26. ************************************************************/
  27. BOOL
  28. WINAPI
  29. GetServerVariable(
  30. HCONN hConn,
  31. LPSTR lpszVariableName,
  32. LPVOID lpvBuffer,
  33. LPDWORD lpdwSize
  34. );
  35. BOOL
  36. WINAPI
  37. WriteClient(
  38. HCONN ConnID,
  39. LPVOID Buffer,
  40. LPDWORD lpdwBytes,
  41. DWORD dwReserved
  42. );
  43. BOOL
  44. WINAPI
  45. ReadClient(
  46. HCONN ConnID,
  47. LPVOID lpvBuffer,
  48. LPDWORD lpdwSize
  49. );
  50. BOOL
  51. WINAPI
  52. ServerSupportFunction(
  53. HCONN hConn,
  54. DWORD dwHSERequest,
  55. LPVOID lpvBuffer,
  56. LPDWORD lpdwSize,
  57. LPDWORD lpdwDataType
  58. );
  59. HRESULT
  60. ProcessIsapiRequest(
  61. IIsapiCore * pIsapiCore,
  62. ISAPI_CORE_DATA * pCoreData,
  63. DWORD * pHseResult
  64. );
  65. HRESULT
  66. ProcessIsapiCompletion(
  67. VOID * pContext,
  68. DWORD cbCompletion,
  69. DWORD dwCompletionStatus
  70. );
  71. HRESULT
  72. InitModule(
  73. LPCSTR szClsid,
  74. LPCSTR szIsapiHandlerInstance,
  75. DWORD dwPidW3Core
  76. );
  77. VOID
  78. TerminateModule( VOID );
  79. // BUGBUG
  80. #undef INET_INFO_KEY
  81. #undef INET_INFO_PARAMETERS_KEY
  82. //
  83. // Configuration parameters registry key.
  84. //
  85. #define INET_INFO_KEY \
  86. "System\\CurrentControlSet\\Services\\w3svc"
  87. #define INET_INFO_PARAMETERS_KEY \
  88. INET_INFO_KEY "\\Parameters"
  89. const CHAR g_pszWpRegLocation[] =
  90. INET_INFO_PARAMETERS_KEY "\\w3isapi";
  91. DECLARE_DEBUG_PRINTS_OBJECT();
  92. DECLARE_DEBUG_VARIABLE();
  93. DECLARE_PLATFORM_TYPE();
  94. /************************************************************
  95. * Type Definitions
  96. ************************************************************/
  97. HRESULT
  98. InitModule(
  99. LPCSTR szClsid,
  100. LPCSTR szIsapiHandlerInstance,
  101. DWORD dwPidW3Core
  102. )
  103. /*++
  104. Routine Description:
  105. Initializes the w3isapi module
  106. Arguments:
  107. szClsid - In the OOP case, this is the CLSID of
  108. the application being hosted. This
  109. value may be NULL (ie. in the case of
  110. inproc ISAPI).
  111. szIsapiHandlerInstance - The instance ID of the ISAPI handler
  112. that's initializing this module.
  113. dwPidW3Core - The PID of the process containing the
  114. core server that's responsible for this
  115. module
  116. Return Value:
  117. HRESULT
  118. --*/
  119. {
  120. HRESULT hr = NOERROR;
  121. CREATE_DEBUG_PRINT_OBJECT("w3isapi");
  122. if (!VALID_DEBUG_PRINT_OBJECT())
  123. {
  124. return E_FAIL;
  125. }
  126. LOAD_DEBUG_FLAGS_FROM_REG_STR( g_pszWpRegLocation, DEBUG_ERROR );
  127. INITIALIZE_PLATFORM_TYPE();
  128. DBGPRINTF((
  129. DBG_CONTEXT,
  130. "Initializing w3isapi.dll - CLSID: %s, "
  131. "ISAPI Handler: %s, W3Core PID %d.\r\n",
  132. szClsid ? szClsid : "NULL",
  133. szIsapiHandlerInstance,
  134. dwPidW3Core
  135. ));
  136. //
  137. // If g_pDllManager is not NULL at this point, then
  138. // this module is being intialized multiple times. This
  139. // is an unexpected state.
  140. //
  141. if ( g_pDllManager != NULL )
  142. {
  143. DBGPRINTF((
  144. DBG_CONTEXT,
  145. "Warning - w3isapi.dll previously initalized.\r\n"
  146. "Previous CLSID: %s, Previous ISAPI Handler: %s, "
  147. "Previous W3Core PID: %d.\r\n",
  148. g_szClsid,
  149. g_szIsapiHandlerInstance,
  150. g_dwPidW3Core
  151. ));
  152. DBG_ASSERT( FALSE && "w3isapi.dll previously initialized." );
  153. }
  154. g_pDllManager = new ISAPI_DLL_MANAGER();
  155. if( g_pDllManager == NULL )
  156. {
  157. hr = E_OUTOFMEMORY;
  158. }
  159. hr = ISAPI_CONTEXT::Initialize();
  160. if ( FAILED( hr ) )
  161. {
  162. delete g_pDllManager;
  163. g_pDllManager = NULL;
  164. }
  165. hr = ISAPI_DLL::Initialize();
  166. if ( FAILED( hr ) )
  167. {
  168. delete g_pDllManager;
  169. g_pDllManager = NULL;
  170. ISAPI_CONTEXT::Terminate();
  171. }
  172. //
  173. // If we've successfully initialized, then store
  174. // the information from the caller so that we can
  175. // debug double initializations.
  176. //
  177. if ( SUCCEEDED( hr ) )
  178. {
  179. if ( szClsid )
  180. {
  181. strncpy(
  182. g_szClsid,
  183. szClsid,
  184. SIZE_CLSID_STRING
  185. );
  186. g_szClsid[SIZE_CLSID_STRING - 1] = '\0';
  187. }
  188. else
  189. {
  190. strcpy( g_szClsid, "NULL" );
  191. }
  192. strncpy(
  193. g_szIsapiHandlerInstance,
  194. szIsapiHandlerInstance,
  195. SIZE_CLSID_STRING
  196. );
  197. g_szIsapiHandlerInstance[SIZE_CLSID_STRING - 1] = '\0';
  198. g_dwPidW3Core = dwPidW3Core;
  199. }
  200. return hr;
  201. }
  202. VOID
  203. TerminateModule( VOID )
  204. /*++
  205. Routine Description:
  206. Terminates the w3isapi module
  207. Arguments:
  208. None
  209. Return Value:
  210. None
  211. --*/
  212. {
  213. ISAPI_CONTEXT::Terminate();
  214. DBG_ASSERT( g_pDllManager );
  215. if( g_pDllManager )
  216. {
  217. delete g_pDllManager;
  218. g_pDllManager = NULL;
  219. }
  220. ISAPI_DLL::Terminate();
  221. DELETE_DEBUG_PRINT_OBJECT();
  222. }
  223. HRESULT
  224. ProcessIsapiRequest(
  225. IIsapiCore * pIsapiCore,
  226. ISAPI_CORE_DATA * pCoreData,
  227. DWORD * pHseResult
  228. )
  229. /*++
  230. Routine Description:
  231. Processes an ISAPI request
  232. Arguments:
  233. pIsapiCore - The interface that provides connectivity to the core server
  234. pCoreData - The core data that describes the request
  235. pHseResult - Upon return, contains the return code from
  236. the extension's HttpExtensionProc
  237. Return Value:
  238. HRESULT
  239. --*/
  240. {
  241. ISAPI_DLL * pIsapiDll = NULL;
  242. DWORD dwIsapiReturn = HSE_STATUS_ERROR;
  243. ISAPI_CONTEXT * pIsapiContext = NULL;
  244. PFN_HTTPEXTENSIONPROC pfnHttpExtensionProc;
  245. EXTENSION_CONTROL_BLOCK * pEcb = NULL;
  246. HRESULT hr = NO_ERROR;
  247. ISAPI_CORE_DATA * pTempCoreData = NULL;
  248. DBG_ASSERT( g_pDllManager );
  249. //
  250. // This function is only called by w3core.dll
  251. //
  252. DBG_ASSERT( pIsapiCore );
  253. DBG_ASSERT( pCoreData );
  254. DBG_ASSERT( pHseResult );
  255. //
  256. // If this request is running OOP, then make a local copy
  257. // and fix up the core data internal pointers.
  258. //
  259. if ( pCoreData->fIsOop )
  260. {
  261. pTempCoreData = (ISAPI_CORE_DATA*) LocalAlloc( LPTR, pCoreData->cbSize );
  262. if ( !pTempCoreData )
  263. {
  264. hr = HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
  265. goto Failed;
  266. }
  267. memcpy( pTempCoreData, pCoreData, pCoreData->cbSize );
  268. //
  269. // All the extra data begins right at the end of pCoreData, start
  270. // pointing there
  271. //
  272. pTempCoreData->szGatewayImage = (LPWSTR)(pTempCoreData + 1);
  273. pTempCoreData->szApplMdPathW = (LPWSTR)((LPSTR)pTempCoreData->szGatewayImage + pTempCoreData->cbGatewayImage);
  274. pTempCoreData->szPathTranslatedW = (LPWSTR)((LPSTR)pTempCoreData->szApplMdPathW + pTempCoreData->cbApplMdPathW);
  275. pTempCoreData->szPhysicalPath = (LPSTR)pTempCoreData->szPathTranslatedW + pTempCoreData->cbPathTranslatedW;
  276. pTempCoreData->szPathInfo = pTempCoreData->szPhysicalPath + pTempCoreData->cbPhysicalPath;
  277. pTempCoreData->szMethod = pTempCoreData->szPathInfo + pTempCoreData->cbPathInfo;
  278. pTempCoreData->szQueryString = pTempCoreData->szMethod + pTempCoreData->cbMethod;
  279. pTempCoreData->szPathTranslated = pTempCoreData->szQueryString + pTempCoreData->cbQueryString;
  280. pTempCoreData->szContentType = pTempCoreData->szPathTranslated + pTempCoreData->cbPathTranslated;
  281. pTempCoreData->szConnection = pTempCoreData->szContentType + pTempCoreData->cbContentType;
  282. pTempCoreData->szUserAgent = pTempCoreData->szConnection + pTempCoreData->cbConnection;
  283. pTempCoreData->szCookie = pTempCoreData->szUserAgent + pTempCoreData->cbUserAgent;
  284. pTempCoreData->szApplMdPath = pTempCoreData->szCookie + pTempCoreData->cbCookie;
  285. if ( pTempCoreData->cbAvailableEntity )
  286. {
  287. pTempCoreData->pAvailableEntity = pTempCoreData->szApplMdPath + pTempCoreData->cbApplMdPath;
  288. }
  289. else
  290. {
  291. pTempCoreData->pAvailableEntity = NULL;
  292. }
  293. //
  294. // We'll set pCoreData to point to our temp one. This
  295. // doesn't leak because the ISAPI_CONTEXT destructor is smart
  296. // enough to know it needs to be deleted in the OOP case.
  297. //
  298. pCoreData = pTempCoreData;
  299. }
  300. //
  301. // Get the entry point for the ISAPI
  302. //
  303. hr = g_pDllManager->GetIsapi(
  304. pCoreData->szGatewayImage,
  305. &pIsapiDll,
  306. pCoreData->hToken,
  307. pCoreData->pSid
  308. );
  309. if ( FAILED( hr ) )
  310. {
  311. goto Failed;
  312. }
  313. //
  314. // Construct the ISAPI_CONTEXT for this request. Once it's
  315. // allocated, it owns the lifetime of the ISAPI_REQUEST. When
  316. // the ISAPI_CONTEXT is deallocated, it may release the final
  317. // reference.
  318. //
  319. pIsapiContext = new ISAPI_CONTEXT( pIsapiCore, pCoreData, pIsapiDll );
  320. if ( pIsapiContext == NULL )
  321. {
  322. hr = HRESULT_FROM_WIN32( GetLastError () );
  323. goto Failed;
  324. }
  325. //
  326. // Set the ECB
  327. //
  328. pEcb = pIsapiContext->QueryECB();
  329. //
  330. // Set the ECB function pointers
  331. //
  332. pEcb->GetServerVariable = GetServerVariable;
  333. pEcb->WriteClient = WriteClient;
  334. pEcb->ReadClient = ReadClient;
  335. pEcb->ServerSupportFunction = ServerSupportFunction;
  336. //
  337. // Get the extension's entry point
  338. //
  339. pfnHttpExtensionProc = pIsapiDll->QueryHttpExtensionProc();
  340. //
  341. // If we are running OOP, set the COM state so that the
  342. // extension can CoInitialize/CoUninitialize.
  343. //
  344. if ( pIsapiContext->QueryIsOop() )
  345. {
  346. hr = pIsapiContext->SetComStateForOop();
  347. DBG_ASSERT( SUCCEEDED( hr ) );
  348. }
  349. //
  350. // Impersonate the authenticated user and call it
  351. //
  352. if ( !SetThreadToken( NULL, pIsapiContext->QueryToken() ) )
  353. {
  354. hr = HRESULT_FROM_WIN32( GetLastError() );
  355. goto Failed;
  356. }
  357. pIsapiContext->ReferenceIsapiContext();
  358. dwIsapiReturn = pfnHttpExtensionProc( pEcb );
  359. DBG_REQUIRE( RevertToSelf() );
  360. if ( pIsapiContext->QueryIsOop() )
  361. {
  362. pIsapiContext->RestoreComStateForOop();
  363. }
  364. pIsapiContext->DereferenceIsapiContext();
  365. switch ( dwIsapiReturn )
  366. {
  367. case HSE_STATUS_PENDING:
  368. //
  369. // Don't dereference the ISAPI_CONTEXT. This
  370. // will guarantee that it lives on beyond the
  371. // return from this function.
  372. //
  373. break;
  374. case HSE_STATUS_SUCCESS_AND_KEEP_CONN:
  375. //
  376. // Special case of success. The extension wants
  377. // to keep the connection open, even though we may
  378. // not have detected proper response headers.
  379. //
  380. // After setting the disconnect mode, fall through.
  381. //
  382. if ( pIsapiContext->QueryClientKeepConn() )
  383. {
  384. pIsapiContext->SetKeepConn( TRUE );
  385. pIsapiCore->SetConnectionClose( FALSE );
  386. }
  387. case HSE_STATUS_ERROR:
  388. case HSE_STATUS_SUCCESS:
  389. default:
  390. pIsapiContext->DereferenceIsapiContext();
  391. break;
  392. }
  393. *pHseResult = dwIsapiReturn;
  394. pIsapiDll->DereferenceIsapiDll();
  395. pIsapiDll = NULL;
  396. return NO_ERROR;
  397. Failed:
  398. DBG_ASSERT( FAILED( hr ) );
  399. if ( pIsapiContext )
  400. {
  401. pIsapiContext->DereferenceIsapiContext();
  402. pIsapiContext = NULL;
  403. }
  404. else
  405. {
  406. //
  407. // In OOP case, we're depending on the ISAPI_CONTEXT destructor
  408. // to free the copy of the core data and close the impersonation
  409. // token. If we weren't able to allocate one, we'll have to
  410. // do it here.
  411. //
  412. if ( pCoreData->fIsOop )
  413. {
  414. CloseHandle( pCoreData->hToken );
  415. if ( pTempCoreData )
  416. {
  417. LocalFree( pTempCoreData );
  418. pTempCoreData = NULL;
  419. }
  420. }
  421. }
  422. if ( pIsapiDll )
  423. {
  424. pIsapiDll->DereferenceIsapiDll();
  425. pIsapiDll = NULL;
  426. }
  427. return hr;
  428. }
  429. HRESULT
  430. ProcessIsapiCompletion(
  431. DWORD64 IsaContext,
  432. DWORD cbCompletion,
  433. DWORD dwCompletionStatus
  434. )
  435. /*++
  436. Routine Description:
  437. Processes an I/O completion for an ISAPI extension
  438. Arguments:
  439. IsaContext - The ISAPI_CONTEXT for this completion
  440. cbCompletion - The byte count associated with the completion
  441. dwCompletionStatus - The result code associated with the completion
  442. Return Value:
  443. HRESULT
  444. --*/
  445. {
  446. ISAPI_CONTEXT * pIsapiContext;
  447. ASYNC_PENDING IoType;
  448. PFN_HSE_IO_COMPLETION pfnCompletion;
  449. DWORD cbLastIo;
  450. HRESULT hr = NO_ERROR;
  451. DBG_REQUIRE( pIsapiContext = reinterpret_cast<ISAPI_CONTEXT*>( IsaContext ) );
  452. pIsapiContext->ReferenceIsapiContext();
  453. //
  454. // Magical hand waving:
  455. //
  456. // If this is a completion for a write, then we need to
  457. // restore the original buffer size. This is necessary
  458. // to keep from confusing ISAPI extensions that examine
  459. // the cbCompletion value in the case where a filter
  460. // changed the size of the buffer before the actual
  461. // IO occured.
  462. //
  463. // If this is a completion for an EXEC_URL, then we need
  464. // to set the dwCompletionStatus to ERROR_SUCCESS. The
  465. // caller of the EXEC_URL should use GET_EXECUTE_URL_STATUS
  466. // to see the result of the child URL.
  467. //
  468. cbLastIo = pIsapiContext->QueryLastAsyncIo();
  469. pIsapiContext->SetLastAsyncIo( 0 );
  470. IoType = pIsapiContext->UninitAsyncIo();
  471. if ( IoType == AsyncWritePending )
  472. {
  473. cbCompletion = cbLastIo;
  474. }
  475. else if ( IoType == AsyncExecPending )
  476. {
  477. dwCompletionStatus = ERROR_SUCCESS;
  478. }
  479. //
  480. // If the completion context indicates a completion routine,
  481. // then call it.
  482. //
  483. pfnCompletion = pIsapiContext->QueryPfnIoCompletion();
  484. if ( pfnCompletion )
  485. {
  486. //
  487. // First, impersonate the client
  488. //
  489. if ( SetThreadToken( NULL, pIsapiContext->QueryToken() ) )
  490. {
  491. pfnCompletion(
  492. pIsapiContext->QueryECB(),
  493. pIsapiContext->QueryExtensionContext(),
  494. cbCompletion,
  495. dwCompletionStatus
  496. );
  497. DBG_REQUIRE( RevertToSelf() );
  498. }
  499. else
  500. {
  501. hr = HRESULT_FROM_WIN32( GetLastError() );
  502. }
  503. }
  504. pIsapiContext->DereferenceIsapiContext();
  505. return hr;
  506. }
  507. BOOL
  508. WINAPI
  509. GetServerVariable(
  510. HCONN hConn,
  511. LPSTR lpszVariableName,
  512. LPVOID lpvBuffer,
  513. LPDWORD lpdwSize
  514. )
  515. /*++
  516. Routine Description:
  517. Retrieves a server variable
  518. Arguments:
  519. hConn - The ConnID associated with the request. This
  520. value is opaque to the ISAPI that calls into
  521. this function, but it can be cast to the
  522. ISAPI_CONTEXT associated with the request.
  523. lpszVariableName - The name of the variable to retrieve
  524. lpvBuffer - Upon return, contains the value of the variable
  525. lpdwSize - On entry, contains the size of lpvBuffer, upon
  526. return, contains the number of bytes actually
  527. needed to contain the value.
  528. Return Value:
  529. HRESULT
  530. --*/
  531. {
  532. ISAPI_CONTEXT * pIsapiContext;
  533. IIsapiCore * pIsapiCore;
  534. HANDLE hCurrentUser;
  535. HRESULT hr;
  536. pIsapiContext = reinterpret_cast<ISAPI_CONTEXT*>( hConn );
  537. //
  538. // Parameter validation
  539. //
  540. if ( pIsapiContext == NULL ||
  541. lpszVariableName == NULL ||
  542. lpdwSize == NULL ||
  543. ( *lpdwSize != 0 && lpvBuffer == NULL ) )
  544. {
  545. SetLastError( ERROR_INVALID_PARAMETER );
  546. return FALSE;
  547. }
  548. pIsapiCore = pIsapiContext->QueryIsapiCoreInterface();
  549. if ( pIsapiCore == NULL )
  550. {
  551. SetLastError( ERROR_INVALID_PARAMETER );
  552. return FALSE;
  553. }
  554. //
  555. // If we are running OOP, then try and get the data
  556. // locally from the process.
  557. //
  558. if ( pIsapiContext->QueryIsOop() )
  559. {
  560. SERVER_VARIABLE_INDEX Index;
  561. Index = LookupServerVariableIndex( lpszVariableName );
  562. if ( Index != ServerVariableExternal )
  563. {
  564. return pIsapiContext->GetOopServerVariableByIndex(
  565. Index,
  566. lpvBuffer,
  567. lpdwSize
  568. );
  569. }
  570. }
  571. //
  572. // Call it
  573. //
  574. pIsapiContext->IsapiDoRevertHack( &hCurrentUser );
  575. hr = pIsapiCore->GetServerVariable(
  576. lpszVariableName,
  577. *lpdwSize ? (BYTE*)lpvBuffer : NULL,
  578. *lpdwSize,
  579. lpdwSize
  580. );
  581. pIsapiContext->IsapiUndoRevertHack( &hCurrentUser);
  582. if ( FAILED( hr ) )
  583. {
  584. SetLastError( WIN32_FROM_HRESULT( hr ) );
  585. return FALSE;
  586. }
  587. return TRUE;
  588. }
  589. BOOL
  590. WINAPI
  591. WriteClient(
  592. HCONN ConnID,
  593. LPVOID Buffer,
  594. LPDWORD lpdwBytes,
  595. DWORD dwReserved
  596. )
  597. /*++
  598. Routine Description:
  599. Writes data to the client
  600. Arguments:
  601. hConn - The ConnID associated with the request. This
  602. value is opaque to the ISAPI that calls into
  603. this function, but it can be cast to the
  604. ISAPI_CONTEXT associated with the request.
  605. Buffer - The data to write
  606. lpdwBytes - On entry, the number of bytes to write. Upon
  607. return, the number of bytes written (or so the
  608. docs say)
  609. dwReserved - Flags (ie. HSE_IO_SYNC, etc.)
  610. Return Value:
  611. HRESULT
  612. --*/
  613. {
  614. ISAPI_CONTEXT * pIsapiContext;
  615. IIsapiCore * pIsapiCore;
  616. HANDLE hCurrentUser;
  617. BOOL fResult;
  618. HRESULT hr;
  619. pIsapiContext = reinterpret_cast<ISAPI_CONTEXT*>( ConnID );
  620. //
  621. // Parameter validation
  622. //
  623. if ( pIsapiContext == NULL ||
  624. lpdwBytes == NULL ||
  625. ( *lpdwBytes != 0 && Buffer == NULL ) )
  626. {
  627. SetLastError( ERROR_INVALID_PARAMETER );
  628. return FALSE;
  629. }
  630. pIsapiCore = pIsapiContext->QueryIsapiCoreInterface();
  631. if ( pIsapiCore == NULL )
  632. {
  633. SetLastError( ERROR_INVALID_PARAMETER );
  634. return FALSE;
  635. }
  636. //
  637. // If the user is sending zero bytes, return TRUE here. Yeah, this
  638. // will be kind of a bogus thing to do because if the call is async,
  639. // we will return successful with no completion ever occuring.
  640. //
  641. // IIS has done this for as long as sync WriteClient has existed, and
  642. // we'd risk breaking legacy code if we change it now.
  643. //
  644. if ( *lpdwBytes == 0 )
  645. {
  646. return TRUE;
  647. }
  648. //
  649. // BUGBUG - Need to map the documented HSE_IO flags to reasonable
  650. // UL equivalents and provide a mechanism to pass them.
  651. //
  652. if ( dwReserved & HSE_IO_ASYNC )
  653. {
  654. //
  655. // Do an asynchronous write
  656. //
  657. // Check to make sure that we have a completion
  658. // function.
  659. //
  660. if ( pIsapiContext->QueryPfnIoCompletion() == NULL ||
  661. pIsapiContext->TryInitAsyncIo( AsyncWritePending ) == FALSE )
  662. {
  663. SetLastError( ERROR_INVALID_PARAMETER );
  664. return FALSE;
  665. }
  666. //
  667. // Some extensions depend on the number of bytes reported in the
  668. // completion to confirm success. In the case where a send raw
  669. // data filter is installed (or if we are using SSL), it's possible
  670. // that the number of bytes in the completion is not what the
  671. // caller expects.
  672. //
  673. // We need to save away the number of bytes that they are sending
  674. // to protect them from themselves.
  675. //
  676. pIsapiContext->SetLastAsyncIo( *lpdwBytes );
  677. pIsapiContext->IsapiDoRevertHack( &hCurrentUser );
  678. hr = pIsapiCore->WriteClient(
  679. reinterpret_cast<DWORD64>( pIsapiContext ),
  680. reinterpret_cast<LPBYTE>( Buffer ),
  681. *lpdwBytes,
  682. HSE_IO_ASYNC
  683. );
  684. pIsapiContext->IsapiUndoRevertHack( &hCurrentUser );
  685. if ( FAILED( hr ) )
  686. {
  687. pIsapiContext->SetLastAsyncIo( 0 );
  688. pIsapiContext->UninitAsyncIo();
  689. }
  690. }
  691. else
  692. {
  693. //
  694. // Do a synchronous write
  695. //
  696. pIsapiContext->IsapiDoRevertHack( &hCurrentUser );
  697. hr = pIsapiCore->WriteClient(
  698. NULL,
  699. reinterpret_cast<LPBYTE>( Buffer ),
  700. *lpdwBytes,
  701. HSE_IO_SYNC
  702. );
  703. pIsapiContext->IsapiUndoRevertHack( &hCurrentUser );
  704. }
  705. if ( FAILED( hr ) )
  706. {
  707. SetLastError( WIN32_FROM_HRESULT( hr ) );
  708. return FALSE;
  709. }
  710. return TRUE;
  711. }
  712. BOOL
  713. WINAPI
  714. ReadClient(
  715. HCONN ConnID,
  716. LPVOID lpvBuffer,
  717. LPDWORD lpdwSize
  718. )
  719. /*++
  720. Routine Description:
  721. Reads data from the client
  722. Arguments:
  723. hConn - The ConnID associated with the request. This
  724. value is opaque to the ISAPI that calls into
  725. this function, but it can be cast to the
  726. ISAPI_CONTEXT associated with the request.
  727. lpvBuffer - Upon return, contains the data read
  728. lpdwsize - On entry, the size of lpvBuffer. Upon
  729. return, the number of bytes read.
  730. Return Value:
  731. HRESULT
  732. --*/
  733. {
  734. ISAPI_CONTEXT * pIsapiContext;
  735. IIsapiCore * pIsapiCore;
  736. HANDLE hCurrentUser;
  737. HRESULT hr;
  738. pIsapiContext = reinterpret_cast<ISAPI_CONTEXT*>( ConnID );
  739. //
  740. // Parameter validation
  741. //
  742. if ( pIsapiContext == NULL ||
  743. lpdwSize == NULL ||
  744. ( *lpdwSize != 0 && lpvBuffer == NULL ) )
  745. {
  746. SetLastError( ERROR_INVALID_PARAMETER );
  747. return FALSE;
  748. }
  749. pIsapiCore = pIsapiContext->QueryIsapiCoreInterface();
  750. if ( pIsapiCore == NULL )
  751. {
  752. SetLastError( ERROR_INVALID_PARAMETER );
  753. return FALSE;
  754. }
  755. pIsapiContext->IsapiDoRevertHack( &hCurrentUser );
  756. hr = pIsapiCore->ReadClient(
  757. NULL,
  758. reinterpret_cast<unsigned char *>( lpvBuffer ),
  759. *lpdwSize,
  760. *lpdwSize,
  761. lpdwSize,
  762. HSE_IO_SYNC
  763. );
  764. pIsapiContext->IsapiUndoRevertHack( &hCurrentUser );
  765. if ( FAILED( hr ) )
  766. {
  767. SetLastError( WIN32_FROM_HRESULT( hr ) );
  768. return FALSE;
  769. }
  770. return TRUE;
  771. }
  772. BOOL
  773. WINAPI
  774. ServerSupportFunction(
  775. HCONN hConn,
  776. DWORD dwHSERequest,
  777. LPVOID lpvBuffer,
  778. LPDWORD lpdwSize,
  779. LPDWORD lpdwDataType
  780. )
  781. /*++
  782. Routine Description:
  783. Dispatches a ServerSupportFunction command to the appropriate
  784. server support function.
  785. Arguments:
  786. hConn - The ConnID associated with the request. This
  787. value is opaque to the ISAPI that calls into
  788. this function, but it can be cast to the
  789. ISAPI_CONTEXT associated with the request.
  790. dwHSERequest - The server support command
  791. lpvBuffer - Command-specific data
  792. lpdwSize - Command-specific data
  793. lpdwDataType - Command-specific data
  794. Return Value:
  795. HRESULT
  796. --*/
  797. {
  798. ISAPI_CONTEXT * pIsapiContext;
  799. HANDLE hCurrentUser;
  800. HRESULT hr = NO_ERROR;
  801. pIsapiContext = reinterpret_cast<ISAPI_CONTEXT*>( hConn );
  802. //
  803. // Parameter validation
  804. //
  805. if ( pIsapiContext == NULL )
  806. {
  807. SetLastError( ERROR_INVALID_PARAMETER );
  808. return FALSE;
  809. }
  810. pIsapiContext->ReferenceIsapiContext();
  811. pIsapiContext->IsapiDoRevertHack( &hCurrentUser );
  812. //
  813. // Handle the specified command
  814. //
  815. switch ( dwHSERequest )
  816. {
  817. case HSE_REQ_SEND_RESPONSE_HEADER:
  818. hr = SSFSendResponseHeader(
  819. pIsapiContext,
  820. reinterpret_cast<LPSTR>( lpvBuffer ),
  821. reinterpret_cast<LPSTR>( lpdwDataType )
  822. );
  823. break;
  824. case HSE_REQ_SEND_RESPONSE_HEADER_EX:
  825. hr = SSFSendResponseHeaderEx(
  826. pIsapiContext,
  827. reinterpret_cast<HSE_SEND_HEADER_EX_INFO*>( lpvBuffer )
  828. );
  829. break;
  830. case HSE_REQ_MAP_URL_TO_PATH:
  831. hr = SSFMapUrlToPath(
  832. pIsapiContext,
  833. reinterpret_cast<LPSTR>( lpvBuffer ),
  834. lpdwSize
  835. );
  836. break;
  837. case HSE_REQ_MAP_URL_TO_PATH_EX:
  838. hr = SSFMapUrlToPathEx(
  839. pIsapiContext,
  840. reinterpret_cast<LPSTR>( lpvBuffer ),
  841. reinterpret_cast<HSE_URL_MAPEX_INFO*>( lpdwDataType ),
  842. lpdwSize
  843. );
  844. break;
  845. case HSE_REQ_MAP_UNICODE_URL_TO_PATH:
  846. hr = SSFMapUnicodeUrlToPath(
  847. pIsapiContext,
  848. reinterpret_cast<LPWSTR>( lpvBuffer ),
  849. lpdwSize
  850. );
  851. break;
  852. case HSE_REQ_MAP_UNICODE_URL_TO_PATH_EX:
  853. hr = SSFMapUnicodeUrlToPathEx(
  854. pIsapiContext,
  855. reinterpret_cast<LPWSTR>( lpvBuffer ),
  856. reinterpret_cast<HSE_UNICODE_URL_MAPEX_INFO*>( lpdwDataType ),
  857. lpdwSize
  858. );
  859. break;
  860. case HSE_REQ_GET_IMPERSONATION_TOKEN:
  861. hr = SSFGetImpersonationToken(
  862. pIsapiContext,
  863. reinterpret_cast<HANDLE*>( lpvBuffer )
  864. );
  865. break;
  866. case HSE_REQ_IS_KEEP_CONN:
  867. hr = SSFIsKeepConn(
  868. pIsapiContext,
  869. reinterpret_cast<BOOL*>( lpvBuffer )
  870. );
  871. break;
  872. case HSE_REQ_DONE_WITH_SESSION:
  873. hr = SSFDoneWithSession(
  874. pIsapiContext,
  875. reinterpret_cast<DWORD*>( lpvBuffer )
  876. );
  877. break;
  878. case HSE_REQ_GET_CERT_INFO_EX:
  879. hr = SSFGetCertInfoEx(
  880. pIsapiContext,
  881. reinterpret_cast<CERT_CONTEXT_EX*>( lpvBuffer )
  882. );
  883. break;
  884. case HSE_REQ_IO_COMPLETION:
  885. hr = SSFIoCompletion(
  886. pIsapiContext,
  887. reinterpret_cast<PFN_HSE_IO_COMPLETION>( lpvBuffer ),
  888. reinterpret_cast<VOID*>( lpdwDataType )
  889. );
  890. break;
  891. case HSE_REQ_ASYNC_READ_CLIENT:
  892. hr = SSFAsyncReadClient(
  893. pIsapiContext,
  894. lpvBuffer,
  895. lpdwSize
  896. );
  897. break;
  898. case HSE_REQ_TRANSMIT_FILE:
  899. hr = SSFTransmitFile(
  900. pIsapiContext,
  901. reinterpret_cast<HSE_TF_INFO*>( lpvBuffer )
  902. );
  903. break;
  904. case HSE_REQ_SEND_URL:
  905. case HSE_REQ_SEND_URL_REDIRECT_RESP:
  906. hr = SSFSendRedirect(
  907. pIsapiContext,
  908. reinterpret_cast<LPSTR>( lpvBuffer )
  909. );
  910. break;
  911. case HSE_REQ_IS_CONNECTED:
  912. hr = SSFIsConnected(
  913. pIsapiContext,
  914. reinterpret_cast<BOOL*>( lpvBuffer )
  915. );
  916. break;
  917. case HSE_APPEND_LOG_PARAMETER:
  918. hr = SSFAppendLog(
  919. pIsapiContext,
  920. reinterpret_cast<LPSTR>( lpvBuffer )
  921. );
  922. break;
  923. case HSE_REQ_EXEC_URL:
  924. hr = SSFExecuteUrl(
  925. pIsapiContext,
  926. reinterpret_cast<HSE_EXEC_URL_INFO*>( lpvBuffer )
  927. );
  928. break;
  929. case HSE_REQ_GET_EXEC_URL_STATUS:
  930. hr = SSFGetExecuteUrlStatus(
  931. pIsapiContext,
  932. reinterpret_cast<HSE_EXEC_URL_STATUS*>( lpvBuffer )
  933. );
  934. break;
  935. case HSE_REQ_SEND_CUSTOM_ERROR:
  936. hr = SSFSendCustomError(
  937. pIsapiContext,
  938. reinterpret_cast<HSE_CUSTOM_ERROR_INFO*>( lpvBuffer )
  939. );
  940. break;
  941. case HSE_REQ_VECTOR_SEND:
  942. hr = SSFVectorSend(
  943. pIsapiContext,
  944. reinterpret_cast<HSE_RESPONSE_VECTOR*>( lpvBuffer )
  945. );
  946. break;
  947. case HSE_REQ_GET_CUSTOM_ERROR_PAGE:
  948. hr = SSFGetCustomErrorPage(
  949. pIsapiContext,
  950. reinterpret_cast<HSE_CUSTOM_ERROR_PAGE_INFO*>( lpvBuffer )
  951. );
  952. break;
  953. case HSE_REQ_IS_IN_PROCESS:
  954. hr = SSFIsInProcess(
  955. pIsapiContext,
  956. reinterpret_cast<DWORD*>( lpvBuffer )
  957. );
  958. break;
  959. case HSE_REQ_GET_SSPI_INFO:
  960. hr = SSFGetSspiInfo(
  961. pIsapiContext,
  962. reinterpret_cast<CtxtHandle*>( lpvBuffer ),
  963. reinterpret_cast<CredHandle*>( lpdwDataType )
  964. );
  965. break;
  966. case HSE_REQ_GET_VIRTUAL_PATH_TOKEN:
  967. hr = SSFGetVirtualPathToken(
  968. pIsapiContext,
  969. reinterpret_cast<LPSTR>( lpvBuffer ),
  970. reinterpret_cast<HANDLE*>( lpdwSize ),
  971. FALSE
  972. );
  973. break;
  974. case HSE_REQ_GET_UNICODE_VIRTUAL_PATH_TOKEN:
  975. hr = SSFGetVirtualPathToken(
  976. pIsapiContext,
  977. reinterpret_cast<LPSTR>( lpvBuffer ),
  978. reinterpret_cast<HANDLE*>( lpdwSize ),
  979. TRUE
  980. );
  981. break;
  982. default:
  983. hr = HRESULT_FROM_WIN32( ERROR_CALL_NOT_IMPLEMENTED );
  984. }
  985. pIsapiContext->IsapiUndoRevertHack( &hCurrentUser );
  986. pIsapiContext->DereferenceIsapiContext();
  987. pIsapiContext = NULL;
  988. if ( FAILED( hr ) )
  989. {
  990. SetLastError( WIN32_FROM_HRESULT( hr ) );
  991. return FALSE;
  992. }
  993. return TRUE;
  994. }