Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2249 lines
61 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. #define W3_ISAPI_MOF_FILE L"W3IsapiMofResource"
  19. #define W3_ISAPI_PATH L"w3isapi.dll"
  20. /************************************************************
  21. * Globals
  22. ************************************************************/
  23. CHAR g_szClsid[SIZE_CLSID_STRING];
  24. CHAR g_szIsapiHandlerInstance[SIZE_CLSID_STRING];
  25. DWORD g_dwPidW3Core;
  26. CEtwTracer * g_pEtwTracer;
  27. /************************************************************
  28. * Declarations
  29. ************************************************************/
  30. BOOL
  31. WINAPI
  32. GetServerVariable(
  33. HCONN hConn,
  34. LPSTR lpszVariableName,
  35. LPVOID lpvBuffer,
  36. LPDWORD lpdwSize
  37. );
  38. BOOL
  39. WINAPI
  40. WriteClient(
  41. HCONN ConnID,
  42. LPVOID Buffer,
  43. LPDWORD lpdwBytes,
  44. DWORD dwReserved
  45. );
  46. BOOL
  47. WINAPI
  48. ReadClient(
  49. HCONN ConnID,
  50. LPVOID lpvBuffer,
  51. LPDWORD lpdwSize
  52. );
  53. BOOL
  54. WINAPI
  55. ServerSupportFunction(
  56. HCONN hConn,
  57. DWORD dwHSERequest,
  58. LPVOID lpvBuffer,
  59. LPDWORD lpdwSize,
  60. LPDWORD lpdwDataType
  61. );
  62. HRESULT
  63. ProcessIsapiRequest(
  64. IIsapiCore * pIsapiCore,
  65. ISAPI_CORE_DATA * pCoreData,
  66. DWORD * pHseResult
  67. );
  68. HRESULT
  69. ProcessIsapiCompletion(
  70. VOID * pContext,
  71. DWORD cbCompletion,
  72. DWORD dwCompletionStatus
  73. );
  74. HRESULT
  75. InitModule(
  76. LPCSTR szClsid,
  77. LPCSTR szIsapiHandlerInstance,
  78. DWORD dwPidW3Core
  79. );
  80. VOID
  81. TerminateModule( VOID );
  82. VOID
  83. FixupIsapiCoreData(
  84. ISAPI_CORE_DATA * pCoreData
  85. );
  86. // BUGBUG
  87. #undef INET_INFO_KEY
  88. #undef INET_INFO_PARAMETERS_KEY
  89. //
  90. // Configuration parameters registry key.
  91. //
  92. #define INET_INFO_KEY \
  93. "System\\CurrentControlSet\\Services\\w3svc"
  94. #define INET_INFO_PARAMETERS_KEY \
  95. INET_INFO_KEY "\\Parameters"
  96. const CHAR g_pszWpRegLocation[] =
  97. INET_INFO_PARAMETERS_KEY "\\w3isapi";
  98. DECLARE_DEBUG_PRINTS_OBJECT();
  99. DECLARE_DEBUG_VARIABLE();
  100. DECLARE_PLATFORM_TYPE();
  101. /************************************************************
  102. * Type Definitions
  103. ************************************************************/
  104. HRESULT
  105. InitModule(
  106. LPCSTR szClsid,
  107. LPCSTR szIsapiHandlerInstance,
  108. DWORD dwPidW3Core
  109. )
  110. /*++
  111. Routine Description:
  112. Initializes the w3isapi module
  113. Arguments:
  114. szClsid - In the OOP case, this is the CLSID of
  115. the application being hosted. This
  116. value may be NULL (ie. in the case of
  117. inproc ISAPI).
  118. szIsapiHandlerInstance - The instance ID of the ISAPI handler
  119. that's initializing this module.
  120. dwPidW3Core - The PID of the process containing the
  121. core server that's responsible for this
  122. module
  123. Return Value:
  124. HRESULT
  125. --*/
  126. {
  127. HRESULT hr = NOERROR;
  128. BOOL fIisUtilInitialized = FALSE;
  129. BOOL fIsapiContextInitialized = FALSE;
  130. BOOL fIsapiDllInitialized = FALSE;
  131. CREATE_DEBUG_PRINT_OBJECT("w3isapi");
  132. if (!VALID_DEBUG_PRINT_OBJECT())
  133. {
  134. return E_FAIL;
  135. }
  136. LOAD_DEBUG_FLAGS_FROM_REG_STR( g_pszWpRegLocation, DEBUG_ERROR );
  137. INITIALIZE_PLATFORM_TYPE();
  138. DBGPRINTF((
  139. DBG_CONTEXT,
  140. "Initializing w3isapi.dll - CLSID: %s, "
  141. "ISAPI Handler: %s, W3Core PID %d.\r\n",
  142. szClsid ? szClsid : "NULL",
  143. szIsapiHandlerInstance,
  144. dwPidW3Core
  145. ));
  146. //
  147. // Initialize IISUTIL
  148. //
  149. if ( !InitializeIISUtil() )
  150. {
  151. hr = HRESULT_FROM_WIN32( GetLastError() );
  152. DBGPRINTF(( DBG_CONTEXT,
  153. "Error initializing IISUTIL. hr = %x\n",
  154. hr ));
  155. goto Failed;
  156. }
  157. fIisUtilInitialized = TRUE;
  158. //
  159. // Intialize trace stuff so that initialization can use it
  160. //
  161. g_pEtwTracer = new CEtwTracer;
  162. if ( g_pEtwTracer == NULL )
  163. {
  164. hr = E_OUTOFMEMORY;
  165. goto Failed;
  166. }
  167. hr = g_pEtwTracer->Register( &IsapiControlGuid,
  168. W3_ISAPI_PATH,
  169. W3_ISAPI_MOF_FILE );
  170. if ( FAILED( hr ) )
  171. {
  172. goto Failed;
  173. }
  174. //
  175. // If g_pDllManager is not NULL at this point, then
  176. // this module is being intialized multiple times. This
  177. // is an unexpected state.
  178. //
  179. if ( g_pDllManager != NULL )
  180. {
  181. DBGPRINTF((
  182. DBG_CONTEXT,
  183. "Warning - w3isapi.dll previously initalized.\r\n"
  184. "Previous CLSID: %s, Previous ISAPI Handler: %s, "
  185. "Previous W3Core PID: %d.\r\n",
  186. g_szClsid,
  187. g_szIsapiHandlerInstance,
  188. g_dwPidW3Core
  189. ));
  190. DBG_ASSERT( g_pDllManager );
  191. //
  192. // Normally, we'd exit this function via "goto Failed" on
  193. // failure. This case is an exception. When this function
  194. // returns here, the WAM_PROCESS_MANAGER will just kill off
  195. // this process, so we're not worried about returning in a
  196. // non-perfect state at this point.
  197. //
  198. return HRESULT_FROM_WIN32( ERROR_ALREADY_INITIALIZED );
  199. }
  200. g_pDllManager = new ISAPI_DLL_MANAGER( szClsid == NULL ? TRUE : FALSE );
  201. if( g_pDllManager == NULL )
  202. {
  203. hr = E_OUTOFMEMORY;
  204. goto Failed;
  205. }
  206. hr = ISAPI_CONTEXT::Initialize();
  207. if ( FAILED( hr ) )
  208. {
  209. goto Failed;
  210. }
  211. fIsapiContextInitialized = TRUE;
  212. hr = ISAPI_DLL::Initialize();
  213. if ( FAILED( hr ) )
  214. {
  215. goto Failed;
  216. }
  217. fIsapiDllInitialized = TRUE;
  218. //
  219. // If we've successfully initialized, then store
  220. // the information from the caller so that we can
  221. // debug double initializations.
  222. //
  223. if ( SUCCEEDED( hr ) )
  224. {
  225. if ( szClsid )
  226. {
  227. strncpy(
  228. g_szClsid,
  229. szClsid,
  230. SIZE_CLSID_STRING
  231. );
  232. g_szClsid[SIZE_CLSID_STRING - 1] = '\0';
  233. }
  234. else
  235. {
  236. strcpy( g_szClsid, "NULL" );
  237. }
  238. strncpy(
  239. g_szIsapiHandlerInstance,
  240. szIsapiHandlerInstance,
  241. SIZE_CLSID_STRING
  242. );
  243. g_szIsapiHandlerInstance[SIZE_CLSID_STRING - 1] = '\0';
  244. g_dwPidW3Core = dwPidW3Core;
  245. }
  246. return hr;
  247. Failed:
  248. DBG_ASSERT( FAILED( hr ) );
  249. if ( g_pEtwTracer )
  250. {
  251. delete g_pEtwTracer;
  252. g_pEtwTracer = NULL;
  253. }
  254. if ( g_pDllManager )
  255. {
  256. delete g_pDllManager;
  257. g_pDllManager = NULL;
  258. }
  259. if ( fIisUtilInitialized )
  260. {
  261. TerminateIISUtil();
  262. fIisUtilInitialized = FALSE;
  263. }
  264. if ( fIsapiContextInitialized )
  265. {
  266. ISAPI_CONTEXT::Terminate();
  267. fIsapiContextInitialized = FALSE;
  268. }
  269. if ( fIsapiDllInitialized )
  270. {
  271. ISAPI_DLL::Terminate();
  272. fIsapiDllInitialized = FALSE;
  273. }
  274. return hr;
  275. }
  276. VOID
  277. TerminateModule( VOID )
  278. /*++
  279. Routine Description:
  280. Terminates the w3isapi module
  281. Arguments:
  282. None
  283. Return Value:
  284. None
  285. --*/
  286. {
  287. ISAPI_CONTEXT::Terminate();
  288. DBG_ASSERT( g_pDllManager );
  289. if( g_pDllManager )
  290. {
  291. delete g_pDllManager;
  292. g_pDllManager = NULL;
  293. }
  294. ISAPI_DLL::Terminate();
  295. if ( g_pEtwTracer != NULL )
  296. {
  297. g_pEtwTracer->UnRegister();
  298. delete g_pEtwTracer;
  299. g_pEtwTracer = NULL;
  300. }
  301. TerminateIISUtil();
  302. DELETE_DEBUG_PRINT_OBJECT();
  303. }
  304. HRESULT
  305. ProcessIsapiRequest(
  306. IIsapiCore * pIsapiCore,
  307. ISAPI_CORE_DATA * pCoreData,
  308. DWORD * pHseResult
  309. )
  310. /*++
  311. Routine Description:
  312. Processes an ISAPI request
  313. Arguments:
  314. pIsapiCore - The interface that provides connectivity to the core server
  315. pCoreData - The core data that describes the request
  316. pHseResult - Upon return, contains the return code from
  317. the extension's HttpExtensionProc
  318. Return Value:
  319. HRESULT
  320. --*/
  321. {
  322. ISAPI_DLL * pIsapiDll = NULL;
  323. DWORD dwIsapiReturn = HSE_STATUS_ERROR;
  324. ISAPI_CONTEXT * pIsapiContext = NULL;
  325. PFN_HTTPEXTENSIONPROC pfnHttpExtensionProc;
  326. EXTENSION_CONTROL_BLOCK * pEcb = NULL;
  327. HRESULT hr = NO_ERROR;
  328. ISAPI_CORE_DATA * pTempCoreData = NULL;
  329. DBG_ASSERT( g_pDllManager );
  330. //
  331. // This function is only called by w3core.dll
  332. //
  333. DBG_ASSERT( pIsapiCore );
  334. DBG_ASSERT( pCoreData );
  335. DBG_ASSERT( pHseResult );
  336. //
  337. // If this request is running OOP, then make a local copy
  338. // and fix up the core data internal pointers.
  339. //
  340. if ( pCoreData->fIsOop )
  341. {
  342. pTempCoreData = (ISAPI_CORE_DATA*) LocalAlloc( LPTR, pCoreData->cbSize );
  343. if ( !pTempCoreData )
  344. {
  345. hr = HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
  346. goto Failed;
  347. }
  348. memcpy( pTempCoreData, pCoreData, pCoreData->cbSize );
  349. //
  350. // We'll set pCoreData to point to our temp one. This
  351. // doesn't leak because the ISAPI_CONTEXT destructor is smart
  352. // enough to know it needs to be deleted in the OOP case.
  353. //
  354. pCoreData = pTempCoreData;
  355. FixupIsapiCoreData( pCoreData );
  356. }
  357. //
  358. // Get the entry point for the ISAPI
  359. //
  360. hr = g_pDllManager->GetIsapi(
  361. pCoreData->szGatewayImage,
  362. &pIsapiDll,
  363. pCoreData->hToken,
  364. pCoreData->pSid
  365. );
  366. if ( FAILED( hr ) )
  367. {
  368. goto Failed;
  369. }
  370. //
  371. // Construct the ISAPI_CONTEXT for this request. Once it's
  372. // allocated, it owns the lifetime of the ISAPI_REQUEST. When
  373. // the ISAPI_CONTEXT is deallocated, it may release the final
  374. // reference.
  375. //
  376. pIsapiContext = new (pIsapiCore) ISAPI_CONTEXT( pIsapiCore, pCoreData, pIsapiDll );
  377. if ( pIsapiContext == NULL )
  378. {
  379. hr = HRESULT_FROM_WIN32( GetLastError () );
  380. goto Failed;
  381. }
  382. //
  383. // Set the ECB
  384. //
  385. pEcb = pIsapiContext->QueryECB();
  386. //
  387. // Set the ECB function pointers
  388. //
  389. pEcb->GetServerVariable = GetServerVariable;
  390. pEcb->WriteClient = WriteClient;
  391. pEcb->ReadClient = ReadClient;
  392. pEcb->ServerSupportFunction = ServerSupportFunction;
  393. //
  394. // Get the extension's entry point
  395. //
  396. pfnHttpExtensionProc = pIsapiDll->QueryHttpExtensionProc();
  397. //
  398. // Trace Hook point that links the HTTP_REQUEST_ID to
  399. // ConnId passed to ISAPI dlls via the ECB.
  400. //
  401. if ( ETW_IS_TRACE_ON(ETW_LEVEL_CP) )
  402. {
  403. g_pEtwTracer->EtwTraceEvent( &IsapiEventGuid,
  404. ETW_TYPE_START,
  405. &pCoreData->RequestId,
  406. sizeof(HTTP_REQUEST_ID),
  407. &pEcb->ConnID,
  408. sizeof(ULONG_PTR),
  409. &pCoreData->fIsOop,
  410. sizeof(ULONG),
  411. NULL,
  412. 0);
  413. }
  414. //
  415. // If we are running OOP, set the COM state so that the
  416. // extension can CoInitialize/CoUninitialize.
  417. //
  418. if ( pIsapiContext->QueryIsOop() )
  419. {
  420. hr = pIsapiContext->SetComStateForOop();
  421. DBG_ASSERT( SUCCEEDED( hr ) );
  422. }
  423. //
  424. // Impersonate the authenticated user and call it
  425. //
  426. if ( !SetThreadToken( NULL, pIsapiContext->QueryToken() ) )
  427. {
  428. hr = HRESULT_FROM_WIN32( GetLastError() );
  429. goto Failed;
  430. }
  431. pIsapiContext->ReferenceIsapiContext();
  432. IF_DEBUG( ISAPI_EXTENSION_ENTRY )
  433. {
  434. DBGPRINTF(( DBG_CONTEXT,
  435. "\r\n"
  436. " Calling into HttpExtensionProc\r\n"
  437. " Extension: '%S'\r\n"
  438. " pECB: %p\r\n"
  439. " <END>\r\n\r\n",
  440. pIsapiContext->QueryGatewayImage(),
  441. pEcb ));
  442. }
  443. dwIsapiReturn = pfnHttpExtensionProc( pEcb );
  444. DBG_REQUIRE( RevertToSelf() );
  445. if ( pIsapiContext->QueryIsOop() )
  446. {
  447. pIsapiContext->RestoreComStateForOop();
  448. }
  449. pIsapiContext->DereferenceIsapiContext();
  450. switch ( dwIsapiReturn )
  451. {
  452. case HSE_STATUS_PENDING:
  453. IF_DEBUG( ISAPI_EXTENSION_ENTRY )
  454. {
  455. DBGPRINTF(( DBG_CONTEXT,
  456. "\r\n"
  457. " HttpExtensionProc returned HSE_STATUS_PENDING\r\n"
  458. " Extension: '%S'\r\n"
  459. " pECB: %p\r\n"
  460. " <END>\r\n\r\n",
  461. pIsapiContext->QueryGatewayImage(),
  462. pEcb ));
  463. }
  464. //
  465. // Don't dereference the ISAPI_CONTEXT. This
  466. // will guarantee that it lives on beyond the
  467. // return from this function.
  468. //
  469. break;
  470. case HSE_STATUS_SUCCESS_AND_KEEP_CONN:
  471. IF_DEBUG( ISAPI_EXTENSION_ENTRY )
  472. {
  473. DBGPRINTF(( DBG_CONTEXT,
  474. "\r\n"
  475. " HttpExtensionProc returned HSE_STATUS_SUCCESS_AND_KEEP_CONN\r\n"
  476. " Extension: '%S'\r\n"
  477. " pECB: %p\r\n"
  478. " <END>\r\n\r\n",
  479. pIsapiContext->QueryGatewayImage(),
  480. pEcb ));
  481. }
  482. //
  483. // Special case of success. The extension wants
  484. // to keep the connection open, even though we may
  485. // not have detected proper response headers.
  486. //
  487. // After setting the disconnect mode, fall through.
  488. //
  489. if ( pIsapiContext->QueryClientKeepConn() &&
  490. pIsapiContext->QueryHonorAndKeepConn() )
  491. {
  492. pIsapiContext->SetKeepConn( TRUE );
  493. pIsapiCore->SetConnectionClose( FALSE );
  494. }
  495. case HSE_STATUS_ERROR:
  496. case HSE_STATUS_SUCCESS:
  497. default:
  498. IF_DEBUG( ISAPI_EXTENSION_ENTRY )
  499. {
  500. if ( dwIsapiReturn == HSE_STATUS_ERROR ||
  501. dwIsapiReturn == HSE_STATUS_SUCCESS )
  502. {
  503. DBGPRINTF(( DBG_CONTEXT,
  504. "\r\n"
  505. " HttpExtensionProc returned %s\r\n"
  506. " Extension: '%S'\r\n"
  507. " pECB: %p\r\n"
  508. " <END>\r\n\r\n",
  509. dwIsapiReturn == HSE_STATUS_SUCCESS ? "HSE_STATUS_SUCCESS" : "HSE_STATUS_ERROR",
  510. pIsapiContext->QueryGatewayImage(),
  511. pEcb ));
  512. }
  513. else
  514. {
  515. DBGPRINTF(( DBG_CONTEXT,
  516. "\r\n"
  517. " HttpExtensionProc returned unknown status 0x%08x (%d)\r\n"
  518. " Extension: '%S'\r\n"
  519. " pECB: %p\r\n"
  520. " <END>\r\n\r\n",
  521. dwIsapiReturn,
  522. dwIsapiReturn,
  523. pIsapiContext->QueryGatewayImage(),
  524. pEcb ));
  525. }
  526. }
  527. DBG_ASSERT( pIsapiContext->QueryIoState() == NoAsyncIoPending );
  528. pIsapiContext->DereferenceIsapiContext();
  529. break;
  530. }
  531. *pHseResult = dwIsapiReturn;
  532. pIsapiDll->DereferenceIsapiDll();
  533. pIsapiDll = NULL;
  534. return NO_ERROR;
  535. Failed:
  536. DBG_ASSERT( FAILED( hr ) );
  537. if ( pIsapiContext )
  538. {
  539. pIsapiContext->DereferenceIsapiContext();
  540. pIsapiContext = NULL;
  541. }
  542. else
  543. {
  544. //
  545. // In OOP case, we're depending on the ISAPI_CONTEXT destructor
  546. // to free the copy of the core data and close the impersonation
  547. // token. If we weren't able to allocate one, we'll have to
  548. // do it here.
  549. //
  550. if ( pCoreData->fIsOop )
  551. {
  552. CloseHandle( pCoreData->hToken );
  553. if ( pTempCoreData )
  554. {
  555. LocalFree( pTempCoreData );
  556. pTempCoreData = NULL;
  557. }
  558. }
  559. }
  560. if ( pIsapiDll )
  561. {
  562. pIsapiDll->DereferenceIsapiDll();
  563. pIsapiDll = NULL;
  564. }
  565. return hr;
  566. }
  567. HRESULT
  568. ProcessIsapiCompletion(
  569. DWORD64 IsaContext,
  570. DWORD cbCompletion,
  571. DWORD dwCompletionStatus
  572. )
  573. /*++
  574. Routine Description:
  575. Processes an I/O completion for an ISAPI extension
  576. Arguments:
  577. IsaContext - The ISAPI_CONTEXT for this completion
  578. cbCompletion - The byte count associated with the completion
  579. dwCompletionStatus - The result code associated with the completion
  580. Return Value:
  581. HRESULT
  582. --*/
  583. {
  584. ISAPI_CONTEXT * pIsapiContext;
  585. ASYNC_PENDING IoType;
  586. PFN_HSE_IO_COMPLETION pfnCompletion;
  587. DWORD cbLastIo;
  588. HRESULT hr = NO_ERROR;
  589. DBG_REQUIRE( ( pIsapiContext = reinterpret_cast<ISAPI_CONTEXT*>( IsaContext ) ) != NULL );
  590. pIsapiContext->ReferenceIsapiContext();
  591. //
  592. // Magical hand waving:
  593. //
  594. // If this is a completion for a write, then we need to
  595. // restore the original buffer size. This is necessary
  596. // to keep from confusing ISAPI extensions that examine
  597. // the cbCompletion value in the case where a filter
  598. // changed the size of the buffer before the actual
  599. // IO occured.
  600. //
  601. // If this is a completion for an EXEC_URL, then we need
  602. // to set the dwCompletionStatus to ERROR_SUCCESS. The
  603. // caller of the EXEC_URL should use GET_EXECUTE_URL_STATUS
  604. // to see the result of the child URL.
  605. //
  606. cbLastIo = pIsapiContext->QueryLastAsyncIo();
  607. pIsapiContext->SetLastAsyncIo( 0 );
  608. IoType = pIsapiContext->UninitAsyncIo();
  609. if ( IoType == AsyncWritePending )
  610. {
  611. cbCompletion = cbLastIo;
  612. }
  613. else if ( IoType == AsyncExecPending )
  614. {
  615. dwCompletionStatus = ERROR_SUCCESS;
  616. }
  617. else if ( IoType == AsyncReadPending &&
  618. dwCompletionStatus == ERROR_HANDLE_EOF )
  619. {
  620. //
  621. // If http.sys returns ERROR_HANDLE_EOF on an
  622. // asynchronous read, then this completion is
  623. // for the end of a chunk transfer encoded
  624. // request. We should mask the error from
  625. // the client and make it look like a successful
  626. // zero byte read.
  627. //
  628. cbCompletion = 0;
  629. dwCompletionStatus = ERROR_SUCCESS;
  630. }
  631. //
  632. // If the completion context indicates a completion routine,
  633. // then call it.
  634. //
  635. pfnCompletion = pIsapiContext->QueryPfnIoCompletion();
  636. if ( pfnCompletion )
  637. {
  638. //
  639. // First, impersonate the client
  640. //
  641. if ( SetThreadToken( NULL, pIsapiContext->QueryToken() ) )
  642. {
  643. IF_DEBUG( ISAPI_EXTENSION_ENTRY )
  644. {
  645. DBGPRINTF(( DBG_CONTEXT,
  646. "\r\n"
  647. " Calling into ISAPI extension for completion\r\n"
  648. " Extension: '%S'\r\n"
  649. " pECB: %p\r\n"
  650. " Completion Routine: %p\r\n"
  651. " Bytes: %d\r\n"
  652. " Status: 0x%08x (%d)\r\n"
  653. " Extension Context: %p\r\n"
  654. " <END>\r\n\r\n",
  655. pIsapiContext->QueryGatewayImage(),
  656. pIsapiContext->QueryECB(),
  657. pfnCompletion,
  658. cbCompletion,
  659. dwCompletionStatus,
  660. dwCompletionStatus,
  661. pIsapiContext->QueryExtensionContext() ));
  662. }
  663. pfnCompletion(
  664. pIsapiContext->QueryECB(),
  665. pIsapiContext->QueryExtensionContext(),
  666. cbCompletion,
  667. dwCompletionStatus
  668. );
  669. IF_DEBUG( ISAPI_EXTENSION_ENTRY )
  670. {
  671. DBGPRINTF(( DBG_CONTEXT,
  672. "\r\n"
  673. " ISAPI extension completion returned\r\n"
  674. " Extension: '%S'\r\n"
  675. " pECB: %p\r\n"
  676. " <END>\r\n\r\n",
  677. pIsapiContext->QueryGatewayImage(),
  678. pIsapiContext->QueryECB() ));
  679. }
  680. DBG_REQUIRE( RevertToSelf() );
  681. }
  682. else
  683. {
  684. hr = HRESULT_FROM_WIN32( GetLastError() );
  685. }
  686. }
  687. pIsapiContext->DereferenceIsapiContext();
  688. return hr;
  689. }
  690. BOOL
  691. WINAPI
  692. GetServerVariable(
  693. HCONN hConn,
  694. LPSTR lpszVariableName,
  695. LPVOID lpvBuffer,
  696. LPDWORD lpdwSize
  697. )
  698. /*++
  699. Routine Description:
  700. Retrieves a server variable
  701. Arguments:
  702. hConn - The ConnID associated with the request. This
  703. value is opaque to the ISAPI that calls into
  704. this function, but it can be cast to the
  705. ISAPI_CONTEXT associated with the request.
  706. lpszVariableName - The name of the variable to retrieve
  707. lpvBuffer - Upon return, contains the value of the variable
  708. lpdwSize - On entry, contains the size of lpvBuffer, upon
  709. return, contains the number of bytes actually
  710. needed to contain the value.
  711. Return Value:
  712. HRESULT
  713. --*/
  714. {
  715. ISAPI_CONTEXT * pIsapiContext;
  716. IIsapiCore * pIsapiCore;
  717. HANDLE hCurrentUser;
  718. HRESULT hr;
  719. pIsapiContext = reinterpret_cast<ISAPI_CONTEXT*>( hConn );
  720. IF_DEBUG( ISAPI_GET_SERVER_VARIABLE )
  721. {
  722. DBGPRINTF(( DBG_CONTEXT,
  723. "\r\n"
  724. " GetServerVariable[%p]: Function Entry\r\n"
  725. " Variable Name: %s\r\n"
  726. " <END>\r\n\r\n",
  727. pIsapiContext,
  728. lpszVariableName ));
  729. }
  730. //
  731. // Parameter validation
  732. //
  733. if ( pIsapiContext == NULL ||
  734. lpszVariableName == NULL ||
  735. lpdwSize == NULL )
  736. {
  737. IF_DEBUG( ISAPI_ERROR_RETURNS )
  738. {
  739. DBGPRINTF(( DBG_CONTEXT,
  740. "\r\n"
  741. " GetServerVariable[%p]: Parameter validation failure\r\n"
  742. " Variable Name: %s\r\n"
  743. " Buffer Size Ptr: %p\r\n"
  744. " Returing FALSE, LastError=ERROR_INVALID_PARAMETER\r\n"
  745. " <END>\r\n\r\n",
  746. pIsapiContext,
  747. lpszVariableName,
  748. lpdwSize ));
  749. }
  750. SetLastError( ERROR_INVALID_PARAMETER );
  751. return FALSE;
  752. }
  753. pIsapiCore = pIsapiContext->QueryIsapiCoreInterface();
  754. if ( pIsapiCore == NULL )
  755. {
  756. IF_DEBUG( ISAPI_ERROR_RETURNS )
  757. {
  758. DBGPRINTF(( DBG_CONTEXT,
  759. "\r\n"
  760. " GetServerVariable[%p]: Failed to get interface to server core\r\n"
  761. " Returning FALSE, LastError=ERROR_INVALID_PARAMETER\r\n"
  762. " <END>\r\n\r\n",
  763. pIsapiContext ));
  764. }
  765. SetLastError( ERROR_INVALID_PARAMETER );
  766. return FALSE;
  767. }
  768. //
  769. // If the caller passed us a NULL buffer, then we should
  770. // treat it as zero size - even if *lpdwBuffer is non-zero
  771. //
  772. if ( lpvBuffer == NULL )
  773. {
  774. *lpdwSize = 0;
  775. }
  776. //
  777. // If we are running OOP, then try and get the data
  778. // locally from the process.
  779. //
  780. if ( pIsapiContext->QueryIsOop() )
  781. {
  782. SERVER_VARIABLE_INDEX Index;
  783. BOOL fResult;
  784. Index = LookupServerVariableIndex( lpszVariableName );
  785. if ( Index != ServerVariableExternal )
  786. {
  787. fResult = pIsapiContext->GetOopServerVariableByIndex(
  788. Index,
  789. lpvBuffer,
  790. lpdwSize
  791. );
  792. if ( !fResult )
  793. {
  794. IF_DEBUG( ISAPI_ERROR_RETURNS )
  795. {
  796. DBGPRINTF(( DBG_CONTEXT,
  797. "\r\n"
  798. " GetServerVariable[%p]: Failed\r\n"
  799. " Returning FALSE, LastError=%d\r\n"
  800. " <END>\r\n\r\n",
  801. pIsapiContext,
  802. GetLastError() ));
  803. }
  804. }
  805. else
  806. {
  807. IF_DEBUG( ISAPI_GET_SERVER_VARIABLE )
  808. {
  809. IF_DEBUG( ISAPI_SUCCESS_RETURNS )
  810. {
  811. if ( _strnicmp( lpszVariableName, "UNICODE_", 8 ) == 0 )
  812. {
  813. DBGPRINTF(( DBG_CONTEXT,
  814. "\r\n"
  815. " GetServerVariable[%p]: Succeeded\r\n"
  816. " %s value: '%S'\r\n"
  817. " Returning TRUE\r\n"
  818. " <END>\r\n\r\n",
  819. pIsapiContext,
  820. lpszVariableName,
  821. (LPWSTR)lpvBuffer ));
  822. }
  823. else
  824. {
  825. DBGPRINTF(( DBG_CONTEXT,
  826. "\r\n"
  827. " GetServerVariable[%p]: Succeeded\r\n"
  828. " %s value: '%s'\r\n"
  829. " Returning TRUE\r\n"
  830. " <END>\r\n\r\n",
  831. pIsapiContext,
  832. lpszVariableName,
  833. (LPSTR)lpvBuffer ));
  834. }
  835. }
  836. }
  837. }
  838. return fResult;
  839. }
  840. }
  841. //
  842. // Call it
  843. //
  844. pIsapiContext->IsapiDoRevertHack( &hCurrentUser );
  845. hr = pIsapiCore->GetServerVariable(
  846. lpszVariableName,
  847. *lpdwSize ? (BYTE*)lpvBuffer : NULL,
  848. *lpdwSize,
  849. lpdwSize
  850. );
  851. pIsapiContext->IsapiUndoRevertHack( &hCurrentUser);
  852. if ( FAILED( hr ) )
  853. {
  854. IF_DEBUG( ISAPI_ERROR_RETURNS )
  855. {
  856. DBGPRINTF(( DBG_CONTEXT,
  857. "\r\n"
  858. " GetServerVariable[%p]: Failed\r\n"
  859. " Returning FALSE, LastError=0x%08x (%d)\r\n"
  860. " <END>\r\n\r\n",
  861. pIsapiContext,
  862. hr,
  863. WIN32_FROM_HRESULT( hr ) ));
  864. }
  865. SetLastError( WIN32_FROM_HRESULT( hr ) );
  866. return FALSE;
  867. }
  868. IF_DEBUG( ISAPI_GET_SERVER_VARIABLE )
  869. {
  870. IF_DEBUG( ISAPI_SUCCESS_RETURNS )
  871. {
  872. if ( _strnicmp( lpszVariableName, "UNICODE_", 8 ) == 0 )
  873. {
  874. DBGPRINTF(( DBG_CONTEXT,
  875. "\r\n"
  876. " GetServerVariable[%p]: Succeeded\r\n"
  877. " %s value: '%S'\r\n"
  878. " Returning TRUE\r\n"
  879. " <END>\r\n\r\n",
  880. pIsapiContext,
  881. lpszVariableName,
  882. (LPWSTR)lpvBuffer ));
  883. }
  884. else
  885. {
  886. DBGPRINTF(( DBG_CONTEXT,
  887. "\r\n"
  888. " GetServerVariable[%p]: Succeeded\r\n"
  889. " %s value: '%s'\r\n"
  890. " Returning TRUE\r\n"
  891. " <END>\r\n\r\n",
  892. pIsapiContext,
  893. lpszVariableName,
  894. (LPSTR)lpvBuffer ));
  895. }
  896. }
  897. }
  898. return TRUE;
  899. }
  900. BOOL
  901. WINAPI
  902. WriteClient(
  903. HCONN ConnID,
  904. LPVOID Buffer,
  905. LPDWORD lpdwBytes,
  906. DWORD dwReserved
  907. )
  908. /*++
  909. Routine Description:
  910. Writes data to the client
  911. Arguments:
  912. hConn - The ConnID associated with the request. This
  913. value is opaque to the ISAPI that calls into
  914. this function, but it can be cast to the
  915. ISAPI_CONTEXT associated with the request.
  916. Buffer - The data to write
  917. lpdwBytes - On entry, the number of bytes to write. Upon
  918. return, the number of bytes written (or so the
  919. docs say)
  920. dwReserved - Flags (ie. HSE_IO_SYNC, etc.)
  921. Return Value:
  922. HRESULT
  923. --*/
  924. {
  925. ISAPI_CONTEXT * pIsapiContext;
  926. IIsapiCore * pIsapiCore;
  927. HANDLE hCurrentUser;
  928. HRESULT hr;
  929. pIsapiContext = reinterpret_cast<ISAPI_CONTEXT*>( ConnID );
  930. IF_DEBUG( ISAPI_WRITE_CLIENT )
  931. {
  932. DBGPRINTF(( DBG_CONTEXT,
  933. "\r\n"
  934. " WriteClient[%p]: Function Entry\r\n"
  935. " Extension: %S\r\n"
  936. " Bytes to Send: %d\r\n"
  937. " Sync Flag: %s\r\n"
  938. " <END>\r\n\r\n",
  939. pIsapiContext,
  940. pIsapiContext ? pIsapiContext->QueryGatewayImage() : L"*",
  941. *lpdwBytes,
  942. dwReserved ? dwReserved & HSE_IO_SYNC ? "HSE_IO_SYNC" : "HSE_IO_ASYNC" : "0" ));
  943. IF_DEBUG( ISAPI_DUMP_BUFFERS )
  944. {
  945. STACK_STRA( strBufferDump,512 );
  946. DWORD dwBytesToDump = *lpdwBytes;
  947. if ( dwBytesToDump > MAX_DEBUG_DUMP )
  948. {
  949. dwBytesToDump = MAX_DEBUG_DUMP;
  950. }
  951. if ( FAILED( strBufferDump.CopyBinary( Buffer, dwBytesToDump ) ) )
  952. {
  953. strBufferDump.Copy( "" );
  954. }
  955. DBGPRINTF(( DBG_CONTEXT,
  956. "\r\n"
  957. " WriteClient[%p]: Dump of up to %d bytes of send buffer\r\n"
  958. "%s"
  959. " <END>\r\n\r\n",
  960. pIsapiContext,
  961. MAX_DEBUG_DUMP,
  962. strBufferDump.QueryStr() ));
  963. }
  964. }
  965. //
  966. // Parameter validation
  967. //
  968. if ( pIsapiContext == NULL ||
  969. lpdwBytes == NULL ||
  970. ( *lpdwBytes != 0 && Buffer == NULL ) )
  971. {
  972. IF_DEBUG( ISAPI_ERROR_RETURNS )
  973. {
  974. DBGPRINTF(( DBG_CONTEXT,
  975. "\r\n"
  976. " WriteClient[%p]: Parameter validation failed\r\n"
  977. " Bytes to send: %d\r\n"
  978. " Buffer Pointer: %p.\r\n"
  979. " Returning FALSE, LastError=ERROR_INVALID_PARAMETER\r\n"
  980. " <END>\r\n\r\n",
  981. pIsapiContext,
  982. lpdwBytes,
  983. Buffer ));
  984. }
  985. SetLastError( ERROR_INVALID_PARAMETER );
  986. return FALSE;
  987. }
  988. pIsapiCore = pIsapiContext->QueryIsapiCoreInterface();
  989. DBG_ASSERT( pIsapiCore );
  990. if ( pIsapiCore == NULL )
  991. {
  992. IF_DEBUG( ISAPI_ERROR_RETURNS )
  993. {
  994. DBGPRINTF(( DBG_CONTEXT,
  995. "\r\n"
  996. " WriteClient[%p]: Failed to get interface to server core\r\n"
  997. " Returning FALSE, LastError=ERROR_INVALID_PARAMETER\r\n"
  998. " <END>\r\n\r\n",
  999. pIsapiContext ));
  1000. }
  1001. SetLastError( ERROR_INVALID_PARAMETER );
  1002. return FALSE;
  1003. }
  1004. //
  1005. // If the user is sending zero bytes, return TRUE here. Yeah, this
  1006. // will be kind of a bogus thing to do because if the call is async,
  1007. // we will return successful with no completion ever occuring.
  1008. //
  1009. // IIS has done this for as long as sync WriteClient has existed, and
  1010. // we'd risk breaking legacy code if we change it now.
  1011. //
  1012. if ( *lpdwBytes == 0 )
  1013. {
  1014. IF_DEBUG( ISAPI_WRITE_CLIENT )
  1015. {
  1016. IF_DEBUG( ISAPI_SUCCESS_RETURNS )
  1017. {
  1018. DBGPRINTF(( DBG_CONTEXT,
  1019. "\r\n"
  1020. " WriteClient[%p]: Bytes to send is zero\r\n"
  1021. " Returning TRUE\r\n"
  1022. " <END>\r\n\r\n",
  1023. pIsapiContext ));
  1024. }
  1025. }
  1026. return TRUE;
  1027. }
  1028. //
  1029. // BUGBUG - Need to map the documented HSE_IO flags to reasonable
  1030. // UL equivalents and provide a mechanism to pass them.
  1031. //
  1032. if ( dwReserved & HSE_IO_ASYNC )
  1033. {
  1034. //
  1035. // Do an asynchronous write
  1036. //
  1037. // Check to make sure that we have a completion
  1038. // function.
  1039. //
  1040. if ( pIsapiContext->QueryPfnIoCompletion() == NULL ||
  1041. pIsapiContext->TryInitAsyncIo( AsyncWritePending ) == FALSE )
  1042. {
  1043. IF_DEBUG( ISAPI_ERROR_RETURNS )
  1044. {
  1045. DBGPRINTF(( DBG_CONTEXT,
  1046. "\r\n"
  1047. " WriteClient[%p]: Failed to perform asynchronous send\r\n"
  1048. " Another async operation was already pending.\r\n"
  1049. " Returning FALSE, LastError=ERROR_INVALID_PARAMETER\r\n"
  1050. " <END>\r\n\r\n",
  1051. pIsapiContext ));
  1052. }
  1053. SetLastError( ERROR_INVALID_PARAMETER );
  1054. return FALSE;
  1055. }
  1056. //
  1057. // Some extensions depend on the number of bytes reported in the
  1058. // completion to confirm success. In the case where a send raw
  1059. // data filter is installed (or if we are using SSL), it's possible
  1060. // that the number of bytes in the completion is not what the
  1061. // caller expects.
  1062. //
  1063. // We need to save away the number of bytes that they are sending
  1064. // to protect them from themselves.
  1065. //
  1066. pIsapiContext->SetLastAsyncIo( *lpdwBytes );
  1067. pIsapiContext->IsapiDoRevertHack( &hCurrentUser );
  1068. hr = pIsapiCore->WriteClient(
  1069. reinterpret_cast<DWORD64>( pIsapiContext ),
  1070. reinterpret_cast<LPBYTE>( Buffer ),
  1071. *lpdwBytes,
  1072. HSE_IO_ASYNC
  1073. );
  1074. pIsapiContext->IsapiUndoRevertHack( &hCurrentUser );
  1075. if ( FAILED( hr ) )
  1076. {
  1077. pIsapiContext->SetLastAsyncIo( 0 );
  1078. pIsapiContext->UninitAsyncIo();
  1079. }
  1080. }
  1081. else
  1082. {
  1083. //
  1084. // Do a synchronous write
  1085. //
  1086. pIsapiContext->IsapiDoRevertHack( &hCurrentUser );
  1087. hr = pIsapiCore->WriteClient(
  1088. NULL,
  1089. reinterpret_cast<LPBYTE>( Buffer ),
  1090. *lpdwBytes,
  1091. HSE_IO_SYNC
  1092. );
  1093. pIsapiContext->IsapiUndoRevertHack( &hCurrentUser );
  1094. }
  1095. if ( FAILED( hr ) )
  1096. {
  1097. IF_DEBUG( ISAPI_ERROR_RETURNS )
  1098. {
  1099. DBGPRINTF(( DBG_CONTEXT,
  1100. "\r\n"
  1101. " WriteClient[%p]: Attempt to write failed\r\n",
  1102. " Returning FALSE, LastError=0x%08x ( %d )\r\n"
  1103. " <END>\r\n\r\n",
  1104. pIsapiContext,
  1105. hr,
  1106. WIN32_FROM_HRESULT( hr ) ));
  1107. }
  1108. SetLastError( WIN32_FROM_HRESULT( hr ) );
  1109. return FALSE;
  1110. }
  1111. IF_DEBUG( ISAPI_WRITE_CLIENT )
  1112. {
  1113. IF_DEBUG( ISAPI_SUCCESS_RETURNS )
  1114. {
  1115. DBGPRINTF(( DBG_CONTEXT,
  1116. "\r\n"
  1117. " WriteClient[%p]: Succeeded\r\n"
  1118. " Returning TRUE\r\n"
  1119. " <END>\r\n\r\n",
  1120. pIsapiContext ));
  1121. }
  1122. }
  1123. return TRUE;
  1124. }
  1125. BOOL
  1126. WINAPI
  1127. ReadClient(
  1128. HCONN ConnID,
  1129. LPVOID lpvBuffer,
  1130. LPDWORD lpdwSize
  1131. )
  1132. /*++
  1133. Routine Description:
  1134. Reads data from the client
  1135. Arguments:
  1136. hConn - The ConnID associated with the request. This
  1137. value is opaque to the ISAPI that calls into
  1138. this function, but it can be cast to the
  1139. ISAPI_CONTEXT associated with the request.
  1140. lpvBuffer - Upon return, contains the data read
  1141. lpdwsize - On entry, the size of lpvBuffer. Upon
  1142. return, the number of bytes read.
  1143. Return Value:
  1144. HRESULT
  1145. --*/
  1146. {
  1147. ISAPI_CONTEXT * pIsapiContext;
  1148. IIsapiCore * pIsapiCore;
  1149. HANDLE hCurrentUser;
  1150. HRESULT hr;
  1151. pIsapiContext = reinterpret_cast<ISAPI_CONTEXT*>( ConnID );
  1152. IF_DEBUG( ISAPI_READ_CLIENT )
  1153. {
  1154. DBGPRINTF(( DBG_CONTEXT,
  1155. "\r\n"
  1156. " ReadClient[%p]: Function Entry\r\n"
  1157. " Bytes to Read: %d\r\n"
  1158. " <END>\r\n\r\n",
  1159. pIsapiContext,
  1160. *lpdwSize ));
  1161. }
  1162. //
  1163. // Parameter validation
  1164. //
  1165. if ( pIsapiContext == NULL ||
  1166. lpdwSize == NULL ||
  1167. ( *lpdwSize != 0 && lpvBuffer == NULL ) )
  1168. {
  1169. IF_DEBUG( ISAPI_ERROR_RETURNS )
  1170. {
  1171. DBGPRINTF(( DBG_CONTEXT,
  1172. "\r\n"
  1173. " ReadClient[%p]: Parameter validation failure\r\n"
  1174. " Bytes to Read Ptr: %p\r\n"
  1175. " Bytes to Read: %d\r\n"
  1176. " Buffer Ptr: %p\r\n"
  1177. " Returning FALSE, LastError=ERROR_INVALID_PARAMETER\r\n"
  1178. " <END>\r\n\r\n",
  1179. pIsapiContext,
  1180. lpdwSize,
  1181. lpdwSize ? *lpdwSize : 0,
  1182. lpvBuffer ));
  1183. }
  1184. SetLastError( ERROR_INVALID_PARAMETER );
  1185. return FALSE;
  1186. }
  1187. pIsapiCore = pIsapiContext->QueryIsapiCoreInterface();
  1188. if ( pIsapiCore == NULL )
  1189. {
  1190. IF_DEBUG( ISAPI_ERROR_RETURNS )
  1191. {
  1192. DBGPRINTF(( DBG_CONTEXT,
  1193. "\r\n"
  1194. " ReadClient[%p]: Failed to get interface to server core\r\n"
  1195. " Returning FALSE, LastError=ERROR_INVALID_PARAMETER\r\n"
  1196. " <END>\r\n\r\n",
  1197. pIsapiContext ));
  1198. }
  1199. SetLastError( ERROR_INVALID_PARAMETER );
  1200. return FALSE;
  1201. }
  1202. pIsapiContext->IsapiDoRevertHack( &hCurrentUser );
  1203. hr = pIsapiCore->ReadClient(
  1204. NULL,
  1205. reinterpret_cast<unsigned char *>( lpvBuffer ),
  1206. *lpdwSize,
  1207. *lpdwSize,
  1208. lpdwSize,
  1209. HSE_IO_SYNC
  1210. );
  1211. pIsapiContext->IsapiUndoRevertHack( &hCurrentUser );
  1212. if ( FAILED( hr ) )
  1213. {
  1214. IF_DEBUG( ISAPI_ERROR_RETURNS )
  1215. {
  1216. DBGPRINTF(( DBG_CONTEXT,
  1217. "\r\n"
  1218. " ReadClient[%p]: Failed\r\n"
  1219. " Returning FALSE, LastError=0x%08x (%d)\r\n"
  1220. " <END>\r\n\r\n",
  1221. pIsapiContext,
  1222. hr,
  1223. WIN32_FROM_HRESULT( hr ) ));
  1224. }
  1225. SetLastError( WIN32_FROM_HRESULT( hr ) );
  1226. return FALSE;
  1227. }
  1228. IF_DEBUG( ISAPI_READ_CLIENT )
  1229. {
  1230. IF_DEBUG( ISAPI_SUCCESS_RETURNS )
  1231. {
  1232. DBGPRINTF(( DBG_CONTEXT,
  1233. "\r\n"
  1234. " ReadClient[%p]: Succeeded\r\n"
  1235. " Bytes Read: %d\r\n"
  1236. " Returning TRUE\r\n"
  1237. " <END>\r\n\r\n",
  1238. pIsapiContext,
  1239. *lpdwSize ));
  1240. IF_DEBUG( ISAPI_DUMP_BUFFERS )
  1241. {
  1242. STACK_STRA( strBufferDump,512 );
  1243. DWORD dwBytesToDump = *lpdwSize;
  1244. if ( dwBytesToDump > MAX_DEBUG_DUMP )
  1245. {
  1246. dwBytesToDump = MAX_DEBUG_DUMP;
  1247. }
  1248. if ( FAILED( strBufferDump.CopyBinary( lpvBuffer, dwBytesToDump ) ) )
  1249. {
  1250. strBufferDump.Copy( "" );
  1251. }
  1252. DBGPRINTF(( DBG_CONTEXT,
  1253. "\r\n"
  1254. " ReadClient[%p]: Dump of up to %d bytes of receive buffer\r\n"
  1255. "%s"
  1256. " <END>\r\n\r\n",
  1257. pIsapiContext,
  1258. MAX_DEBUG_DUMP,
  1259. strBufferDump.QueryStr() ));
  1260. }
  1261. }
  1262. }
  1263. return TRUE;
  1264. }
  1265. BOOL
  1266. WINAPI
  1267. ServerSupportFunction(
  1268. HCONN hConn,
  1269. DWORD dwHSERequest,
  1270. LPVOID lpvBuffer,
  1271. LPDWORD lpdwSize,
  1272. LPDWORD lpdwDataType
  1273. )
  1274. /*++
  1275. Routine Description:
  1276. Dispatches a ServerSupportFunction command to the appropriate
  1277. server support function.
  1278. Arguments:
  1279. hConn - The ConnID associated with the request. This
  1280. value is opaque to the ISAPI that calls into
  1281. this function, but it can be cast to the
  1282. ISAPI_CONTEXT associated with the request.
  1283. dwHSERequest - The server support command
  1284. lpvBuffer - Command-specific data
  1285. lpdwSize - Command-specific data
  1286. lpdwDataType - Command-specific data
  1287. Return Value:
  1288. HRESULT
  1289. --*/
  1290. {
  1291. ISAPI_CONTEXT * pIsapiContext;
  1292. HANDLE hCurrentUser;
  1293. HRESULT hr = NO_ERROR;
  1294. pIsapiContext = reinterpret_cast<ISAPI_CONTEXT*>( hConn );
  1295. IF_DEBUG( ISAPI_SERVER_SUPPORT_FUNCTION )
  1296. {
  1297. CHAR szCommand[64];
  1298. switch ( dwHSERequest )
  1299. {
  1300. case HSE_REQ_SEND_RESPONSE_HEADER:
  1301. wsprintfA( szCommand, "HSE_REQ_SEND_RESPONSE_HEADER" );
  1302. break;
  1303. case HSE_REQ_SEND_RESPONSE_HEADER_EX:
  1304. wsprintfA( szCommand, "HSE_REQ_SEND_RESPONSE_HEADER_EX" );
  1305. break;
  1306. case HSE_REQ_MAP_URL_TO_PATH:
  1307. wsprintfA( szCommand, "HSE_REQ_MAP_URL_TO_PATH" );
  1308. break;
  1309. case HSE_REQ_MAP_URL_TO_PATH_EX:
  1310. wsprintfA( szCommand, "HSE_REQ_MAP_URL_TO_PATH_EX" );
  1311. break;
  1312. case HSE_REQ_MAP_UNICODE_URL_TO_PATH:
  1313. wsprintfA( szCommand, "HSE_REQ_MAP_UNICODE_URL_TO_PATH" );
  1314. break;
  1315. case HSE_REQ_MAP_UNICODE_URL_TO_PATH_EX:
  1316. wsprintfA( szCommand, "HSE_REQ_MAP_UNICODE_URL_TO_PATH_EX" );
  1317. break;
  1318. case HSE_REQ_GET_IMPERSONATION_TOKEN:
  1319. wsprintfA( szCommand, "HSE_REQ_GET_IMPERSONATION_TOKEN" );
  1320. break;
  1321. case HSE_REQ_IS_KEEP_CONN:
  1322. wsprintfA( szCommand, "HSE_REQ_IS_KEEP_CONN" );
  1323. break;
  1324. case HSE_REQ_DONE_WITH_SESSION:
  1325. wsprintfA( szCommand, "HSE_REQ_DONE_WITH_SESSION" );
  1326. break;
  1327. case HSE_REQ_GET_CERT_INFO_EX:
  1328. wsprintfA( szCommand, "HSE_REQ_GET_CERT_INFO_EX" );
  1329. break;
  1330. case HSE_REQ_IO_COMPLETION:
  1331. wsprintfA( szCommand, "HSE_REQ_IO_COMPLETION" );
  1332. break;
  1333. case HSE_REQ_ASYNC_READ_CLIENT:
  1334. wsprintfA( szCommand, "HSE_REQ_ASYNC_READ_CLIENT" );
  1335. break;
  1336. case HSE_REQ_TRANSMIT_FILE:
  1337. wsprintfA( szCommand, "HSE_REQ_TRANSMIT_FILE" );
  1338. break;
  1339. case HSE_REQ_SEND_URL:
  1340. wsprintfA( szCommand, "HSE_REQ_SEND_URL" );
  1341. break;
  1342. case HSE_REQ_SEND_URL_REDIRECT_RESP:
  1343. wsprintfA( szCommand, "HSE_REQ_SEND_URL_REDIRECT_RESP" );
  1344. break;
  1345. case HSE_REQ_IS_CONNECTED:
  1346. wsprintfA( szCommand, "HSE_REQ_IS_CONNECTED" );
  1347. break;
  1348. case HSE_APPEND_LOG_PARAMETER:
  1349. wsprintfA( szCommand, "HSE_REQ_APPEND_LOG_PARAMETER" );
  1350. break;
  1351. case HSE_REQ_EXEC_URL:
  1352. wsprintfA( szCommand, "HSE_REQ_EXEC_URL" );
  1353. break;
  1354. case HSE_REQ_EXEC_UNICODE_URL:
  1355. wsprintfA( szCommand, "HSE_REQ_EXEC_UNICODE" );
  1356. break;
  1357. case HSE_REQ_GET_EXEC_URL_STATUS:
  1358. wsprintfA( szCommand, "HSE_REQ_GET_EXEC_URL_STATUS" );
  1359. break;
  1360. case HSE_REQ_SEND_CUSTOM_ERROR:
  1361. wsprintfA( szCommand, "HSE_REQ_SEND_CUSTOM_ERROR" );
  1362. break;
  1363. case HSE_REQ_VECTOR_SEND_DEPRECATED:
  1364. wsprintfA( szCommand, "HSE_REQ_VECTOR_SEND_DEPRECATED" );
  1365. break;
  1366. case HSE_REQ_VECTOR_SEND:
  1367. wsprintfA( szCommand, "HSE_REQ_VECTOR_SEND" );
  1368. break;
  1369. case HSE_REQ_GET_CUSTOM_ERROR_PAGE:
  1370. wsprintfA( szCommand, "HSE_REQ_GET_CUSTOM_ERROR_PAGE" );
  1371. break;
  1372. case HSE_REQ_IS_IN_PROCESS:
  1373. wsprintfA( szCommand, "HSE_REQ_IS_IN_PROCESS" );
  1374. break;
  1375. case HSE_REQ_GET_SSPI_INFO:
  1376. wsprintfA( szCommand, "HSE_REQ_GET_SSPI_INFO" );
  1377. break;
  1378. case HSE_REQ_GET_VIRTUAL_PATH_TOKEN:
  1379. wsprintfA( szCommand, "HSE_REQ_GET_VIRTUAL_PATH_TOKEN" );
  1380. break;
  1381. case HSE_REQ_GET_UNICODE_VIRTUAL_PATH_TOKEN:
  1382. wsprintfA( szCommand, "HSE_REQ_UNICODE_VIRTUAL_PATH_TOKEN" );
  1383. break;
  1384. case HSE_REQ_REPORT_UNHEALTHY:
  1385. wsprintfA( szCommand, "HSE_REQ_REPORT_UNHEALTHY" );
  1386. break;
  1387. case HSE_REQ_NORMALIZE_URL:
  1388. wsprintfA( szCommand, "HSE_REQ_NORMALIZE_URL" );
  1389. break;
  1390. case HSE_REQ_ADD_FRAGMENT_TO_CACHE:
  1391. wsprintfA( szCommand, "HSE_REQ_ADD_FRAGMENT_TO_CACHE" );
  1392. break;
  1393. case HSE_REQ_READ_FRAGMENT_FROM_CACHE:
  1394. wsprintfA( szCommand, "HSE_REQ_READ_FRAGMENT_FROM_CACHE" );
  1395. break;
  1396. case HSE_REQ_REMOVE_FRAGMENT_FROM_CACHE:
  1397. wsprintfA( szCommand, "HSE_REQ_REMOVE_FRAGMENT_FROM_CACHE" );
  1398. break;
  1399. case HSE_REQ_GET_METADATA_PROPERTY:
  1400. wsprintfA( szCommand, "HSE_REQ_GET_METADATA_PROPERTY" );
  1401. break;
  1402. case HSE_REQ_CLOSE_CONNECTION:
  1403. wsprintfA( szCommand, "HSE_REQ_CLOSE_CONNECTION" );
  1404. break;
  1405. case HSE_REQ_REFRESH_ISAPI_ACL:
  1406. wsprintfA( szCommand, "HSE_REQ_REFRESH_ISAPI_ACL" );
  1407. break;
  1408. case HSE_REQ_ABORTIVE_CLOSE:
  1409. wsprintfA( szCommand, "HSE_REQ_ABORTIVE_CLOSE" );
  1410. break;
  1411. case HSE_REQ_GET_ANONYMOUS_TOKEN:
  1412. wsprintfA( szCommand, "HSE_REQ_GET_ANONYMOUS_TOKEN" );
  1413. break;
  1414. case HSE_REQ_GET_UNICODE_ANONYMOUS_TOKEN:
  1415. wsprintfA( szCommand, "HSE_REQ_GET_UNICODE_ANONYMOUS_TOKEN" );
  1416. break;
  1417. case HSE_REQ_GET_CACHE_INVALIDATION_CALLBACK:
  1418. wsprintfA( szCommand, "HSE_REQ_GET_CACHE_INVALIDATION_CALLBACK" );
  1419. break;
  1420. default:
  1421. wsprintfA( szCommand,
  1422. "Unknown command: 0x%08x (%d)",
  1423. dwHSERequest,
  1424. dwHSERequest );
  1425. break;
  1426. }
  1427. DBGPRINTF(( DBG_CONTEXT,
  1428. "\r\n"
  1429. " ServerSupportFunction[%p]: Function Entry\r\n"
  1430. " Command: %s\r\n"
  1431. " <END>\r\n\r\n",
  1432. pIsapiContext,
  1433. szCommand ));
  1434. }
  1435. //
  1436. // Parameter validation
  1437. //
  1438. if ( pIsapiContext == NULL )
  1439. {
  1440. IF_DEBUG( ISAPI_ERROR_RETURNS )
  1441. {
  1442. DBGPRINTF(( DBG_CONTEXT,
  1443. "\r\n"
  1444. " ServerSupportFunction[%p]: Invalid ConnID\r\n"
  1445. " Returning FALSE, LastError=ERROR_INVALID_PARAMETER\r\n"
  1446. " <END>\r\n\r\n",
  1447. pIsapiContext ));
  1448. }
  1449. SetLastError( ERROR_INVALID_PARAMETER );
  1450. return FALSE;
  1451. }
  1452. pIsapiContext->ReferenceIsapiContext();
  1453. pIsapiContext->IsapiDoRevertHack( &hCurrentUser );
  1454. //
  1455. // Handle the specified command
  1456. //
  1457. switch ( dwHSERequest )
  1458. {
  1459. case HSE_REQ_SEND_RESPONSE_HEADER:
  1460. hr = SSFSendResponseHeader(
  1461. pIsapiContext,
  1462. reinterpret_cast<LPSTR>( lpvBuffer ),
  1463. reinterpret_cast<LPSTR>( lpdwDataType )
  1464. );
  1465. break;
  1466. case HSE_REQ_SEND_RESPONSE_HEADER_EX:
  1467. hr = SSFSendResponseHeaderEx(
  1468. pIsapiContext,
  1469. reinterpret_cast<HSE_SEND_HEADER_EX_INFO*>( lpvBuffer )
  1470. );
  1471. break;
  1472. case HSE_REQ_MAP_URL_TO_PATH:
  1473. hr = SSFMapUrlToPath(
  1474. pIsapiContext,
  1475. reinterpret_cast<LPSTR>( lpvBuffer ),
  1476. lpdwSize
  1477. );
  1478. break;
  1479. case HSE_REQ_MAP_URL_TO_PATH_EX:
  1480. hr = SSFMapUrlToPathEx(
  1481. pIsapiContext,
  1482. reinterpret_cast<LPSTR>( lpvBuffer ),
  1483. reinterpret_cast<HSE_URL_MAPEX_INFO*>( lpdwDataType ),
  1484. lpdwSize
  1485. );
  1486. break;
  1487. case HSE_REQ_MAP_UNICODE_URL_TO_PATH:
  1488. hr = SSFMapUnicodeUrlToPath(
  1489. pIsapiContext,
  1490. reinterpret_cast<LPWSTR>( lpvBuffer ),
  1491. lpdwSize
  1492. );
  1493. break;
  1494. case HSE_REQ_MAP_UNICODE_URL_TO_PATH_EX:
  1495. hr = SSFMapUnicodeUrlToPathEx(
  1496. pIsapiContext,
  1497. reinterpret_cast<LPWSTR>( lpvBuffer ),
  1498. reinterpret_cast<HSE_UNICODE_URL_MAPEX_INFO*>( lpdwDataType ),
  1499. lpdwSize
  1500. );
  1501. break;
  1502. case HSE_REQ_GET_IMPERSONATION_TOKEN:
  1503. hr = SSFGetImpersonationToken(
  1504. pIsapiContext,
  1505. reinterpret_cast<HANDLE*>( lpvBuffer )
  1506. );
  1507. break;
  1508. case HSE_REQ_IS_KEEP_CONN:
  1509. hr = SSFIsKeepConn(
  1510. pIsapiContext,
  1511. reinterpret_cast<BOOL*>( lpvBuffer )
  1512. );
  1513. break;
  1514. case HSE_REQ_DONE_WITH_SESSION:
  1515. hr = SSFDoneWithSession(
  1516. pIsapiContext,
  1517. reinterpret_cast<DWORD*>( lpvBuffer )
  1518. );
  1519. break;
  1520. case HSE_REQ_GET_CERT_INFO_EX:
  1521. hr = SSFGetCertInfoEx(
  1522. pIsapiContext,
  1523. reinterpret_cast<CERT_CONTEXT_EX*>( lpvBuffer )
  1524. );
  1525. break;
  1526. case HSE_REQ_IO_COMPLETION:
  1527. hr = SSFIoCompletion(
  1528. pIsapiContext,
  1529. reinterpret_cast<PFN_HSE_IO_COMPLETION>( lpvBuffer ),
  1530. reinterpret_cast<VOID*>( lpdwDataType )
  1531. );
  1532. break;
  1533. case HSE_REQ_ASYNC_READ_CLIENT:
  1534. hr = SSFAsyncReadClient(
  1535. pIsapiContext,
  1536. lpvBuffer,
  1537. lpdwSize
  1538. );
  1539. break;
  1540. case HSE_REQ_TRANSMIT_FILE:
  1541. hr = SSFTransmitFile(
  1542. pIsapiContext,
  1543. reinterpret_cast<HSE_TF_INFO*>( lpvBuffer )
  1544. );
  1545. break;
  1546. case HSE_REQ_SEND_URL:
  1547. case HSE_REQ_SEND_URL_REDIRECT_RESP:
  1548. hr = SSFSendRedirect(
  1549. pIsapiContext,
  1550. reinterpret_cast<LPSTR>( lpvBuffer )
  1551. );
  1552. break;
  1553. case HSE_REQ_IS_CONNECTED:
  1554. hr = SSFIsConnected(
  1555. pIsapiContext,
  1556. reinterpret_cast<BOOL*>( lpvBuffer )
  1557. );
  1558. break;
  1559. case HSE_APPEND_LOG_PARAMETER:
  1560. hr = SSFAppendLog(
  1561. pIsapiContext,
  1562. reinterpret_cast<LPSTR>( lpvBuffer )
  1563. );
  1564. break;
  1565. case HSE_REQ_EXEC_URL:
  1566. hr = SSFExecuteUrl(
  1567. pIsapiContext,
  1568. lpvBuffer,
  1569. FALSE
  1570. );
  1571. break;
  1572. case HSE_REQ_EXEC_UNICODE_URL:
  1573. hr = SSFExecuteUrl(
  1574. pIsapiContext,
  1575. lpvBuffer,
  1576. TRUE
  1577. );
  1578. break;
  1579. case HSE_REQ_GET_EXEC_URL_STATUS:
  1580. hr = SSFGetExecuteUrlStatus(
  1581. pIsapiContext,
  1582. reinterpret_cast<HSE_EXEC_URL_STATUS*>( lpvBuffer )
  1583. );
  1584. break;
  1585. case HSE_REQ_SEND_CUSTOM_ERROR:
  1586. hr = SSFSendCustomError(
  1587. pIsapiContext,
  1588. reinterpret_cast<HSE_CUSTOM_ERROR_INFO*>( lpvBuffer )
  1589. );
  1590. break;
  1591. case HSE_REQ_VECTOR_SEND_DEPRECATED:
  1592. hr = SSFVectorSendDeprecated(
  1593. pIsapiContext,
  1594. reinterpret_cast<HSE_RESPONSE_VECTOR_DEPRECATED*>( lpvBuffer )
  1595. );
  1596. break;
  1597. case HSE_REQ_VECTOR_SEND:
  1598. hr = SSFVectorSend(
  1599. pIsapiContext,
  1600. reinterpret_cast<HSE_RESPONSE_VECTOR*>( lpvBuffer )
  1601. );
  1602. break;
  1603. case HSE_REQ_GET_CUSTOM_ERROR_PAGE:
  1604. hr = SSFGetCustomErrorPage(
  1605. pIsapiContext,
  1606. reinterpret_cast<HSE_CUSTOM_ERROR_PAGE_INFO*>( lpvBuffer )
  1607. );
  1608. break;
  1609. case HSE_REQ_IS_IN_PROCESS:
  1610. hr = SSFIsInProcess(
  1611. pIsapiContext,
  1612. reinterpret_cast<DWORD*>( lpvBuffer )
  1613. );
  1614. break;
  1615. case HSE_REQ_GET_SSPI_INFO:
  1616. hr = SSFGetSspiInfo(
  1617. pIsapiContext,
  1618. reinterpret_cast<CtxtHandle*>( lpvBuffer ),
  1619. reinterpret_cast<CredHandle*>( lpdwDataType )
  1620. );
  1621. break;
  1622. case HSE_REQ_GET_VIRTUAL_PATH_TOKEN:
  1623. hr = SSFGetVirtualPathToken(
  1624. pIsapiContext,
  1625. reinterpret_cast<LPSTR>( lpvBuffer ),
  1626. reinterpret_cast<HANDLE*>( lpdwSize ),
  1627. FALSE
  1628. );
  1629. break;
  1630. case HSE_REQ_GET_UNICODE_VIRTUAL_PATH_TOKEN:
  1631. hr = SSFGetVirtualPathToken(
  1632. pIsapiContext,
  1633. reinterpret_cast<LPSTR>( lpvBuffer ),
  1634. reinterpret_cast<HANDLE*>( lpdwSize ),
  1635. TRUE
  1636. );
  1637. break;
  1638. case HSE_REQ_REPORT_UNHEALTHY:
  1639. hr = SSFReportUnhealthy(
  1640. pIsapiContext,
  1641. reinterpret_cast<LPSTR>( lpvBuffer )
  1642. );
  1643. break;
  1644. case HSE_REQ_NORMALIZE_URL:
  1645. hr = SSFNormalizeUrl(
  1646. reinterpret_cast<LPSTR>( lpvBuffer )
  1647. );
  1648. break;
  1649. case HSE_REQ_ADD_FRAGMENT_TO_CACHE:
  1650. hr = SSFAddFragmentToCache(
  1651. pIsapiContext,
  1652. (HSE_VECTOR_ELEMENT *)lpvBuffer,
  1653. (WCHAR *)lpdwSize
  1654. );
  1655. break;
  1656. case HSE_REQ_READ_FRAGMENT_FROM_CACHE:
  1657. hr = SSFReadFragmentFromCache(
  1658. pIsapiContext,
  1659. (WCHAR *)lpdwDataType,
  1660. (BYTE *)lpvBuffer,
  1661. lpdwSize
  1662. );
  1663. break;
  1664. case HSE_REQ_REMOVE_FRAGMENT_FROM_CACHE:
  1665. hr = SSFRemoveFragmentFromCache(
  1666. pIsapiContext,
  1667. (WCHAR *)lpvBuffer
  1668. );
  1669. break;
  1670. case HSE_REQ_GET_METADATA_PROPERTY:
  1671. hr = SSFGetMetadataProperty(
  1672. pIsapiContext,
  1673. (DWORD_PTR) lpdwDataType,
  1674. (BYTE*) lpvBuffer,
  1675. lpdwSize
  1676. );
  1677. break;
  1678. case HSE_REQ_CLOSE_CONNECTION:
  1679. hr = SSFCloseConnection(
  1680. pIsapiContext
  1681. );
  1682. break;
  1683. //
  1684. // The following are deprecated SSF commands that are not
  1685. // applicable to the new http.sys architecture.
  1686. //
  1687. // While we are not doing anything if an ISAPI uses these,
  1688. // we should not fail the call.
  1689. //
  1690. case HSE_REQ_REFRESH_ISAPI_ACL: // Codework. Probably need this one
  1691. case HSE_REQ_ABORTIVE_CLOSE:
  1692. IF_DEBUG( ISAPI_SSF_DETAILS )
  1693. {
  1694. DBGPRINTF(( DBG_CONTEXT,
  1695. "\r\n"
  1696. " ServerSupportFunction[%p]: Command not implemented in this IIS version\r\n"
  1697. " <END>\r\n\r\n",
  1698. pIsapiContext ));
  1699. }
  1700. hr = NO_ERROR;
  1701. break;
  1702. case HSE_REQ_GET_ANONYMOUS_TOKEN:
  1703. hr = SSFGetAnonymousToken(
  1704. pIsapiContext,
  1705. reinterpret_cast<LPSTR>( lpvBuffer ),
  1706. reinterpret_cast<HANDLE*>( lpdwSize ),
  1707. FALSE
  1708. );
  1709. break;
  1710. case HSE_REQ_GET_UNICODE_ANONYMOUS_TOKEN:
  1711. hr = SSFGetAnonymousToken(
  1712. pIsapiContext,
  1713. reinterpret_cast<LPSTR>( lpvBuffer ),
  1714. reinterpret_cast<HANDLE*>( lpdwSize ),
  1715. TRUE
  1716. );
  1717. break;
  1718. case HSE_REQ_GET_CACHE_INVALIDATION_CALLBACK:
  1719. hr = SSFGetCacheInvalidationCallback(
  1720. pIsapiContext,
  1721. (PFN_HSE_CACHE_INVALIDATION_CALLBACK *)lpvBuffer
  1722. );
  1723. break;
  1724. default:
  1725. hr = HRESULT_FROM_WIN32( ERROR_CALL_NOT_IMPLEMENTED );
  1726. }
  1727. pIsapiContext->IsapiUndoRevertHack( &hCurrentUser );
  1728. pIsapiContext->DereferenceIsapiContext();
  1729. if ( FAILED( hr ) )
  1730. {
  1731. IF_DEBUG( ISAPI_ERROR_RETURNS )
  1732. {
  1733. DBGPRINTF(( DBG_CONTEXT,
  1734. "\r\n"
  1735. " ServerSupportFunction[%p]: Command failed\r\n"
  1736. " Returning FALSE, LastError=0x%08x (%d)\r\n"
  1737. " <END>\r\n\r\n",
  1738. pIsapiContext,
  1739. hr,
  1740. WIN32_FROM_HRESULT( hr ) ));
  1741. }
  1742. SetLastError( WIN32_FROM_HRESULT( hr ) );
  1743. return FALSE;
  1744. }
  1745. IF_DEBUG( ISAPI_SERVER_SUPPORT_FUNCTION )
  1746. {
  1747. IF_DEBUG( ISAPI_SUCCESS_RETURNS )
  1748. {
  1749. DBGPRINTF(( DBG_CONTEXT,
  1750. "\r\n"
  1751. " ServerSupportFunction[%p]: Succeeded\r\n"
  1752. " Returning TRUE\r\n"
  1753. " <END>\r\n\r\n",
  1754. pIsapiContext ));
  1755. }
  1756. }
  1757. pIsapiContext = NULL;
  1758. return TRUE;
  1759. }
  1760. VOID
  1761. FixupIsapiCoreData(
  1762. ISAPI_CORE_DATA * pCoreData
  1763. )
  1764. {
  1765. //
  1766. // Caution. This code must be kept in sync
  1767. // with the W3_HANDLER::SerializeCoreDataForOop
  1768. // function in the core server.
  1769. //
  1770. BYTE * pCursor = (BYTE*)pCoreData;
  1771. pCursor += sizeof(ISAPI_CORE_DATA);
  1772. pCoreData->szGatewayImage = (LPWSTR)pCursor;
  1773. pCursor += pCoreData->cbGatewayImage;
  1774. pCoreData->szApplMdPathW = (LPWSTR)pCursor;
  1775. pCursor += pCoreData->cbApplMdPathW;
  1776. pCoreData->szPathTranslatedW = (LPWSTR)pCursor;
  1777. pCursor += pCoreData->cbPathTranslatedW;
  1778. pCoreData->szPhysicalPath = (LPSTR)pCursor;
  1779. pCursor += pCoreData->cbPhysicalPath;
  1780. pCoreData->szPathInfo = (LPSTR)pCursor;
  1781. pCursor += pCoreData->cbPathInfo;
  1782. pCoreData->szMethod = (LPSTR)pCursor;
  1783. pCursor += pCoreData->cbMethod;
  1784. pCoreData->szQueryString = (LPSTR)pCursor;
  1785. pCursor += pCoreData->cbQueryString;
  1786. pCoreData->szPathTranslated = (LPSTR)pCursor;
  1787. pCursor += pCoreData->cbPathTranslated;
  1788. pCoreData->szContentType = (LPSTR)pCursor;
  1789. pCursor += pCoreData->cbContentType;
  1790. pCoreData->szConnection = (LPSTR)pCursor;
  1791. pCursor += pCoreData->cbConnection;
  1792. pCoreData->szUserAgent = (LPSTR)pCursor;
  1793. pCursor += pCoreData->cbUserAgent;
  1794. pCoreData->szCookie = (LPSTR)pCursor;
  1795. pCursor += pCoreData->cbCookie;
  1796. pCoreData->szApplMdPath = (LPSTR)pCursor;
  1797. pCursor += pCoreData->cbApplMdPath;
  1798. if ( pCoreData->cbAvailableEntity )
  1799. {
  1800. pCoreData->pAvailableEntity = pCursor;
  1801. }
  1802. else
  1803. {
  1804. pCoreData->pAvailableEntity = NULL;
  1805. }
  1806. }