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.

2814 lines
78 KiB

  1. /*++
  2. Copyright (c) 1998-2002 Microsoft Corporation
  3. Module Name:
  4. init.c
  5. Abstract:
  6. This module performs initialization for the UL device driver.
  7. Author:
  8. Keith Moore (keithmo) 10-Jun-1998
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. PDRIVER_OBJECT g_UlDriverObject = NULL;
  13. //
  14. // Private constants.
  15. //
  16. #define DEFAULT_THREAD_AFFINITY_MASK ((1ui64 << KeNumberProcessors) - 1)
  17. //
  18. // Private types.
  19. //
  20. //
  21. // Private prototypes.
  22. //
  23. NTSTATUS
  24. UlpApplySecurityToDeviceObjects(
  25. VOID
  26. );
  27. NTSTATUS
  28. UlpSetDeviceObjectSecurity(
  29. IN PDEVICE_OBJECT pDeviceObject,
  30. IN SECURITY_INFORMATION SecurityInformation,
  31. IN PSECURITY_DESCRIPTOR pSecurityDescriptor
  32. );
  33. ULONG
  34. UlpReadUrlC14nConfig(
  35. HANDLE parametersHandle
  36. );
  37. VOID
  38. UlpReadErrorLogConfig(
  39. HANDLE parametersHandle
  40. );
  41. VOID
  42. UlpReadRegistry (
  43. IN PUL_CONFIG pConfig
  44. );
  45. VOID
  46. UlpTerminateModules(
  47. VOID
  48. );
  49. VOID
  50. UlpUnload (
  51. IN PDRIVER_OBJECT DriverObject
  52. );
  53. //
  54. // Private globals.
  55. //
  56. #if DBG
  57. ULONG g_UlpForceInitFailure = 0;
  58. #endif // DBG
  59. #ifdef ALLOC_PRAGMA
  60. #pragma alloc_text( INIT, DriverEntry )
  61. #pragma alloc_text( INIT, UlpApplySecurityToDeviceObjects )
  62. #pragma alloc_text( INIT, UlpSetDeviceObjectSecurity )
  63. #pragma alloc_text( INIT, UlpReadUrlC14nConfig )
  64. #pragma alloc_text( INIT, UlpReadRegistry )
  65. #pragma alloc_text( INIT, UlpReadErrorLogConfig )
  66. #pragma alloc_text( PAGE, UlpUnload )
  67. #pragma alloc_text( PAGE, UlpTerminateModules )
  68. //
  69. // Note that UlpTerminateModules() must be "page" if driver unloading
  70. // is enabled (it's called from UlpUnload), but can be "init" otherwise
  71. // (it's only called after initialization failure).
  72. //
  73. #pragma alloc_text( PAGE, UlpTerminateModules )
  74. #endif // ALLOC_PRAGMA
  75. //
  76. // Public functions.
  77. //
  78. /***************************************************************************++
  79. Routine Description:
  80. This is the initialization routine for the UL device driver.
  81. Arguments:
  82. DriverObject - Supplies a pointer to driver object created by the
  83. system.
  84. RegistryPath - Supplies the name of the driver's configuration
  85. registry tree.
  86. Return Value:
  87. NTSTATUS - Completion status.
  88. --***************************************************************************/
  89. NTSTATUS
  90. DriverEntry(
  91. IN PDRIVER_OBJECT DriverObject,
  92. IN PUNICODE_STRING RegistryPath
  93. )
  94. {
  95. NTSTATUS status;
  96. UNICODE_STRING deviceName;
  97. OBJECT_ATTRIBUTES objectAttributes;
  98. UL_CONFIG config;
  99. SYSTEM_BASIC_INFORMATION sbi;
  100. UNREFERENCED_PARAMETER(RegistryPath);
  101. //
  102. // Sanity check.
  103. //
  104. PAGED_CODE();
  105. g_UlDriverObject = DriverObject;
  106. //
  107. // Grab the number of processors in the system.
  108. //
  109. g_UlNumberOfProcessors = KeNumberProcessors;
  110. g_UlThreadAffinityMask = DEFAULT_THREAD_AFFINITY_MASK;
  111. //
  112. // Grab the largest cache line size in the system
  113. //
  114. g_UlCacheLineSize = KeGetRecommendedSharedDataAlignment();
  115. for (g_UlCacheLineBits = 0;
  116. (1U << g_UlCacheLineBits) < g_UlCacheLineSize;
  117. ++g_UlCacheLineBits)
  118. {}
  119. ASSERT(g_UlCacheLineSize <= (1U << g_UlCacheLineBits));
  120. status = NtQuerySystemInformation(
  121. SystemBasicInformation,
  122. &sbi,
  123. sizeof(sbi),
  124. NULL);
  125. ASSERT(NT_SUCCESS(status));
  126. //
  127. // Capture total physical memory, in terms of megabytes.
  128. //
  129. g_UlTotalPhysicalMemMB = PAGES_TO_MEGABYTES(sbi.NumberOfPhysicalPages);
  130. //
  131. // Estimate the total number of NPP available in bytes since Landy
  132. // doesn't want to export MmSizeOfNonPagedPoolInBytes.
  133. //
  134. // CODEWORK: Whenever we have a mechanism for discovering the
  135. // NonPagedPool size, use that instead of the total physical
  136. // RAM on the system.
  137. //
  138. #if defined(_WIN64)
  139. //
  140. // On IA64, assume NPP can be 50% of total physical memory.
  141. //
  142. g_UlTotalNonPagedPoolBytes = MEGABYTES_TO_BYTES(g_UlTotalPhysicalMemMB/2);
  143. #else
  144. //
  145. // On X86, assume NPP is either 50% of total physical memory or 256MB,
  146. // whichever is less.
  147. //
  148. g_UlTotalNonPagedPoolBytes = MEGABYTES_TO_BYTES(
  149. MIN(256, g_UlTotalPhysicalMemMB/2)
  150. );
  151. #endif
  152. //
  153. // Snag a pointer to the system process.
  154. //
  155. g_pUlSystemProcess = (PKPROCESS)IoGetCurrentProcess();
  156. //
  157. // Temporarily initialize the IS_HTTP_*() macros.
  158. // Will be initialized properly by InitializeHttpUtil() later.
  159. //
  160. HttpCmnInitializeHttpCharsTable(FALSE);
  161. //
  162. // Read registry information.
  163. //
  164. UlpReadRegistry( &config );
  165. #if DBG
  166. //
  167. // Give anyone using the kernel debugger a chance to abort
  168. // initialization.
  169. //
  170. if (g_UlpForceInitFailure != 0)
  171. {
  172. status = STATUS_UNSUCCESSFUL;
  173. goto fatal;
  174. }
  175. #endif // DBG
  176. //
  177. // Initialize the global trace logs.
  178. //
  179. CREATE_REF_TRACE_LOG( g_pMondoGlobalTraceLog,
  180. 16384 - REF_TRACE_OVERHEAD,
  181. 0, TRACELOG_HIGH_PRIORITY,
  182. UL_REF_TRACE_LOG_POOL_TAG );
  183. CREATE_REF_TRACE_LOG( g_pPoolAllocTraceLog,
  184. 16384 - REF_TRACE_OVERHEAD,
  185. 0, TRACELOG_HIGH_PRIORITY,
  186. UL_REF_TRACE_LOG_POOL_TAG );
  187. CREATE_REF_TRACE_LOG( g_pUriTraceLog,
  188. 2048 - REF_TRACE_OVERHEAD,
  189. 0, TRACELOG_HIGH_PRIORITY,
  190. UL_REF_TRACE_LOG_POOL_TAG );
  191. CREATE_REF_TRACE_LOG( g_pTdiTraceLog,
  192. 32768 - REF_TRACE_OVERHEAD,
  193. 0, TRACELOG_HIGH_PRIORITY,
  194. UL_REF_TRACE_LOG_POOL_TAG );
  195. CREATE_REF_TRACE_LOG( g_pHttpRequestTraceLog,
  196. 2048 - REF_TRACE_OVERHEAD,
  197. 0, TRACELOG_HIGH_PRIORITY,
  198. UL_REF_TRACE_LOG_POOL_TAG );
  199. CREATE_REF_TRACE_LOG( g_pHttpConnectionTraceLog,
  200. 2048 - REF_TRACE_OVERHEAD,
  201. 0, TRACELOG_HIGH_PRIORITY,
  202. UL_REF_TRACE_LOG_POOL_TAG );
  203. CREATE_REF_TRACE_LOG( g_pHttpResponseTraceLog,
  204. 2048 - REF_TRACE_OVERHEAD,
  205. 0, TRACELOG_HIGH_PRIORITY,
  206. UL_REF_TRACE_LOG_POOL_TAG );
  207. CREATE_REF_TRACE_LOG( g_pAppPoolTraceLog,
  208. 2048 - REF_TRACE_OVERHEAD,
  209. 0, TRACELOG_HIGH_PRIORITY,
  210. UL_REF_TRACE_LOG_POOL_TAG );
  211. CREATE_REF_TRACE_LOG( g_pAppPoolProcessTraceLog,
  212. 2048 - REF_TRACE_OVERHEAD,
  213. 0, TRACELOG_HIGH_PRIORITY,
  214. UL_REF_TRACE_LOG_POOL_TAG );
  215. CREATE_REF_TRACE_LOG( g_pConfigGroupTraceLog,
  216. 2048 - REF_TRACE_OVERHEAD,
  217. 0, TRACELOG_HIGH_PRIORITY,
  218. UL_REF_TRACE_LOG_POOL_TAG );
  219. CREATE_REF_TRACE_LOG( g_pControlChannelTraceLog,
  220. 2048 - REF_TRACE_OVERHEAD,
  221. 0, TRACELOG_HIGH_PRIORITY,
  222. UL_REF_TRACE_LOG_POOL_TAG );
  223. CREATE_REF_TRACE_LOG( g_pThreadTraceLog,
  224. 16384 - REF_TRACE_OVERHEAD,
  225. 0, TRACELOG_HIGH_PRIORITY,
  226. UL_REF_TRACE_LOG_POOL_TAG );
  227. CREATE_REF_TRACE_LOG( g_pMdlTraceLog,
  228. 2048 - REF_TRACE_OVERHEAD,
  229. 0, TRACELOG_HIGH_PRIORITY,
  230. UL_REF_TRACE_LOG_POOL_TAG );
  231. CREATE_REF_TRACE_LOG( g_pFilterTraceLog,
  232. 2048 - REF_TRACE_OVERHEAD,
  233. 0, TRACELOG_HIGH_PRIORITY,
  234. UL_REF_TRACE_LOG_POOL_TAG );
  235. CREATE_REF_TRACE_LOG( g_pSiteCounterTraceLog,
  236. 2048 - REF_TRACE_OVERHEAD,
  237. 0, TRACELOG_HIGH_PRIORITY,
  238. UL_REF_TRACE_LOG_POOL_TAG );
  239. CREATE_REF_TRACE_LOG( g_pConnectionCountTraceLog,
  240. 2048 - REF_TRACE_OVERHEAD,
  241. 0, TRACELOG_HIGH_PRIORITY,
  242. UL_REF_TRACE_LOG_POOL_TAG );
  243. CREATE_REF_TRACE_LOG( g_pConfigGroupInfoTraceLog,
  244. 2048 - REF_TRACE_OVERHEAD,
  245. 0, TRACELOG_HIGH_PRIORITY,
  246. UL_REF_TRACE_LOG_POOL_TAG );
  247. CREATE_REF_TRACE_LOG( g_pChunkTrackerTraceLog,
  248. 2048 - REF_TRACE_OVERHEAD,
  249. 0, TRACELOG_HIGH_PRIORITY,
  250. UL_REF_TRACE_LOG_POOL_TAG );
  251. CREATE_REF_TRACE_LOG( g_pWorkItemTraceLog,
  252. 32768 - REF_TRACE_OVERHEAD,
  253. 0, TRACELOG_HIGH_PRIORITY,
  254. UL_REF_TRACE_LOG_POOL_TAG );
  255. CREATE_REF_TRACE_LOG( g_pEndpointUsageTraceLog,
  256. 16384 - REF_TRACE_OVERHEAD,
  257. 0, TRACELOG_HIGH_PRIORITY,
  258. UL_REF_TRACE_LOG_POOL_TAG );
  259. CREATE_IRP_TRACE_LOG( g_pIrpTraceLog,
  260. 32768 - REF_TRACE_OVERHEAD, 0 );
  261. CREATE_TIME_TRACE_LOG( g_pTimeTraceLog,
  262. 32768 - REF_TRACE_OVERHEAD, 0 );
  263. CREATE_APP_POOL_TIME_TRACE_LOG( g_pAppPoolTimeTraceLog,
  264. 32768 - REF_TRACE_OVERHEAD, 0 );
  265. CREATE_STRING_LOG( g_pGlobalStringLog, 5 * 1024 * 1024, 0, FALSE );
  266. CREATE_UC_TRACE_LOG( g_pUcTraceLog,
  267. 16384 - REF_TRACE_OVERHEAD, 0 );
  268. //
  269. // Create an object directory to contain our device objects.
  270. //
  271. status = UlInitUnicodeStringEx( &deviceName, HTTP_DIRECTORY_NAME );
  272. if (!NT_SUCCESS(status))
  273. {
  274. goto fatal;
  275. }
  276. InitializeObjectAttributes(
  277. &objectAttributes, // ObjectAttributes
  278. &deviceName, // ObjectName
  279. OBJ_CASE_INSENSITIVE | // Attributes
  280. OBJ_KERNEL_HANDLE,
  281. NULL, // RootDirectory
  282. NULL // SecurityDescriptor
  283. );
  284. status = ZwCreateDirectoryObject(
  285. &g_UlDirectoryObject, // DirectoryHandle
  286. DIRECTORY_ALL_ACCESS, // AccessMask
  287. &objectAttributes // ObjectAttributes
  288. );
  289. if (!NT_SUCCESS(status))
  290. {
  291. goto fatal;
  292. }
  293. //
  294. // Create the control channel device object.
  295. //
  296. status = UlInitUnicodeStringEx( &deviceName, HTTP_CONTROL_DEVICE_NAME );
  297. if (!NT_SUCCESS(status))
  298. {
  299. goto fatal;
  300. }
  301. status = IoCreateDevice(
  302. DriverObject, // DriverObject
  303. 0, // DeviceExtension
  304. &deviceName, // DeviceName
  305. FILE_DEVICE_NETWORK, // DeviceType
  306. 0, // DeviceCharacteristics
  307. FALSE, // Exclusive
  308. &g_pUlControlDeviceObject // DeviceObject
  309. );
  310. if (!NT_SUCCESS(status))
  311. {
  312. goto fatal;
  313. }
  314. //
  315. // Create the filter device object.
  316. //
  317. status = UlInitUnicodeStringEx( &deviceName, HTTP_FILTER_DEVICE_NAME );
  318. if (!NT_SUCCESS(status))
  319. {
  320. goto fatal;
  321. }
  322. status = IoCreateDevice(
  323. DriverObject, // DriverObject
  324. 0, // DeviceExtension
  325. &deviceName, // DeviceName
  326. FILE_DEVICE_NETWORK, // DeviceType
  327. 0, // DeviceCharacteristics
  328. FALSE, // Exclusive
  329. &g_pUlFilterDeviceObject // DeviceObject
  330. );
  331. if (!NT_SUCCESS(status))
  332. {
  333. goto fatal;
  334. }
  335. g_pUlFilterDeviceObject->StackSize = DEFAULT_IRP_STACK_SIZE;
  336. //
  337. // Create the app pool device object.
  338. //
  339. status = UlInitUnicodeStringEx( &deviceName, HTTP_APP_POOL_DEVICE_NAME );
  340. if (!NT_SUCCESS(status))
  341. {
  342. goto fatal;
  343. }
  344. status = IoCreateDevice(
  345. DriverObject, // DriverObject
  346. 0, // DeviceExtension
  347. &deviceName, // DeviceName
  348. FILE_DEVICE_NETWORK, // DeviceType
  349. 0, // DeviceCharacteristics
  350. FALSE, // Exclusive
  351. &g_pUlAppPoolDeviceObject // DeviceObject
  352. );
  353. if (!NT_SUCCESS(status))
  354. {
  355. goto fatal;
  356. }
  357. g_pUlAppPoolDeviceObject->StackSize = DEFAULT_IRP_STACK_SIZE;
  358. //
  359. // Initialize the driver object with this driver's entrypoints.
  360. //
  361. DriverObject->MajorFunction[IRP_MJ_CREATE] = &UlCreate;
  362. DriverObject->MajorFunction[IRP_MJ_CLOSE] = &UlClose;
  363. DriverObject->MajorFunction[IRP_MJ_CLEANUP] = &UlCleanup;
  364. DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = &UlDeviceControl;
  365. DriverObject->MajorFunction[IRP_MJ_QUERY_SECURITY] = &UlQuerySecurityDispatch;
  366. DriverObject->MajorFunction[IRP_MJ_SET_SECURITY] = &UlSetSecurityDispatch;
  367. DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = &UlEtwDispatch;
  368. DriverObject->FastIoDispatch = &UlFastIoDispatch;
  369. DriverObject->DriverUnload = NULL;
  370. //
  371. // Initialize global data.
  372. //
  373. status = UlInitializeData(&config);
  374. if (!NT_SUCCESS(status))
  375. {
  376. goto fatal;
  377. }
  378. //
  379. // Create the thread pool.
  380. //
  381. status = UlInitializeThreadPool(config.ThreadsPerCpu);
  382. if (!NT_SUCCESS(status))
  383. {
  384. goto fatal;
  385. }
  386. //
  387. // Initialize common TDI code.
  388. //
  389. status = UxInitializeTdi();
  390. if (!NT_SUCCESS(status))
  391. {
  392. goto fatal;
  393. }
  394. //
  395. // Initialize server connection code.
  396. //
  397. status = UlInitializeTdi();
  398. if (!NT_SUCCESS(status))
  399. {
  400. goto fatal;
  401. }
  402. //
  403. // Initialize George.
  404. //
  405. status = UlLargeMemInitialize();
  406. if (!NT_SUCCESS(status))
  407. {
  408. goto fatal;
  409. }
  410. //
  411. // Initialize Keith.
  412. //
  413. status = UlInitializeControlChannel();
  414. if (!NT_SUCCESS(status))
  415. {
  416. goto fatal;
  417. }
  418. //
  419. // Initialize Henry.
  420. //
  421. status = InitializeHttpUtil();
  422. if (!NT_SUCCESS(status))
  423. {
  424. goto fatal;
  425. }
  426. status = InitializeParser();
  427. if (!NT_SUCCESS(status))
  428. {
  429. goto fatal;
  430. }
  431. status = UlInitializeOpaqueIdTable();
  432. if (!NT_SUCCESS(status))
  433. {
  434. goto fatal;
  435. }
  436. status = InitializeFileCache();
  437. if (!NT_SUCCESS(status))
  438. {
  439. goto fatal;
  440. }
  441. //
  442. // Initialize Michael.
  443. //
  444. status = UlInitializeFilterChannel(&config);
  445. if (!NT_SUCCESS(status))
  446. {
  447. goto fatal;
  448. }
  449. //
  450. // Initialize Alex.
  451. //
  452. status = UlInitializeUriCache(&config);
  453. if (!NT_SUCCESS(status))
  454. {
  455. goto fatal;
  456. }
  457. status = UlInitializeDateCache();
  458. if (!NT_SUCCESS(status))
  459. {
  460. goto fatal;
  461. }
  462. //
  463. // Initialize Paul.
  464. //
  465. status = UlInitializeCG();
  466. if (!NT_SUCCESS(status))
  467. {
  468. goto fatal;
  469. }
  470. status = UlInitializeAP();
  471. if (!NT_SUCCESS(status))
  472. {
  473. goto fatal;
  474. }
  475. //
  476. // Initialize Ali
  477. //
  478. status = UlInitializeLogUtil();
  479. if (!NT_SUCCESS(status))
  480. {
  481. goto fatal;
  482. }
  483. status = UlInitializeLogs();
  484. if (!NT_SUCCESS(status))
  485. {
  486. goto fatal;
  487. }
  488. status = UlInitializeBinaryLog();
  489. if (!NT_SUCCESS(status))
  490. {
  491. goto fatal;
  492. }
  493. status = UlInitializeErrorLog();
  494. if (!NT_SUCCESS(status))
  495. {
  496. goto fatal;
  497. }
  498. status = UlTcInitialize();
  499. if (!NT_SUCCESS(status))
  500. {
  501. goto fatal;
  502. }
  503. status = UlInitGlobalConnectionLimits();
  504. if (!NT_SUCCESS(status))
  505. {
  506. goto fatal;
  507. }
  508. status = UlInitializeHttpConnection();
  509. if (!NT_SUCCESS(status))
  510. {
  511. goto fatal;
  512. }
  513. //
  514. // Initialize Eric.
  515. //
  516. status = UlInitializeCounters();
  517. if (!NT_SUCCESS(status))
  518. {
  519. goto fatal;
  520. }
  521. UlInitializeTimeoutMonitor();
  522. //
  523. // Initialize ETW Tracing
  524. //
  525. UlEtwInitLog( g_pUlControlDeviceObject );
  526. //
  527. // Initialize HTTP client
  528. //
  529. if(config.EnableHttpClient)
  530. {
  531. //
  532. // All of the client code live under a "section" called PAGEUC. This
  533. // section is paged by default & gets locked down when there is an app
  534. // that uses the client APIs (specifically, opens a handle to a server).
  535. //
  536. // There are two ways of demand locking this section. We can either use
  537. // MmLockPagableCodeSection or MmLockPagableSectionByHandle. It's a lot
  538. // cheaper to use MmLockPagableSectionByHandle.
  539. //
  540. // So, during our DriverEntry, we first lock the entire PAGEUC section
  541. // to obtain the handle. We then immediately unlock it, but remember
  542. // the handle. This allows us to use MmLockPagableSectionByHandle for
  543. // subsequent locks, which is much faster.
  544. //
  545. // In order to use MmLockPagableCodeSection, we'll pick one function
  546. // that lives under this section --> UcpTdiReceiveHandler
  547. //
  548. g_ClientImageHandle =
  549. MmLockPagableCodeSection((PVOID)((ULONG_PTR)UcpTdiReceiveHandler));
  550. MmUnlockPagableImageSection(g_ClientImageHandle);
  551. //
  552. // Create the server device object
  553. //
  554. status = UlInitUnicodeStringEx(&deviceName, HTTP_SERVER_DEVICE_NAME);
  555. if(!NT_SUCCESS(status))
  556. {
  557. goto fatal;
  558. }
  559. status = IoCreateDevice(DriverObject,
  560. 0,
  561. &deviceName,
  562. FILE_DEVICE_NETWORK,
  563. 0,
  564. FALSE,
  565. &g_pUcServerDeviceObject
  566. );
  567. if(!NT_SUCCESS(status))
  568. {
  569. goto fatal;
  570. }
  571. g_pUcServerDeviceObject->StackSize ++;
  572. //
  573. // Initialize the client connection code.
  574. //
  575. status = UcInitializeServerInformation();
  576. if(!NT_SUCCESS(status))
  577. {
  578. goto fatal;
  579. }
  580. status = UcInitializeClientConnections();
  581. if(!NT_SUCCESS(status))
  582. {
  583. goto fatal;
  584. }
  585. status = UcInitializeSSPI();
  586. if(!NT_SUCCESS(status))
  587. {
  588. goto fatal;
  589. }
  590. status = UcInitializeHttpRequests();
  591. if (!NT_SUCCESS(status))
  592. {
  593. goto fatal;
  594. }
  595. }
  596. else
  597. {
  598. // Disable all the client IOCTLs.
  599. UlSetDummyIoctls();
  600. }
  601. //
  602. // Apply security to the device objects.
  603. //
  604. status = UlpApplySecurityToDeviceObjects();
  605. if (!NT_SUCCESS(status))
  606. {
  607. goto fatal;
  608. }
  609. //
  610. // Initialize Namespace.
  611. // Note: This initialization must be done after
  612. // UlpApplySecurityToDeviceObjects() has been called.
  613. // Otherwise, g_pAdminAllSystemAll will not be initialzied.
  614. // UlInitializeNamespace() uses that global security descriptor.
  615. //
  616. status = UlInitializeNamespace();
  617. if (!NT_SUCCESS(status))
  618. {
  619. goto fatal;
  620. }
  621. #if DBG
  622. //
  623. // Give anyone using the kernel debugger one final chance to abort
  624. // initialization.
  625. //
  626. if (g_UlpForceInitFailure != 0)
  627. {
  628. status = STATUS_UNSUCCESSFUL;
  629. goto fatal;
  630. }
  631. #endif // DBG
  632. //
  633. // Set DriverUnload only after everything has succeeded to synchronize
  634. // DriverEntry and DriverUnload. In theory however, the DriverUnload
  635. // routine can still be called once we set it, but that can't be fixed
  636. // by the drivers, it needs to be fixed by IO or SCM.
  637. //
  638. DriverObject->DriverUnload = &UlpUnload;
  639. return STATUS_SUCCESS;
  640. //
  641. // Fatal error handlers.
  642. //
  643. fatal:
  644. ASSERT( !NT_SUCCESS(status) );
  645. UlpTerminateModules();
  646. return status;
  647. } // DriverEntry
  648. //
  649. // Private functions.
  650. //
  651. /***************************************************************************++
  652. Routine Description:
  653. Applies the appropriate security descriptors to the global device
  654. objects created at initialization time.
  655. Return Value:
  656. NTSTATUS - Completion status.
  657. --***************************************************************************/
  658. NTSTATUS
  659. UlpApplySecurityToDeviceObjects(
  660. VOID
  661. )
  662. {
  663. NTSTATUS status;
  664. SECURITY_DESCRIPTOR securityDescriptor;
  665. PGENERIC_MAPPING pFileObjectGenericMapping;
  666. ACCESS_MASK fileReadWrite;
  667. ACCESS_MASK fileAll;
  668. SID_MASK_PAIR sidMaskPairs[4];
  669. //
  670. // Sanity check.
  671. //
  672. PAGED_CODE();
  673. ASSERT( IS_VALID_DEVICE_OBJECT( g_pUlControlDeviceObject ) );
  674. ASSERT( IS_VALID_DEVICE_OBJECT( g_pUlFilterDeviceObject ) );
  675. ASSERT( IS_VALID_DEVICE_OBJECT( g_pUlAppPoolDeviceObject ) );
  676. //
  677. // Gain access to the predefined SIDs and other security-related
  678. // goodies exported by the kernel.
  679. //
  680. //SeEnableAccessToExports();
  681. //
  682. // Map a couple of generic file access types to their corresponding
  683. // object-specific rights.
  684. //
  685. pFileObjectGenericMapping = IoGetFileObjectGenericMapping();
  686. ASSERT( pFileObjectGenericMapping != NULL );
  687. //
  688. // FILE_READ & FILE_WRITE
  689. //
  690. fileReadWrite = GENERIC_READ | GENERIC_WRITE;
  691. RtlMapGenericMask(
  692. &fileReadWrite,
  693. pFileObjectGenericMapping
  694. );
  695. //
  696. // FILE_ALL
  697. //
  698. fileAll = GENERIC_ALL;
  699. RtlMapGenericMask(
  700. &fileAll,
  701. pFileObjectGenericMapping
  702. );
  703. //
  704. // Build a restrictive security descriptor for the filter device
  705. // object:
  706. //
  707. // Full access for NT AUTHORITY\SYSTEM
  708. // Full access for BUILTIN\Administrators
  709. //
  710. sidMaskPairs[0].pSid = SeExports->SeLocalSystemSid;
  711. sidMaskPairs[0].AccessMask = fileAll;
  712. sidMaskPairs[0].AceFlags = 0;
  713. sidMaskPairs[1].pSid = SeExports->SeAliasAdminsSid;
  714. sidMaskPairs[1].AccessMask = fileAll;
  715. sidMaskPairs[1].AceFlags = 0;
  716. status = UlCreateSecurityDescriptor(
  717. &securityDescriptor, // pSecurityDescriptor
  718. &sidMaskPairs[0], // pSidMaskPairs
  719. 2 // NumSidMaskPairs
  720. );
  721. if (!NT_SUCCESS(status))
  722. {
  723. return status;
  724. }
  725. //
  726. // Filter object
  727. //
  728. status = UlpSetDeviceObjectSecurity(
  729. g_pUlFilterDeviceObject,
  730. DACL_SECURITY_INFORMATION,
  731. &securityDescriptor
  732. );
  733. UlCleanupSecurityDescriptor(&securityDescriptor);
  734. if (!NT_SUCCESS(status))
  735. {
  736. return status;
  737. }
  738. //
  739. // We want a global security descriptor that allows fileAll to
  740. // System and Administrators and nothing else for world. Incidently,
  741. // the filter device object provides this exact feature. We'll save
  742. // a pointer to this security descriptor.
  743. //
  744. // WARNING: If we ever change the ACL on the Filter Device Object, we'll
  745. // have to create a new security descriptor for this.
  746. //
  747. //
  748. g_pAdminAllSystemAll = g_pUlFilterDeviceObject->SecurityDescriptor;
  749. //
  750. // Build a slightly less restrictive security descriptor for the
  751. // other device objects.
  752. //
  753. // Full access for NT AUTHORITY\SYSTEM
  754. // Full access for BUILTIN\Administrators
  755. // Read/Write access for Authenticated users
  756. // Read/Write access for Guest.
  757. //
  758. sidMaskPairs[2].pSid = SeExports->SeAuthenticatedUsersSid;
  759. sidMaskPairs[2].AccessMask = fileReadWrite;
  760. sidMaskPairs[2].AceFlags = 0;
  761. sidMaskPairs[3].pSid = SeExports->SeAliasGuestsSid;
  762. sidMaskPairs[3].AccessMask = fileReadWrite;
  763. sidMaskPairs[3].AceFlags = 0;
  764. status = UlCreateSecurityDescriptor(
  765. &securityDescriptor,
  766. &sidMaskPairs[0], // pSidMaskPairs
  767. 4 // NumSidMaskPairs
  768. );
  769. if (!NT_SUCCESS(status))
  770. {
  771. return status;
  772. }
  773. for(;;)
  774. {
  775. //
  776. // App Pool
  777. //
  778. status = UlpSetDeviceObjectSecurity(
  779. g_pUlAppPoolDeviceObject,
  780. DACL_SECURITY_INFORMATION,
  781. &securityDescriptor
  782. );
  783. if (!NT_SUCCESS(status))
  784. {
  785. break;
  786. }
  787. //
  788. // Control Channel
  789. //
  790. status = UlpSetDeviceObjectSecurity(
  791. g_pUlControlDeviceObject,
  792. DACL_SECURITY_INFORMATION,
  793. &securityDescriptor
  794. );
  795. if (!NT_SUCCESS(status))
  796. {
  797. break;
  798. }
  799. //
  800. // Server
  801. //
  802. if(g_pUcServerDeviceObject)
  803. {
  804. status = UlpSetDeviceObjectSecurity(
  805. g_pUcServerDeviceObject,
  806. DACL_SECURITY_INFORMATION,
  807. &securityDescriptor
  808. );
  809. }
  810. break;
  811. }
  812. UlCleanupSecurityDescriptor(&securityDescriptor);
  813. return status;
  814. } // UlpApplySecurityToDeviceObjects
  815. /***************************************************************************++
  816. Routine Description:
  817. Applies the specified security descriptor to the specified device
  818. object.
  819. Arguments:
  820. pDeviceObject - Supplies the device object to manipulate.
  821. SecurityInformation - Supplies the level of information to change.
  822. pSecurityDescriptor - Supplies the new security descriptor for the
  823. device object.
  824. Return Value:
  825. NTSTATUS - Completion status.
  826. --***************************************************************************/
  827. NTSTATUS
  828. UlpSetDeviceObjectSecurity(
  829. IN PDEVICE_OBJECT pDeviceObject,
  830. IN SECURITY_INFORMATION SecurityInformation,
  831. IN PSECURITY_DESCRIPTOR pSecurityDescriptor
  832. )
  833. {
  834. NTSTATUS status;
  835. HANDLE handle;
  836. //
  837. // Sanity check.
  838. //
  839. PAGED_CODE();
  840. ASSERT( IS_VALID_DEVICE_OBJECT( pDeviceObject ) );
  841. ASSERT( RtlValidSecurityDescriptor( pSecurityDescriptor ) );
  842. //
  843. // Open a handle to the device object.
  844. //
  845. status = ObOpenObjectByPointer(
  846. pDeviceObject, // Object
  847. OBJ_CASE_INSENSITIVE | // HandleAttributes
  848. OBJ_KERNEL_HANDLE,
  849. NULL, // PassedAccessState
  850. MAXIMUM_ALLOWED, // DesiredAccess
  851. NULL, // ObjectType
  852. KernelMode, // AccessMode
  853. &handle // Handle
  854. );
  855. if (NT_SUCCESS(status))
  856. {
  857. status = NtSetSecurityObject(
  858. handle, // Handle
  859. SecurityInformation, // SecurityInformation
  860. pSecurityDescriptor // SecurityDescriptor
  861. );
  862. ZwClose( handle );
  863. }
  864. return status;
  865. } // UlpSetDeviceObjectSecurity
  866. //
  867. // Read URL processing parameters.
  868. //
  869. ULONG
  870. UlpReadUrlC14nConfig(
  871. HANDLE parametersHandle
  872. )
  873. {
  874. LONG tmp;
  875. LONG DefaultBoolRegValue = -123; // sane values are 0 and 1
  876. LONG EnableDbcs;
  877. LONG FavorUtf8;
  878. LONG EnableNonUtf8 ;
  879. LONG PercentUAllowed ;
  880. LONG AllowRestrictedChars ;
  881. LONG UrlSegmentMaxLength;
  882. LONG UrlSegmentMaxCount;
  883. NTSTATUS status;
  884. UNICODE_STRING registryPathNLS;
  885. HANDLE codePageHandle;
  886. UNICODE_STRING ACPCodeString;
  887. ULONG ACPCode = 0;
  888. PKEY_VALUE_PARTIAL_INFORMATION pInfo;
  889. //
  890. // Tune defaults based on whether we are running on a DBCS system.
  891. // Since we do not have a convenient API to do so, use this algorithm:
  892. //
  893. // 1- Get ACP from the registry at:
  894. // HKLM\System\CurrentControlSet\Control\NLS\CodePage
  895. // 2- check against the list of DBCS in:
  896. // http://www.microsoft.com/globaldev/reference/WinCP.asp
  897. //
  898. // TODO - use kernel mode API when provided.
  899. //
  900. EnableDbcs = FALSE;
  901. status = UlInitUnicodeStringEx(&registryPathNLS, REGISTRY_NLS_PATH);
  902. if(NT_SUCCESS(status))
  903. {
  904. status = UlOpenRegistry(
  905. &registryPathNLS,
  906. &codePageHandle,
  907. REGISTRY_NLS_CODEPAGE_KEY
  908. );
  909. if (NT_SUCCESS(status))
  910. {
  911. pInfo = NULL;
  912. status = UlReadGenericParameter(
  913. codePageHandle,
  914. REGISTRY_ACP_NAME,
  915. &pInfo
  916. );
  917. if (NT_SUCCESS(status))
  918. {
  919. ASSERT(pInfo);
  920. if (pInfo->Type == REG_SZ)
  921. {
  922. status = UlInitUnicodeStringEx(
  923. &ACPCodeString,
  924. (PWSTR)pInfo->Data
  925. );
  926. if (NT_SUCCESS(status))
  927. {
  928. status = HttpWideStringToULong(
  929. ACPCodeString.Buffer,
  930. ACPCodeString.Length / sizeof(WCHAR),
  931. FALSE,
  932. 10,
  933. NULL,
  934. &ACPCode
  935. );
  936. if (NT_SUCCESS(status))
  937. {
  938. //
  939. // Check if this is one of the known DBCS codes:
  940. //
  941. if ((ACPCode == CP_JAPANESE_SHIFT_JIS) ||
  942. (ACPCode == CP_SIMPLIFIED_CHINESE_GBK) ||
  943. (ACPCode == CP_KOREAN) ||
  944. (ACPCode == CP_TRADITIONAL_CHINESE_BIG5))
  945. {
  946. EnableDbcs = TRUE;
  947. }
  948. else
  949. {
  950. EnableDbcs = FALSE;
  951. }
  952. }
  953. }
  954. }
  955. //
  956. // Free up the returned value.
  957. //
  958. UL_FREE_POOL( pInfo, UL_REGISTRY_DATA_POOL_TAG );
  959. }
  960. ZwClose( codePageHandle );
  961. }
  962. }
  963. //
  964. // Now check if we have registry overrides for each of these.
  965. //
  966. EnableNonUtf8 = UlReadLongParameter(
  967. parametersHandle,
  968. REGISTRY_ENABLE_NON_UTF8_URL,
  969. DefaultBoolRegValue);
  970. if (EnableNonUtf8 != DefaultBoolRegValue)
  971. {
  972. //
  973. // A registry setting is present; use it.
  974. //
  975. EnableNonUtf8 = (BOOLEAN) (EnableNonUtf8 != 0);
  976. }
  977. else
  978. {
  979. EnableNonUtf8 = DEFAULT_ENABLE_NON_UTF8_URL;
  980. }
  981. if (EnableNonUtf8)
  982. {
  983. FavorUtf8 = UlReadLongParameter(
  984. parametersHandle,
  985. REGISTRY_FAVOR_UTF8_URL,
  986. DefaultBoolRegValue
  987. );
  988. if (FavorUtf8 != DefaultBoolRegValue)
  989. {
  990. //
  991. // A registry setting is present; use it.
  992. //
  993. FavorUtf8 = (BOOLEAN) (FavorUtf8 != 0);
  994. }
  995. else
  996. {
  997. FavorUtf8 = DEFAULT_FAVOR_UTF8_URL;
  998. }
  999. }
  1000. else
  1001. {
  1002. //
  1003. // We can't do DBCS or favor UTF-8 if we accept UTF-8 only.
  1004. //
  1005. EnableDbcs = FALSE;
  1006. FavorUtf8 = FALSE;
  1007. }
  1008. PercentUAllowed = UlReadLongParameter(
  1009. parametersHandle,
  1010. REGISTRY_PERCENT_U_ALLOWED,
  1011. DefaultBoolRegValue);
  1012. if (PercentUAllowed != DefaultBoolRegValue)
  1013. {
  1014. //
  1015. // A registry setting is present; use it.
  1016. //
  1017. PercentUAllowed = (BOOLEAN) (PercentUAllowed != 0);
  1018. }
  1019. else
  1020. {
  1021. PercentUAllowed = DEFAULT_PERCENT_U_ALLOWED;
  1022. }
  1023. AllowRestrictedChars = UlReadLongParameter(
  1024. parametersHandle,
  1025. REGISTRY_ALLOW_RESTRICTED_CHARS,
  1026. DefaultBoolRegValue);
  1027. if (AllowRestrictedChars != DefaultBoolRegValue)
  1028. {
  1029. //
  1030. // A registry setting is present; use it.
  1031. //
  1032. AllowRestrictedChars = (BOOLEAN) (AllowRestrictedChars != 0);
  1033. }
  1034. else
  1035. {
  1036. AllowRestrictedChars = DEFAULT_ALLOW_RESTRICTED_CHARS;
  1037. }
  1038. tmp = UlReadLongParameter(
  1039. parametersHandle,
  1040. REGISTRY_URL_SEGMENT_MAX_LENGTH,
  1041. DEFAULT_URL_SEGMENT_MAX_LENGTH
  1042. );
  1043. if (tmp == 0)
  1044. {
  1045. // 0 in the registry turns this feature off
  1046. UrlSegmentMaxLength = C14N_URL_SEGMENT_UNLIMITED_LENGTH;
  1047. }
  1048. else if (tmp < WCSLEN_LIT(L"/x") || tmp > UNICODE_STRING_MAX_WCHAR_LEN)
  1049. {
  1050. UrlSegmentMaxLength = DEFAULT_URL_SEGMENT_MAX_LENGTH;
  1051. }
  1052. else
  1053. {
  1054. UrlSegmentMaxLength = tmp;
  1055. }
  1056. tmp = UlReadLongParameter(
  1057. parametersHandle,
  1058. REGISTRY_URL_SEGMENT_MAX_COUNT,
  1059. DEFAULT_URL_SEGMENT_MAX_COUNT
  1060. );
  1061. if (tmp == 0)
  1062. {
  1063. // 0 in the registry turns this feature off
  1064. UrlSegmentMaxCount = C14N_URL_SEGMENT_UNLIMITED_COUNT;
  1065. }
  1066. else if (tmp < 2 || tmp > UNICODE_STRING_MAX_WCHAR_LEN / WCSLEN_LIT(L"/x"))
  1067. {
  1068. UrlSegmentMaxCount = DEFAULT_URL_SEGMENT_MAX_COUNT;
  1069. }
  1070. else
  1071. {
  1072. UrlSegmentMaxCount = tmp;
  1073. }
  1074. //
  1075. // Initialize the default Url Canonicalization settings
  1076. //
  1077. HttpInitializeDefaultUrlC14nConfigEncoding(
  1078. &g_UrlC14nConfig,
  1079. (BOOLEAN) EnableNonUtf8,
  1080. (BOOLEAN) FavorUtf8,
  1081. (BOOLEAN) EnableDbcs
  1082. );
  1083. g_UrlC14nConfig.PercentUAllowed = (BOOLEAN) PercentUAllowed;
  1084. g_UrlC14nConfig.AllowRestrictedChars = (BOOLEAN) AllowRestrictedChars;
  1085. g_UrlC14nConfig.CodePage = ACPCode;
  1086. g_UrlC14nConfig.UrlSegmentMaxLength = UrlSegmentMaxLength;
  1087. g_UrlC14nConfig.UrlSegmentMaxCount = UrlSegmentMaxCount;
  1088. return ACPCode;
  1089. } // UlpReadUrlC14nConfig
  1090. /***************************************************************************++
  1091. Routine Description:
  1092. Reads the error logging config from registry and initializes the
  1093. global config structure.
  1094. Arguments:
  1095. parametersHandle - Supplies the reg handle to the http param folder.
  1096. --***************************************************************************/
  1097. VOID
  1098. UlpReadErrorLogConfig(
  1099. HANDLE parametersHandle
  1100. )
  1101. {
  1102. LONG tmp;
  1103. NTSTATUS Status;
  1104. PKEY_VALUE_PARTIAL_INFORMATION pInfo;
  1105. PAGED_CODE();
  1106. //
  1107. // First see whether it's enabled or not.
  1108. //
  1109. tmp = UlReadLongParameter(
  1110. parametersHandle,
  1111. REGISTRY_ERROR_LOGGING_ENABLED,
  1112. DEFAULT_ENABLE_ERROR_LOGGING
  1113. );
  1114. if (tmp == 0)
  1115. {
  1116. g_UlErrLoggingConfig.Enabled = FALSE;
  1117. }
  1118. else if (tmp == 1)
  1119. {
  1120. g_UlErrLoggingConfig.Enabled = TRUE;
  1121. }
  1122. else
  1123. {
  1124. g_UlErrLoggingConfig.Enabled = DEFAULT_ENABLE_ERROR_LOGGING;
  1125. }
  1126. //
  1127. // Now try to read the whole config if it is enabled.
  1128. //
  1129. if (g_UlErrLoggingConfig.Enabled == TRUE)
  1130. {
  1131. //
  1132. // Rollover size.
  1133. //
  1134. tmp = UlReadLongParameter(
  1135. parametersHandle,
  1136. REGISTRY_ERROR_LOGGING_TRUNCATION_SIZE,
  1137. 0
  1138. );
  1139. if (tmp < 0)
  1140. {
  1141. //
  1142. // Interpret the neg values as infinite.
  1143. //
  1144. g_UlErrLoggingConfig.TruncateSize = HTTP_LIMIT_INFINITE;
  1145. }
  1146. else if (tmp < DEFAULT_MIN_ERROR_FILE_TRUNCATION_SIZE)
  1147. {
  1148. //
  1149. // If the it is invalid, set it to default.
  1150. //
  1151. g_UlErrLoggingConfig.TruncateSize = DEFAULT_ERROR_FILE_TRUNCATION_SIZE;
  1152. }
  1153. else
  1154. {
  1155. g_UlErrLoggingConfig.TruncateSize = (ULONG) tmp;
  1156. }
  1157. //
  1158. // Error logging directory.
  1159. //
  1160. g_UlErrLoggingConfig.Dir.Buffer = g_UlErrLoggingConfig._DirBuffer;
  1161. g_UlErrLoggingConfig.Dir.Length = 0;
  1162. g_UlErrLoggingConfig.Dir.MaximumLength =
  1163. (USHORT) sizeof(g_UlErrLoggingConfig._DirBuffer);
  1164. //
  1165. // Lets make sure the buffer is big enough to hold.
  1166. //
  1167. ASSERT(sizeof(g_UlErrLoggingConfig._DirBuffer)
  1168. >= (( MAX_PATH // From reg
  1169. + UL_ERROR_LOG_SUB_DIR_LENGTH // SubDir
  1170. + 1 // UnicodeNull
  1171. ) * sizeof(WCHAR))
  1172. );
  1173. pInfo = NULL;
  1174. Status = UlReadGenericParameter(
  1175. parametersHandle,
  1176. REGISTRY_ERROR_LOGGING_DIRECTORY,
  1177. &pInfo
  1178. );
  1179. if (NT_SUCCESS(Status))
  1180. {
  1181. ASSERT(pInfo);
  1182. if (pInfo->Type == REG_EXPAND_SZ || pInfo->Type == REG_SZ)
  1183. {
  1184. USHORT RegDirLength = (USHORT) wcslen((PWCHAR) pInfo->Data);
  1185. if (RegDirLength <= MAX_PATH)
  1186. {
  1187. //
  1188. // Copy the beginning portion from the registry.
  1189. //
  1190. Status = UlBuildErrorLoggingDirStr(
  1191. (PCWSTR) pInfo->Data,
  1192. &g_UlErrLoggingConfig.Dir
  1193. );
  1194. ASSERT(NT_SUCCESS(Status));
  1195. //
  1196. // Check the user's directory.
  1197. //
  1198. Status = UlCheckErrorLogConfig(&g_UlErrLoggingConfig);
  1199. if (NT_SUCCESS(Status))
  1200. {
  1201. //
  1202. // Good to go.
  1203. //
  1204. UL_FREE_POOL( pInfo, UL_REGISTRY_DATA_POOL_TAG );
  1205. return;
  1206. }
  1207. }
  1208. }
  1209. //
  1210. // Free up the returned value.
  1211. //
  1212. UL_FREE_POOL( pInfo, UL_REGISTRY_DATA_POOL_TAG );
  1213. }
  1214. //
  1215. // Fall back to the default directory.
  1216. //
  1217. ASSERT(wcslen(DEFAULT_ERROR_LOGGING_DIR) <= MAX_PATH);
  1218. Status = UlBuildErrorLoggingDirStr(
  1219. DEFAULT_ERROR_LOGGING_DIR,
  1220. &g_UlErrLoggingConfig.Dir
  1221. );
  1222. ASSERT(NT_SUCCESS(Status));
  1223. Status = UlCheckErrorLogConfig(&g_UlErrLoggingConfig);
  1224. if (!NT_SUCCESS(Status))
  1225. {
  1226. //
  1227. // This call should not fail.
  1228. //
  1229. ASSERT(!"Invalid default error logging config !");
  1230. g_UlErrLoggingConfig.Enabled = FALSE;
  1231. }
  1232. }
  1233. return;
  1234. }
  1235. /***************************************************************************++
  1236. Routine Description:
  1237. Reads the UL section of the registry. Any values contained in the
  1238. registry override defaults.
  1239. BUGBUG: the limits on many of these settings seem particularly arbitrary,
  1240. not to mention undocumented.
  1241. Arguments:
  1242. pConfig - Supplies a pointer to a UL_CONFIG structure that receives
  1243. init-time configuration parameters. These are basically
  1244. parameters that do not need to persist in the driver once
  1245. initialization is complete.
  1246. --***************************************************************************/
  1247. VOID
  1248. UlpReadRegistry(
  1249. IN PUL_CONFIG pConfig
  1250. )
  1251. {
  1252. HANDLE parametersHandle;
  1253. NTSTATUS status;
  1254. LONG tmp;
  1255. LONGLONG tmp64;
  1256. UNICODE_STRING registryPath;
  1257. UNICODE_STRING registryPathComputerName;
  1258. PKEY_VALUE_PARTIAL_INFORMATION pInfo;
  1259. PKEY_VALUE_PARTIAL_INFORMATION pValue;
  1260. HANDLE computerNameHandle;
  1261. ULONG ACPCode;
  1262. //
  1263. // Sanity check.
  1264. //
  1265. PAGED_CODE();
  1266. //
  1267. // Establish defaults.
  1268. //
  1269. pConfig->ThreadsPerCpu = DEFAULT_THREADS_PER_CPU;
  1270. pConfig->IrpContextLookasideDepth = DEFAULT_IRP_CONTEXT_LOOKASIDE_DEPTH;
  1271. pConfig->ReceiveBufferLookasideDepth = DEFAULT_RCV_BUFFER_LOOKASIDE_DEPTH;
  1272. pConfig->ResourceLookasideDepth = DEFAULT_RESOURCE_LOOKASIDE_DEPTH;
  1273. pConfig->RequestBufferLookasideDepth = DEFAULT_REQ_BUFFER_LOOKASIDE_DEPTH;
  1274. pConfig->InternalRequestLookasideDepth = DEFAULT_INT_REQUEST_LOOKASIDE_DEPTH;
  1275. pConfig->ResponseBufferLookasideDepth = DEFAULT_RESP_BUFFER_LOOKASIDE_DEPTH;
  1276. pConfig->SendTrackerLookasideDepth = DEFAULT_SEND_TRACKER_LOOKASIDE_DEPTH;
  1277. pConfig->LogFileBufferLookasideDepth = DEFAULT_LOG_BUFFER_LOOKASIDE_DEPTH;
  1278. pConfig->LogDataBufferLookasideDepth = DEFAULT_LOG_DATA_BUFFER_LOOKASIDE_DEPTH;
  1279. pConfig->ErrorLogBufferLookasideDepth = DEFAULT_ERROR_LOG_BUFFER_LOOKASIDE_DEPTH;
  1280. pConfig->FilterWriteTrackerLookasideDepth = DEFAULT_LOOKASIDE_DEPTH;
  1281. pConfig->UriConfig.EnableCache = DEFAULT_CACHE_ENABLED;
  1282. pConfig->UriConfig.MaxCacheUriCount = DEFAULT_MAX_CACHE_URI_COUNT;
  1283. pConfig->UriConfig.MaxCacheMegabyteCount = DEFAULT_MAX_CACHE_MEGABYTE_COUNT;
  1284. pConfig->UriConfig.MaxUriBytes = DEFAULT_MAX_URI_BYTES;
  1285. pConfig->UriConfig.ScavengerPeriod = DEFAULT_CACHE_SCAVENGER_PERIOD;
  1286. pConfig->EnableHttpClient = DEFAULT_HTTP_CLIENT_ENABLED;
  1287. //
  1288. // Open the registry.
  1289. //
  1290. status = UlInitUnicodeStringEx( &registryPath, REGISTRY_UL_INFORMATION );
  1291. if(!NT_SUCCESS(status))
  1292. {
  1293. return;
  1294. }
  1295. status = UlOpenRegistry( &registryPath, &parametersHandle, NULL );
  1296. if(!NT_SUCCESS(status))
  1297. {
  1298. return;
  1299. }
  1300. #if DBG
  1301. //
  1302. // Read the debug flags.
  1303. //
  1304. g_UlDebug = (ULONGLONG)
  1305. UlReadLongLongParameter(
  1306. parametersHandle,
  1307. REGISTRY_DEBUG_FLAGS,
  1308. (LONGLONG)g_UlDebug
  1309. );
  1310. //
  1311. // Force a breakpoint if so requested.
  1312. //
  1313. if (UlReadLongParameter(
  1314. parametersHandle,
  1315. REGISTRY_BREAK_ON_STARTUP,
  1316. DEFAULT_BREAK_ON_STARTUP) != 0 )
  1317. {
  1318. DbgBreakPoint();
  1319. }
  1320. //
  1321. // Read the break-on-error flags.
  1322. //
  1323. g_UlBreakOnError = (BOOLEAN) UlReadLongParameter(
  1324. parametersHandle,
  1325. REGISTRY_BREAK_ON_ERROR,
  1326. g_UlBreakOnError
  1327. ) != 0;
  1328. g_UlVerboseErrors = (BOOLEAN) UlReadLongParameter(
  1329. parametersHandle,
  1330. REGISTRY_VERBOSE_ERRORS,
  1331. g_UlVerboseErrors
  1332. ) != 0;
  1333. //
  1334. // Break-on-error implies verbose-errors.
  1335. //
  1336. if (g_UlBreakOnError)
  1337. {
  1338. g_UlVerboseErrors = TRUE;
  1339. }
  1340. #endif // DBG
  1341. //
  1342. // Read the thread pool parameters.
  1343. //
  1344. tmp = UlReadLongParameter(
  1345. parametersHandle,
  1346. REGISTRY_THREADS_PER_CPU,
  1347. (LONG)pConfig->ThreadsPerCpu
  1348. );
  1349. if (tmp > MAX_THREADS_PER_CPU || tmp <= 0)
  1350. {
  1351. tmp = DEFAULT_THREADS_PER_CPU;
  1352. }
  1353. pConfig->ThreadsPerCpu = (USHORT)tmp;
  1354. //
  1355. // Other configuration parameters. (Lookaside depths are USHORTs)
  1356. //
  1357. tmp = UlReadLongParameter(
  1358. parametersHandle,
  1359. REGISTRY_IDLE_CONNECTIONS_LOW_MARK,
  1360. (LONG)g_UlIdleConnectionsLowMark
  1361. );
  1362. if (tmp > UL_MAX_SLIST_DEPTH || tmp < 1)
  1363. {
  1364. //
  1365. // If the low mark is bad, don't even try to read the high mark.
  1366. //
  1367. g_UlIdleConnectionsLowMark = DEFAULT_IDLE_CONNECTIONS_LOW_MARK;
  1368. g_UlIdleConnectionsHighMark = DEFAULT_IDLE_CONNECTIONS_HIGH_MARK;
  1369. }
  1370. else
  1371. {
  1372. g_UlIdleConnectionsLowMark = (USHORT)tmp;
  1373. //
  1374. // Now read the high mark, again if it is bad, discard the low mark
  1375. // as well.
  1376. //
  1377. tmp = UlReadLongParameter(
  1378. parametersHandle,
  1379. REGISTRY_IDLE_CONNECTIONS_HIGH_MARK,
  1380. (LONG)g_UlIdleConnectionsHighMark
  1381. );
  1382. if (tmp < g_UlIdleConnectionsLowMark ||
  1383. tmp > UL_MAX_SLIST_DEPTH
  1384. )
  1385. {
  1386. g_UlIdleConnectionsLowMark = DEFAULT_IDLE_CONNECTIONS_LOW_MARK;
  1387. g_UlIdleConnectionsHighMark = DEFAULT_IDLE_CONNECTIONS_HIGH_MARK;
  1388. }
  1389. else
  1390. {
  1391. g_UlIdleConnectionsHighMark = (USHORT)tmp;
  1392. }
  1393. }
  1394. tmp = UlReadLongParameter(
  1395. parametersHandle,
  1396. REGISTRY_IDLE_LIST_TRIMMER_PERIOD,
  1397. (LONG)g_UlIdleListTrimmerPeriod
  1398. );
  1399. if (tmp > (24 * 60 * 60) || tmp < 5)
  1400. {
  1401. tmp = DEFAULT_IDLE_LIST_TRIMMER_PERIOD;
  1402. }
  1403. g_UlIdleListTrimmerPeriod = (ULONG)tmp;
  1404. tmp = UlReadLongParameter(
  1405. parametersHandle,
  1406. REGISTRY_MAX_ENDPOINTS,
  1407. (LONG)g_UlMaxEndpoints
  1408. );
  1409. if (tmp > 1024 || tmp < 0)
  1410. {
  1411. tmp = DEFAULT_MAX_ENDPOINTS;
  1412. }
  1413. g_UlMaxEndpoints = (USHORT)tmp;
  1414. tmp = UlReadLongParameter(
  1415. parametersHandle,
  1416. REGISTRY_IRP_CONTEXT_LOOKASIDE_DEPTH,
  1417. (LONG)pConfig->IrpContextLookasideDepth
  1418. );
  1419. if (tmp > UL_MAX_SLIST_DEPTH || tmp < 0)
  1420. {
  1421. tmp = DEFAULT_IRP_CONTEXT_LOOKASIDE_DEPTH;
  1422. }
  1423. pConfig->IrpContextLookasideDepth = (USHORT)tmp;
  1424. tmp = UlReadLongParameter(
  1425. parametersHandle,
  1426. REGISTRY_RCV_BUFFER_LOOKASIDE_DEPTH,
  1427. (LONG)pConfig->ReceiveBufferLookasideDepth
  1428. );
  1429. if (tmp > UL_MAX_SLIST_DEPTH || tmp < 0)
  1430. {
  1431. tmp = DEFAULT_RCV_BUFFER_LOOKASIDE_DEPTH;
  1432. }
  1433. pConfig->ReceiveBufferLookasideDepth = (USHORT)tmp;
  1434. tmp = UlReadLongParameter(
  1435. parametersHandle,
  1436. REGISTRY_REQ_BUFFER_LOOKASIDE_DEPTH,
  1437. (LONG)pConfig->RequestBufferLookasideDepth
  1438. );
  1439. if (tmp > UL_MAX_SLIST_DEPTH || tmp < 0)
  1440. {
  1441. tmp = DEFAULT_REQ_BUFFER_LOOKASIDE_DEPTH;
  1442. }
  1443. pConfig->RequestBufferLookasideDepth = (USHORT)tmp;
  1444. tmp = UlReadLongParameter(
  1445. parametersHandle,
  1446. REGISTRY_INT_REQUEST_LOOKASIDE_DEPTH,
  1447. (LONG)pConfig->InternalRequestLookasideDepth
  1448. );
  1449. if (tmp > UL_MAX_SLIST_DEPTH || tmp < 0)
  1450. {
  1451. tmp = DEFAULT_INT_REQUEST_LOOKASIDE_DEPTH;
  1452. }
  1453. pConfig->InternalRequestLookasideDepth = (USHORT)tmp;
  1454. tmp = UlReadLongParameter(
  1455. parametersHandle,
  1456. REGISTRY_RESP_BUFFER_LOOKASIDE_DEPTH,
  1457. (LONG)pConfig->ResponseBufferLookasideDepth
  1458. );
  1459. if (tmp > UL_MAX_SLIST_DEPTH || tmp < 0)
  1460. {
  1461. tmp = DEFAULT_RESP_BUFFER_LOOKASIDE_DEPTH;
  1462. }
  1463. pConfig->ResponseBufferLookasideDepth = (USHORT)tmp;
  1464. tmp = UlReadLongParameter(
  1465. parametersHandle,
  1466. REGISTRY_SEND_TRACKER_LOOKASIDE_DEPTH,
  1467. (LONG)pConfig->SendTrackerLookasideDepth
  1468. );
  1469. if (tmp > UL_MAX_SLIST_DEPTH || tmp < 0)
  1470. {
  1471. tmp = DEFAULT_SEND_TRACKER_LOOKASIDE_DEPTH;
  1472. }
  1473. pConfig->SendTrackerLookasideDepth = (USHORT)tmp;
  1474. tmp = UlReadLongParameter(
  1475. parametersHandle,
  1476. REGISTRY_LOG_BUFFER_LOOKASIDE_DEPTH,
  1477. (LONG)pConfig->LogFileBufferLookasideDepth
  1478. );
  1479. if (tmp > UL_MAX_SLIST_DEPTH || tmp < 0)
  1480. {
  1481. tmp = DEFAULT_LOG_BUFFER_LOOKASIDE_DEPTH;
  1482. }
  1483. pConfig->LogFileBufferLookasideDepth = (USHORT)tmp;
  1484. tmp = UlReadLongParameter(
  1485. parametersHandle,
  1486. REGISTRY_LOG_DATA_BUFFER_LOOKASIDE_DEPTH,
  1487. (LONG)pConfig->LogDataBufferLookasideDepth
  1488. );
  1489. if (tmp > UL_MAX_SLIST_DEPTH || tmp < 0)
  1490. {
  1491. tmp = DEFAULT_LOG_DATA_BUFFER_LOOKASIDE_DEPTH;
  1492. }
  1493. pConfig->LogDataBufferLookasideDepth = (USHORT)tmp;
  1494. g_UlOptForIntrMod = (BOOLEAN) UlReadLongParameter(
  1495. parametersHandle,
  1496. REGISTRY_OPT_FOR_INTR_MOD,
  1497. (LONG)g_UlOptForIntrMod
  1498. ) != 0;
  1499. g_UlEnableNagling = (BOOLEAN) UlReadLongParameter(
  1500. parametersHandle,
  1501. REGISTRY_ENABLE_NAGLING,
  1502. (LONG)g_UlEnableNagling
  1503. ) != 0;
  1504. g_UlEnableThreadAffinity = (BOOLEAN) UlReadLongParameter(
  1505. parametersHandle,
  1506. REGISTRY_ENABLE_THREAD_AFFINITY,
  1507. (LONG)g_UlEnableThreadAffinity
  1508. ) != 0;
  1509. tmp64 = UlReadLongLongParameter(
  1510. parametersHandle,
  1511. REGISTRY_THREAD_AFFINITY_MASK,
  1512. g_UlThreadAffinityMask
  1513. );
  1514. if ((ULONGLONG)tmp64 > DEFAULT_THREAD_AFFINITY_MASK
  1515. || (ULONGLONG)tmp64 == 0)
  1516. {
  1517. tmp64 = DEFAULT_THREAD_AFFINITY_MASK;
  1518. }
  1519. g_UlThreadAffinityMask = (ULONGLONG)tmp64;
  1520. tmp = UlReadLongParameter(
  1521. parametersHandle,
  1522. REGISTRY_MAX_WORK_QUEUE_DEPTH,
  1523. (LONG)g_UlMaxWorkQueueDepth
  1524. );
  1525. if (tmp > UL_MAX_SLIST_DEPTH || tmp < 0)
  1526. {
  1527. tmp = DEFAULT_MAX_WORK_QUEUE_DEPTH;
  1528. }
  1529. g_UlMaxWorkQueueDepth = (USHORT)tmp;
  1530. tmp = UlReadLongParameter(
  1531. parametersHandle,
  1532. REGISTRY_MIN_WORK_DEQUEUE_DEPTH,
  1533. (LONG)g_UlMinWorkDequeueDepth
  1534. );
  1535. if (tmp > UL_MAX_SLIST_DEPTH || tmp < 0)
  1536. {
  1537. tmp = DEFAULT_MIN_WORK_DEQUEUE_DEPTH;
  1538. }
  1539. g_UlMinWorkDequeueDepth = (USHORT)tmp;
  1540. tmp = UlReadLongParameter(
  1541. parametersHandle,
  1542. REGISTRY_MAX_COPY_THRESHOLD,
  1543. (LONG)g_UlMaxCopyThreshold
  1544. );
  1545. if (tmp > (128 * 1024) || tmp < 0)
  1546. {
  1547. tmp = DEFAULT_MAX_COPY_THRESHOLD;
  1548. }
  1549. g_UlMaxCopyThreshold = tmp;
  1550. tmp = UlReadLongParameter(
  1551. parametersHandle,
  1552. REGISTRY_MAX_BUFFERED_SENDS,
  1553. (LONG)g_UlMaxBufferedSends
  1554. );
  1555. if (tmp > 64 || tmp < 0)
  1556. {
  1557. tmp = DEFAULT_MAX_BUFFERED_SENDS;
  1558. }
  1559. g_UlMaxBufferedSends = tmp;
  1560. tmp = UlReadLongParameter(
  1561. parametersHandle,
  1562. REGISTRY_MAX_BYTES_PER_SEND,
  1563. (LONG)g_UlMaxBytesPerSend
  1564. );
  1565. if (tmp > 0xFFFFF || tmp < 0)
  1566. {
  1567. tmp = DEFAULT_MAX_BYTES_PER_SEND;
  1568. }
  1569. g_UlMaxBytesPerSend = tmp;
  1570. tmp = UlReadLongParameter(
  1571. parametersHandle,
  1572. REGISTRY_MAX_BYTES_PER_READ,
  1573. (LONG)g_UlMaxBytesPerRead
  1574. );
  1575. if (tmp > 0xFFFFF || tmp < 0)
  1576. {
  1577. tmp = DEFAULT_MAX_BYTES_PER_READ;
  1578. }
  1579. g_UlMaxBytesPerRead = tmp;
  1580. tmp = UlReadLongParameter(
  1581. parametersHandle,
  1582. REGISTRY_MAX_PIPELINED_REQUESTS,
  1583. (LONG)g_UlMaxPipelinedRequests
  1584. );
  1585. if (tmp > 1024 || tmp < 0)
  1586. {
  1587. tmp = DEFAULT_MAX_PIPELINED_REQUESTS;
  1588. }
  1589. g_UlMaxPipelinedRequests = tmp;
  1590. g_UlEnableCopySend = (BOOLEAN) UlReadLongParameter(
  1591. parametersHandle,
  1592. REGISTRY_ENABLE_COPY_SEND,
  1593. DEFAULT_ENABLE_COPY_SEND
  1594. ) != 0;
  1595. tmp = UlReadLongParameter(
  1596. parametersHandle,
  1597. REGISTRY_CONNECTION_SEND_LIMIT,
  1598. (LONG)g_UlConnectionSendLimit
  1599. );
  1600. if (tmp > (1024 * 1024) || tmp < 0)
  1601. {
  1602. tmp = DEFAULT_CONNECTION_SEND_LIMIT;
  1603. }
  1604. g_UlConnectionSendLimit = tmp;
  1605. tmp64 = UlReadLongLongParameter(
  1606. parametersHandle,
  1607. REGISTRY_GLOBAL_SEND_LIMIT,
  1608. g_UlGlobalSendLimit
  1609. );
  1610. if (tmp64 > (LONGLONG)g_UlTotalNonPagedPoolBytes / 2 ||
  1611. tmp64 < (LONGLONG)g_UlConnectionSendLimit)
  1612. {
  1613. tmp64 = DEFAULT_GLOBAL_SEND_LIMIT;
  1614. }
  1615. g_UlGlobalSendLimit = tmp64;
  1616. tmp = UlReadLongParameter(
  1617. parametersHandle,
  1618. REGISTRY_OPAQUE_ID_TABLE_SIZE,
  1619. (LONG)g_UlOpaqueIdTableSize
  1620. );
  1621. if (tmp > 0xFFFF || tmp <= 0)
  1622. {
  1623. tmp = DEFAULT_OPAQUE_ID_TABLE_SIZE;
  1624. }
  1625. g_UlOpaqueIdTableSize = tmp;
  1626. //
  1627. // MaxInternalUrlLength is a hint for allocating the inline buffer
  1628. // of WCHARs to hold the URL at the end of a UL_INTERNAL_REQUEST.
  1629. // Note: This is not the maximum possible length of a URL received off
  1630. // the wire; that's MaxFieldLength.
  1631. //
  1632. tmp = UlReadLongParameter(
  1633. parametersHandle,
  1634. REGISTRY_MAX_INTERNAL_URL_LENGTH,
  1635. g_UlMaxInternalUrlLength
  1636. );
  1637. //
  1638. // Round up to an even number, as it measures the size in bytes
  1639. // of a WCHAR array
  1640. //
  1641. tmp = (tmp + 1) & ~1;
  1642. #define MIN_MAX_INTERNAL_URL_LENGTH (64 * sizeof(WCHAR))
  1643. #define MAX_MAX_INTERNAL_URL_LENGTH (MAX_PATH * sizeof(WCHAR))
  1644. tmp = min(tmp, MAX_MAX_INTERNAL_URL_LENGTH);
  1645. tmp = max(tmp, MIN_MAX_INTERNAL_URL_LENGTH);
  1646. ASSERT(MIN_MAX_INTERNAL_URL_LENGTH <= tmp
  1647. && tmp <= MAX_MAX_INTERNAL_URL_LENGTH);
  1648. g_UlMaxInternalUrlLength = tmp;
  1649. //
  1650. // MAX allowed field length in HTTP requests, in bytes
  1651. //
  1652. tmp = UlReadLongParameter(
  1653. parametersHandle,
  1654. REGISTRY_MAX_FIELD_LENGTH,
  1655. (LONG)g_UlMaxFieldLength
  1656. );
  1657. // Set a 64KB-2 hard upper limit for each individual header.
  1658. // Note: the length fields in HTTP_KNOWN_HEADER and HTTP_UNKNOWN_HEADER
  1659. // are USHORTs. We have to allow a terminating '\0' in the data
  1660. // we pass up, hence -2.
  1661. tmp = min(tmp, ANSI_STRING_MAX_CHAR_LEN);
  1662. tmp = max(tmp, 64);
  1663. ASSERT(64 <= tmp && tmp <= ANSI_STRING_MAX_CHAR_LEN);
  1664. g_UlMaxFieldLength = tmp;
  1665. //
  1666. // MaxRequestBytes is the total size of all the headers, including
  1667. // the initial verb/URL/version line.
  1668. //
  1669. tmp = UlReadLongParameter(
  1670. parametersHandle,
  1671. REGISTRY_MAX_REQUEST_BYTES,
  1672. g_UlMaxRequestBytes
  1673. );
  1674. // Set a 16MB hard upper limit for all the headers. Don't want to
  1675. // set it bigger than this to minimize Denial of Service attacks.
  1676. // If you really want to send a lot of data, send it in the entity body.
  1677. tmp = min(tmp, (16 * 1024 * 1024));
  1678. tmp = max(tmp, 256);
  1679. ASSERT(256 <= tmp && tmp <= (16 * 1024 * 1024));
  1680. g_UlMaxRequestBytes = tmp;
  1681. // An individual field can't be bigger than the aggregated fields
  1682. if (g_UlMaxRequestBytes < g_UlMaxFieldLength)
  1683. {
  1684. g_UlMaxFieldLength = g_UlMaxRequestBytes;
  1685. }
  1686. tmp = UlReadLongParameter(
  1687. parametersHandle,
  1688. REGISTRY_DISABLE_LOG_BUFFERING,
  1689. (LONG)g_UlDisableLogBuffering
  1690. );
  1691. g_UlDisableLogBuffering = (BOOLEAN) (tmp != 0);
  1692. tmp = UlReadLongParameter(
  1693. parametersHandle,
  1694. REGISTRY_LOG_BUFFER_SIZE,
  1695. (LONG)g_UlLogBufferSize
  1696. );
  1697. if (tmp > MAXIMUM_ALLOWED_LOG_BUFFER_SIZE
  1698. || tmp < MINIMUM_ALLOWED_LOG_BUFFER_SIZE )
  1699. {
  1700. // Basically this value will be discarted by the logging code
  1701. // instead systems granularity size (64K) will be used.
  1702. tmp = DEFAULT_LOG_BUFFER_SIZE;
  1703. }
  1704. tmp -= tmp % 4096; // Align down to 4k
  1705. g_UlLogBufferSize = (ULONG) tmp;
  1706. //
  1707. // read the resource lookaside config
  1708. //
  1709. tmp = UlReadLongParameter(
  1710. parametersHandle,
  1711. REGISTRY_RESOURCE_LOOKASIDE_DEPTH,
  1712. (LONG)pConfig->ResourceLookasideDepth
  1713. );
  1714. if (tmp > UL_MAX_SLIST_DEPTH || tmp < 0)
  1715. {
  1716. tmp = DEFAULT_RESOURCE_LOOKASIDE_DEPTH;
  1717. }
  1718. pConfig->ResourceLookasideDepth = (USHORT)tmp;
  1719. tmp = UlReadLongParameter(
  1720. parametersHandle,
  1721. REGISTRY_MAX_REQUESTS_QUEUED,
  1722. g_UlMaxRequestsQueued
  1723. );
  1724. if (tmp > UL_MAX_REQUESTS_QUEUED || tmp < UL_MIN_REQUESTS_QUEUED)
  1725. {
  1726. tmp = DEFAULT_MAX_REQUESTS_QUEUED;
  1727. }
  1728. g_UlMaxRequestsQueued = tmp;
  1729. tmp = UlReadLongParameter(
  1730. parametersHandle,
  1731. REGISTRY_MAX_ZOMBIE_HTTP_CONN_COUNT,
  1732. g_UlMaxZombieHttpConnectionCount
  1733. );
  1734. if (tmp > 0xFFFF || tmp < 0)
  1735. {
  1736. tmp = DEFAULT_MAX_ZOMBIE_HTTP_CONN_COUNT;
  1737. }
  1738. g_UlMaxZombieHttpConnectionCount = tmp;
  1739. //
  1740. // Max UL_CONNECTION override
  1741. //
  1742. tmp = UlReadLongParameter(
  1743. parametersHandle,
  1744. REGISTRY_MAX_CONNECTIONS,
  1745. g_MaxConnections
  1746. );
  1747. // Restrict from 1K min to 2M max
  1748. if (tmp > 0x1F0000 || tmp < 0x400 )
  1749. {
  1750. tmp = HTTP_LIMIT_INFINITE;
  1751. }
  1752. g_MaxConnections = tmp;
  1753. tmp = UlReadLongParameter(
  1754. parametersHandle,
  1755. REGISTRY_RCV_BUFFER_SIZE,
  1756. g_UlReceiveBufferSize
  1757. );
  1758. if (tmp > 0xFFFF || tmp < 128)
  1759. {
  1760. tmp = DEFAULT_RCV_BUFFER_SIZE;
  1761. }
  1762. g_UlReceiveBufferSize = ALIGN_UP( tmp, PVOID );
  1763. tmp = UlReadLongParameter(
  1764. parametersHandle,
  1765. REGISTRY_RESP_BUFFER_SIZE,
  1766. g_UlResponseBufferSize
  1767. );
  1768. if (tmp > 0xFFFF || tmp < 128)
  1769. {
  1770. tmp = DEFAULT_RESP_BUFFER_SIZE;
  1771. }
  1772. g_UlResponseBufferSize = tmp;
  1773. ACPCode = UlpReadUrlC14nConfig(parametersHandle);
  1774. //
  1775. // Should we disable the Server: response header?
  1776. //
  1777. tmp = UlReadLongParameter(
  1778. parametersHandle,
  1779. REGISTRY_DISABLE_SERVER_HEADER,
  1780. (LONG)g_UlDisableServerHeader
  1781. );
  1782. if (tmp >= 0 && tmp <= 2)
  1783. {
  1784. g_UlDisableServerHeader = (ULONG) tmp;
  1785. }
  1786. //
  1787. // Read error logging config.
  1788. //
  1789. UlpReadErrorLogConfig(parametersHandle);
  1790. //
  1791. // Read the ComputerName from the Registry.
  1792. //
  1793. wcsncpy(g_UlComputerName, L"<server>", MAX_COMPUTER_NAME_LEN);
  1794. status = UlInitUnicodeStringEx( &registryPathComputerName,
  1795. REGISTRY_COMPUTER_NAME_PATH );
  1796. if (NT_SUCCESS(status))
  1797. {
  1798. status = UlOpenRegistry(
  1799. &registryPathComputerName,
  1800. &computerNameHandle,
  1801. REGISTRY_COMPUTER_NAME
  1802. );
  1803. if (NT_SUCCESS(status))
  1804. {
  1805. pInfo = NULL;
  1806. status = UlReadGenericParameter(
  1807. computerNameHandle,
  1808. REGISTRY_COMPUTER_NAME,
  1809. &pInfo
  1810. );
  1811. if (NT_SUCCESS(status))
  1812. {
  1813. ASSERT(pInfo);
  1814. if (pInfo->Type == REG_SZ)
  1815. {
  1816. wcsncpy(g_UlComputerName,
  1817. (PWCHAR)pInfo->Data,
  1818. MAX_COMPUTER_NAME_LEN
  1819. );
  1820. //
  1821. // Make sure we're NULL terminated. This will truncate
  1822. // the name from the registry.
  1823. //
  1824. g_UlComputerName[MAX_COMPUTER_NAME_LEN] = L'\0';
  1825. }
  1826. //
  1827. // Free up the returned value.
  1828. //
  1829. UL_FREE_POOL( pInfo, UL_REGISTRY_DATA_POOL_TAG );
  1830. }
  1831. ZwClose( computerNameHandle );
  1832. }
  1833. }
  1834. //
  1835. // Read URI Cache parameters
  1836. //
  1837. pConfig->UriConfig.EnableCache = (BOOLEAN) UlReadLongParameter(
  1838. parametersHandle,
  1839. REGISTRY_CACHE_ENABLED,
  1840. DEFAULT_CACHE_ENABLED
  1841. ) != 0;
  1842. pConfig->UriConfig.MaxCacheUriCount = UlReadLongParameter(
  1843. parametersHandle,
  1844. REGISTRY_MAX_CACHE_URI_COUNT,
  1845. DEFAULT_MAX_CACHE_URI_COUNT
  1846. );
  1847. pConfig->UriConfig.MaxCacheMegabyteCount = UlReadLongParameter(
  1848. parametersHandle,
  1849. REGISTRY_MAX_CACHE_MEGABYTE_COUNT,
  1850. DEFAULT_MAX_CACHE_MEGABYTE_COUNT
  1851. );
  1852. tmp = UlReadLongParameter(
  1853. parametersHandle,
  1854. REGISTRY_MAX_URI_BYTES,
  1855. DEFAULT_MAX_URI_BYTES
  1856. );
  1857. if (tmp < (4 * 1024) || tmp > (16 * 1024 * 1024))
  1858. {
  1859. tmp = DEFAULT_MAX_URI_BYTES;
  1860. }
  1861. pConfig->UriConfig.MaxUriBytes = tmp;
  1862. pConfig->UriConfig.ScavengerPeriod = UlReadLongParameter(
  1863. parametersHandle,
  1864. REGISTRY_CACHE_SCAVENGER_PERIOD,
  1865. DEFAULT_CACHE_SCAVENGER_PERIOD
  1866. );
  1867. pConfig->UriConfig.HashTableBits = UlReadLongParameter(
  1868. parametersHandle,
  1869. REGISTRY_HASH_TABLE_BITS,
  1870. DEFAULT_HASH_TABLE_BITS
  1871. );
  1872. #if 0
  1873. pConfig->EnableHttpClient = (BOOLEAN) UlReadLongParameter(
  1874. parametersHandle,
  1875. REGISTRY_HTTP_CLIENT_ENABLED,
  1876. DEFAULT_HTTP_CLIENT_ENABLED
  1877. ) != 0;
  1878. #endif
  1879. g_HttpClientEnabled = pConfig->EnableHttpClient;
  1880. //
  1881. // Read list of IP addresses for ListenOnlyList
  1882. //
  1883. pValue = NULL;
  1884. status = UlReadGenericParameter(
  1885. parametersHandle,
  1886. REGISTRY_LISTEN_ONLY_LIST,
  1887. &pValue
  1888. );
  1889. if (NT_SUCCESS(status) && REG_MULTI_SZ == pValue->Type)
  1890. {
  1891. // If UlRegMultiSzToUlAddrArray fails then we simply use
  1892. // the default.
  1893. status = UlRegMultiSzToUlAddrArray(
  1894. (PWSTR)pValue->Data,
  1895. &g_pTdiListenAddresses,
  1896. &g_TdiListenAddrCount
  1897. );
  1898. if ( STATUS_INVALID_PARAMETER == status )
  1899. {
  1900. //
  1901. // Write event log message that ListenOnlyList was found, but
  1902. // no entries could be converted.
  1903. //
  1904. UlWriteEventLogEntry(
  1905. EVENT_HTTP_LISTEN_ONLY_ALL_CONVERT_FAILED,
  1906. 0,
  1907. 0,
  1908. NULL,
  1909. 0,
  1910. NULL
  1911. );
  1912. }
  1913. }
  1914. if ( pValue )
  1915. {
  1916. UL_FREE_POOL( pValue, UL_REGISTRY_DATA_POOL_TAG );
  1917. pValue = NULL;
  1918. }
  1919. //
  1920. // Make sure we can always buffer enough bytes for an entire request
  1921. // header.
  1922. //
  1923. g_UlMaxBufferedBytes = MAX(g_UlMaxBufferedBytes, g_UlMaxRequestBytes);
  1924. //
  1925. // Scavenger Config - MB to reclaim each time
  1926. //
  1927. g_UlScavengerTrimMB = UlReadLongParameter(
  1928. parametersHandle,
  1929. REGISTRY_SCAVENGER_TRIM_MB,
  1930. DEFAULT_SCAVENGER_TRIM_MB
  1931. );
  1932. //
  1933. // Dump configuration on checked builds.
  1934. //
  1935. #if DBG
  1936. DbgPrint( "Http.sys Configuration:\n" );
  1937. // These settings are only present on checked builds
  1938. DbgPrint( " g_UlDebug = 0x%016I64x\n", g_UlDebug );
  1939. DbgPrint( " g_UlBreakOnError = %lu\n", g_UlBreakOnError );
  1940. DbgPrint( " g_UlVerboseErrors = %lu\n", g_UlVerboseErrors );
  1941. // These settings are present on all builds
  1942. DbgPrint( " g_UlComputerName = %ls\n", g_UlComputerName );
  1943. DbgPrint( " g_UlIdleConnectionsHighMark = %lu\n", g_UlIdleConnectionsHighMark );
  1944. DbgPrint( " g_UlIdleConnectionsLowMark = %lu\n", g_UlIdleConnectionsLowMark );
  1945. DbgPrint( " g_UlIdleListTrimmerPeriod = %lu\n", g_UlIdleListTrimmerPeriod );
  1946. DbgPrint( " g_UlMaxEndpoints = %lu\n", g_UlMaxEndpoints );
  1947. DbgPrint( " g_UlOptForIntrMod = %lu\n", g_UlOptForIntrMod );
  1948. DbgPrint( " g_UlEnableNagling = %lu\n", g_UlEnableNagling );
  1949. DbgPrint( " g_UlEnableThreadAffinity = %lu\n", g_UlEnableThreadAffinity );
  1950. DbgPrint( " g_UlThreadAffinityMask = 0x%I64x\n", g_UlThreadAffinityMask );
  1951. DbgPrint( " g_UlMaxCopyThreshold = %lu\n", g_UlMaxCopyThreshold );
  1952. DbgPrint( " g_UlMaxBufferedSends = %lu\n", g_UlMaxBufferedSends );
  1953. DbgPrint( " g_UlMaxBytesPerSend = %lu\n", g_UlMaxBytesPerSend );
  1954. DbgPrint( " g_UlMaxBytesPerRead = %lu\n", g_UlMaxBytesPerRead );
  1955. DbgPrint( " g_UlMaxPipelinedRequests = %lu\n", g_UlMaxPipelinedRequests );
  1956. DbgPrint( " g_UlEnableCopySend = %lu\n", g_UlEnableCopySend );
  1957. DbgPrint( " g_UlConnectionSendLimit = %lu\n", g_UlConnectionSendLimit );
  1958. DbgPrint( " g_UlGlobalSendLimit = %I64u\n", g_UlGlobalSendLimit );
  1959. DbgPrint( " g_UlOpaqueIdTableSize = %lu\n", g_UlOpaqueIdTableSize );
  1960. DbgPrint( " g_UlMaxRequestsQueued = %lu\n", g_UlMaxRequestsQueued );
  1961. DbgPrint( " g_UlMaxRequestBytes = %lu\n", g_UlMaxRequestBytes );
  1962. DbgPrint( " g_UlReceiveBufferSize = %lu\n", g_UlReceiveBufferSize );
  1963. DbgPrint( " g_UlResponseBufferSize = %lu\n", g_UlResponseBufferSize );
  1964. DbgPrint( " g_UlMaxFieldLength = %lu\n", g_UlMaxFieldLength );
  1965. DbgPrint( " g_MaxConnections = 0x%lx\n", g_MaxConnections );
  1966. DbgPrint( " g_UlDisableLogBuffering = %lu\n", g_UlDisableLogBuffering );
  1967. DbgPrint( " g_UlLogBufferSize = %lu\n", g_UlLogBufferSize );
  1968. DbgPrint( " CodePage = %lu\n", ACPCode );
  1969. DbgPrint( " EnableNonUtf8 = %lu\n", g_UrlC14nConfig.EnableNonUtf8 );
  1970. DbgPrint( " FavorUtf8 = %lu\n", g_UrlC14nConfig.FavorUtf8 );
  1971. DbgPrint( " EnableDbcs = %lu\n", g_UrlC14nConfig.EnableDbcs );
  1972. DbgPrint( " PercentUAllowed = %lu\n", g_UrlC14nConfig.PercentUAllowed );
  1973. DbgPrint( " AllowRestrictedChars = %lu\n", g_UrlC14nConfig.AllowRestrictedChars );
  1974. DbgPrint( " HostnameDecodeOrder = 0x%lx\n", g_UrlC14nConfig.HostnameDecodeOrder );
  1975. DbgPrint( " AbsPathDecodeOrder = 0x%lx\n", g_UrlC14nConfig.AbsPathDecodeOrder );
  1976. DbgPrint( " UrlSegmentMaxLength = %lu\n", g_UrlC14nConfig.UrlSegmentMaxLength );
  1977. DbgPrint( " UrlSegmentMaxCount = %lu\n", g_UrlC14nConfig.UrlSegmentMaxCount );
  1978. DbgPrint( " g_UlMaxInternalUrlLength = %lu\n", g_UlMaxInternalUrlLength );
  1979. DbgPrint( " g_UlMaxZombieHttpConnCount = %lu\n", g_UlMaxZombieHttpConnectionCount );
  1980. DbgPrint( " g_UlDisableServerHeader = %lu\n", g_UlDisableServerHeader );
  1981. DbgPrint( " ThreadsPerCpu = %lu\n", pConfig->ThreadsPerCpu );
  1982. DbgPrint( " IrpContextLookasideDepth = %lu\n", pConfig->IrpContextLookasideDepth );
  1983. DbgPrint( " ReceiveBufferLookasideDepth = %lu\n", pConfig->ReceiveBufferLookasideDepth );
  1984. DbgPrint( " ResourceLookasideDepth = %lu\n", pConfig->ResourceLookasideDepth );
  1985. DbgPrint( " RequestBufferLookasideDepth = %lu\n", pConfig->RequestBufferLookasideDepth );
  1986. DbgPrint( " IntlRequestLookasideDepth = %lu\n", pConfig->InternalRequestLookasideDepth );
  1987. DbgPrint( " ResponseBufferLookasideDepth = %lu\n", pConfig->ResponseBufferLookasideDepth );
  1988. DbgPrint( " SendTrackerLookasideDepth = %lu\n", pConfig->SendTrackerLookasideDepth );
  1989. DbgPrint( " LogFileBufferLookasideDepth = %lu\n", pConfig->LogFileBufferLookasideDepth );
  1990. DbgPrint( " LogDataBufferLookasideDepth = %lu\n", pConfig->LogDataBufferLookasideDepth );
  1991. DbgPrint( " WriteTrackerLookasideDepth = %lu\n", pConfig->FilterWriteTrackerLookasideDepth );
  1992. DbgPrint( " EnableCache = %lu\n", pConfig->UriConfig.EnableCache );
  1993. DbgPrint( " MaxCacheUriCount = %lu\n", pConfig->UriConfig.MaxCacheUriCount );
  1994. DbgPrint( " MaxCacheMegabyteCount = %lu\n", pConfig->UriConfig.MaxCacheMegabyteCount );
  1995. DbgPrint( " ScavengerPeriod = %lu\n", pConfig->UriConfig.ScavengerPeriod );
  1996. DbgPrint( " HashTableBits = %ld\n", pConfig->UriConfig.HashTableBits);
  1997. DbgPrint( " MaxUriBytes = %lu\n", pConfig->UriConfig.MaxUriBytes );
  1998. DbgPrint( " ScavengerTrimMB = %ld\n", g_UlScavengerTrimMB);
  1999. #endif // DBG
  2000. //
  2001. // Cleanup.
  2002. //
  2003. ZwClose( parametersHandle );
  2004. } // UlpReadRegistry
  2005. /***************************************************************************++
  2006. Routine Description:
  2007. Unload routine called by the IO subsystem when UL is getting
  2008. unloaded.
  2009. --***************************************************************************/
  2010. VOID
  2011. UlpUnload(
  2012. IN PDRIVER_OBJECT DriverObject
  2013. )
  2014. {
  2015. UNREFERENCED_PARAMETER(DriverObject);
  2016. //
  2017. // Sanity check.
  2018. //
  2019. PAGED_CODE();
  2020. UL_ENTER_DRIVER("http!UlpUnload", NULL);
  2021. #if DBG
  2022. KdPrint(( "UlpUnload called.\n" ));
  2023. #endif // DBG
  2024. //
  2025. // Terminate the UL modules.
  2026. //
  2027. UlpTerminateModules();
  2028. //
  2029. // Flush all kernel DPCs to ensure our periodic timer DPCs cannot
  2030. // get called after we unload.
  2031. //
  2032. KeFlushQueuedDpcs();
  2033. UL_LEAVE_DRIVER("UlpUnload");
  2034. #if DBG
  2035. //
  2036. // Terminate any debug-specific data after UL_LEAVE_DRIVER
  2037. //
  2038. UlDbgTerminateDebugData( );
  2039. #endif // DBG
  2040. #if DBG
  2041. KdPrint(( "\n"
  2042. "------\n"
  2043. "http!UlpUnload finished.\n"
  2044. "------\n" ));
  2045. #endif // DBG
  2046. } // UlpUnload
  2047. /***************************************************************************++
  2048. Routine Description:
  2049. Terminates the various UL modules in the correct order.
  2050. --***************************************************************************/
  2051. VOID
  2052. UlpTerminateModules(
  2053. VOID
  2054. )
  2055. {
  2056. //
  2057. // Sanity check.
  2058. //
  2059. PAGED_CODE();
  2060. //
  2061. // Wait for endpoints to go away, so we're sure all I/O is done.
  2062. //
  2063. UlWaitForEndpointDrain();
  2064. //
  2065. // Kill Michael.
  2066. //
  2067. UlTerminateDateCache();
  2068. UlTerminateUriCache();
  2069. UlTerminateFilterChannel();
  2070. //
  2071. // Kill Henry.
  2072. //
  2073. TerminateFileCache();
  2074. //
  2075. // Kill Paul.
  2076. //
  2077. UlTerminateCG();
  2078. UlTerminateAP();
  2079. //
  2080. // Kill Keith.
  2081. //
  2082. UlTerminateControlChannel();
  2083. //
  2084. // TerminateLogs Blocks until all Io To Be Complete
  2085. //
  2086. // Note:CG should be terminated before Logs.
  2087. // Otherwise we won't stop issuing the buffer writes.
  2088. // ThreadPool should be terminated after Logs.
  2089. // Otherwise our Completion APCs won't be completed back.
  2090. //
  2091. //
  2092. // Kill ETW Logging
  2093. //
  2094. UlEtwUnRegisterLog( g_pUlControlDeviceObject );
  2095. //
  2096. // Kill Ali
  2097. //
  2098. UlTerminateLogs();
  2099. UlTerminateBinaryLog();
  2100. UlTerminateErrorLog();
  2101. UlTerminateLogUtil();
  2102. UlTcTerminate();
  2103. UlTerminateHttpConnection();
  2104. //
  2105. // Kill Eric.
  2106. //
  2107. UlTerminateCounters();
  2108. UlTerminateTimeoutMonitor();
  2109. //
  2110. // Kill George.
  2111. //
  2112. UlLargeMemTerminate();
  2113. //
  2114. // Kill TDI.
  2115. //
  2116. UxTerminateTdi();
  2117. UlTerminateTdi();
  2118. //
  2119. // Kill the thread pool.
  2120. //
  2121. UlTerminateThreadPool();
  2122. //
  2123. // Kill the opaque Ids
  2124. //
  2125. UlTerminateOpaqueIdTable();
  2126. //
  2127. // Kill any global data.
  2128. //
  2129. UlTerminateData();
  2130. //
  2131. // Kill Listen-Only address list
  2132. //
  2133. if ( g_pTdiListenAddresses )
  2134. {
  2135. ASSERT( 0 != g_TdiListenAddrCount );
  2136. UlFreeUlAddr( g_pTdiListenAddresses );
  2137. }
  2138. //
  2139. // Kill namespace.
  2140. //
  2141. UlTerminateNamespace();
  2142. //
  2143. // Kill Client.
  2144. //
  2145. if (g_ClientImageHandle)
  2146. {
  2147. //
  2148. // g_ClientImageHandle != NULL <=> client code was initialized.
  2149. // Call client terminate functions now.
  2150. //
  2151. g_ClientImageHandle = NULL;
  2152. UcTerminateServerInformation();
  2153. UcTerminateClientConnections();
  2154. UcTerminateHttpRequests();
  2155. }
  2156. //
  2157. // Delete our device objects.
  2158. //
  2159. if (g_pUlAppPoolDeviceObject != NULL)
  2160. {
  2161. IoDeleteDevice( g_pUlAppPoolDeviceObject );
  2162. }
  2163. if (g_pUlFilterDeviceObject != NULL)
  2164. {
  2165. IoDeleteDevice( g_pUlFilterDeviceObject );
  2166. }
  2167. if (g_pUlControlDeviceObject != NULL)
  2168. {
  2169. IoDeleteDevice( g_pUlControlDeviceObject );
  2170. }
  2171. if (g_pUcServerDeviceObject != NULL)
  2172. {
  2173. IoDeleteDevice( g_pUcServerDeviceObject );
  2174. }
  2175. //
  2176. // Delete the directory container.
  2177. //
  2178. if (g_UlDirectoryObject != NULL)
  2179. {
  2180. ZwClose( g_UlDirectoryObject );
  2181. }
  2182. //
  2183. // Delete the global trace logs.
  2184. //
  2185. DESTROY_REF_TRACE_LOG( g_pEndpointUsageTraceLog, UL_REF_TRACE_LOG_POOL_TAG );
  2186. DESTROY_REF_TRACE_LOG( g_pTdiTraceLog, UL_REF_TRACE_LOG_POOL_TAG );
  2187. DESTROY_REF_TRACE_LOG( g_pHttpRequestTraceLog, UL_REF_TRACE_LOG_POOL_TAG );
  2188. DESTROY_REF_TRACE_LOG( g_pHttpConnectionTraceLog, UL_REF_TRACE_LOG_POOL_TAG );
  2189. DESTROY_REF_TRACE_LOG( g_pHttpResponseTraceLog, UL_REF_TRACE_LOG_POOL_TAG );
  2190. DESTROY_REF_TRACE_LOG( g_pAppPoolTraceLog, UL_REF_TRACE_LOG_POOL_TAG );
  2191. DESTROY_REF_TRACE_LOG( g_pAppPoolProcessTraceLog, UL_REF_TRACE_LOG_POOL_TAG );
  2192. DESTROY_REF_TRACE_LOG( g_pConfigGroupTraceLog, UL_REF_TRACE_LOG_POOL_TAG );
  2193. DESTROY_REF_TRACE_LOG( g_pControlChannelTraceLog, UL_REF_TRACE_LOG_POOL_TAG );
  2194. DESTROY_REF_TRACE_LOG( g_pThreadTraceLog, UL_REF_TRACE_LOG_POOL_TAG );
  2195. DESTROY_REF_TRACE_LOG( g_pMdlTraceLog, UL_REF_TRACE_LOG_POOL_TAG );
  2196. DESTROY_REF_TRACE_LOG( g_pFilterTraceLog, UL_REF_TRACE_LOG_POOL_TAG );
  2197. DESTROY_REF_TRACE_LOG( g_pUriTraceLog, UL_REF_TRACE_LOG_POOL_TAG );
  2198. DESTROY_IRP_TRACE_LOG( g_pIrpTraceLog );
  2199. DESTROY_TIME_TRACE_LOG( g_pTimeTraceLog );
  2200. DESTROY_APP_POOL_TIME_TRACE_LOG( g_pAppPoolTimeTraceLog );
  2201. DESTROY_REF_TRACE_LOG( g_pSiteCounterTraceLog, UL_REF_TRACE_LOG_POOL_TAG );
  2202. DESTROY_REF_TRACE_LOG( g_pConnectionCountTraceLog, UL_REF_TRACE_LOG_POOL_TAG );
  2203. DESTROY_REF_TRACE_LOG( g_pConfigGroupInfoTraceLog, UL_REF_TRACE_LOG_POOL_TAG );
  2204. DESTROY_REF_TRACE_LOG( g_pChunkTrackerTraceLog, UL_REF_TRACE_LOG_POOL_TAG );
  2205. DESTROY_REF_TRACE_LOG( g_pWorkItemTraceLog, UL_REF_TRACE_LOG_POOL_TAG );
  2206. DESTROY_REF_TRACE_LOG( g_pPoolAllocTraceLog, UL_REF_TRACE_LOG_POOL_TAG );
  2207. DESTROY_REF_TRACE_LOG( g_pMondoGlobalTraceLog, UL_REF_TRACE_LOG_POOL_TAG );
  2208. DESTROY_STRING_LOG( g_pGlobalStringLog );
  2209. DESTROY_UC_TRACE_LOG( g_pUcTraceLog);
  2210. } // UlpTerminateModules