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.

1074 lines
23 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. tcpip\ip\mcastini.c
  5. Abstract:
  6. Initialization for IP Multicasting
  7. Author:
  8. Amritansh Raghav
  9. Revision History:
  10. AmritanR Created
  11. Notes:
  12. --*/
  13. #include "precomp.h"
  14. #if IPMCAST
  15. #define __FILE_SIG__ INI_SIG
  16. #include "ipmcast.h"
  17. #include "ipmcstxt.h"
  18. #include "mcastioc.h"
  19. #include "mcastmfe.h"
  20. //
  21. // Storage for extern declarations
  22. //
  23. //#pragma data_seg("PAGE")
  24. LIST_ENTRY g_lePendingNotification;
  25. LIST_ENTRY g_lePendingIrpQueue;
  26. GROUP_ENTRY g_rgGroupTable[GROUP_TABLE_SIZE];
  27. NPAGED_LOOKASIDE_LIST g_llGroupBlocks;
  28. NPAGED_LOOKASIDE_LIST g_llSourceBlocks;
  29. NPAGED_LOOKASIDE_LIST g_llOifBlocks;
  30. NPAGED_LOOKASIDE_LIST g_llMsgBlocks;
  31. PVOID g_pvCodeSectionHandle, g_pvDataSectionHandle;
  32. KTIMER g_ktTimer;
  33. KDPC g_kdTimerDpc;
  34. DWORD g_ulNextHashIndex;
  35. DWORD g_dwMcastState;
  36. DWORD g_dwNumThreads;
  37. LONG g_lNumOpens;
  38. KEVENT g_keStateEvent;
  39. FAST_MUTEX g_StartStopMutex;
  40. RT_LOCK g_rlStateLock;
  41. //#pragma data_seg()
  42. //
  43. // Forward declarations of functions
  44. //
  45. BOOLEAN
  46. SetupExternalName(
  47. PUNICODE_STRING pusNtName,
  48. BOOLEAN bCreate
  49. );
  50. NTSTATUS
  51. InitializeMcastData(
  52. VOID
  53. );
  54. NTSTATUS
  55. InitializeIpMcast(
  56. IN PDRIVER_OBJECT DriverObject,
  57. IN PUNICODE_STRING RegistryPath,
  58. OUT PDEVICE_OBJECT * ppIpMcastDevice
  59. );
  60. NTSTATUS
  61. IpMcastDispatch(
  62. IN PDEVICE_OBJECT DeviceObject,
  63. IN PIRP Irp
  64. );
  65. NTSTATUS
  66. StartDriver(
  67. VOID
  68. );
  69. NTSTATUS
  70. StopDriver(
  71. VOID
  72. );
  73. VOID
  74. McastTimerRoutine(
  75. PKDPC Dpc,
  76. PVOID DeferredContext,
  77. PVOID SystemArgument1,
  78. PVOID SystemArgument2
  79. );
  80. NTSTATUS
  81. OpenRegKeyEx(
  82. OUT PHANDLE phHandle,
  83. IN PUNICODE_STRING pusKeyName
  84. );
  85. NTSTATUS
  86. GetRegDWORDValue(
  87. HANDLE KeyHandle,
  88. PWCHAR ValueName,
  89. PULONG ValueData
  90. );
  91. BOOLEAN
  92. EnterDriverCode(
  93. IN DWORD dwIoCode
  94. );
  95. VOID
  96. ExitDriverCode(
  97. IN DWORD dwIoCode
  98. );
  99. //////////////////////////////////////////////////////////////////////////////
  100. // //
  101. // Routines //
  102. // //
  103. //////////////////////////////////////////////////////////////////////////////
  104. //
  105. // The code is only called on initialization
  106. //
  107. #pragma alloc_text(INIT, InitializeIpMcast)
  108. NTSTATUS
  109. InitializeIpMcast(
  110. IN PDRIVER_OBJECT DriverObject,
  111. IN PUNICODE_STRING RegistryPath,
  112. OUT PDEVICE_OBJECT * ppIpMcastDevice
  113. )
  114. /*++
  115. Routine Description:
  116. Reads the registry value for multicast forwarding. If enabled,
  117. creates the IPMcast device object. Does other MCast specific
  118. initialization
  119. Locks:
  120. Arguments:
  121. pIpMcastDevice Pointer to created device
  122. Return Value:
  123. STATUS_SUCCESS or an error status
  124. --*/
  125. {
  126. UNICODE_STRING usDeviceName, usParamString, usTempString;
  127. NTSTATUS nStatus;
  128. HANDLE hRegKey;
  129. DWORD dwMcastEnable, dwVal;
  130. USHORT usRegLen;
  131. PWCHAR pwcBuffer;
  132. RtInitializeDebug();
  133. usRegLen = RegistryPath->Length +
  134. (sizeof(WCHAR) * (wcslen(L"\\Parameters") + 2));
  135. //
  136. // use a random tag
  137. //
  138. pwcBuffer = ExAllocatePoolWithTag(NonPagedPool,
  139. usRegLen,
  140. MSG_TAG);
  141. if(pwcBuffer is NULL)
  142. {
  143. return STATUS_INSUFFICIENT_RESOURCES;
  144. }
  145. RtlZeroMemory(pwcBuffer,
  146. usRegLen);
  147. usParamString.MaximumLength = usRegLen;
  148. usParamString.Buffer = pwcBuffer;
  149. RtlCopyUnicodeString(&usParamString,
  150. RegistryPath);
  151. RtlInitUnicodeString(&usTempString,
  152. L"\\Parameters");
  153. RtlAppendUnicodeStringToString(&usParamString,
  154. &usTempString);
  155. nStatus = OpenRegKeyEx(&hRegKey,
  156. &usParamString);
  157. ExFreePool(pwcBuffer);
  158. if(nStatus is STATUS_SUCCESS)
  159. {
  160. #if RT_TRACE_DEBUG
  161. nStatus = GetRegDWORDValue(hRegKey,
  162. L"DebugLevel",
  163. &dwVal);
  164. if(nStatus is STATUS_SUCCESS)
  165. {
  166. g_byDebugLevel = (BYTE) dwVal;
  167. }
  168. nStatus = GetRegDWORDValue(hRegKey,
  169. L"DebugComp",
  170. &dwVal);
  171. if(nStatus is STATUS_SUCCESS)
  172. {
  173. g_fDebugComp = dwVal;
  174. }
  175. #endif
  176. #if DBG
  177. nStatus = GetRegDWORDValue(hRegKey,
  178. L"DebugBreak",
  179. &dwVal);
  180. if((nStatus is STATUS_SUCCESS) and
  181. (dwVal is 1))
  182. {
  183. DbgBreakPoint();
  184. }
  185. #endif
  186. ZwClose(hRegKey);
  187. }
  188. TraceEnter(GLOBAL, "InitializeIpMcast");
  189. //
  190. // Read the value for multicast forwarding
  191. //
  192. //
  193. // The g_dwMcastStart controls whether any forwarding actually happens
  194. // It gets set to 1 one an NtCreateFile is done on the Multicast Device.
  195. // It gets reset when the handle is closed
  196. //
  197. g_dwMcastState = MCAST_STOPPED;
  198. g_dwNumThreads = 0;
  199. g_lNumOpens = 0;
  200. //
  201. // Handles to code and data sections
  202. //
  203. g_pvCodeSectionHandle = NULL;
  204. g_pvDataSectionHandle = NULL;
  205. //
  206. // Used for the timer routine. Tells the DPC which index to start in in the
  207. // group hash table
  208. //
  209. g_ulNextHashIndex = 0;
  210. //
  211. // Create the device
  212. //
  213. RtlInitUnicodeString(&usDeviceName,
  214. DD_IPMCAST_DEVICE_NAME);
  215. nStatus = IoCreateDevice(DriverObject,
  216. 0,
  217. &usDeviceName,
  218. FILE_DEVICE_NETWORK,
  219. FILE_DEVICE_SECURE_OPEN,
  220. FALSE,
  221. ppIpMcastDevice);
  222. if(!NT_SUCCESS(nStatus))
  223. {
  224. Trace(GLOBAL, ERROR,
  225. ("InitializeIpMcast: IP initialization failed: Unable to create device object %ws, status %lx.\n",
  226. DD_IPMCAST_DEVICE_NAME,
  227. nStatus));
  228. TraceLeave(GLOBAL, "InitializeIpMcast");
  229. return nStatus;
  230. }
  231. //
  232. // Create a symbolic link in Dos Space
  233. //
  234. if(!SetupExternalName(&usDeviceName, TRUE))
  235. {
  236. Trace(GLOBAL, ERROR,
  237. ("InitializeIpMcast: Win32 device name could not be created\n"));
  238. IoDeleteDevice(*ppIpMcastDevice);
  239. TraceLeave(GLOBAL, "InitializeIpMcast");
  240. return STATUS_UNSUCCESSFUL;
  241. }
  242. RtInitializeSpinLock(&g_rlStateLock);
  243. KeInitializeEvent(&(g_keStateEvent),
  244. SynchronizationEvent,
  245. FALSE);
  246. ExInitializeFastMutex(&g_StartStopMutex);
  247. return STATUS_SUCCESS;
  248. }
  249. VOID
  250. DeinitializeIpMcast(
  251. IN PDEVICE_OBJECT DeviceObject
  252. )
  253. {
  254. StopDriver();
  255. IoDeleteDevice(DeviceObject);
  256. }
  257. #pragma alloc_text(PAGE, SetupExternalName)
  258. BOOLEAN
  259. SetupExternalName(
  260. PUNICODE_STRING pusNtName,
  261. BOOLEAN bCreate
  262. )
  263. {
  264. UNICODE_STRING usSymbolicLinkName;
  265. WCHAR rgwcBuffer[100];
  266. PAGED_CODE();
  267. //
  268. // Form the full symbolic link name we wish to create.
  269. //
  270. usSymbolicLinkName.Buffer = rgwcBuffer;
  271. RtlInitUnicodeString(&usSymbolicLinkName,
  272. WIN32_IPMCAST_SYMBOLIC_LINK);
  273. if(bCreate)
  274. {
  275. if(!NT_SUCCESS(IoCreateSymbolicLink(&usSymbolicLinkName,
  276. pusNtName)))
  277. {
  278. return FALSE;
  279. }
  280. }
  281. else
  282. {
  283. IoDeleteSymbolicLink(&usSymbolicLinkName);
  284. }
  285. return TRUE;
  286. }
  287. #pragma alloc_text(PAGE, InitializeMcastData)
  288. NTSTATUS
  289. InitializeMcastData(
  290. VOID
  291. )
  292. {
  293. LARGE_INTEGER liDueTime;
  294. ULONG ulCnt;
  295. NTSTATUS nStatus;
  296. if(g_pvCodeSectionHandle)
  297. {
  298. MmLockPagableSectionByHandle(g_pvCodeSectionHandle);
  299. }else
  300. {
  301. g_pvCodeSectionHandle = MmLockPagableCodeSection(McastTimerRoutine);
  302. if(g_pvCodeSectionHandle is NULL)
  303. {
  304. RtAssert(FALSE);
  305. }
  306. }
  307. for(ulCnt = 0; ulCnt < GROUP_TABLE_SIZE; ulCnt++)
  308. {
  309. InitializeListHead(&(g_rgGroupTable[ulCnt].leHashHead));
  310. InitRwLock(&(g_rgGroupTable[ulCnt].rwlLock));
  311. #if DBG
  312. g_rgGroupTable[ulCnt].ulGroupCount = 0;
  313. g_rgGroupTable[ulCnt].ulCacheHits = 0;
  314. g_rgGroupTable[ulCnt].ulCacheMisses = 0;
  315. #endif
  316. g_rgGroupTable[ulCnt].pGroup = NULL;
  317. }
  318. InitializeListHead(&g_lePendingNotification);
  319. InitializeListHead(&g_lePendingIrpQueue);
  320. ExInitializeNPagedLookasideList(&g_llGroupBlocks,
  321. NULL,
  322. NULL,
  323. 0,
  324. sizeof(GROUP),
  325. GROUP_TAG,
  326. GROUP_LOOKASIDE_DEPTH);
  327. ExInitializeNPagedLookasideList(&g_llSourceBlocks,
  328. NULL,
  329. NULL,
  330. 0,
  331. sizeof(SOURCE),
  332. SOURCE_TAG,
  333. SOURCE_LOOKASIDE_DEPTH);
  334. ExInitializeNPagedLookasideList(&g_llOifBlocks,
  335. NULL,
  336. NULL,
  337. 0,
  338. sizeof(OUT_IF),
  339. OIF_TAG,
  340. OIF_LOOKASIDE_DEPTH);
  341. ExInitializeNPagedLookasideList(&g_llMsgBlocks,
  342. NULL,
  343. NULL,
  344. 0,
  345. sizeof(NOTIFICATION_MSG),
  346. MSG_TAG,
  347. MSG_LOOKASIDE_DEPTH);
  348. KeInitializeDpc(&g_kdTimerDpc,
  349. McastTimerRoutine,
  350. NULL);
  351. KeInitializeTimer(&g_ktTimer);
  352. liDueTime = RtlEnlargedUnsignedMultiply(TIMER_IN_MILLISECS,
  353. SYS_UNITS_IN_ONE_MILLISEC);
  354. liDueTime = RtlLargeIntegerNegate(liDueTime);
  355. KeSetTimerEx(&g_ktTimer,
  356. liDueTime,
  357. 0,
  358. &g_kdTimerDpc);
  359. return STATUS_SUCCESS;
  360. }
  361. #pragma alloc_text(PAGE, IpMcastDispatch)
  362. NTSTATUS
  363. IpMcastDispatch(
  364. IN PDEVICE_OBJECT DeviceObject,
  365. IN PIRP Irp
  366. )
  367. /*++
  368. Routine Description:
  369. The functions which handles the IRPs sent to the driver
  370. The IOCTLS are further dispatched using a function table
  371. THIS CODE IS PAGEABLE so it CAN NOT ACQUIRE ANY LOCKS
  372. Locks:
  373. Must be at passive
  374. Arguments:
  375. Return Value:
  376. NO_ERROR
  377. --*/
  378. {
  379. PIO_STACK_LOCATION irpStack;
  380. ULONG ulInputBuffLen;
  381. ULONG ulOutputBuffLen;
  382. ULONG ioControlCode;
  383. NTSTATUS ntStatus;
  384. KIRQL kiIrql;
  385. BOOLEAN bEnter;
  386. UNREFERENCED_PARAMETER(DeviceObject);
  387. PAGED_CODE();
  388. TraceEnter(GLOBAL, "IpMcastDispatch");
  389. Irp->IoStatus.Information = 0;
  390. //
  391. // Get a pointer to the current location in the Irp. This is where
  392. // the function codes and parameters are located.
  393. //
  394. irpStack = IoGetCurrentIrpStackLocation(Irp);
  395. //
  396. // Get the pointer to the input/output buffer and it's length
  397. //
  398. ulInputBuffLen = irpStack->Parameters.DeviceIoControl.InputBufferLength;
  399. ulOutputBuffLen = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
  400. switch (irpStack->MajorFunction)
  401. {
  402. case IRP_MJ_CREATE:
  403. {
  404. Trace(GLOBAL, TRACE,
  405. ("IpMcastDispatch: IRP_MJ_CREATE\n"));
  406. //
  407. // Make sure that the user is not attempting to sneak around the
  408. // security checks. Make sure that FileObject->RelatedFileObject is
  409. // NULL and that the FileName length is zero!
  410. //
  411. if((irpStack->FileObject->RelatedFileObject isnot NULL) or
  412. (irpStack->FileObject->FileName.Length isnot 0))
  413. {
  414. ntStatus = STATUS_ACCESS_DENIED;
  415. break;
  416. }
  417. InterlockedIncrement(&g_lNumOpens);
  418. ntStatus = STATUS_SUCCESS;
  419. break;
  420. }
  421. case IRP_MJ_CLOSE:
  422. {
  423. Trace(GLOBAL, TRACE,
  424. ("IpMcastDispatch: IRP_MJ_CLOSE\n"));
  425. ntStatus = STATUS_SUCCESS;
  426. break;
  427. }
  428. case IRP_MJ_CLEANUP:
  429. {
  430. Trace(GLOBAL, TRACE,
  431. ("IpMcastDispatch: IRP_MJ_CLEANUP\n"));
  432. if((InterlockedDecrement(&g_lNumOpens) is 0) and
  433. (g_dwMcastState isnot MCAST_STOPPED))
  434. {
  435. StopDriver();
  436. }
  437. ntStatus = STATUS_SUCCESS;
  438. break;
  439. }
  440. case IRP_MJ_DEVICE_CONTROL:
  441. {
  442. DWORD dwState;
  443. ULONG ulControl;
  444. //
  445. // The assumption is that IOCTL_IPMCAST_START_STOP will be
  446. // serialized wrt to 2 calls, i.e we wont get a stop when a start
  447. // is in progress and we will not get a start when a stop has been
  448. // issued. No assumption is made about IOCTL_IPMCAST_START_STOP's
  449. // serialization with other IRPS.
  450. // So when we are in this code we assume that we wont get
  451. // a close beneath us
  452. //
  453. ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
  454. ulControl = IoGetFunctionCodeFromCtlCode(ioControlCode);
  455. bEnter = EnterDriverCode(ioControlCode);
  456. if(!bEnter)
  457. {
  458. // keep devioctl testers happy
  459. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,
  460. "IpMcastDispatch: Driver is not started\n"));
  461. ntStatus = STATUS_NO_SUCH_DEVICE;
  462. break;
  463. }
  464. switch (ioControlCode)
  465. {
  466. case IOCTL_IPMCAST_SET_MFE:
  467. {
  468. ntStatus = SetMfe(Irp,
  469. ulInputBuffLen,
  470. ulOutputBuffLen);
  471. break;
  472. }
  473. case IOCTL_IPMCAST_GET_MFE:
  474. {
  475. ntStatus = GetMfe(Irp,
  476. ulInputBuffLen,
  477. ulOutputBuffLen);
  478. break;
  479. }
  480. case IOCTL_IPMCAST_DELETE_MFE:
  481. {
  482. ntStatus = DeleteMfe(Irp,
  483. ulInputBuffLen,
  484. ulOutputBuffLen);
  485. break;
  486. }
  487. case IOCTL_IPMCAST_SET_TTL:
  488. {
  489. ntStatus = SetTtl(Irp,
  490. ulInputBuffLen,
  491. ulOutputBuffLen);
  492. break;
  493. }
  494. case IOCTL_IPMCAST_GET_TTL:
  495. {
  496. ntStatus = GetTtl(Irp,
  497. ulInputBuffLen,
  498. ulOutputBuffLen);
  499. break;
  500. }
  501. case IOCTL_IPMCAST_POST_NOTIFICATION:
  502. {
  503. ntStatus = ProcessNotification(Irp,
  504. ulInputBuffLen,
  505. ulOutputBuffLen);
  506. break;
  507. }
  508. case IOCTL_IPMCAST_START_STOP:
  509. {
  510. ntStatus = StartStopDriver(Irp,
  511. ulInputBuffLen,
  512. ulOutputBuffLen);
  513. break;
  514. }
  515. case IOCTL_IPMCAST_SET_IF_STATE:
  516. {
  517. ntStatus = SetIfState(Irp,
  518. ulInputBuffLen,
  519. ulOutputBuffLen);
  520. break;
  521. }
  522. default:
  523. {
  524. // Keep devioctl testers happy
  525. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,
  526. "IpMcastDispatch: unknown IRP_MJ_DEVICE_CONTROL - 0x%X which evaluates to a code of %d\n",
  527. ioControlCode, ulControl));
  528. ntStatus = STATUS_INVALID_PARAMETER;
  529. break;
  530. }
  531. }
  532. ExitDriverCode(ioControlCode);
  533. break;
  534. }
  535. default:
  536. {
  537. Trace(GLOBAL, ERROR,
  538. ("IpMcastDispatch: unknown IRP_MJ_XX - %x\n",
  539. irpStack->MajorFunction));
  540. ntStatus = STATUS_INVALID_PARAMETER;
  541. break;
  542. }
  543. }
  544. //
  545. // Fill in status into IRP
  546. //
  547. //
  548. // This bit commented out because we cant touch the irp since it
  549. // may have been completed
  550. //
  551. // Trace(GLOBAL, INFO,
  552. // ("IpMcastDispatch: Returning status %x info %d\n",
  553. // ntStatus, Irp->IoStatus.Information));
  554. if(ntStatus isnot STATUS_PENDING)
  555. {
  556. Irp->IoStatus.Status = ntStatus;
  557. IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
  558. }
  559. TraceLeave(GLOBAL, "IpMcastDispatch");
  560. return ntStatus;
  561. }
  562. NTSTATUS
  563. StartDriver(
  564. VOID
  565. )
  566. {
  567. KIRQL irql;
  568. TraceEnter(GLOBAL, "StartDriver");
  569. RtAcquireSpinLock(&g_rlStateLock,
  570. &irql);
  571. if(g_dwMcastState is MCAST_STARTED)
  572. {
  573. RtReleaseSpinLock(&g_rlStateLock,
  574. irql);
  575. return STATUS_SUCCESS;
  576. }
  577. RtReleaseSpinLock(&g_rlStateLock,
  578. irql);
  579. InitializeMcastData();
  580. g_dwMcastState = MCAST_STARTED;
  581. TraceLeave(GLOBAL, "StartDriver");
  582. return STATUS_SUCCESS;
  583. }
  584. //
  585. // MUST BE PAGED IN
  586. //
  587. #pragma alloc_text(PAGEIPMc, StopDriver)
  588. NTSTATUS
  589. StopDriver(
  590. VOID
  591. )
  592. {
  593. DWORD i;
  594. KIRQL irql;
  595. PLIST_ENTRY pleGrpNode, pleSrcNode;
  596. PGROUP pGroup;
  597. PSOURCE pSource;
  598. BOOLEAN bWait;
  599. NTSTATUS nStatus;
  600. TraceEnter(GLOBAL, "StopDriver");
  601. //
  602. // Set the state to STOPPING
  603. //
  604. RtAcquireSpinLock(&g_rlStateLock,
  605. &irql);
  606. if(g_dwMcastState isnot MCAST_STARTED)
  607. {
  608. Trace(GLOBAL, ERROR,
  609. ("StopDriver: Called when state is %d\n", g_dwMcastState));
  610. // RtAssert(FALSE);
  611. RtReleaseSpinLock(&g_rlStateLock,
  612. irql);
  613. TraceLeave(GLOBAL, "StopDriver");
  614. return STATUS_SUCCESS;
  615. }
  616. else
  617. {
  618. g_dwMcastState = MCAST_STOPPED;
  619. }
  620. RtReleaseSpinLock(&g_rlStateLock,
  621. irql);
  622. //
  623. // First of all, kill the timer
  624. //
  625. i = 0;
  626. while(KeCancelTimer(&g_ktTimer) is FALSE)
  627. {
  628. LARGE_INTEGER liTimeOut;
  629. //
  630. // Hmm, timer was not in the system queue.
  631. // Set the wait to 2, 4, 6... secs
  632. //
  633. liTimeOut.QuadPart = (LONGLONG) ((i + 1) * 2 * 1000 * 1000 * 10 * -1);
  634. KeDelayExecutionThread(UserMode,
  635. FALSE,
  636. &liTimeOut);
  637. i++;
  638. }
  639. //
  640. // Delete all the (S,G) entries
  641. //
  642. for(i = 0; i < GROUP_TABLE_SIZE; i++)
  643. {
  644. //
  645. // Lock out the bucket
  646. //
  647. EnterWriter(&g_rgGroupTable[i].rwlLock,
  648. &irql);
  649. pleGrpNode = g_rgGroupTable[i].leHashHead.Flink;
  650. while(pleGrpNode isnot & (g_rgGroupTable[i].leHashHead))
  651. {
  652. pGroup = CONTAINING_RECORD(pleGrpNode, GROUP, leHashLink);
  653. pleGrpNode = pleGrpNode->Flink;
  654. pleSrcNode = pGroup->leSrcHead.Flink;
  655. while(pleSrcNode isnot & pGroup->leSrcHead)
  656. {
  657. pSource = CONTAINING_RECORD(pleSrcNode, SOURCE, leGroupLink);
  658. pleSrcNode = pleSrcNode->Flink;
  659. //
  660. // Ref and lock the source, since we need to pass it that
  661. // way to RemoveSource
  662. //
  663. ReferenceSource(pSource);
  664. RtAcquireSpinLockAtDpcLevel(&(pSource->mlLock));
  665. RemoveSource(pGroup->dwGroup,
  666. pSource->dwSource,
  667. pSource->dwSrcMask,
  668. pGroup,
  669. pSource);
  670. }
  671. }
  672. ExitWriter(&g_rgGroupTable[i].rwlLock,
  673. irql);
  674. }
  675. //
  676. // Complete any pendying IRP
  677. //
  678. ClearPendingIrps();
  679. //
  680. // Free any pending messages
  681. //
  682. ClearPendingNotifications();
  683. //
  684. // Wait for everyone to leave the code
  685. //
  686. RtAcquireSpinLock(&g_rlStateLock,
  687. &irql);
  688. //
  689. // Need to wait if the number of threads isnot 0
  690. //
  691. bWait = (g_dwNumThreads isnot 0);
  692. RtReleaseSpinLock(&g_rlStateLock,
  693. irql);
  694. if(bWait)
  695. {
  696. nStatus = KeWaitForSingleObject(&g_keStateEvent,
  697. Executive,
  698. KernelMode,
  699. FALSE,
  700. NULL);
  701. RtAssert(nStatus is STATUS_SUCCESS);
  702. }
  703. //
  704. // Clear out the last of the data structures
  705. //
  706. ExDeleteNPagedLookasideList(&g_llGroupBlocks);
  707. ExDeleteNPagedLookasideList(&g_llSourceBlocks);
  708. ExDeleteNPagedLookasideList(&g_llOifBlocks);
  709. ExDeleteNPagedLookasideList(&g_llMsgBlocks);
  710. //
  711. // Page out the code and data
  712. //
  713. MmUnlockPagableImageSection(g_pvCodeSectionHandle);
  714. g_pvCodeSectionHandle = NULL;
  715. //MmUnlockPagableImageSection(g_pvDataSectionHandle);
  716. g_pvDataSectionHandle = NULL;
  717. TraceLeave(GLOBAL, "StopDriver");
  718. return STATUS_SUCCESS;
  719. }
  720. BOOLEAN
  721. EnterDriverCode(
  722. DWORD dwIoCode
  723. )
  724. {
  725. KIRQL irql;
  726. BOOLEAN bEnter;
  727. RtAcquireSpinLock(&g_rlStateLock,
  728. &irql);
  729. if((g_dwMcastState is MCAST_STARTED) or
  730. (dwIoCode is IOCTL_IPMCAST_START_STOP))
  731. {
  732. g_dwNumThreads++;
  733. bEnter = TRUE;
  734. }
  735. else
  736. {
  737. bEnter = FALSE;
  738. }
  739. RtReleaseSpinLock(&g_rlStateLock,
  740. irql);
  741. if(dwIoCode is IOCTL_IPMCAST_START_STOP)
  742. {
  743. ExAcquireFastMutex(&g_StartStopMutex);
  744. }
  745. return bEnter;
  746. }
  747. VOID
  748. ExitDriverCode(
  749. DWORD dwIoCode
  750. )
  751. {
  752. KIRQL irql;
  753. RtAcquireSpinLock(&g_rlStateLock,
  754. &irql);
  755. g_dwNumThreads--;
  756. if((g_dwMcastState is MCAST_STOPPED) and
  757. (g_dwNumThreads is 0))
  758. {
  759. KeSetEvent(&g_keStateEvent,
  760. 0,
  761. FALSE);
  762. }
  763. RtReleaseSpinLock(&g_rlStateLock,
  764. irql);
  765. if(dwIoCode is IOCTL_IPMCAST_START_STOP)
  766. {
  767. ExReleaseFastMutex(&g_StartStopMutex);
  768. }
  769. }
  770. #pragma alloc_text(PAGE, OpenRegKeyEx)
  771. NTSTATUS
  772. OpenRegKeyEx(
  773. OUT PHANDLE phHandle,
  774. IN PUNICODE_STRING pusKeyName
  775. )
  776. {
  777. NTSTATUS Status;
  778. OBJECT_ATTRIBUTES ObjectAttributes;
  779. PAGED_CODE();
  780. RtlZeroMemory(&ObjectAttributes,
  781. sizeof(OBJECT_ATTRIBUTES));
  782. InitializeObjectAttributes(&ObjectAttributes,
  783. pusKeyName,
  784. OBJ_CASE_INSENSITIVE,
  785. NULL,
  786. NULL);
  787. Status = ZwOpenKey(phHandle,
  788. KEY_READ,
  789. &ObjectAttributes);
  790. return Status;
  791. }
  792. #endif // IPMCAST