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.

1363 lines
29 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. net\ip\ipinip\driver.c
  5. Abstract:
  6. IP in IP driver shell
  7. Revision History:
  8. Gurdeep Singh Pall 8/2/95 Created
  9. --*/
  10. #define __FILE_SIG__ DRIVER_SIG
  11. #include "inc.h"
  12. #pragma alloc_text(INIT, DriverEntry)
  13. NTSTATUS
  14. DriverEntry(
  15. IN PDRIVER_OBJECT DriverObject,
  16. IN PUNICODE_STRING RegistryPath
  17. )
  18. /*++
  19. Routine Description
  20. Installable driver initialization entry point.
  21. This entry point is called directly by the I/O system and must be named
  22. "Driver Entry"
  23. The function is discardable since it is only called once
  24. On checked builds we read some values from registry and initialize the
  25. debugging
  26. We create a DEVICE_OBJECT for ourselves to field the IOCTLs, create
  27. a DOS name for the device and initialize some events and spinlocks
  28. Locks
  29. None
  30. Arguments
  31. DriverObject Pointer to I/O subsystem created driver object
  32. RegistryPath Points to driver key in HKLM\CCS\Services...
  33. Return Value
  34. STATUS_SUCCESS if everything went as planned or some status code from
  35. ntstatus.h
  36. --*/
  37. {
  38. NTSTATUS nStatus;
  39. PDEVICE_OBJECT pDeviceObject;
  40. UNICODE_STRING usDeviceName;
  41. DWORD dwVal, i;
  42. HANDLE hRegKey;
  43. WCHAR ParametersRegistryPath[] =
  44. L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\IpInIp\\Parameters";
  45. RtInitializeDebug();
  46. //
  47. // Read the registry for parameters
  48. //
  49. nStatus = OpenRegKey(&hRegKey,
  50. ParametersRegistryPath);
  51. if(nStatus is STATUS_SUCCESS)
  52. {
  53. #if RT_TRACE_DEBUG
  54. nStatus = GetRegDWORDValue(hRegKey,
  55. L"DebugLevel",
  56. &dwVal);
  57. if(nStatus is STATUS_SUCCESS)
  58. {
  59. g_byDebugLevel = (BYTE)dwVal;
  60. }
  61. nStatus = GetRegDWORDValue(hRegKey,
  62. L"DebugComp",
  63. &dwVal);
  64. if(nStatus is STATUS_SUCCESS)
  65. {
  66. g_fDebugComp = dwVal;
  67. }
  68. #endif
  69. #if DBG
  70. nStatus = GetRegDWORDValue(hRegKey,
  71. L"DebugBreak",
  72. &dwVal);
  73. if((nStatus is STATUS_SUCCESS) and
  74. (dwVal is 1))
  75. {
  76. DbgBreakPoint();
  77. }
  78. #endif
  79. ZwClose(hRegKey);
  80. }
  81. TraceEnter(GLOBAL, "DriverEntry");
  82. //
  83. // Initialize some globals
  84. //
  85. g_dwDriverState = DRIVER_STOPPED;
  86. g_ulNumThreads = 0;
  87. g_ulNumOpens = 0;
  88. g_hIpRegistration = NULL;
  89. //
  90. // Create the device
  91. //
  92. RtlInitUnicodeString(&usDeviceName,
  93. DD_IPINIP_DEVICE_NAME);
  94. nStatus = IoCreateDevice(DriverObject,
  95. 0,
  96. &usDeviceName,
  97. FILE_DEVICE_NETWORK,
  98. FILE_DEVICE_SECURE_OPEN,
  99. FALSE,
  100. &pDeviceObject);
  101. if (!NT_SUCCESS(nStatus))
  102. {
  103. Trace(GLOBAL, ERROR,
  104. ("DriverEntry: Cant create device object %ws, status %lx.\n",
  105. DD_IPINIP_DEVICE_NAME,
  106. nStatus));
  107. TraceLeave(GLOBAL, "DriverEntry");
  108. return nStatus;
  109. }
  110. //
  111. // Initialize the driver object
  112. //
  113. DriverObject->DriverUnload = IpIpUnload;
  114. DriverObject->FastIoDispatch = NULL;
  115. for(i=0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
  116. {
  117. DriverObject->MajorFunction[i] = IpIpDispatch;
  118. }
  119. if(!SetupExternalName(&usDeviceName,
  120. WIN32_IPINIP_SYMBOLIC_LINK,
  121. TRUE))
  122. {
  123. Trace(GLOBAL,ERROR,
  124. ("DriverEntry: Win32 device name could not be created\n"));
  125. IoDeleteDevice(pDeviceObject);
  126. TraceLeave(GLOBAL, "DriverEntry");
  127. return STATUS_UNSUCCESSFUL;
  128. }
  129. //
  130. // Lock and event needed to keep track of threads in the driver
  131. //
  132. RtInitializeSpinLock(&g_rlStateLock);
  133. KeInitializeEvent(&(g_keStateEvent),
  134. SynchronizationEvent,
  135. FALSE);
  136. //
  137. // Many threads may be waiting for us to start so this needs to be a
  138. // NotificationEvent
  139. //
  140. KeInitializeEvent(&(g_keStartEvent),
  141. NotificationEvent,
  142. FALSE);
  143. InitRwLock(&g_rwlTunnelLock);
  144. InitializeListHead(&g_leTunnelList);
  145. InitializeListHead(&g_lePendingMessageList);
  146. InitializeListHead(&g_lePendingIrpList);
  147. //
  148. // Register with IP
  149. //
  150. nStatus = RegisterWithIp();
  151. if(nStatus isnot STATUS_SUCCESS)
  152. {
  153. Trace(GLOBAL, ERROR,
  154. ("DriverEntry: RegisterWithIP failed\n"));
  155. IoDeleteDevice(pDeviceObject);
  156. TraceLeave(GLOBAL, "InitializeDriver");
  157. return FALSE;
  158. }
  159. g_pIpIpDevice = pDeviceObject;
  160. TraceLeave(GLOBAL, "DriverEntry");
  161. return nStatus;
  162. }
  163. #pragma alloc_text(PAGE, IpIpDispatch)
  164. NTSTATUS
  165. IpIpDispatch(
  166. IN PDEVICE_OBJECT DeviceObject,
  167. IN PIRP Irp
  168. )
  169. /*++
  170. Routine Description
  171. The functions which handles the IRPs sent to the driver
  172. Locks
  173. This code is PAGEABLE so can not acquire locks
  174. Arguments
  175. Return Value
  176. STATUS_SUCCESS
  177. --*/
  178. {
  179. PIO_STACK_LOCATION irpStack;
  180. ULONG ulInputBuffLen;
  181. ULONG ulOutputBuffLen;
  182. ULONG ioControlCode;
  183. NTSTATUS nStatus;
  184. KIRQL kiIrql;
  185. LARGE_INTEGER liTimeOut;
  186. BOOLEAN bEnter;
  187. PAGED_CODE();
  188. TraceEnter(GLOBAL, "IpIpDispatch");
  189. Irp->IoStatus.Information = 0;
  190. //
  191. // Get a pointer to the current location in the Irp. This is where
  192. // the function codes and parameters are located.
  193. //
  194. irpStack = IoGetCurrentIrpStackLocation(Irp);
  195. //
  196. // Get the pointer to the input/output buffer and it's length
  197. //
  198. ulInputBuffLen = irpStack->Parameters.DeviceIoControl.InputBufferLength;
  199. ulOutputBuffLen = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
  200. switch (irpStack->MajorFunction)
  201. {
  202. case IRP_MJ_CREATE:
  203. {
  204. Trace(GLOBAL, TRACE,
  205. ("IpIpDispatch: IRP_MJ_CREATE\n"));
  206. //
  207. // We start the driver when the first CreateFile is done
  208. // But we need to serialize the Creates
  209. //
  210. nStatus = StartDriver();
  211. if(nStatus is STATUS_PENDING)
  212. {
  213. //
  214. // Means someone is trying to start the driver
  215. // We wait for some time (since we are at PASSIVE)
  216. //
  217. liTimeOut.QuadPart = START_TIMEOUT;
  218. nStatus = KeWaitForSingleObject(&g_keStartEvent,
  219. UserRequest,
  220. KernelMode,
  221. FALSE,
  222. &liTimeOut);
  223. if(nStatus isnot STATUS_SUCCESS)
  224. {
  225. //
  226. // We timed out - bad things are happening here
  227. //
  228. Trace(GLOBAL, ERROR,
  229. ("IpIpDispatch: Timeout trying to start driver\n"));
  230. nStatus = STATUS_UNSUCCESSFUL;
  231. }
  232. else
  233. {
  234. //
  235. // Make sure the driver actually started
  236. //
  237. bEnter = EnterDriverCode();
  238. ExitDriverCode();
  239. if(!bEnter)
  240. {
  241. Trace(GLOBAL, ERROR,
  242. ("IpIpDispatch: Wait successful, but unable to start driver\n"));
  243. nStatus = STATUS_UNSUCCESSFUL;
  244. }
  245. }
  246. }
  247. break;
  248. }
  249. case IRP_MJ_CLOSE:
  250. {
  251. Trace(GLOBAL, TRACE,
  252. ("IpIpDispatch: IRP_MJ_CLOSE\n"));
  253. //
  254. // We handle cleanup and not close
  255. //
  256. nStatus = STATUS_SUCCESS;
  257. break;
  258. }
  259. case IRP_MJ_CLEANUP:
  260. {
  261. Trace(GLOBAL, TRACE,
  262. ("IpIpDispatch: IRP_MJ_CLEANUP\n"));
  263. StopDriver();
  264. nStatus = STATUS_SUCCESS;
  265. break;
  266. }
  267. case IRP_MJ_DEVICE_CONTROL:
  268. {
  269. DWORD dwState;
  270. ULONG ulControl;
  271. //
  272. // Get the control code and our code
  273. //
  274. ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
  275. //
  276. // If the driver is stopping, dont process anything else
  277. //
  278. bEnter = EnterDriverCode();
  279. if(!bEnter)
  280. {
  281. Trace(GLOBAL, ERROR,
  282. ("IpIpDispatch: Driver is not started\n"));
  283. nStatus = STATUS_NO_SUCH_DEVICE;
  284. break;
  285. }
  286. switch(ioControlCode)
  287. {
  288. case IOCTL_IPINIP_CREATE_TUNNEL:
  289. {
  290. nStatus = AddTunnelInterface(Irp,
  291. ulInputBuffLen,
  292. ulOutputBuffLen);
  293. break;
  294. }
  295. case IOCTL_IPINIP_DELETE_TUNNEL:
  296. {
  297. nStatus = DeleteTunnelInterface(Irp,
  298. ulInputBuffLen,
  299. ulOutputBuffLen);
  300. break;
  301. }
  302. case IOCTL_IPINIP_SET_TUNNEL_INFO:
  303. {
  304. nStatus = SetTunnelInfo(Irp,
  305. ulInputBuffLen,
  306. ulOutputBuffLen);
  307. break;
  308. }
  309. case IOCTL_IPINIP_GET_TUNNEL_TABLE:
  310. {
  311. nStatus = GetTunnelTable(Irp,
  312. ulInputBuffLen,
  313. ulOutputBuffLen);
  314. break;
  315. }
  316. case IOCTL_IPINIP_NOTIFICATION:
  317. {
  318. nStatus = ProcessNotification(Irp,
  319. ulInputBuffLen,
  320. ulOutputBuffLen);
  321. break;
  322. }
  323. default:
  324. {
  325. Trace(GLOBAL, ERROR,
  326. ("IpIpDispatch: Unknown IRP_MJ_DEVICE_CONTROL %x\n",
  327. ioControlCode));
  328. nStatus = STATUS_INVALID_PARAMETER;
  329. }
  330. }
  331. ExitDriverCode();
  332. break;
  333. }
  334. default:
  335. {
  336. Trace(GLOBAL, ERROR,
  337. ("IpIpDispatch: Unknown IRP_MJ_XX - %x\n",
  338. irpStack->MajorFunction));
  339. nStatus = STATUS_INVALID_PARAMETER;
  340. break;
  341. }
  342. }
  343. if(nStatus isnot STATUS_PENDING)
  344. {
  345. Irp->IoStatus.Status = nStatus;
  346. IoCompleteRequest(Irp,
  347. IO_NETWORK_INCREMENT);
  348. }
  349. TraceLeave(GLOBAL, "IpIpDispatch");
  350. return nStatus;
  351. }
  352. VOID
  353. IpIpUnload(
  354. PDRIVER_OBJECT DriverObject
  355. )
  356. /*++
  357. Routine Description
  358. Called by the I/O subsystem, when our driver is being unloaded
  359. Locks
  360. Arguments
  361. Return Value
  362. None
  363. --*/
  364. {
  365. UNICODE_STRING usDeviceName;
  366. BOOLEAN bWait;
  367. KIRQL kiIrql;
  368. NDIS_STATUS nsStatus;
  369. NTSTATUS nStatus;
  370. TraceEnter(GLOBAL,"IpIpUnload");
  371. //
  372. // The driver must have stopped before it came here
  373. //
  374. RtAssert(g_dwDriverState is DRIVER_STOPPED);
  375. RemoveAllTunnels();
  376. //
  377. // Clear out IP's state
  378. //
  379. DeregisterWithIp();
  380. //
  381. // Remove ourself from NT and DOS namespace
  382. //
  383. RtlInitUnicodeString(&usDeviceName,
  384. DD_IPINIP_DEVICE_NAME);
  385. SetupExternalName(&usDeviceName,
  386. WIN32_IPINIP_SYMBOLIC_LINK,
  387. FALSE);
  388. //
  389. // Clean out address blocks, if any
  390. //
  391. while(!IsListEmpty(&g_leAddressList))
  392. {
  393. PADDRESS_BLOCK pAddrBlock;
  394. PLIST_ENTRY pleNode;
  395. pleNode = RemoveHeadList(&g_leAddressList);
  396. pAddrBlock = CONTAINING_RECORD(pleNode,
  397. ADDRESS_BLOCK,
  398. leAddressLink);
  399. RtFree(pAddrBlock);
  400. }
  401. //
  402. // See if we have any free memory
  403. //
  404. RtAuditMemory();
  405. //
  406. // Delete the device object
  407. //
  408. IoDeleteDevice(DriverObject->DeviceObject);
  409. TraceLeave(GLOBAL,"IpIpUnload");
  410. }
  411. #pragma alloc_text(PAGE, SetupExternalName)
  412. BOOLEAN
  413. SetupExternalName(
  414. PUNICODE_STRING pusNtName,
  415. PWCHAR pwcDosName,
  416. BOOLEAN bCreate
  417. )
  418. /*++
  419. Routine Description
  420. Setup or delete a symbolic link to DOS namespace
  421. Locks
  422. Arguments
  423. pusNtName Name in NT space
  424. pwcDosName Name in DOS space
  425. bCreate Set to TRUE to create, FALSE to delete
  426. Return Value
  427. TRUE if successful
  428. FALSE otherwise
  429. --*/
  430. {
  431. UNICODE_STRING usSymbolicLinkName;
  432. WCHAR rgwcBuffer[100];
  433. PAGED_CODE();
  434. //
  435. // Form the full symbolic link name we wish to create.
  436. //
  437. usSymbolicLinkName.Buffer = rgwcBuffer;
  438. RtlInitUnicodeString(&usSymbolicLinkName,
  439. pwcDosName);
  440. if(bCreate)
  441. {
  442. if(!NT_SUCCESS(IoCreateSymbolicLink(&usSymbolicLinkName,
  443. pusNtName)))
  444. {
  445. return FALSE;
  446. }
  447. }
  448. else
  449. {
  450. IoDeleteSymbolicLink(&usSymbolicLinkName);
  451. }
  452. return TRUE;
  453. }
  454. NTSTATUS
  455. StartDriver(
  456. VOID
  457. )
  458. /*++
  459. Routine Description
  460. Main routine to start the driver. We call this when we get CREATE irp
  461. If the driver has started, we return success. If someone is starting the
  462. driver, we return pending. The caller then needs to wait on g_keStartEvent
  463. We try and start the driver. If all goes well, we set the event and
  464. everyone parties on from there
  465. Locks
  466. The function takes the g_rlStateLock to check the state and increment
  467. the number of CREATEs it has received (open handles)
  468. Arguments
  469. None
  470. Return Value
  471. STATUS_SUCCESS if the driver started
  472. STATUS_PENDING if the driver is being started by some other thread's
  473. --*/
  474. {
  475. KIRQL kiOldIrql;
  476. NTSTATUS nStatus;
  477. DWORD dwState;
  478. OPEN_CONTEXT TdixContext;
  479. WORK_QUEUE_ITEM WorkItem;
  480. KEVENT keTempEvent;
  481. TraceEnter(GLOBAL, "StartDriver");
  482. RtAcquireSpinLock(&g_rlStateLock,
  483. &kiOldIrql);
  484. g_ulNumOpens++;
  485. if(g_ulNumOpens isnot 1)
  486. {
  487. if(g_dwDriverState is DRIVER_STARTING)
  488. {
  489. //
  490. // Someone is trying to start the driver
  491. //
  492. Trace(GLOBAL, INFO,
  493. ("StartDriver: Driver is being started by someone else\n"));
  494. nStatus = STATUS_PENDING;
  495. }
  496. else
  497. {
  498. //
  499. // If we are not the first CreateFile, and the driver is not
  500. // starting then the driver must already be running
  501. //
  502. RtAssert(g_dwDriverState is DRIVER_STARTED);
  503. nStatus = STATUS_SUCCESS;
  504. }
  505. RtReleaseSpinLock(&g_rlStateLock,
  506. kiOldIrql);
  507. return nStatus;
  508. }
  509. //
  510. // The first CreateFile
  511. //
  512. RtAssert(g_dwDriverState is DRIVER_STOPPED);
  513. //
  514. // Set the state to starting, release the lock and actually start
  515. // the driver
  516. //
  517. g_dwDriverState = DRIVER_STARTING;
  518. RtReleaseSpinLock(&g_rlStateLock,
  519. kiOldIrql);
  520. dwState = DRIVER_STARTED;
  521. //
  522. // Initialize the event and work item to start TDI
  523. //
  524. KeInitializeEvent(&keTempEvent,
  525. SynchronizationEvent,
  526. FALSE);
  527. TdixContext.pkeEvent = &keTempEvent;
  528. ExInitializeWorkItem(&WorkItem,
  529. TdixInitialize,
  530. &TdixContext);
  531. //
  532. // Start TDI in the system context so that we the handles are not
  533. // associated with the current process
  534. //
  535. ExQueueWorkItem(&WorkItem,
  536. DelayedWorkQueue);
  537. //
  538. // Wait for TDI to get done
  539. //
  540. nStatus = KeWaitForSingleObject(TdixContext.pkeEvent,
  541. UserRequest,
  542. KernelMode,
  543. FALSE,
  544. NULL);
  545. if((nStatus isnot STATUS_SUCCESS) or
  546. (TdixContext.nStatus isnot STATUS_SUCCESS))
  547. {
  548. Trace(GLOBAL, ERROR,
  549. ("StartDriver: TdixInitialize failed with %x %x\n",
  550. nStatus, TdixContext.nStatus));
  551. dwState = DRIVER_STOPPED;
  552. }
  553. if(dwState is DRIVER_STARTED)
  554. {
  555. LARGE_INTEGER liDueTime;
  556. KeInitializeDpc(&g_kdTimerDpc,
  557. IpIpTimerRoutine,
  558. NULL);
  559. KeInitializeTimer(&g_ktTimer);
  560. liDueTime = RtlEnlargedUnsignedMultiply(TIMER_IN_MILLISECS,
  561. SYS_UNITS_IN_ONE_MILLISEC);
  562. liDueTime = RtlLargeIntegerNegate(liDueTime);
  563. KeSetTimerEx(&g_ktTimer,
  564. liDueTime,
  565. 0,
  566. &g_kdTimerDpc);
  567. }
  568. RtAcquireSpinLock(&g_rlStateLock,
  569. &kiOldIrql);
  570. g_dwDriverState = dwState;
  571. //
  572. // Someone may have been waiting for us to start
  573. //
  574. KeSetEvent(&g_keStartEvent,
  575. 0,
  576. FALSE);
  577. RtReleaseSpinLock(&g_rlStateLock,
  578. kiOldIrql);
  579. TraceLeave(GLOBAL, "StartDriver");
  580. return nStatus;
  581. }
  582. VOID
  583. StopDriver(
  584. VOID
  585. )
  586. /*++
  587. Routine Description
  588. Called when we get an IRP_MJ_CLEANUP. It is the inverse of StartDriver
  589. If this is the last thread, we set the state to STOPPED and wait till
  590. all threads of execution have exited the driver.
  591. We then clean out resources
  592. Locks
  593. The function takes the g_rlStateLock
  594. Arguments
  595. None
  596. Return Value
  597. None
  598. --*/
  599. {
  600. KIRQL kiOldIrql;
  601. NTSTATUS nStatus;
  602. BOOLEAN bWait;
  603. ULONG i;
  604. OPEN_CONTEXT TdixContext;
  605. WORK_QUEUE_ITEM WorkItem;
  606. KEVENT keTempEvent;
  607. PIO_WORKITEM pIoWorkItem;
  608. TraceEnter(GLOBAL, "StopDriver");
  609. //
  610. // Acquire the state and ref count spin lock
  611. //
  612. RtAcquireSpinLock(&g_rlStateLock,
  613. &kiOldIrql);
  614. g_ulNumOpens--;
  615. if(g_ulNumOpens isnot 0)
  616. {
  617. //
  618. // Other people still around
  619. //
  620. RtReleaseSpinLock(&g_rlStateLock,
  621. kiOldIrql);
  622. TraceLeave(GLOBAL, "StopDriver");
  623. return;
  624. }
  625. //
  626. // Set the state to stopping. Any reader will
  627. // return on seeing this. So essentially we are not
  628. // allowing any new readers in
  629. //
  630. g_dwDriverState = DRIVER_STOPPED;
  631. //
  632. // However there may already be readers. We wait
  633. // if there are any
  634. //
  635. bWait = (g_ulNumThreads > 0);
  636. RtReleaseSpinLock(&g_rlStateLock,
  637. kiOldIrql);
  638. //
  639. // Now do a wait. We can do this since we are at PASSIVE
  640. //
  641. if(bWait)
  642. {
  643. Trace(GLOBAL, INFO,
  644. ("StopDriver: Need to wait for threads to exit\n"));
  645. do
  646. {
  647. nStatus = KeWaitForSingleObject(&g_keStateEvent,
  648. Executive,
  649. KernelMode,
  650. FALSE,
  651. NULL);
  652. }while((nStatus is STATUS_USER_APC) or
  653. (nStatus is STATUS_ALERTED) or
  654. (nStatus is STATUS_TIMEOUT));
  655. }
  656. //
  657. // Undo the timer
  658. //
  659. i = 0;
  660. while(KeCancelTimer(&g_ktTimer) is FALSE)
  661. {
  662. LARGE_INTEGER liTimeOut;
  663. //
  664. // Hmm, timer was not in the system queue.
  665. // Set the wait to 2, 4, 6... secs
  666. //
  667. liTimeOut.QuadPart = (LONGLONG)((i + 1) * 2 * 1000 * 1000 * 10 * -1);
  668. KeDelayExecutionThread(UserMode,
  669. FALSE,
  670. &liTimeOut);
  671. i++;
  672. }
  673. //
  674. // Initialize the event and work item to stop TDI
  675. //
  676. KeInitializeEvent(&keTempEvent,
  677. SynchronizationEvent,
  678. FALSE);
  679. TdixContext.pkeEvent = &keTempEvent;
  680. pIoWorkItem = IoAllocateWorkItem(g_pIpIpDevice);
  681. //
  682. // Must have a work item - no failure code path
  683. //
  684. RtAssert(pIoWorkItem);
  685. IoQueueWorkItem(pIoWorkItem,
  686. TdixDeinitialize,
  687. DelayedWorkQueue,
  688. &TdixContext);
  689. //
  690. // Wait for TDI to get done
  691. //
  692. nStatus = KeWaitForSingleObject(TdixContext.pkeEvent,
  693. UserRequest,
  694. KernelMode,
  695. FALSE,
  696. NULL);
  697. RtAssert(nStatus is STATUS_SUCCESS);
  698. IoFreeWorkItem(pIoWorkItem);
  699. //
  700. // Cleanup all resources
  701. //
  702. while(!IsListEmpty(&g_lePendingMessageList))
  703. {
  704. PLIST_ENTRY pleNode;
  705. PPENDING_MESSAGE pMessage;
  706. //
  707. // We have some old info
  708. // Remove it off the pending list
  709. //
  710. pleNode = RemoveHeadList(&g_lePendingMessageList);
  711. //
  712. // Get a pointer to the structure
  713. //
  714. pMessage = CONTAINING_RECORD(pleNode,
  715. PENDING_MESSAGE,
  716. leMessageLink);
  717. //
  718. // Free the allocated message
  719. //
  720. FreeMessage(pMessage);
  721. }
  722. ClearPendingIrps();
  723. TraceLeave(GLOBAL, "StopDriver");
  724. }
  725. NTSTATUS
  726. RegisterWithIp(
  727. VOID
  728. )
  729. /*++
  730. Routine Description
  731. Registers the ARP module with IP
  732. Locks
  733. Arguments
  734. Return Value
  735. --*/
  736. {
  737. NDIS_STRING nsIpIpName;
  738. WCHAR pwszName[] = IPINIP_ARP_NAME;
  739. IP_STATUS Status;
  740. IPInfo Info;
  741. TraceEnter(GLOBAL, "RegisterWithIP");
  742. Status = IPGetInfo(&Info,
  743. sizeof(Info));
  744. if(Status isnot IP_SUCCESS)
  745. {
  746. Trace(GLOBAL, ERROR,
  747. ("RegisterWithIp: Couldnt get IPInfo %x\n", Status));
  748. TraceLeave(GLOBAL,
  749. "RegisterWithIP");
  750. return STATUS_UNSUCCESSFUL;
  751. }
  752. g_pfnOpenRce = Info.ipi_openrce;
  753. g_pfnCloseRce = Info.ipi_closerce;
  754. nsIpIpName.MaximumLength = sizeof(pwszName);
  755. nsIpIpName.Length = sizeof(IPINIP_ARP_NAME) - sizeof(WCHAR);
  756. nsIpIpName.Buffer = pwszName;
  757. Status = IPRegisterARP(&nsIpIpName,
  758. IP_ARP_BIND_VERSION,
  759. IpIpBindAdapter,
  760. &g_pfnIpAddInterface,
  761. &g_pfnIpDeleteInterface,
  762. &g_pfnIpBindComplete,
  763. &g_pfnIpAddLink,
  764. &g_pfnIpDeleteLink,
  765. &g_pfnIpChangeIndex,
  766. &g_pfnIpReserveIndex,
  767. &g_pfnIpDereserveIndex,
  768. &g_hIpRegistration);
  769. if(Status isnot IP_SUCCESS)
  770. {
  771. Trace(GLOBAL, ERROR,
  772. ("RegisterWithIp: Couldnt register with IP\n"));
  773. TraceLeave(GLOBAL,
  774. "RegisterWithIP");
  775. return STATUS_UNSUCCESSFUL;
  776. }
  777. TraceLeave(GLOBAL,
  778. "RegisterWithIP");
  779. return STATUS_SUCCESS;
  780. }
  781. VOID
  782. DeregisterWithIp(
  783. VOID
  784. )
  785. /*++
  786. Routine Description
  787. DeRegisters the ARP module with IP
  788. Locks
  789. Arguments
  790. Return Value
  791. --*/
  792. {
  793. NTSTATUS nStatus;
  794. TraceEnter(GLOBAL, "DeregisterWithIp");
  795. nStatus = IPDeregisterARP(g_hIpRegistration);
  796. if(nStatus isnot STATUS_SUCCESS)
  797. {
  798. Trace(GLOBAL, ERROR,
  799. ("DeregisterWithIp: Couldnt deregister with IP. Error %x\n",
  800. nStatus));
  801. }
  802. g_pfnIpAddInterface = NULL;
  803. g_pfnIpDeleteInterface = NULL;
  804. g_pfnIpBindComplete = NULL;
  805. g_pfnIpRcv = NULL;
  806. g_pfnIpRcvComplete = NULL;
  807. g_pfnIpSendComplete = NULL;
  808. g_pfnIpTDComplete = NULL;
  809. g_pfnIpStatus = NULL;
  810. g_pfnIpRcvPkt = NULL;
  811. g_pfnIpPnp = NULL;
  812. g_hIpRegistration = NULL;
  813. TraceLeave(GLOBAL, "DeregisterWithIp");
  814. }
  815. #pragma alloc_text(PAGE, OpenRegKey)
  816. NTSTATUS
  817. OpenRegKey(
  818. PHANDLE HandlePtr,
  819. PWCHAR KeyName
  820. )
  821. {
  822. NTSTATUS Status;
  823. OBJECT_ATTRIBUTES ObjectAttributes;
  824. UNICODE_STRING UKeyName;
  825. PAGED_CODE();
  826. RtlInitUnicodeString(&UKeyName, KeyName);
  827. RtlZeroMemory(&ObjectAttributes,
  828. sizeof(OBJECT_ATTRIBUTES));
  829. InitializeObjectAttributes(&ObjectAttributes,
  830. &UKeyName,
  831. OBJ_CASE_INSENSITIVE,
  832. NULL,
  833. NULL);
  834. Status = ZwOpenKey(HandlePtr,
  835. KEY_READ,
  836. &ObjectAttributes);
  837. return Status;
  838. }
  839. #pragma alloc_text(PAGE, GetRegDWORDValue)
  840. NTSTATUS
  841. GetRegDWORDValue(
  842. HANDLE KeyHandle,
  843. PWCHAR ValueName,
  844. PULONG ValueData
  845. )
  846. {
  847. NTSTATUS status;
  848. ULONG resultLength;
  849. PKEY_VALUE_FULL_INFORMATION keyValueFullInformation;
  850. UCHAR keybuf[128];
  851. UNICODE_STRING UValueName;
  852. PAGED_CODE();
  853. RtlInitUnicodeString(&UValueName, ValueName);
  854. keyValueFullInformation = (PKEY_VALUE_FULL_INFORMATION)keybuf;
  855. RtlZeroMemory(keyValueFullInformation, sizeof(keyValueFullInformation));
  856. status = ZwQueryValueKey(KeyHandle,
  857. &UValueName,
  858. KeyValueFullInformation,
  859. keyValueFullInformation,
  860. 128,
  861. &resultLength);
  862. if (NT_SUCCESS(status)) {
  863. if (keyValueFullInformation->Type != REG_DWORD) {
  864. status = STATUS_INVALID_PARAMETER_MIX;
  865. } else {
  866. *ValueData = *((ULONG UNALIGNED *)((PCHAR)keyValueFullInformation +
  867. keyValueFullInformation->DataOffset));
  868. }
  869. }
  870. return status;
  871. }
  872. BOOLEAN
  873. EnterDriverCode(
  874. VOID
  875. )
  876. {
  877. KIRQL irql;
  878. BOOLEAN bEnter;
  879. RtAcquireSpinLock(&g_rlStateLock,
  880. &irql);
  881. if(g_dwDriverState is DRIVER_STARTED)
  882. {
  883. g_ulNumThreads++;
  884. bEnter = TRUE;
  885. }
  886. else
  887. {
  888. bEnter = FALSE;
  889. }
  890. RtReleaseSpinLock(&g_rlStateLock,
  891. irql);
  892. return bEnter;
  893. }
  894. VOID
  895. ExitDriverCode(
  896. VOID
  897. )
  898. {
  899. KIRQL irql;
  900. RtAcquireSpinLock(&g_rlStateLock,
  901. &irql);
  902. g_ulNumThreads--;
  903. if((g_dwDriverState is DRIVER_STOPPED) and
  904. (g_ulNumThreads is 0))
  905. {
  906. KeSetEvent(&g_keStateEvent,
  907. 0,
  908. FALSE);
  909. }
  910. RtReleaseSpinLock(&g_rlStateLock,
  911. irql);
  912. }
  913. VOID
  914. ClearPendingIrps(
  915. VOID
  916. )
  917. /*++
  918. Routine Description:
  919. Called at cleanup time to return any pending IRPs
  920. Locks:
  921. Acquires the IoCancelSpinLock since it controls the pending irp list
  922. Arguments:
  923. None
  924. Return Value:
  925. None
  926. --*/
  927. {
  928. KIRQL irql;
  929. TraceEnter(GLOBAL, "ClearPendingIrps");
  930. IoAcquireCancelSpinLock (&irql);
  931. while(!IsListEmpty(&g_lePendingIrpList))
  932. {
  933. PLIST_ENTRY pleNode;
  934. PIRP pIrp;
  935. pleNode = RemoveHeadList(&g_lePendingIrpList);
  936. pIrp = CONTAINING_RECORD(pleNode,
  937. IRP,
  938. Tail.Overlay.ListEntry);
  939. IoSetCancelRoutine(pIrp,
  940. NULL);
  941. pIrp->IoStatus.Status = STATUS_NO_SUCH_DEVICE;
  942. pIrp->IoStatus.Information = 0;
  943. //
  944. // release lock to complete the IRP
  945. //
  946. IoReleaseCancelSpinLock(irql);
  947. IoCompleteRequest(pIrp,
  948. IO_NETWORK_INCREMENT);
  949. //
  950. // Reaquire the lock
  951. //
  952. IoAcquireCancelSpinLock(&irql);
  953. }
  954. IoReleaseCancelSpinLock(irql);
  955. }