Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1440 lines
39 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. init.c
  5. Abstract:
  6. This module performs initialization for the AFD device driver.
  7. Author:
  8. David Treadwell (davidtr) 21-Feb-1992
  9. Revision History:
  10. --*/
  11. #include "afdp.h"
  12. #define REGISTRY_PARAMETERS L"Parameters"
  13. #define REGISTRY_AFD_INFORMATION L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Afd"
  14. #define REGISTRY_IRP_STACK_SIZE L"IrpStackSize"
  15. #define REGISTRY_PRIORITY_BOOST L"PriorityBoost"
  16. #define REGISTRY_IGNORE_PUSH_BIT L"IgnorePushBitOnReceives"
  17. #define REGISTRY_NO_RAW_SECURITY L"DisableRawSecurity"
  18. #define REGISTRY_NO_SHARED_ADDRESSES L"DisableAddressSharing"
  19. #define REGISTRY_NO_DIRECT_ACCEPTEX L"DisableDirectAcceptEx"
  20. #define REGISTRY_MAX_ACTIVE_TRANSMIT_FILE_COUNT L"MaxActiveTransmitFileCount"
  21. #define REGISTRY_ENABLE_DYNAMIC_BACKLOG L"EnableDynamicBacklog"
  22. #define REGISTRY_DISABLE_CHAINED_RECV L"DisableChainedReceive"
  23. #ifdef TDI_SERVICE_SEND_AND_DISCONNECT
  24. #define REGISTRY_USE_TDI_SEND_AND_DISCONNECT L"UseTdiSendAndDisconnect"
  25. #endif // TDI_SERVICE_SEND_AND_DISCONNECT
  26. #define REGISTRY_BUFFER_ALIGNMENT L"BufferAlignment"
  27. #define REGISTRY_VOLATILE_PARAMETERS L"VolatileParameters"
  28. #if DBG
  29. #define REGISTRY_DEBUG_FLAGS L"DebugFlags"
  30. #define REGISTRY_BREAK_ON_STARTUP L"BreakOnStartup"
  31. #define REGISTRY_USE_PRIVATE_ASSERT L"UsePrivateAssert"
  32. #endif
  33. #if AFD_PERF_DBG
  34. #define REGISTRY_DISABLE_FAST_IO L"DisableFastIO"
  35. #define REGISTRY_DISABLE_CONN_REUSE L"DisableConnectionReuse"
  36. #endif
  37. //
  38. // A list of longwords that are configured by the registry.
  39. //
  40. struct _AfdConfigInfo {
  41. PWCHAR RegistryValueName;
  42. PULONG Variable;
  43. } AfdConfigInfo[] = {
  44. { L"LargeBufferSize", (PULONG)&AfdLargeBufferSize },
  45. { L"LargeBufferListDepth", &AfdLargeBufferListDepth },
  46. { L"MediumBufferSize", &AfdMediumBufferSize },
  47. { L"MediumBufferListDepth", &AfdMediumBufferListDepth },
  48. { L"SmallBufferSize", &AfdSmallBufferSize },
  49. { L"SmallBufferListDepth", &AfdSmallBufferListDepth },
  50. { L"BufferTagListDepth", &AfdBufferTagListDepth },
  51. { L"FastSendDatagramThreshold", &AfdFastSendDatagramThreshold },
  52. { L"PacketFragmentCopyThreshold", &AfdTPacketsCopyThreshold },
  53. { L"StandardAddressLength", &AfdStandardAddressLength },
  54. { L"DefaultReceiveWindow", &AfdReceiveWindowSize },
  55. { L"DefaultSendWindow", &AfdSendWindowSize },
  56. { L"TransmitIoLength", &AfdTransmitIoLength },
  57. { L"MaxFastTransmit", &AfdMaxFastTransmit },
  58. { L"MaxFastCopyTransmit", &AfdMaxFastCopyTransmit },
  59. { L"MinimumDynamicBacklog", &AfdMinimumDynamicBacklog },
  60. { L"MaximumDynamicBacklog", &AfdMaximumDynamicBacklog },
  61. { L"DynamicBacklogGrowthDelta", &AfdDynamicBacklogGrowthDelta },
  62. { L"DefaultPacketElementCount", &AfdDefaultTpInfoElementCount },
  63. { L"TransmitWorker", &AfdDefaultTransmitWorker}
  64. },
  65. AfdVolatileConfigInfo []= {
  66. { L"FastSendDatagramThreshold", &AfdFastSendDatagramThreshold },
  67. { L"PacketFragmentCopyThreshold", &AfdTPacketsCopyThreshold },
  68. { L"TransmitIoLength", &AfdTransmitIoLength },
  69. { L"MaxFastTransmit", &AfdMaxFastTransmit },
  70. { L"MaxFastCopyTransmit", &AfdMaxFastCopyTransmit }
  71. };
  72. #define AFD_CONFIG_VAR_COUNT (sizeof(AfdConfigInfo) / sizeof(AfdConfigInfo[0]))
  73. #define AFD_VOLATILE_CONFIG_VAR_COUNT (sizeof(AfdVolatileConfigInfo) / sizeof(AfdVolatileConfigInfo[0]))
  74. VOID
  75. AfdReadVolatileParameters (
  76. PVOID Parameter
  77. );
  78. VOID
  79. AfdReleaseRegistryHandleWait (
  80. IN PDEVICE_OBJECT DeviceObject,
  81. IN PVOID Context
  82. );
  83. ULONG
  84. AfdReadSingleParameter(
  85. IN HANDLE ParametersHandle,
  86. IN PWCHAR ValueName,
  87. IN LONG DefaultValue
  88. );
  89. NTSTATUS
  90. AfdOpenRegistry(
  91. IN PUNICODE_STRING BaseName,
  92. OUT PHANDLE ParametersHandle
  93. );
  94. VOID
  95. AfdReadRegistry (
  96. VOID
  97. );
  98. VOID
  99. AfdUnload (
  100. IN PDRIVER_OBJECT DriverObject
  101. );
  102. NTSTATUS
  103. DriverEntry (
  104. IN PDRIVER_OBJECT DriverObject,
  105. IN PUNICODE_STRING RegistryPath
  106. );
  107. NTSTATUS
  108. AfdCreateSecurityDescriptor(
  109. VOID
  110. );
  111. NTSTATUS
  112. AfdBuildDeviceAcl(
  113. OUT PACL *DeviceAcl
  114. );
  115. #ifdef ALLOC_PRAGMA
  116. #pragma alloc_text( INIT, DriverEntry )
  117. #pragma alloc_text( PAGE, AfdReadSingleParameter )
  118. #pragma alloc_text( INIT, AfdOpenRegistry )
  119. #pragma alloc_text( INIT, AfdReadRegistry )
  120. #pragma alloc_text( INIT, AfdCreateSecurityDescriptor )
  121. #pragma alloc_text( INIT, AfdBuildDeviceAcl )
  122. #pragma alloc_text( PAGE, AfdUnload )
  123. #pragma alloc_text( PAGE, AfdReadVolatileParameters )
  124. #pragma alloc_text( PAGE, AfdReleaseRegistryHandleWait )
  125. #endif
  126. NTSTATUS
  127. DriverEntry (
  128. IN PDRIVER_OBJECT DriverObject,
  129. IN PUNICODE_STRING RegistryPath
  130. )
  131. /*++
  132. Routine Description:
  133. This is the initialization routine for the AFD device driver.
  134. Arguments:
  135. DriverObject - Pointer to driver object created by the system.
  136. Return Value:
  137. The function value is the final status from the initialization operation.
  138. --*/
  139. {
  140. NTSTATUS status;
  141. UNICODE_STRING deviceName;
  142. CLONG i;
  143. BOOLEAN success;
  144. ULONG size;
  145. PAGED_CODE( );
  146. //
  147. // Create the device object. (IoCreateDevice zeroes the memory
  148. // occupied by the object.)
  149. //
  150. // !!! Apply an ACL to the device object.
  151. //
  152. RtlInitUnicodeString( &deviceName, AFD_DEVICE_NAME );
  153. status = IoCreateDevice(
  154. DriverObject, // DriverObject
  155. 0, // DeviceExtension
  156. &deviceName, // DeviceName
  157. FILE_DEVICE_NAMED_PIPE, // DeviceType
  158. 0, // DeviceCharacteristics
  159. FALSE, // Exclusive
  160. &AfdDeviceObject // DeviceObject
  161. );
  162. if ( !NT_SUCCESS(status) ) {
  163. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_ERROR_LEVEL,
  164. "AFD DriverEntry: unable to create device object: %lx\n",
  165. status ));
  166. goto error_exit;
  167. }
  168. AfdWorkQueueItem = IoAllocateWorkItem (AfdDeviceObject);
  169. if (AfdWorkQueueItem==NULL) {
  170. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  171. "AFD DriverEntry: unable to allocate work queue item\n" ));
  172. status = STATUS_INSUFFICIENT_RESOURCES;
  173. goto error_exit;
  174. }
  175. KeInitializeEvent (&AfdContextWaitEvent, NotificationEvent, FALSE);
  176. //
  177. // Create the security descriptor used for socket access checks.
  178. //
  179. status = AfdCreateSecurityDescriptor();
  180. if (!NT_SUCCESS(status)) {
  181. goto error_exit;
  182. }
  183. //
  184. // Initialize global data.
  185. //
  186. AfdInitializeData( );
  187. //
  188. // Read registry information.
  189. // This may override hard-coded global
  190. // initialization above.
  191. //
  192. AfdReadRegistry( );
  193. #ifdef AFD_CHECK_ALIGNMENT
  194. AfdGlobalData = AFD_ALLOCATE_POOL_PRIORITY(
  195. NonPagedPool,
  196. FIELD_OFFSET (AFD_GLOBAL_DATA, BufferAlignmentTable[AfdAlignmentTableSize])
  197. // Note that although we have an array of UCHARs above
  198. // we do not need to align the array of ULONGs
  199. // since the UCHAR array size is aligned
  200. // to processor requirement.
  201. + AfdAlignmentTableSize*sizeof(LONG),
  202. AFD_RESOURCE_POOL_TAG,
  203. HighPoolPriority
  204. );
  205. #else
  206. AfdGlobalData = AFD_ALLOCATE_POOL_PRIORITY(
  207. NonPagedPool,
  208. FIELD_OFFSET (AFD_GLOBAL_DATA, BufferAlignmentTable[AfdAlignmentTableSize]),
  209. AFD_RESOURCE_POOL_TAG,
  210. HighPoolPriority
  211. );
  212. #endif
  213. if ( AfdGlobalData == NULL ) {
  214. status = STATUS_INSUFFICIENT_RESOURCES;
  215. goto error_exit;
  216. }
  217. ExInitializeResourceLite( AfdResource );
  218. AfdInitializeBufferManager();
  219. //
  220. // Initialize the AFD buffer lookaside lists. These must be
  221. // initialized *after* the registry data has been read.
  222. //
  223. size = AfdCalculateBufferSize (AfdLargeBufferSize, AfdStandardAddressLength);
  224. ExInitializeNPagedLookasideList(
  225. &AfdLookasideLists->LargeBufferList,
  226. AfdAllocateBuffer,
  227. AfdFreeBuffer,
  228. 0,
  229. size,
  230. AFD_DATA_BUFFER_POOL_TAG,
  231. (USHORT)AfdLargeBufferListDepth
  232. );
  233. //
  234. // Make sure that if as the result of alignment the allocation size is adjusted
  235. // to equal to the larger one, the actual buffer sizes are adjusted as well.
  236. // This is necessary to avoid confusing block allocator which determines
  237. // buffer size based on the allocation size passed by the lookaside list
  238. // code.
  239. //
  240. size = AfdCalculateBufferSize (AfdMediumBufferSize, AfdStandardAddressLength);
  241. if (size==AfdLookasideLists->LargeBufferList.L.Size) {
  242. AfdMediumBufferSize = AfdLargeBufferSize;
  243. }
  244. else {
  245. ASSERT (size<AfdLookasideLists->LargeBufferList.L.Size);
  246. }
  247. ExInitializeNPagedLookasideList(
  248. &AfdLookasideLists->MediumBufferList,
  249. AfdAllocateBuffer,
  250. AfdFreeBuffer,
  251. 0,
  252. size,
  253. AFD_DATA_BUFFER_POOL_TAG,
  254. (USHORT)AfdMediumBufferListDepth
  255. );
  256. size = AfdCalculateBufferSize (AfdSmallBufferSize, AfdStandardAddressLength);
  257. if (size==AfdLookasideLists->MediumBufferList.L.Size) {
  258. AfdSmallBufferSize = AfdMediumBufferSize;
  259. }
  260. else {
  261. ASSERT (size<AfdLookasideLists->MediumBufferList.L.Size);
  262. }
  263. ExInitializeNPagedLookasideList(
  264. &AfdLookasideLists->SmallBufferList,
  265. AfdAllocateBuffer,
  266. AfdFreeBuffer,
  267. 0,
  268. size,
  269. AFD_DATA_BUFFER_POOL_TAG,
  270. (USHORT)AfdSmallBufferListDepth
  271. );
  272. ExInitializeNPagedLookasideList(
  273. &AfdLookasideLists->BufferTagList,
  274. AfdAllocateBufferTag,
  275. AfdFreeBufferTag,
  276. 0,
  277. sizeof (AFD_BUFFER_TAG),
  278. AFD_DATA_BUFFER_POOL_TAG,
  279. (USHORT)AfdBufferTagListDepth
  280. );
  281. ExInitializeNPagedLookasideList(
  282. &AfdLookasideLists->TpInfoList,
  283. AfdAllocateTpInfo,
  284. AfdFreeTpInfo,
  285. 0,
  286. AfdComputeTpInfoSize (AfdDefaultTpInfoElementCount,
  287. AFD_TP_MIN_SEND_IRPS,
  288. AfdIrpStackSize-1),
  289. AFD_TRANSMIT_INFO_POOL_TAG,
  290. 0
  291. );
  292. ExInitializeNPagedLookasideList(
  293. &AfdLookasideLists->RemoteAddrList,
  294. AfdAllocateRemoteAddress,
  295. AfdFreeRemoteAddress,
  296. 0,
  297. AfdStandardAddressLength,
  298. AFD_REMOTE_ADDRESS_POOL_TAG,
  299. (USHORT)AfdBufferTagListDepth
  300. );
  301. AfdLookasideLists->TrimFlags = 0;
  302. //
  303. // Initialize group ID manager.
  304. //
  305. success = AfdInitializeGroup();
  306. if ( !success ) {
  307. status = STATUS_INSUFFICIENT_RESOURCES;
  308. goto error_exit;
  309. }
  310. //
  311. // Initialize the driver object for this file system driver.
  312. //
  313. for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) {
  314. DriverObject->MajorFunction[i] = AfdDispatch;
  315. }
  316. //
  317. // Special case for IRP_MJ_DEVICE_CONTROL since it is
  318. // the most often used function in AFD.
  319. //
  320. DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] =
  321. AfdDispatchDeviceControl;
  322. DriverObject->FastIoDispatch = &AfdFastIoDispatch;
  323. DriverObject->DriverUnload = AfdUnload;
  324. //
  325. // Initialize our device object.
  326. //
  327. AfdDeviceObject->Flags |= DO_DIRECT_IO;
  328. AfdDeviceObject->StackSize = AfdIrpStackSize;
  329. //
  330. // Remember a pointer to the system process. We'll use this pointer
  331. // for KeAttachProcess() calls so that we can open handles in the
  332. // context of the system process.
  333. //
  334. AfdSystemProcess = (PKPROCESS)IoGetCurrentProcess();
  335. //
  336. // Start notification for volatile parameters if necessary.
  337. //
  338. if (AfdParametersNotifyHandle) {
  339. AfdReadVolatileParameters (NULL);
  340. }
  341. //
  342. // Tell MM that it can page all of AFD it is desires. We will reset
  343. // to normal paging of AFD code as soon as an AFD endpoint is
  344. // opened.
  345. //
  346. AfdLoaded = NULL;
  347. MmPageEntireDriver( DriverEntry );
  348. return (status);
  349. error_exit:
  350. //
  351. // Terminate the group ID manager.
  352. //
  353. AfdTerminateGroup();
  354. if (AfdAdminSecurityDescriptor!=NULL) {
  355. ExFreePool (AfdAdminSecurityDescriptor);
  356. AfdAdminSecurityDescriptor = NULL;
  357. }
  358. if( AfdGlobalData != NULL ) {
  359. ExDeleteNPagedLookasideList( &AfdLookasideLists->LargeBufferList );
  360. ExDeleteNPagedLookasideList( &AfdLookasideLists->MediumBufferList );
  361. ExDeleteNPagedLookasideList( &AfdLookasideLists->SmallBufferList );
  362. ExDeleteNPagedLookasideList( &AfdLookasideLists->BufferTagList );
  363. ExDeleteNPagedLookasideList( &AfdLookasideLists->TpInfoList );
  364. ExDeleteNPagedLookasideList( &AfdLookasideLists->RemoteAddrList );
  365. ExDeleteResourceLite( AfdResource );
  366. AFD_FREE_POOL(
  367. AfdGlobalData,
  368. AFD_RESOURCE_POOL_TAG
  369. );
  370. AfdGlobalData = NULL;
  371. }
  372. if (AfdWorkQueueItem!=NULL) {
  373. IoFreeWorkItem (AfdWorkQueueItem);
  374. AfdWorkQueueItem = NULL;
  375. }
  376. if (AfdDeviceObject!=NULL) {
  377. IoDeleteDevice(AfdDeviceObject);
  378. AfdDeviceObject = NULL;
  379. }
  380. return status;
  381. } // DriverEntry
  382. VOID
  383. AfdUnload (
  384. IN PDRIVER_OBJECT DriverObject
  385. )
  386. {
  387. PLIST_ENTRY listEntry;
  388. KEVENT event;
  389. BOOLEAN wait;
  390. UNREFERENCED_PARAMETER( DriverObject );
  391. PAGED_CODE( );
  392. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_INFO_LEVEL,
  393. "AfdUnload called.\n" ));
  394. if (AfdParametersNotifyHandle!=NULL) {
  395. KeEnterCriticalRegion ();
  396. ExAcquireResourceExclusiveLite( AfdResource, TRUE );
  397. ZwClose (AfdParametersNotifyHandle);
  398. AfdParametersNotifyHandle = NULL;
  399. KeInitializeEvent( &event, SynchronizationEvent, FALSE );
  400. AfdParametersUnloadEvent = &event;
  401. ExReleaseResourceLite( AfdResource );
  402. KeLeaveCriticalRegion ();
  403. }
  404. //
  405. // Check if AFD has already cleaned up all endpoints and
  406. // is ready to get unloaded.
  407. //
  408. KeEnterCriticalRegion ();
  409. ExAcquireResourceExclusiveLite( AfdResource, TRUE );
  410. if (AfdLoaded!=NULL) {
  411. //
  412. // Some work still needs to be done. Setup the wait.
  413. //
  414. ASSERT (AfdLoaded==(PKEVENT)1);
  415. KeInitializeEvent( &event, SynchronizationEvent, FALSE );
  416. AfdLoaded = &event;
  417. wait = TRUE;
  418. }
  419. else
  420. wait = FALSE;
  421. ExReleaseResourceLite( AfdResource );
  422. KeLeaveCriticalRegion ();
  423. if (wait) {
  424. NTSTATUS status;
  425. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_INFO_LEVEL,
  426. "AfdUnload: Waiting for endpoints to cleanup...\n"));
  427. status = KeWaitForSingleObject( (PVOID)&event, Executive, KernelMode, FALSE, NULL );
  428. ASSERT (NT_SUCCESS (status));
  429. }
  430. //
  431. // Kill the transport info list.
  432. //
  433. while( !IsListEmpty( &AfdTransportInfoListHead ) ) {
  434. PAFD_TRANSPORT_INFO transportInfo;
  435. listEntry = RemoveHeadList( &AfdTransportInfoListHead );
  436. transportInfo = CONTAINING_RECORD(
  437. listEntry,
  438. AFD_TRANSPORT_INFO,
  439. TransportInfoListEntry
  440. );
  441. ASSERT (transportInfo->ReferenceCount == 1);
  442. AFD_FREE_POOL(
  443. transportInfo,
  444. AFD_TRANSPORT_INFO_POOL_TAG
  445. );
  446. }
  447. //
  448. // Free address list and associated structures
  449. //
  450. AfdDeregisterPnPHandlers (NULL);
  451. if (AfdAddressListLock) {
  452. ExDeleteResourceLite( AfdAddressListLock );
  453. AFD_FREE_POOL(
  454. AfdAddressListLock,
  455. AFD_RESOURCE_POOL_TAG
  456. );
  457. }
  458. //
  459. // Do some cleanup for SAN
  460. //
  461. if (IoCompletionObjectType!=NULL) {
  462. ObDereferenceObject (IoCompletionObjectType);
  463. IoCompletionObjectType = NULL;
  464. }
  465. if (AfdAdminSecurityDescriptor!=NULL) {
  466. ExFreePool (AfdAdminSecurityDescriptor);
  467. AfdAdminSecurityDescriptor = NULL;
  468. }
  469. //
  470. // Terminate the group ID manager.
  471. //
  472. AfdTerminateGroup();
  473. #if DBG || REFERENCE_DEBUG
  474. AfdFreeDebugData ();
  475. #endif
  476. //
  477. // Kill the lookaside lists and resouce in the global data
  478. //
  479. if( AfdGlobalData != NULL ) {
  480. ExDeleteNPagedLookasideList( &AfdLookasideLists->LargeBufferList );
  481. ExDeleteNPagedLookasideList( &AfdLookasideLists->MediumBufferList );
  482. ExDeleteNPagedLookasideList( &AfdLookasideLists->SmallBufferList );
  483. ExDeleteNPagedLookasideList( &AfdLookasideLists->BufferTagList );
  484. ExDeleteNPagedLookasideList( &AfdLookasideLists->TpInfoList );
  485. ExDeleteNPagedLookasideList( &AfdLookasideLists->RemoteAddrList );
  486. ExDeleteResourceLite( AfdResource );
  487. AFD_FREE_POOL(
  488. AfdGlobalData,
  489. AFD_RESOURCE_POOL_TAG
  490. );
  491. }
  492. //
  493. // Delete our device object.
  494. //
  495. IoDeleteDevice( AfdDeviceObject );
  496. } // AfdUnload
  497. VOID
  498. AfdReadRegistry (
  499. VOID
  500. )
  501. /*++
  502. Routine Description:
  503. Reads the AFD section of the registry. Any values listed in the
  504. registry override defaults.
  505. Arguments:
  506. None.
  507. Return Value:
  508. None -- if anything fails, the default value is used.
  509. --*/
  510. {
  511. HANDLE parametersHandle;
  512. NTSTATUS status;
  513. ULONG stackSize;
  514. ULONG priorityBoost;
  515. ULONG bufferAlignment;
  516. UNICODE_STRING registryPath;
  517. ULONG i;
  518. PAGED_CODE( );
  519. RtlInitUnicodeString( &registryPath, REGISTRY_AFD_INFORMATION );
  520. status = AfdOpenRegistry( &registryPath, &parametersHandle );
  521. if (status != STATUS_SUCCESS) {
  522. return;
  523. }
  524. #if DBG
  525. //
  526. // Read the debug flags from the registry.
  527. //
  528. AfdDebug = AfdReadSingleParameter(
  529. parametersHandle,
  530. REGISTRY_DEBUG_FLAGS,
  531. AfdDebug
  532. );
  533. //
  534. // Force a breakpoint if so requested.
  535. //
  536. if( AfdReadSingleParameter(
  537. parametersHandle,
  538. REGISTRY_BREAK_ON_STARTUP,
  539. 0 ) != 0 ) {
  540. DbgBreakPoint();
  541. }
  542. //
  543. // Enable private assert function if requested.
  544. //
  545. AfdUsePrivateAssert = AfdReadSingleParameter(
  546. parametersHandle,
  547. REGISTRY_USE_PRIVATE_ASSERT,
  548. (LONG)AfdUsePrivateAssert
  549. ) != 0;
  550. #endif
  551. #if AFD_PERF_DBG
  552. //
  553. // Read a flag from the registry that allows us to disable Fast IO.
  554. //
  555. AfdDisableFastIo = AfdReadSingleParameter(
  556. parametersHandle,
  557. REGISTRY_DISABLE_FAST_IO,
  558. (LONG)AfdDisableFastIo
  559. ) != 0;
  560. if( AfdDisableFastIo ) {
  561. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_INFO_LEVEL,
  562. "AFD: Fast IO disabled\n" ));
  563. }
  564. //
  565. // Read a flag from the registry that allows us to disable connection
  566. // reuse.
  567. //
  568. AfdDisableConnectionReuse = AfdReadSingleParameter(
  569. parametersHandle,
  570. REGISTRY_DISABLE_CONN_REUSE,
  571. (LONG)AfdDisableConnectionReuse
  572. ) != 0;
  573. if( AfdDisableConnectionReuse ) {
  574. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_INFO_LEVEL,
  575. "AFD: Connection Reuse disabled\n" ));
  576. }
  577. #endif
  578. //
  579. // Read the stack size and priority boost values from the registry.
  580. //
  581. stackSize = AfdReadSingleParameter(
  582. parametersHandle,
  583. REGISTRY_IRP_STACK_SIZE,
  584. (ULONG)AfdIrpStackSize
  585. );
  586. //
  587. // We do not support more than 63 layers below us.
  588. // (The system allows for 127, but some can be sitting above us
  589. // as well.
  590. //
  591. if ( stackSize > 64 ) {
  592. stackSize = 64;
  593. }
  594. if (stackSize<2) {
  595. //
  596. // Can't be less than two since we have to call
  597. // at least one driver below us.
  598. //
  599. stackSize = 2;
  600. }
  601. AfdIrpStackSize = (CCHAR)stackSize;
  602. priorityBoost = AfdReadSingleParameter(
  603. parametersHandle,
  604. REGISTRY_PRIORITY_BOOST,
  605. (ULONG)AfdPriorityBoost
  606. );
  607. if ( priorityBoost > 16 ) {
  608. priorityBoost = AFD_DEFAULT_PRIORITY_BOOST;
  609. }
  610. AfdPriorityBoost = (CCHAR)priorityBoost;
  611. //
  612. // Read other config variables from the registry.
  613. //
  614. for ( i = 0; i < AFD_CONFIG_VAR_COUNT; i++ ) {
  615. *AfdConfigInfo[i].Variable =
  616. AfdReadSingleParameter(
  617. parametersHandle,
  618. AfdConfigInfo[i].RegistryValueName,
  619. *AfdConfigInfo[i].Variable
  620. );
  621. }
  622. //
  623. // Validate standard buffer sizes.
  624. // (we use buffer for KAPC or WORK_QUEUE_ITEM storage
  625. // in fast transmit file processing).
  626. //
  627. if (AfdSmallBufferSize<max (sizeof(KAPC),sizeof (WORK_QUEUE_ITEM)))
  628. AfdSmallBufferSize = max (sizeof(KAPC),sizeof (WORK_QUEUE_ITEM));
  629. if (AfdMediumBufferSize<AfdSmallBufferSize)
  630. AfdMediumBufferSize = AfdSmallBufferSize;
  631. if (AfdLargeBufferSize<AfdMediumBufferSize)
  632. AfdLargeBufferSize = AfdMediumBufferSize;
  633. AfdIgnorePushBitOnReceives = AfdReadSingleParameter(
  634. parametersHandle,
  635. REGISTRY_IGNORE_PUSH_BIT,
  636. (LONG)AfdIgnorePushBitOnReceives
  637. )!=0;
  638. AfdDisableRawSecurity = AfdReadSingleParameter(
  639. parametersHandle,
  640. REGISTRY_NO_RAW_SECURITY,
  641. (LONG)AfdDisableRawSecurity
  642. )!=0;
  643. AfdDontShareAddresses = AfdReadSingleParameter(
  644. parametersHandle,
  645. REGISTRY_NO_SHARED_ADDRESSES,
  646. (LONG)AfdDontShareAddresses
  647. )!=0;
  648. AfdDisableDirectSuperAccept = AfdReadSingleParameter(
  649. parametersHandle,
  650. REGISTRY_NO_DIRECT_ACCEPTEX,
  651. (LONG)AfdDisableDirectSuperAccept
  652. )!=0;
  653. AfdDisableChainedReceive = AfdReadSingleParameter(
  654. parametersHandle,
  655. REGISTRY_DISABLE_CHAINED_RECV,
  656. (LONG)AfdDisableChainedReceive
  657. ) != 0;
  658. #ifdef TDI_SERVICE_SEND_AND_DISCONNECT
  659. AfdUseTdiSendAndDisconnect = AfdReadSingleParameter(
  660. parametersHandle,
  661. REGISTRY_USE_TDI_SEND_AND_DISCONNECT,
  662. (LONG)AfdUseTdiSendAndDisconnect
  663. ) != 0;
  664. #endif //TDI_SERVICE_SEND_AND_DISCONNECT
  665. if( MmIsThisAnNtAsSystem() ) {
  666. //
  667. // On the NT Server product, make the maximum active TransmitFile
  668. // count configurable. This value is fixed (not configurable) on
  669. // the NT Workstation product.
  670. //
  671. AfdMaxActiveTransmitFileCount = AfdReadSingleParameter(
  672. parametersHandle,
  673. REGISTRY_MAX_ACTIVE_TRANSMIT_FILE_COUNT,
  674. (LONG)AfdMaxActiveTransmitFileCount
  675. );
  676. //
  677. // Dynamic backlog is only possible on NT Server.
  678. //
  679. AfdEnableDynamicBacklog = AfdReadSingleParameter(
  680. parametersHandle,
  681. REGISTRY_ENABLE_DYNAMIC_BACKLOG,
  682. (LONG)AfdEnableDynamicBacklog
  683. ) != 0;
  684. } else {
  685. AfdEnableDynamicBacklog = FALSE;
  686. }
  687. switch (AfdDefaultTransmitWorker) {
  688. case AFD_TF_USE_SYSTEM_THREAD:
  689. case AFD_TF_USE_KERNEL_APC:
  690. break;
  691. default:
  692. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_ERROR_LEVEL,
  693. "AFD: Invalid TransmitWorker registry parameter value: %ld\n"
  694. "AFD; Using default - %ld\n",
  695. AfdDefaultTransmitWorker,
  696. AFD_DEFAULT_TRANSMIT_WORKER));
  697. AfdDefaultTransmitWorker = AFD_DEFAULT_TRANSMIT_WORKER;
  698. break;
  699. }
  700. bufferAlignment = AfdReadSingleParameter(
  701. parametersHandle,
  702. REGISTRY_BUFFER_ALIGNMENT,
  703. (LONG)AfdBufferAlignment
  704. );
  705. if (bufferAlignment!=AfdBufferAlignment) {
  706. if (bufferAlignment<AFD_MINIMUM_BUFFER_ALIGNMENT ||
  707. bufferAlignment>PAGE_SIZE ||
  708. (bufferAlignment & (bufferAlignment-1))!=0) {
  709. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_ERROR_LEVEL,
  710. "AFD: Invalid %ls registry parameter value: %ld\n"
  711. "AFD; Using default - %ld\n",
  712. REGISTRY_BUFFER_ALIGNMENT,
  713. bufferAlignment,
  714. AfdBufferAlignment));
  715. }
  716. else {
  717. AfdBufferAlignment = bufferAlignment;
  718. AfdAlignmentTableSize = AfdBufferAlignment/AFD_MINIMUM_BUFFER_ALIGNMENT;
  719. }
  720. }
  721. AfdVolatileConfig = AfdReadSingleParameter (
  722. parametersHandle,
  723. REGISTRY_VOLATILE_PARAMETERS,
  724. (LONG)AfdVolatileConfig)!=0;
  725. if (AfdVolatileConfig) {
  726. AfdParametersNotifyHandle = parametersHandle;
  727. ExInitializeWorkItem (&AfdParametersNotifyWorker, AfdReadVolatileParameters, NULL);
  728. }
  729. else {
  730. ZwClose( parametersHandle );
  731. }
  732. //
  733. // Need to recalculate size of the page-long buffer if standard
  734. // address length has changed
  735. //
  736. if (AfdStandardAddressLength!=AFD_DEFAULT_STD_ADDRESS_LENGTH) {
  737. CLONG oldBufferLengthForOnePage = AfdBufferLengthForOnePage;
  738. AfdBufferOverhead = AfdCalculateBufferSize( PAGE_SIZE, AfdStandardAddressLength) - PAGE_SIZE;
  739. AfdBufferLengthForOnePage = ALIGN_DOWN_A(
  740. PAGE_SIZE-AfdBufferOverhead,
  741. AFD_MINIMUM_BUFFER_ALIGNMENT);
  742. if (AfdLargeBufferSize==oldBufferLengthForOnePage) {
  743. AfdLargeBufferSize = AfdBufferLengthForOnePage;
  744. }
  745. }
  746. return;
  747. } // AfdReadRegistry
  748. NTSTATUS
  749. AfdOpenRegistry(
  750. IN PUNICODE_STRING BaseName,
  751. OUT PHANDLE ParametersHandle
  752. )
  753. /*++
  754. Routine Description:
  755. This routine is called by AFD to open the registry. If the registry
  756. tree exists, then it opens it and returns an error. If not, it
  757. creates the appropriate keys in the registry, opens it, and
  758. returns STATUS_SUCCESS.
  759. Arguments:
  760. BaseName - Where in the registry to start looking for the information.
  761. LinkageHandle - Returns the handle used to read linkage information.
  762. ParametersHandle - Returns the handle used to read other
  763. parameters.
  764. Return Value:
  765. The status of the request.
  766. --*/
  767. {
  768. HANDLE configHandle;
  769. NTSTATUS status;
  770. PWSTR parametersString = REGISTRY_PARAMETERS;
  771. UNICODE_STRING parametersKeyName;
  772. OBJECT_ATTRIBUTES objectAttributes;
  773. ULONG disposition;
  774. PAGED_CODE( );
  775. //
  776. // Open the registry for the initial string.
  777. //
  778. InitializeObjectAttributes(
  779. &objectAttributes,
  780. BaseName, // name
  781. OBJ_CASE_INSENSITIVE, // attributes
  782. NULL, // root
  783. NULL // security descriptor
  784. );
  785. status = ZwCreateKey(
  786. &configHandle,
  787. KEY_WRITE,
  788. &objectAttributes,
  789. 0, // title index
  790. NULL, // class
  791. 0, // create options
  792. &disposition // disposition
  793. );
  794. if (!NT_SUCCESS(status)) {
  795. return STATUS_UNSUCCESSFUL;
  796. }
  797. //
  798. // Now open the parameters key.
  799. //
  800. RtlInitUnicodeString (&parametersKeyName, parametersString);
  801. InitializeObjectAttributes(
  802. &objectAttributes,
  803. &parametersKeyName, // name
  804. OBJ_CASE_INSENSITIVE, // attributes
  805. configHandle, // root
  806. NULL // security descriptor
  807. );
  808. status = ZwOpenKey(
  809. ParametersHandle,
  810. KEY_READ,
  811. &objectAttributes
  812. );
  813. if (!NT_SUCCESS(status)) {
  814. ZwClose( configHandle );
  815. return status;
  816. }
  817. //
  818. // All keys successfully opened or created.
  819. //
  820. ZwClose( configHandle );
  821. return STATUS_SUCCESS;
  822. } // AfdOpenRegistry
  823. ULONG
  824. AfdReadSingleParameter(
  825. IN HANDLE ParametersHandle,
  826. IN PWCHAR ValueName,
  827. IN LONG DefaultValue
  828. )
  829. /*++
  830. Routine Description:
  831. This routine is called by AFD to read a single parameter
  832. from the registry. If the parameter is found it is stored
  833. in Data.
  834. Arguments:
  835. ParametersHandle - A pointer to the open registry.
  836. ValueName - The name of the value to search for.
  837. DefaultValue - The default value.
  838. Return Value:
  839. The value to use; will be the default if the value is not
  840. found or is not in the correct range.
  841. --*/
  842. {
  843. static ULONG informationBuffer[32]; // declare ULONG to get it aligned
  844. PKEY_VALUE_FULL_INFORMATION information =
  845. (PKEY_VALUE_FULL_INFORMATION)informationBuffer;
  846. UNICODE_STRING valueKeyName;
  847. ULONG informationLength;
  848. LONG returnValue;
  849. NTSTATUS status;
  850. PAGED_CODE( );
  851. RtlInitUnicodeString( &valueKeyName, ValueName );
  852. status = ZwQueryValueKey(
  853. ParametersHandle,
  854. &valueKeyName,
  855. KeyValueFullInformation,
  856. (PVOID)information,
  857. sizeof (informationBuffer),
  858. &informationLength
  859. );
  860. if ((status == STATUS_SUCCESS) && (information->DataLength == sizeof(ULONG))) {
  861. RtlMoveMemory(
  862. (PVOID)&returnValue,
  863. ((PUCHAR)information) + information->DataOffset,
  864. sizeof(ULONG)
  865. );
  866. if (returnValue < 0) {
  867. returnValue = DefaultValue;
  868. }
  869. else if (returnValue!=DefaultValue) {
  870. DbgPrint ("AFD: Read %ls from the registry, value: 0x%lx (%s: 0x%lx))\n",
  871. ValueName, returnValue,
  872. AfdVolatileConfig ? "previous" : "default",
  873. DefaultValue);
  874. }
  875. } else {
  876. returnValue = DefaultValue;
  877. }
  878. return returnValue;
  879. } // AfdReadSingleParameter
  880. NTSTATUS
  881. AfdBuildDeviceAcl(
  882. OUT PACL *DeviceAcl
  883. )
  884. /*++
  885. Routine Description:
  886. This routine builds an ACL which gives Administrators, LocalSystem,
  887. and NetworkService principals full access. All other principals have no access.
  888. Arguments:
  889. DeviceAcl - Output pointer to the new ACL.
  890. Return Value:
  891. STATUS_SUCCESS or an appropriate error code.
  892. --*/
  893. {
  894. PGENERIC_MAPPING GenericMapping;
  895. ULONG AclLength;
  896. NTSTATUS Status;
  897. ACCESS_MASK AccessMask = GENERIC_ALL;
  898. PACL NewAcl;
  899. //
  900. // Enable access to all the globally defined SIDs
  901. //
  902. GenericMapping = IoGetFileObjectGenericMapping();
  903. RtlMapGenericMask( &AccessMask, GenericMapping );
  904. AclLength = sizeof( ACL ) +
  905. 3 * FIELD_OFFSET (ACCESS_ALLOWED_ACE, SidStart) +
  906. RtlLengthSid( SeExports->SeAliasAdminsSid ) +
  907. RtlLengthSid( SeExports->SeLocalSystemSid ) +
  908. RtlLengthSid( SeExports->SeNetworkServiceSid );
  909. NewAcl = AFD_ALLOCATE_POOL_PRIORITY (
  910. PagedPool,
  911. AclLength,
  912. AFD_SECURITY_POOL_TAG,
  913. HighPoolPriority
  914. );
  915. if (NewAcl == NULL) {
  916. return( STATUS_INSUFFICIENT_RESOURCES );
  917. }
  918. Status = RtlCreateAcl (NewAcl, AclLength, ACL_REVISION );
  919. if (!NT_SUCCESS( Status )) {
  920. AFD_FREE_POOL(
  921. NewAcl,
  922. AFD_SECURITY_POOL_TAG
  923. );
  924. return( Status );
  925. }
  926. Status = RtlAddAccessAllowedAce (
  927. NewAcl,
  928. ACL_REVISION2,
  929. AccessMask,
  930. SeExports->SeAliasAdminsSid
  931. );
  932. ASSERT( NT_SUCCESS( Status ));
  933. Status = RtlAddAccessAllowedAce (
  934. NewAcl,
  935. ACL_REVISION2,
  936. AccessMask,
  937. SeExports->SeLocalSystemSid
  938. );
  939. ASSERT( NT_SUCCESS( Status ));
  940. Status = RtlAddAccessAllowedAce (
  941. NewAcl,
  942. ACL_REVISION2,
  943. AccessMask,
  944. SeExports->SeNetworkServiceSid
  945. );
  946. ASSERT( NT_SUCCESS( Status ));
  947. *DeviceAcl = NewAcl;
  948. return( STATUS_SUCCESS );
  949. } // AfdBuildDeviceAcl
  950. NTSTATUS
  951. AfdCreateSecurityDescriptor(
  952. VOID
  953. )
  954. /*++
  955. Routine Description:
  956. This routine creates a security descriptor which gives access
  957. only to certain priviliged accounts. This descriptor is used
  958. to access check raw endpoint opens and exclisive access to transport
  959. addresses.
  960. Arguments:
  961. None.
  962. Return Value:
  963. STATUS_SUCCESS or an appropriate error code.
  964. --*/
  965. {
  966. PACL devAcl = NULL;
  967. NTSTATUS status;
  968. BOOLEAN memoryAllocated = FALSE;
  969. PSECURITY_DESCRIPTOR afdSecurityDescriptor;
  970. ULONG afdSecurityDescriptorLength;
  971. CHAR buffer[SECURITY_DESCRIPTOR_MIN_LENGTH];
  972. PSECURITY_DESCRIPTOR localSecurityDescriptor =
  973. (PSECURITY_DESCRIPTOR) &buffer;
  974. PSECURITY_DESCRIPTOR localAfdAdminSecurityDescriptor;
  975. SECURITY_INFORMATION securityInformation = DACL_SECURITY_INFORMATION;
  976. //
  977. // Get a pointer to the security descriptor from the AFD device object.
  978. //
  979. status = ObGetObjectSecurity(
  980. AfdDeviceObject,
  981. &afdSecurityDescriptor,
  982. &memoryAllocated
  983. );
  984. if (!NT_SUCCESS(status)) {
  985. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_ERROR_LEVEL,
  986. "AFD: Unable to get security descriptor, error: %x\n",
  987. status
  988. ));
  989. ASSERT(memoryAllocated == FALSE);
  990. return(status);
  991. }
  992. //
  993. // Build a local security descriptor with an ACL giving only
  994. // certain priviliged accounts.
  995. //
  996. status = AfdBuildDeviceAcl(&devAcl);
  997. if (!NT_SUCCESS(status)) {
  998. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_ERROR_LEVEL,
  999. "AFD: Unable to create Raw ACL, error: %x\n", status));
  1000. goto error_exit;
  1001. }
  1002. (VOID) RtlCreateSecurityDescriptor(
  1003. localSecurityDescriptor,
  1004. SECURITY_DESCRIPTOR_REVISION
  1005. );
  1006. (VOID) RtlSetDaclSecurityDescriptor(
  1007. localSecurityDescriptor,
  1008. TRUE,
  1009. devAcl,
  1010. FALSE
  1011. );
  1012. //
  1013. // Make a copy of the AFD descriptor. This copy will be the raw descriptor.
  1014. //
  1015. afdSecurityDescriptorLength = RtlLengthSecurityDescriptor(
  1016. afdSecurityDescriptor
  1017. );
  1018. localAfdAdminSecurityDescriptor = ExAllocatePoolWithTag (
  1019. PagedPool,
  1020. afdSecurityDescriptorLength,
  1021. AFD_SECURITY_POOL_TAG
  1022. );
  1023. if (localAfdAdminSecurityDescriptor == NULL) {
  1024. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_ERROR_LEVEL,
  1025. "AFD: couldn't allocate security descriptor\n"));
  1026. goto error_exit;
  1027. }
  1028. RtlMoveMemory(
  1029. localAfdAdminSecurityDescriptor,
  1030. afdSecurityDescriptor,
  1031. afdSecurityDescriptorLength
  1032. );
  1033. AfdAdminSecurityDescriptor = localAfdAdminSecurityDescriptor;
  1034. //
  1035. // Now apply the local descriptor to the raw descriptor.
  1036. //
  1037. status = SeSetSecurityDescriptorInfo(
  1038. NULL,
  1039. &securityInformation,
  1040. localSecurityDescriptor,
  1041. &AfdAdminSecurityDescriptor,
  1042. PagedPool,
  1043. IoGetFileObjectGenericMapping()
  1044. );
  1045. if (!NT_SUCCESS(status)) {
  1046. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_ERROR_LEVEL,
  1047. "AFD: SeSetSecurity failed, %lx\n",
  1048. status));
  1049. ASSERT (AfdAdminSecurityDescriptor==localAfdAdminSecurityDescriptor);
  1050. ExFreePool (AfdAdminSecurityDescriptor);
  1051. AfdAdminSecurityDescriptor = NULL;
  1052. goto error_exit;
  1053. }
  1054. if (AfdAdminSecurityDescriptor!=localAfdAdminSecurityDescriptor) {
  1055. ExFreePool (localAfdAdminSecurityDescriptor);
  1056. }
  1057. status = STATUS_SUCCESS;
  1058. error_exit:
  1059. ObReleaseObjectSecurity(
  1060. afdSecurityDescriptor,
  1061. memoryAllocated
  1062. );
  1063. if (devAcl!=NULL) {
  1064. AFD_FREE_POOL(
  1065. devAcl,
  1066. AFD_SECURITY_POOL_TAG
  1067. );
  1068. }
  1069. return(status);
  1070. }
  1071. VOID
  1072. AfdReadVolatileParameters (
  1073. PVOID Parameter
  1074. )
  1075. {
  1076. PAGED_CODE ();
  1077. ExAcquireResourceExclusiveLite( AfdResource, TRUE );
  1078. if (AfdParametersNotifyHandle!=NULL) {
  1079. ULONG i;
  1080. NTSTATUS status;
  1081. status = ZwNotifyChangeKey (
  1082. AfdParametersNotifyHandle,
  1083. NULL,
  1084. (PIO_APC_ROUTINE)&AfdParametersNotifyWorker,
  1085. (PVOID)(UINT_PTR)(unsigned int)DelayedWorkQueue,
  1086. &AfdDontCareIoStatus,
  1087. REG_NOTIFY_CHANGE_LAST_SET,
  1088. FALSE,
  1089. NULL, 0,
  1090. TRUE);
  1091. if (NT_SUCCESS (status)) {
  1092. for ( i = 0; i < AFD_VOLATILE_CONFIG_VAR_COUNT; i++ ) {
  1093. *AfdVolatileConfigInfo[i].Variable =
  1094. AfdReadSingleParameter(
  1095. AfdParametersNotifyHandle,
  1096. AfdVolatileConfigInfo[i].RegistryValueName,
  1097. *AfdVolatileConfigInfo[i].Variable
  1098. );
  1099. }
  1100. }
  1101. else {
  1102. DbgPrint (
  1103. "AFD: Failed to start notification for volatile parameter changes, status: %lx\n",
  1104. status);
  1105. ZwClose (AfdParametersNotifyHandle);
  1106. AfdParametersNotifyHandle = NULL;
  1107. }
  1108. }
  1109. else {
  1110. ASSERT (AfdParametersUnloadEvent!=NULL);
  1111. IoQueueWorkItem (AfdWorkQueueItem,
  1112. AfdReleaseRegistryHandleWait,
  1113. DelayedWorkQueue,
  1114. NULL);
  1115. }
  1116. ExReleaseResourceLite( AfdResource );
  1117. }
  1118. VOID
  1119. AfdReleaseRegistryHandleWait (
  1120. IN PDEVICE_OBJECT DeviceObject,
  1121. IN PVOID Context
  1122. )
  1123. {
  1124. ASSERT (AfdParametersUnloadEvent!=NULL);
  1125. KeSetEvent (AfdParametersUnloadEvent, AfdPriorityBoost, FALSE);
  1126. }