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.

1089 lines
30 KiB

  1. /*++
  2. Copyright (c) 1999-2002 Microsoft Corporation
  3. Module Name:
  4. Init.c
  5. Abstract:
  6. User-mode interface to HTTP.SYS: DLL initialization/termination routines.
  7. Author:
  8. Eric Stenson (ericsten) 31-May-2001
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. //
  13. // Private macros.
  14. //
  15. //
  16. // Private data.
  17. //
  18. //
  19. // Initialize/Terminate control
  20. //
  21. static DWORD g_InitServerRefCount;
  22. static DWORD g_InitClientRefCount;
  23. static DWORD g_InitConfigRefCount;
  24. static DWORD g_InitResourcesRefCount;
  25. //
  26. // Critical section for accessing the init counts. Also used by client
  27. // api for synchronization during initialization.
  28. //
  29. CRITICAL_SECTION g_InitCritSec;
  30. #if DBG
  31. extern DWORD g_HttpTraceId = 0;
  32. #endif
  33. //
  34. // DLL ref count (for tracking one-time DLL init)
  35. //
  36. static DWORD g_DllRefCount = 0;
  37. //
  38. // global, singleton control channel
  39. //
  40. extern HANDLE g_ControlChannel = NULL;
  41. //
  42. // Thread load storage index for synchronous I/O event
  43. //
  44. extern DWORD g_TlsIndex = 0;
  45. //
  46. // Public functions.
  47. //
  48. /***************************************************************************++
  49. Routine Description:
  50. Performs DLL initialization/termination.
  51. Arguments:
  52. DllHandle - Supplies a handle to the current DLL.
  53. Reason - Supplies the notification code.
  54. pContext - Optionally supplies a context.
  55. Return Value:
  56. BOOLEAN - TRUE if initialization completed successfully, FALSE
  57. otherwise. Ignored for notifications other than process
  58. attach.
  59. --***************************************************************************/
  60. BOOL
  61. WINAPI
  62. DllMain(
  63. IN HMODULE DllHandle,
  64. IN DWORD Reason,
  65. IN LPVOID pContext OPTIONAL
  66. )
  67. {
  68. BOOL result = TRUE;
  69. HANDLE hEvent = NULL;
  70. UNREFERENCED_PARAMETER(pContext);
  71. UNREFERENCED_PARAMETER(DllHandle);
  72. //
  73. // Interpret the reason code.
  74. //
  75. switch (Reason)
  76. {
  77. case DLL_PROCESS_ATTACH:
  78. //
  79. // One time init
  80. //
  81. if ( 1 == InterlockedIncrement( (PLONG)&g_DllRefCount ) )
  82. {
  83. //
  84. // Allocate space in TLS for cached event for synchronous
  85. // IOCTL calls
  86. //
  87. g_TlsIndex = TlsAlloc();
  88. if(g_TlsIndex == TLS_OUT_OF_INDEXES)
  89. {
  90. result = FALSE;
  91. }
  92. if(TRUE == result)
  93. {
  94. HttpCmnInitializeHttpCharsTable(FALSE);
  95. result = InitializeCriticalSectionAndSpinCount( &g_InitCritSec, 0 );
  96. g_InitServerRefCount = 0L;
  97. g_InitClientRefCount = 0L;
  98. g_InitConfigRefCount = 0L;
  99. g_InitResourcesRefCount = 0L;
  100. }
  101. #if DBG
  102. if(TRUE == result)
  103. {
  104. g_HttpTraceId = TraceRegisterEx( HTTP_TRACE_NAME, 0 );
  105. }
  106. #endif
  107. }
  108. break;
  109. case DLL_PROCESS_DETACH:
  110. //
  111. // Ref counting & cleanup assertion(s).
  112. //
  113. if ( 0 == InterlockedDecrement( (PLONG)&g_DllRefCount ) )
  114. {
  115. // Check to see if we've been cleaned up.
  116. if ( NULL != g_ControlChannel )
  117. {
  118. HttpTrace( "DLL_PROCESS_DETACH called with Control Channel still OPEN!\n" );
  119. }
  120. if ( ( 0L != g_InitServerRefCount ) ||
  121. ( 0L != g_InitClientRefCount ) ||
  122. ( 0L != g_InitConfigRefCount ) ||
  123. ( 0L != g_InitResourcesRefCount ) )
  124. {
  125. HttpTrace( "DLL_PROCESS_DETACH called with nonzero Reference Count(s)!\n" );
  126. }
  127. #if DBG
  128. if(0 != g_HttpTraceId)
  129. {
  130. TraceDeregisterEx(g_HttpTraceId, 0);
  131. g_HttpTraceId = 0;
  132. }
  133. #endif
  134. // If DeleteCriticalSection raises an exception should we catch it?
  135. DeleteCriticalSection( &g_InitCritSec );
  136. TlsFree( g_TlsIndex );
  137. }
  138. break;
  139. case DLL_THREAD_DETACH:
  140. hEvent = (HANDLE) TlsGetValue( g_TlsIndex );
  141. if ( hEvent != NULL )
  142. {
  143. NtClose( hEvent );
  144. TlsSetValue( g_TlsIndex, NULL );
  145. }
  146. break;
  147. }
  148. return result;
  149. } // DllMain
  150. /***************************************************************************++
  151. Routine Description:
  152. Performs global initialization.
  153. Arguments:
  154. Reserved - Must be zero. May be used in future for interface version
  155. negotiation.
  156. Return Value:
  157. ULONG - Completion status.
  158. --***************************************************************************/
  159. ULONG
  160. WINAPI
  161. HttpInitialize(
  162. IN HTTPAPI_VERSION Version,
  163. IN ULONG Flags,
  164. IN OUT VOID* Reserved
  165. )
  166. {
  167. ULONG result = ERROR_INVALID_FUNCTION;
  168. HTTPAPI_VERSION HttpVersion = HTTPAPI_VERSION_1;
  169. HttpTrace4("=> HttpInitialize Major=%d Minor%d Flags=%ld Reserved=%p",
  170. Version.HttpApiMajorVersion, Version.HttpApiMinorVersion, Flags, Reserved);
  171. if ( Version.HttpApiMajorVersion != HttpVersion.HttpApiMajorVersion ||
  172. Version.HttpApiMinorVersion != HttpVersion.HttpApiMinorVersion )
  173. {
  174. result = ERROR_INVALID_DLL;
  175. }
  176. else if( (NULL != Reserved) || (HTTP_ILLEGAL_INIT_FLAGS & Flags) )
  177. {
  178. result = ERROR_INVALID_PARAMETER;
  179. }
  180. else
  181. {
  182. EnterCriticalSection( &g_InitCritSec );
  183. // Initialize event cache even if no flags are set
  184. result = HttpApiInitializeResources( Flags );
  185. // Perform specified initialization
  186. if ( NO_ERROR == result )
  187. {
  188. if ( HTTP_INITIALIZE_CONFIG & Flags )
  189. {
  190. result = HttpApiInitializeConfiguration( Flags );
  191. }
  192. if ( NO_ERROR == result )
  193. {
  194. // Perform specified initialization
  195. if ( HTTP_INITIALIZE_SERVER & Flags )
  196. {
  197. result = HttpApiInitializeListener( Flags );
  198. }
  199. if ( NO_ERROR == result )
  200. {
  201. if ( HTTP_INITIALIZE_CLIENT & Flags )
  202. {
  203. result = HttpApiInitializeClient( Flags );
  204. }
  205. if ( ( NO_ERROR != result ) && ( HTTP_INITIALIZE_SERVER & Flags ) )
  206. {
  207. // If we try to initialize both the server and client features then we must succeed with both
  208. // initializations or fail both. We have no error code that distinguishes between total and
  209. // partial failure.
  210. HttpApiTerminateListener( Flags );
  211. }
  212. }
  213. // If we fail to initialize the specified server or client features then we terminate the associated configuration
  214. // as well even if HTTP_INITIALIZE_CONFIGURATION was set in the Flags. We have no error code that
  215. // distinguishes between total and partial failure.
  216. if ( ( NO_ERROR != result ) && ( HTTP_INITIALIZE_CONFIG & Flags ) )
  217. {
  218. // Terminate config
  219. HttpApiTerminateConfiguration( Flags );
  220. }
  221. }
  222. // If we fail any initialization step then we terminate the associated cache initialization. We have no error code
  223. // that distinguishes between total and partial failure.
  224. if ( NO_ERROR != result )
  225. {
  226. HttpApiTerminateResources( Flags );
  227. }
  228. }
  229. LeaveCriticalSection( &g_InitCritSec );
  230. }
  231. HttpTrace1( "<= HttpInitialize = 0x%0x", result );
  232. ASSERT( ERROR_INVALID_FUNCTION != result );
  233. return result;
  234. } // HttpInitialize
  235. /***************************************************************************++
  236. Routine Description:
  237. Performs global termination.
  238. --***************************************************************************/
  239. ULONG
  240. WINAPI
  241. HttpTerminate(
  242. IN ULONG Flags,
  243. IN OUT VOID* Reserved
  244. )
  245. {
  246. ULONG result;
  247. HttpTrace2("=> HttpTerminate Flags=%ld Reserved=%p", Flags, Reserved);
  248. if( (NULL != Reserved) || (HTTP_ILLEGAL_TERM_FLAGS & Flags) )
  249. {
  250. result = ERROR_INVALID_PARAMETER;
  251. }
  252. else
  253. {
  254. ULONG tempResult;
  255. result = NO_ERROR;
  256. EnterCriticalSection( &g_InitCritSec );
  257. if ( (HTTP_INITIALIZE_SERVER) & Flags )
  258. {
  259. result = HttpApiTerminateListener( Flags );
  260. }
  261. if ( (HTTP_INITIALIZE_CLIENT) & Flags )
  262. {
  263. tempResult = HttpApiTerminateClient( Flags );
  264. result = ( NO_ERROR == result ) ? tempResult : NO_ERROR;
  265. }
  266. if ( (HTTP_INITIALIZE_CONFIG) & Flags )
  267. {
  268. tempResult = HttpApiTerminateConfiguration( Flags );
  269. result = ( NO_ERROR == result ) ? tempResult : NO_ERROR;
  270. }
  271. HttpApiTerminateResources( Flags );
  272. LeaveCriticalSection( &g_InitCritSec );
  273. }
  274. HttpTrace1( "<= HttpApiTerminate = 0x%0x", result );
  275. return result;
  276. } // HttpTerminate
  277. /***************************************************************************++
  278. Routine Description:
  279. Predicate to test if DLL has been initalized.
  280. --***************************************************************************/
  281. BOOL
  282. HttpIsInitialized(
  283. IN ULONG Flags
  284. )
  285. {
  286. BOOL fRet = FALSE;
  287. //
  288. // Grab crit sec
  289. //
  290. EnterCriticalSection( &g_InitCritSec );
  291. if ( 0 == Flags )
  292. {
  293. fRet = (BOOL) (0 != g_InitResourcesRefCount );
  294. }
  295. else if ( HTTP_LEGAL_INIT_FLAGS & Flags )
  296. {
  297. fRet = (BOOL) (0 != g_InitResourcesRefCount );
  298. if ( HTTP_INITIALIZE_SERVER & Flags )
  299. {
  300. fRet &= (BOOL) (0 != g_InitServerRefCount);
  301. }
  302. if ( HTTP_INITIALIZE_CLIENT & Flags )
  303. {
  304. fRet &= (BOOL) (0 != g_InitClientRefCount);
  305. }
  306. if ( HTTP_INITIALIZE_CONFIG & Flags )
  307. {
  308. fRet &= (BOOL) (0 != g_InitConfigRefCount);
  309. }
  310. }
  311. LeaveCriticalSection( &g_InitCritSec );
  312. return fRet;
  313. } // HttpIsInitalized
  314. //
  315. // Private functions.
  316. //
  317. /***************************************************************************++
  318. Routine Description:
  319. Performs configuration initialization. This internal function must be called from with the critical
  320. section g_ApiCriticalSection held. With any Flags bit set we check the reference count
  321. and initialize the configuration if needed. On success we increment the reference count.
  322. Arguments:
  323. Flags -
  324. HTTP_INITIALIZE_SERVER - Initializes the HTTP API layer and driver for server applications
  325. HTTP_INITIALIZE_CLIENT - Initializes the HTTP API layer and driver for client applications
  326. HTTP_INITIALIZE_CONFIG - Initializes the HTTP API layer and driver for applications
  327. that will modify the HTTP configuration.
  328. Return Value:
  329. ULONG - Completion status.
  330. --***************************************************************************/
  331. ULONG
  332. HttpApiInitializeConfiguration(
  333. IN ULONG Flags
  334. )
  335. {
  336. ULONG result = ERROR_INVALID_PARAMETER;
  337. HttpTrace1("=> HttpApiInitializeConfiguration Flags=%ld Reserved=%p", Flags);
  338. if ( HTTP_LEGAL_INIT_FLAGS & Flags )
  339. {
  340. result = NO_ERROR;
  341. if ( 0 == g_InitConfigRefCount )
  342. {
  343. // component not configured
  344. result = InitializeConfigurationGlobals();
  345. }
  346. else if ( MAXULONG == g_InitConfigRefCount )
  347. {
  348. // don't want to overflow the reference count
  349. result = ERROR_TOO_MANY_SEM_REQUESTS;
  350. }
  351. if ( NO_ERROR == result )
  352. {
  353. g_InitConfigRefCount++;
  354. }
  355. }
  356. HttpTrace2( "<= HttpApiInitializeConfiguration = 0x%0x RefCount = 0x%0x", result, g_InitConfigRefCount );
  357. return result;
  358. }
  359. /***************************************************************************++
  360. Routine Description:
  361. Performs Resources initialization. This internal function must be called
  362. from with the critical section g_ApiCriticalSection held. On success we
  363. increment the reference count.
  364. Arguments:
  365. Flags -
  366. HTTP_INITIALIZE_SERVER - Initializes the HTTP API layer and driver for
  367. server applications
  368. HTTP_INITIALIZE_CLIENT - Initializes the HTTP API layer and driver for
  369. client applications
  370. HTTP_INITIALIZE_CONFIG - Initializes the HTTP API layer and driver for
  371. applications that will modify the HTTP configuration.
  372. Return Value:
  373. ULONG - Completion status.
  374. --***************************************************************************/
  375. ULONG
  376. HttpApiInitializeResources(
  377. IN ULONG Flags
  378. )
  379. {
  380. ULONG result = ERROR_INVALID_PARAMETER;
  381. ULONG count;
  382. HttpTrace1( "=> HttpApiInitializeResources Flags=%ld Reserved=%p",
  383. Flags);
  384. if ( ( HTTP_LEGAL_INIT_FLAGS & Flags ) || ( 0L == Flags ) )
  385. {
  386. result = NO_ERROR;
  387. // We increment the resources ref count twice
  388. // for every legal bit set. We increment the ref count
  389. // once when the flags are ZERO.
  390. // HttpInitialize may be called with no flags indicating
  391. // that only the resources are to be initialized. This
  392. // convention allows support for existing code.
  393. if ( 0 == Flags )
  394. {
  395. count = 1;
  396. }
  397. else
  398. {
  399. count = 0;
  400. if ( HTTP_INITIALIZE_CLIENT & Flags ) count += 2;
  401. if ( HTTP_INITIALIZE_SERVER & Flags ) count += 2;
  402. if ( HTTP_INITIALIZE_CONFIG & Flags ) count += 2;
  403. }
  404. if ( MAXULONG-count < g_InitResourcesRefCount )
  405. {
  406. // don't want to overflow the reference count
  407. result = ERROR_TOO_MANY_SEM_REQUESTS;
  408. }
  409. else
  410. {
  411. g_InitResourcesRefCount += count;
  412. }
  413. }
  414. HttpTrace2( "<= HttpApiInitializeResources = 0x%0x RefCount = 0x%0x",
  415. result,
  416. g_InitResourcesRefCount );
  417. return result;
  418. }
  419. /***************************************************************************++
  420. Routine Description:
  421. Private function to open a HTTP.sys control channel and enable it.
  422. Arguments:
  423. ControlChannelHandle - Supplies a ptr to hold the control channel handle.
  424. Return Value:
  425. ULONG - Completion status.
  426. --***************************************************************************/
  427. DWORD
  428. OpenAndEnableControlChannel(
  429. OUT PHANDLE pHandle
  430. )
  431. {
  432. DWORD result;
  433. result = HttpOpenControlChannel(
  434. pHandle,
  435. 0
  436. );
  437. if ( NO_ERROR == result )
  438. {
  439. //
  440. // Turn on Control Channel
  441. //
  442. HTTP_ENABLED_STATE controlState = HttpEnabledStateActive;
  443. result = HttpSetControlChannelInformation(
  444. *pHandle,
  445. HttpControlChannelStateInformation,
  446. &controlState,
  447. sizeof(controlState)
  448. );
  449. if ( NO_ERROR != result )
  450. {
  451. CloseHandle(*pHandle);
  452. *pHandle = NULL;
  453. }
  454. }
  455. return result;
  456. }
  457. /***************************************************************************++
  458. Routine Description:
  459. Performs server initialization. This internal function must be called from with the critical
  460. section g_ApiCriticalSection held. With the HTTP_INITIALIZE_SERVER Flags bit set we
  461. check the reference count and initialize the configuration if needed. On success we
  462. increment the reference count.
  463. Arguments:
  464. Flags -
  465. HTTP_INITIALIZE_SERVER - Initializes the HTTP API layer and driver for server applications
  466. HTTP_INITIALIZE_CLIENT - Initializes the HTTP API layer and driver for client applications
  467. HTTP_INITIALIZE_CONFIG - Initializes the HTTP API layer and driver for applications
  468. that will modify the HTTP configuration.
  469. Return Value:
  470. ULONG - Completion status.
  471. --***************************************************************************/
  472. ULONG
  473. HttpApiInitializeListener(
  474. IN ULONG Flags
  475. )
  476. {
  477. ULONG result = ERROR_INVALID_PARAMETER;
  478. HttpTrace1("=> HttpApiInitializeListener Flags=%ld Reserved=%p", Flags);
  479. if ( HTTP_INITIALIZE_SERVER & Flags )
  480. {
  481. result = NO_ERROR;
  482. if ( 0 == g_InitServerRefCount )
  483. {
  484. //
  485. // Start HTTPFilter service
  486. //
  487. HttpApiTryToStartDriver(HTTP_FILTER_SERVICE_NAME);
  488. //
  489. // Open Control channel
  490. //
  491. ASSERT( NULL == g_ControlChannel );
  492. result = OpenAndEnableControlChannel(
  493. &g_ControlChannel
  494. );
  495. if(NO_ERROR == result)
  496. {
  497. //
  498. // Init Config Group Hash Table
  499. //
  500. result = InitializeConfigGroupTable();
  501. if(NO_ERROR != result)
  502. {
  503. CloseHandle(g_ControlChannel);
  504. }
  505. }
  506. }
  507. else if ( MAXULONG == g_InitServerRefCount )
  508. {
  509. // don't want to overflow the reference count
  510. result = ERROR_TOO_MANY_SEM_REQUESTS;
  511. }
  512. if ( NO_ERROR == result )
  513. {
  514. g_InitServerRefCount++;
  515. }
  516. }
  517. HttpTrace2( "<= HttpApiInitializeListener = 0x%0x RefCount = 0x%0x", result, g_InitServerRefCount );
  518. return result;
  519. } // HttpApiInitializeListener
  520. /***************************************************************************++
  521. Routine Description:
  522. Performs server initialization. This internal function must be called from with the critical
  523. section g_ApiCriticalSection held. With the HTTP_INITIALIZE_CLIENT Flags bit set we
  524. check the reference count and initialize the configuration if needed. On success we
  525. increment the reference count.
  526. Arguments:
  527. Flags -
  528. HTTP_INITIALIZE_SERVER - Initializes the HTTP API layer and driver for server applications
  529. HTTP_INITIALIZE_CLIENT - Initializes the HTTP API layer and driver for client applications
  530. HTTP_INITIALIZE_CONFIG - Initializes the HTTP API layer and driver for applications
  531. that will modify the HTTP configuration.
  532. Return Value:
  533. ULONG - Completion status.
  534. --***************************************************************************/
  535. ULONG
  536. HttpApiInitializeClient(
  537. IN ULONG Flags
  538. )
  539. {
  540. ULONG result = ERROR_INVALID_PARAMETER;
  541. HttpTrace1("=> HttpApiInitializeClient Flags=%ld Reserved=%p", Flags);
  542. if ( HTTP_INITIALIZE_CLIENT & Flags )
  543. {
  544. result = NO_ERROR;
  545. if ( 0 == g_InitClientRefCount )
  546. {
  547. WORD wVersionRequested;
  548. WSADATA wsaData;
  549. result = NO_ERROR;
  550. wVersionRequested = MAKEWORD( 2, 2 );
  551. if(WSAStartup( wVersionRequested, &wsaData ) != 0)
  552. {
  553. result = GetLastError();
  554. }
  555. }
  556. else if ( MAXULONG == g_InitClientRefCount )
  557. {
  558. // don't want to overflow the reference count
  559. result = ERROR_TOO_MANY_SEM_REQUESTS;
  560. }
  561. if ( NO_ERROR == result )
  562. {
  563. g_InitClientRefCount++;
  564. }
  565. }
  566. HttpTrace2( "<= HttpApiInitializeClient = 0x%0x RefCount = 0x%0x", result, g_InitClientRefCount );
  567. return result;
  568. } // HttpApiInitializeClient
  569. /***************************************************************************++
  570. Routine Description:
  571. Performs configuration termination. This internal function must be called from with the critical
  572. section g_ApiCriticalSection held. With any Flags bit set we check the reference count
  573. and terminate the configuration if needed. On success we decrement the reference count.
  574. Arguments:
  575. Flags -
  576. HTTP_INITIALIZE_SERVER - Initializes the HTTP API layer and driver for server applications
  577. HTTP_INITIALIZE_CLIENT - Initializes the HTTP API layer and driver for client applications
  578. HTTP_INITIALIZE_CONFIG - Initializes the HTTP API layer and driver for applications
  579. that will modify the HTTP configuration.
  580. Return Value:
  581. ULONG - Completion status.
  582. --***************************************************************************/
  583. ULONG
  584. HttpApiTerminateConfiguration(
  585. IN ULONG Flags
  586. )
  587. {
  588. ULONG result = ERROR_INVALID_PARAMETER;
  589. HttpTrace1("=> HttpApiTerminateConfiguration Flags=%ld Reserved=%p", Flags);
  590. if ( (HTTP_INITIALIZE_CONFIG) & Flags )
  591. {
  592. result = NO_ERROR;
  593. if ( 0L == g_InitConfigRefCount )
  594. {
  595. //
  596. // Configuration not initalized, or init previously failed, or terminated
  597. //
  598. result = ERROR_DLL_INIT_FAILED;
  599. }
  600. else
  601. {
  602. if ( 1L == g_InitConfigRefCount )
  603. {
  604. TerminateConfigurationGlobals();
  605. g_InitConfigRefCount = 0L;
  606. }
  607. else
  608. {
  609. g_InitConfigRefCount--;
  610. }
  611. }
  612. }
  613. HttpTrace2( "<= HttpApiTerminateConfiguration = 0x%0x RefCount = 0x%0x", result, g_InitConfigRefCount );
  614. return result;
  615. }
  616. /***************************************************************************++
  617. Routine Description:
  618. Performs resource termination. This internal function must be called from with the critical
  619. section g_ApiCriticalSection held. On success we decrement the reference count.
  620. We need to hold onto the cache configuration if any of the other ref counts for server, client,
  621. or config are nonzero. This is true because we need event objects available in the cache
  622. for 'synchronous' IO calls to http.sys.
  623. As a result of our dependency on the other ref counts, HttpApiTerminateResources MUST be
  624. called last in HttpTerminate or any similar termination routine.
  625. Arguments:
  626. Flags -
  627. HTTP_INITIALIZE_SERVER - Initializes the HTTP API layer and driver for server applications
  628. HTTP_INITIALIZE_CLIENT - Initializes the HTTP API layer and driver for client applications
  629. HTTP_INITIALIZE_CONFIG - Initializes the HTTP API layer and driver for applications
  630. that will modify the HTTP configuration.
  631. Return Value:
  632. ULONG - Completion status.
  633. --***************************************************************************/
  634. ULONG
  635. HttpApiTerminateResources(
  636. IN ULONG Flags
  637. )
  638. {
  639. ULONG result = ERROR_INVALID_PARAMETER;
  640. HttpTrace1("=> HttpApiTerminateResources Flags=%ld Reserved=%p", Flags);
  641. if ( ( HTTP_LEGAL_TERM_FLAGS & Flags ) || ( 0L == Flags ) )
  642. {
  643. result = NO_ERROR;
  644. if ( 0L == g_InitResourcesRefCount )
  645. {
  646. //
  647. // Configuration not initalized, or init previously failed, or terminated
  648. //
  649. result = ERROR_DLL_INIT_FAILED;
  650. }
  651. else
  652. {
  653. ULONG count = 1;
  654. BOOL bTerminate = FALSE;
  655. // We decrement the resources ref count twice
  656. // for every legal initialization bit in the Flags.
  657. // We decrement the ref count once if the flags are ZERO.
  658. // HttpTerminate may be called with no flags indicating
  659. // that only the resources are to be released. This
  660. // convention allows support for existing code.
  661. if ( 0 == Flags )
  662. {
  663. count = 1;
  664. }
  665. else
  666. {
  667. count = 0;
  668. if ( HTTP_INITIALIZE_CLIENT & Flags ) count += 2;
  669. if ( HTTP_INITIALIZE_SERVER & Flags ) count += 2;
  670. if ( HTTP_INITIALIZE_CONFIG & Flags ) count += 2;
  671. }
  672. bTerminate = (BOOL) ( count >= g_InitResourcesRefCount );
  673. g_InitResourcesRefCount -= count;
  674. if ( bTerminate )
  675. {
  676. g_InitResourcesRefCount = 0L;
  677. }
  678. }
  679. }
  680. HttpTrace2( "<= HttpApiTerminateResources = 0x%0x RefCount = 0x%0x", result, g_InitResourcesRefCount );
  681. return result;
  682. }
  683. /***************************************************************************++
  684. Routine Description:
  685. Performs server termination. This internal function must be called from with the critical
  686. section g_ApiCriticalSection held. With any Flags bit set we check the reference count
  687. and terminate the server context if needed. On success we decrement the reference count.
  688. Arguments:
  689. Flags -
  690. HTTP_INITIALIZE_SERVER - Initializes the HTTP API layer and driver for server applications
  691. HTTP_INITIALIZE_CLIENT - Initializes the HTTP API layer and driver for client applications
  692. HTTP_INITIALIZE_CONFIG - Initializes the HTTP API layer and driver for applications
  693. that will modify the HTTP configuration.
  694. Return Value:
  695. ULONG - Completion status.
  696. --***************************************************************************/
  697. ULONG
  698. HttpApiTerminateListener(
  699. IN ULONG Flags
  700. )
  701. {
  702. ULONG result = ERROR_INVALID_PARAMETER;
  703. HttpTrace1("=> HttpApiTerminateListener Flags=%ld Reserved=%p", Flags);
  704. if ( (HTTP_INITIALIZE_SERVER) & Flags )
  705. {
  706. result = NO_ERROR;
  707. if ( 0L == g_InitServerRefCount )
  708. {
  709. //
  710. // DLL not initalized, or init previously failed, or terminated
  711. //
  712. result = ERROR_DLL_INIT_FAILED;
  713. }
  714. else
  715. {
  716. if ( 1L == g_InitServerRefCount )
  717. {
  718. // Clean up Config Group table
  719. TerminateConfigGroupTable();
  720. // Clean up Control Channel
  721. if ( g_ControlChannel )
  722. {
  723. __try
  724. {
  725. CloseHandle( g_ControlChannel );
  726. }
  727. __finally
  728. {
  729. HttpTrace1(
  730. "HttpTerminateListener: exception closing control channel handle %p\n",
  731. g_ControlChannel
  732. );
  733. }
  734. g_ControlChannel = NULL;
  735. }
  736. g_InitServerRefCount = 0L;
  737. }
  738. else
  739. {
  740. g_InitServerRefCount--;
  741. }
  742. }
  743. }
  744. HttpTrace2( "<= HttpApiTerminateListener = 0x%0x RefCount = 0x%0x", result, g_InitServerRefCount );
  745. return result;
  746. } // HttpTerminateListener
  747. /***************************************************************************++
  748. Routine Description:
  749. Performs client termination. This internal function must be called from with the critical
  750. section g_ApiCriticalSection held. With any Flags bit set we check the reference count
  751. and terminate the client context if needed. On success we decrement the reference count.
  752. Arguments:
  753. Flags -
  754. HTTP_INITIALIZE_SERVER - Initializes the HTTP API layer and driver for server applications
  755. HTTP_INITIALIZE_CLIENT - Initializes the HTTP API layer and driver for client applications
  756. HTTP_INITIALIZE_CONFIG - Initializes the HTTP API layer and driver for applications
  757. that will modify the HTTP configuration.
  758. Return Value:
  759. ULONG - Completion status.
  760. --***************************************************************************/
  761. ULONG
  762. HttpApiTerminateClient(
  763. IN ULONG Flags
  764. )
  765. {
  766. ULONG result = ERROR_INVALID_PARAMETER;
  767. HttpTrace1("=> HttpApiTerminateClient Flags=%ld Reserved=%p", Flags);
  768. if ( HTTP_INITIALIZE_CLIENT & Flags )
  769. {
  770. result = NO_ERROR;
  771. if ( 0L == g_InitClientRefCount )
  772. {
  773. //
  774. // Configuration not initalized, or init previously failed, or terminated
  775. //
  776. result = ERROR_DLL_INIT_FAILED;
  777. }
  778. else
  779. {
  780. if ( 1L == g_InitClientRefCount )
  781. {
  782. g_InitClientRefCount = 0L;
  783. // Unload Ssl filter, if it was loaded.
  784. UnloadStrmFilt();
  785. WSACleanup();
  786. }
  787. else
  788. {
  789. g_InitClientRefCount--;
  790. }
  791. }
  792. }
  793. HttpTrace2( "<= HttpApiTerminateClient = 0x%0x RefCount = 0x%0x", result, g_InitClientRefCount );
  794. return result;
  795. }