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.

1804 lines
38 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. net\ip\wanarp\driver.c
  5. Abstract:
  6. WAN ARP 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 hdrstop
  13. BOOLEAN g_bExit;
  14. BOOLEAN g_bPoolsInitialized;
  15. NPAGED_LOOKASIDE_LIST g_llNotificationBlocks;
  16. NPAGED_LOOKASIDE_LIST g_llConnBlocks;
  17. #pragma alloc_text(INIT, DriverEntry)
  18. NTSTATUS
  19. DriverEntry(
  20. IN PDRIVER_OBJECT DriverObject,
  21. IN PUNICODE_STRING RegistryPath
  22. )
  23. /*++
  24. Routine Description:
  25. Installable driver initialization entry point.
  26. This entry point is called directly by the I/O system and must be named
  27. "Driver Entry"
  28. The function is discardable since it is only called once
  29. On checked builds we read some values from registry and initialize the
  30. debugging
  31. We create a DEVICE_OBJECT for ourselves to field the IOCTLs, create
  32. a DOS name for the device and initialize some events and spinlocks
  33. Locks:
  34. None
  35. Arguments:
  36. DriverObject Pointer to I/O subsystem created driver object
  37. RegistryPath Points to driver key in HKLM\System\CCS\Services...
  38. Return Value:
  39. STATUS_SUCCESS if everything went as planned or some status code from
  40. ntstatus.h
  41. --*/
  42. {
  43. NTSTATUS nStatus;
  44. PDEVICE_OBJECT pDeviceObject;
  45. UNICODE_STRING usDeviceName, usParamString, usTempString;
  46. DWORD dwVal, i;
  47. HANDLE hRegKey;
  48. USHORT usRegLen;
  49. PWCHAR pwcBuffer;
  50. RtInitializeDebug();
  51. usRegLen = RegistryPath->Length +
  52. (sizeof(WCHAR) * (wcslen(L"\\Parameters") + 2));
  53. pwcBuffer = RtAllocate(NonPagedPool,
  54. usRegLen,
  55. WAN_STRING_TAG);
  56. if(pwcBuffer is NULL)
  57. {
  58. return STATUS_INSUFFICIENT_RESOURCES;
  59. }
  60. RtlZeroMemory(pwcBuffer,
  61. usRegLen);
  62. usParamString.MaximumLength = usRegLen;
  63. usParamString.Buffer = pwcBuffer;
  64. RtlCopyUnicodeString(&usParamString,
  65. RegistryPath);
  66. RtlInitUnicodeString(&usTempString,
  67. L"\\Parameters");
  68. RtlAppendUnicodeStringToString(&usParamString,
  69. &usTempString);
  70. nStatus = OpenRegKey(&hRegKey,
  71. &usParamString);
  72. RtFree(pwcBuffer);
  73. if(nStatus is STATUS_SUCCESS)
  74. {
  75. #if RT_TRACE_DEBUG
  76. nStatus = GetRegDWORDValue(hRegKey,
  77. L"DebugLevel",
  78. &dwVal);
  79. if(nStatus is STATUS_SUCCESS)
  80. {
  81. g_byDebugLevel = (BYTE)dwVal;
  82. }
  83. nStatus = GetRegDWORDValue(hRegKey,
  84. L"DebugComp",
  85. &dwVal);
  86. if(nStatus is STATUS_SUCCESS)
  87. {
  88. g_fDebugComp = dwVal;
  89. }
  90. #endif
  91. #if DBG
  92. nStatus = GetRegDWORDValue(hRegKey,
  93. L"DebugBreak",
  94. &dwVal);
  95. if((nStatus is STATUS_SUCCESS) and
  96. (dwVal is 1))
  97. {
  98. DbgBreakPoint();
  99. }
  100. #endif
  101. ZwClose(hRegKey);
  102. }
  103. TraceEnter(GLOBAL, "DriverEntry");
  104. //DbgBreakPoint();
  105. if(g_bExit)
  106. {
  107. return STATUS_UNSUCCESSFUL;
  108. }
  109. //
  110. // Initialize some globals (rest are all 0s)
  111. //
  112. g_dwDriverState = DRIVER_STOPPED;
  113. //
  114. // Create the device
  115. //
  116. RtlInitUnicodeString(&usDeviceName,
  117. DD_WANARP_DEVICE_NAME_W);
  118. nStatus = IoCreateDevice(DriverObject,
  119. 0,
  120. &usDeviceName,
  121. FILE_DEVICE_NETWORK,
  122. FILE_DEVICE_SECURE_OPEN,
  123. FALSE,
  124. &pDeviceObject);
  125. if(nStatus isnot STATUS_SUCCESS)
  126. {
  127. Trace(GLOBAL, ERROR,
  128. ("DriverEntry: Cant create device object %S, status %x.\n",
  129. DD_WANARP_DEVICE_NAME_W,
  130. nStatus));
  131. TraceLeave(GLOBAL, "DriverEntry");
  132. return nStatus;
  133. }
  134. //
  135. // Initialize the driver object
  136. //
  137. DriverObject->DriverUnload = WanUnload;
  138. DriverObject->FastIoDispatch = NULL;
  139. for(i=0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
  140. {
  141. DriverObject->MajorFunction[i] = WanDispatch;
  142. }
  143. //
  144. // Initialize Events etc
  145. //
  146. WanpInitializeDriverStructures();
  147. if(!WanpSetupExternalName(&usDeviceName,
  148. WIN32_WANARP_SYMBOLIC_LINK,
  149. TRUE))
  150. {
  151. Trace(GLOBAL,ERROR,
  152. ("DriverEntry: Win32 device name %S could not be created\n",
  153. WIN32_WANARP_SYMBOLIC_LINK));
  154. IoDeleteDevice(pDeviceObject);
  155. TraceLeave(GLOBAL, "DriverEntry");
  156. return STATUS_UNSUCCESSFUL;
  157. }
  158. //
  159. // Register with IP
  160. //
  161. WanpAcquireResource(&g_wrBindMutex);
  162. nStatus = WanpRegisterWithIp();
  163. if(nStatus isnot STATUS_SUCCESS)
  164. {
  165. Trace(GLOBAL, ERROR,
  166. ("DriverEntry: RegisterWithIp failed %x\n",
  167. nStatus));
  168. WanpSetupExternalName(&usDeviceName,
  169. WIN32_WANARP_SYMBOLIC_LINK,
  170. FALSE);
  171. IoDeleteDevice(pDeviceObject);
  172. WanpReleaseResource(&g_wrBindMutex);
  173. TraceLeave(GLOBAL, "InitializeDriver");
  174. return FALSE;
  175. }
  176. nStatus = WanpInitializeNdis();
  177. if(nStatus isnot STATUS_SUCCESS)
  178. {
  179. Trace(GLOBAL, ERROR,
  180. ("DriverEntry: IntializeNdis failed %x\n",
  181. nStatus));
  182. WanpDeregisterWithIp();
  183. WanpSetupExternalName(&usDeviceName,
  184. WIN32_WANARP_SYMBOLIC_LINK,
  185. FALSE);
  186. IoDeleteDevice(pDeviceObject);
  187. WanpReleaseResource(&g_wrBindMutex);
  188. TraceLeave(GLOBAL, "InitializeDriver");
  189. return FALSE;
  190. }
  191. WanpReleaseResource(&g_wrBindMutex);
  192. TraceLeave(GLOBAL, "DriverEntry");
  193. return nStatus;
  194. }
  195. #pragma alloc_text(PAGE, WanDispatch)
  196. NTSTATUS
  197. WanDispatch(
  198. IN PDEVICE_OBJECT DeviceObject,
  199. IN PIRP Irp
  200. )
  201. /*++
  202. Routine Description:
  203. The functions which handles the IRPs sent to the driver
  204. Locks:
  205. This code is PAGEABLE so can not acquire locks
  206. Arguments:
  207. Return Value:
  208. STATUS_SUCCESS
  209. --*/
  210. {
  211. PIO_STACK_LOCATION irpStack;
  212. ULONG ulInputBuffLen;
  213. ULONG ulOutputBuffLen;
  214. ULONG ioControlCode;
  215. NTSTATUS nStatus;
  216. KIRQL kiIrql;
  217. LARGE_INTEGER liTimeOut;
  218. BOOLEAN bEnter;
  219. PAGED_CODE();
  220. TraceEnter(GLOBAL, "WanDispatch");
  221. Irp->IoStatus.Information = 0;
  222. //
  223. // Get a pointer to the current location in the Irp. This is where
  224. // the function codes and parameters are located.
  225. //
  226. irpStack = IoGetCurrentIrpStackLocation(Irp);
  227. switch (irpStack->MajorFunction)
  228. {
  229. case IRP_MJ_CREATE:
  230. {
  231. Trace(GLOBAL, TRACE,
  232. ("WanDispatch: IRP_MJ_CREATE\n"));
  233. //
  234. // We start the driver when the first CreateFile is done
  235. // But we need to serialize the Creates
  236. //
  237. nStatus = WanpStartDriver();
  238. if(nStatus isnot STATUS_SUCCESS)
  239. {
  240. //
  241. // If pending, wait on the start event
  242. //
  243. if(nStatus is STATUS_PENDING)
  244. {
  245. }
  246. else
  247. {
  248. break;
  249. }
  250. }
  251. //
  252. // Make sure the driver actually started
  253. //
  254. bEnter = EnterDriverCode();
  255. if(!bEnter)
  256. {
  257. Trace(GLOBAL, ERROR,
  258. ("WanDispatch: Wait successful, but unable to start driver\n"));
  259. nStatus = STATUS_UNSUCCESSFUL;
  260. }
  261. else
  262. {
  263. ExitDriverCode();
  264. }
  265. break;
  266. }
  267. case IRP_MJ_CLOSE:
  268. {
  269. Trace(GLOBAL, TRACE,
  270. ("WanDispatch: IRP_MJ_CLOSE\n"));
  271. //
  272. // We handle cleanup and not close
  273. //
  274. nStatus = STATUS_SUCCESS;
  275. break;
  276. }
  277. case IRP_MJ_CLEANUP:
  278. {
  279. Trace(GLOBAL, TRACE,
  280. ("WanDispatch: IRP_MJ_CLEANUP\n"));
  281. nStatus = STATUS_SUCCESS;
  282. if(InterlockedDecrement(&g_ulNumCreates) is 0)
  283. {
  284. //
  285. // Last handle open is now closed; lets clean up
  286. //
  287. WanpStopDriver();
  288. }
  289. break;
  290. }
  291. case IRP_MJ_DEVICE_CONTROL:
  292. {
  293. DWORD dwState;
  294. ULONG ulControl;
  295. //
  296. // Get the control code and our code
  297. //
  298. ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
  299. //
  300. // Get the pointer to the input/output buffer and it's length
  301. //
  302. ulInputBuffLen =
  303. irpStack->Parameters.DeviceIoControl.InputBufferLength;
  304. ulOutputBuffLen =
  305. irpStack->Parameters.DeviceIoControl.OutputBufferLength;
  306. //
  307. // If the driver is stopping, dont process anything else
  308. //
  309. bEnter = EnterDriverCode();
  310. if(!bEnter)
  311. {
  312. Trace(GLOBAL, ERROR,
  313. ("WanDispatch: Driver is not started\n"));
  314. nStatus = STATUS_NO_SUCH_DEVICE;
  315. break;
  316. }
  317. switch(ioControlCode)
  318. {
  319. case IOCTL_WANARP_NOTIFICATION:
  320. {
  321. nStatus = WanProcessNotification(Irp,
  322. ulInputBuffLen,
  323. ulOutputBuffLen);
  324. break;
  325. }
  326. case IOCTL_WANARP_ADD_INTERFACE:
  327. {
  328. nStatus = WanAddUserModeInterface(Irp,
  329. ulInputBuffLen,
  330. ulOutputBuffLen);
  331. break;
  332. }
  333. case IOCTL_WANARP_DELETE_INTERFACE:
  334. {
  335. nStatus = WanDeleteUserModeInterface(Irp,
  336. ulInputBuffLen,
  337. ulOutputBuffLen);
  338. break;
  339. }
  340. case IOCTL_WANARP_CONNECT_FAILED:
  341. {
  342. nStatus = WanProcessConnectionFailure(Irp,
  343. ulInputBuffLen,
  344. ulOutputBuffLen);
  345. break;
  346. }
  347. case IOCTL_WANARP_GET_IF_STATS:
  348. {
  349. nStatus = WanGetIfStats(Irp,
  350. ulInputBuffLen,
  351. ulOutputBuffLen);
  352. break;
  353. }
  354. case IOCTL_WANARP_DELETE_ADAPTERS:
  355. {
  356. nStatus = WanDeleteAdapters(Irp,
  357. ulInputBuffLen,
  358. ulOutputBuffLen);
  359. break;
  360. }
  361. case IOCTL_WANARP_MAP_SERVER_ADAPTER:
  362. {
  363. nStatus = WanMapServerAdapter(Irp,
  364. ulInputBuffLen,
  365. ulOutputBuffLen);
  366. break;
  367. }
  368. case IOCTL_WANARP_QUEUE:
  369. {
  370. nStatus = WanStartStopQueuing(Irp,
  371. ulInputBuffLen,
  372. ulOutputBuffLen);
  373. break;
  374. }
  375. default:
  376. {
  377. Trace(GLOBAL, ERROR,
  378. ("WanDispatch: Unknown IRP_MJ_DEVICE_CONTROL %x\n",
  379. ioControlCode));
  380. nStatus = STATUS_INVALID_PARAMETER;
  381. }
  382. }
  383. ExitDriverCode();
  384. break;
  385. }
  386. default:
  387. {
  388. Trace(GLOBAL, ERROR,
  389. ("WanDispatch: Unknown IRP_MJ_XX - %x\n",
  390. irpStack->MajorFunction));
  391. nStatus = STATUS_INVALID_PARAMETER;
  392. break;
  393. }
  394. }
  395. if(nStatus isnot STATUS_PENDING)
  396. {
  397. Irp->IoStatus.Status = nStatus;
  398. IoCompleteRequest(Irp,
  399. IO_NETWORK_INCREMENT);
  400. }
  401. TraceLeave(GLOBAL, "WanDispatch");
  402. return nStatus;
  403. }
  404. #pragma alloc_text(PAGE, WanUnload)
  405. VOID
  406. WanUnload(
  407. PDRIVER_OBJECT DriverObject
  408. )
  409. /*++
  410. Routine Description:
  411. Called by the I/O subsystem, when our driver is being unloaded
  412. Locks:
  413. Arguments:
  414. Return Value:
  415. None
  416. --*/
  417. {
  418. UNICODE_STRING usDeviceName;
  419. BOOLEAN bWait;
  420. KIRQL kiIrql;
  421. NDIS_STATUS nsStatus;
  422. NTSTATUS nStatus;
  423. TraceEnter(GLOBAL,"WanUnload");
  424. PAGED_CODE();
  425. //
  426. // The driver must have stopped before it came here
  427. //
  428. RtAssert(g_dwDriverState is DRIVER_STOPPED);
  429. //
  430. // Deregister from NDIS etc
  431. //
  432. WanpDeinitializeNdis();
  433. //
  434. // Clear out IP's state. Need to do this after all adapters have
  435. // been removed
  436. //
  437. WanpDeregisterWithIp();
  438. //
  439. // Remove ourself from NT and DOS namespace
  440. //
  441. RtlInitUnicodeString(&usDeviceName,
  442. DD_WANARP_DEVICE_NAME_W);
  443. WanpSetupExternalName(&usDeviceName,
  444. WIN32_WANARP_SYMBOLIC_LINK,
  445. FALSE);
  446. //
  447. // Free all our structures
  448. //
  449. if(g_puipConnTable)
  450. {
  451. RtFree(g_puipConnTable);
  452. }
  453. ExDeleteNPagedLookasideList(&g_llConnBlocks);
  454. ExDeleteNPagedLookasideList(&g_llNotificationBlocks);
  455. if(g_bPoolsInitialized)
  456. {
  457. FreeBufferPool(&g_bpHeaderBufferPool);
  458. FreeBufferPool(&g_bpDataBufferPool);
  459. g_bPoolsInitialized = FALSE;
  460. }
  461. //
  462. // Acquire and release the resource. This lets the close adapter thread
  463. // run if it is still around
  464. //
  465. WanpAcquireResource(&g_wrBindMutex);
  466. WanpReleaseResource(&g_wrBindMutex);
  467. //
  468. // See if we have any free memory
  469. //
  470. RtAuditMemory();
  471. //
  472. // Delete the device object
  473. //
  474. IoDeleteDevice(DriverObject->DeviceObject);
  475. TraceLeave(GLOBAL,"WanUnload");
  476. }
  477. #pragma alloc_text(PAGE, WanpSetupExternalName)
  478. BOOLEAN
  479. WanpSetupExternalName(
  480. PUNICODE_STRING pusNtName,
  481. PWCHAR pwcDosName,
  482. BOOLEAN bCreate
  483. )
  484. /*++
  485. Routine Description:
  486. Setup or delete a symbolic link to DOS namespace
  487. Locks:
  488. Arguments:
  489. pusNtName Name in NT space
  490. pwcDosName Name in DOS space
  491. bCreate Set to TRUE to create, FALSE to delete
  492. Return Value:
  493. TRUE if successful
  494. FALSE otherwise
  495. --*/
  496. {
  497. UNICODE_STRING usSymbolicLinkName;
  498. WCHAR rgwcBuffer[100];
  499. PAGED_CODE();
  500. //
  501. // Form the full symbolic link name we wish to create.
  502. //
  503. usSymbolicLinkName.Buffer = rgwcBuffer;
  504. RtlInitUnicodeString(&usSymbolicLinkName,
  505. pwcDosName);
  506. if(bCreate)
  507. {
  508. if(!NT_SUCCESS(IoCreateSymbolicLink(&usSymbolicLinkName,
  509. pusNtName)))
  510. {
  511. return FALSE;
  512. }
  513. }
  514. else
  515. {
  516. IoDeleteSymbolicLink(&usSymbolicLinkName);
  517. }
  518. return TRUE;
  519. }
  520. NTSTATUS
  521. WanpStartDriver(
  522. VOID
  523. )
  524. /*++
  525. Routine Description:
  526. Main routine to start the driver. We call this when we get a CREATE irp
  527. If the driver has started, we return success. If someone is starting the
  528. driver, we return pending. The caller then needs to wait on g_keStartEvent
  529. We try and start the driver. If all goes well, we set the event and
  530. everyone parties on from there
  531. Locks:
  532. The function takes the g_rlStateLock to check the state and increment
  533. the number of CREATEs it has received (open handles)
  534. Arguments:
  535. None
  536. Return Value:
  537. STATUS_SUCCESS if the driver started
  538. STATUS_PENDING if the driver is being started by some other thread's
  539. --*/
  540. {
  541. KIRQL kiOldIrql;
  542. NTSTATUS nStatus;
  543. DWORD dwState;
  544. TraceEnter(GLOBAL, "StartDriver");
  545. RtAcquireSpinLock(&g_rlStateLock,
  546. &kiOldIrql);
  547. g_ulNumCreates++;
  548. if(g_ulNumCreates isnot 1)
  549. {
  550. if(g_dwDriverState is DRIVER_STARTING)
  551. {
  552. //
  553. // Someone is trying to start the driver
  554. //
  555. Trace(GLOBAL, INFO,
  556. ("StartDriver: Driver is being started by someone else\n"));
  557. nStatus = STATUS_PENDING;
  558. }
  559. else
  560. {
  561. //
  562. // If we are not the first CreateFile, and the driver is not
  563. // starting then the driver must already be running
  564. //
  565. RtAssert(g_dwDriverState is DRIVER_STARTED);
  566. nStatus = STATUS_SUCCESS;
  567. }
  568. RtReleaseSpinLock(&g_rlStateLock,
  569. kiOldIrql);
  570. return nStatus;
  571. }
  572. //
  573. // The first CreateFile
  574. //
  575. RtAssert(g_dwDriverState is DRIVER_STOPPED);
  576. //
  577. // Set the state to starting, release the lock and actually start
  578. // the driver
  579. //
  580. g_dwDriverState = DRIVER_STARTING;
  581. RtReleaseSpinLock(&g_rlStateLock,
  582. kiOldIrql);
  583. //
  584. // Must be called at PASSIVE because it waits for IP to finish
  585. //
  586. WanpSetDemandDialCallback(TRUE);
  587. RtAcquireSpinLock(&g_rlStateLock,
  588. &kiOldIrql);
  589. g_dwDriverState = DRIVER_STARTED;
  590. //
  591. // Someone may have been waiting for us to start
  592. //
  593. KeSetEvent(&g_keStartEvent,
  594. 0,
  595. FALSE);
  596. RtReleaseSpinLock(&g_rlStateLock,
  597. kiOldIrql);
  598. TraceLeave(GLOBAL, "StartDriver");
  599. return STATUS_SUCCESS;
  600. }
  601. VOID
  602. WanpStopDriver(
  603. VOID
  604. )
  605. /*++
  606. Routine Description:
  607. Called when we get an IRP_MJ_CLEANUP. It is the inverse of StartDriver
  608. If this is the last thread, we set the state to STOPPED and wait till
  609. all threads of execution have exited the driver.
  610. We then clean out resources
  611. Locks:
  612. The function takes the g_rlStateLock
  613. Arguments:
  614. None
  615. Return Value:
  616. None
  617. --*/
  618. {
  619. KIRQL kiOldIrql;
  620. NTSTATUS nStatus;
  621. BOOLEAN bWait;
  622. TraceEnter(GLOBAL, "StopDriver");
  623. //
  624. // Acquire the state and ref count spin lock
  625. //
  626. RtAcquireSpinLock(&g_rlStateLock,
  627. &kiOldIrql);
  628. RtAssert(g_ulNumCreates is 0);
  629. //
  630. // Set the state to stopping. Any reader will
  631. // return on seeing this. So essentially we are not
  632. // allowing any new readers in
  633. //
  634. g_dwDriverState = DRIVER_STOPPED;
  635. //
  636. // However there may already be readers. We wait
  637. // if there are any
  638. //
  639. bWait = (g_ulNumThreads > 0);
  640. RtReleaseSpinLock(&g_rlStateLock,
  641. kiOldIrql);
  642. //
  643. // Now do a wait. We can do this since we are at PASSIVE
  644. //
  645. if(bWait)
  646. {
  647. Trace(GLOBAL, INFO,
  648. ("StopDriver: Need to wait for threads to exit\n"));
  649. do
  650. {
  651. nStatus = KeWaitForSingleObject(&g_keStateEvent,
  652. Executive,
  653. KernelMode,
  654. FALSE,
  655. NULL);
  656. }while((nStatus is STATUS_USER_APC) or
  657. (nStatus is STATUS_ALERTED) or
  658. (nStatus is STATUS_TIMEOUT));
  659. }
  660. //
  661. // Cleanup all resources
  662. //
  663. WanpCleanOutInterfaces();
  664. WanpClearPendingIrps();
  665. TraceLeave(GLOBAL, "StopDriver");
  666. }
  667. NTSTATUS
  668. WanpRegisterWithIp(
  669. VOID
  670. )
  671. /*++
  672. Routine Description:
  673. Registers the ARP module with IP
  674. Locks:
  675. Arguments:
  676. Return Value:
  677. --*/
  678. {
  679. NDIS_STRING nsWanName;
  680. WCHAR pwszName[] = WANARP_ARP_NAME;
  681. TraceEnter(GLOBAL, "WanpRegisterWithIp");
  682. nsWanName.MaximumLength = sizeof(pwszName);
  683. nsWanName.Length = sizeof(WANARP_ARP_NAME) - sizeof(WCHAR);
  684. nsWanName.Buffer = pwszName;
  685. if(IPRegisterARP(&nsWanName,
  686. IP_ARP_BIND_VERSION,
  687. WanIpBindAdapter,
  688. &g_pfnIpAddInterface,
  689. &g_pfnIpDeleteInterface,
  690. &g_pfnIpBindComplete,
  691. &g_pfnIpAddLink,
  692. &g_pfnIpDeleteLink,
  693. &g_pfnIpChangeIndex,
  694. &g_pfnIpReserveIndex,
  695. &g_pfnIpDereserveIndex,
  696. &g_hIpRegistration) isnot IP_SUCCESS)
  697. {
  698. Trace(GLOBAL, ERROR,
  699. ("WanpRegisterWithIp: Couldnt register with IP\n"));
  700. TraceLeave(GLOBAL,
  701. "WanpRegisterWithIp");
  702. return STATUS_UNSUCCESSFUL;
  703. }
  704. TraceLeave(GLOBAL,
  705. "WanpRegisterWithIp");
  706. return STATUS_SUCCESS;
  707. }
  708. VOID
  709. WanpDeregisterWithIp(
  710. VOID
  711. )
  712. /*++
  713. Routine Description:
  714. DeRegisters the ARP module with IP
  715. Locks:
  716. Arguments:
  717. Return Value:
  718. --*/
  719. {
  720. NTSTATUS nStatus;
  721. TraceEnter(GLOBAL, "WanpDeregisterWithIP");
  722. nStatus = IPDeregisterARP(g_hIpRegistration);
  723. if(nStatus isnot STATUS_SUCCESS)
  724. {
  725. Trace(GLOBAL, ERROR,
  726. ("WanpDeregisterWithIP: Couldnt deregister with IP. Error %x\n",
  727. nStatus));
  728. }
  729. g_pfnIpAddInterface = NULL;
  730. g_pfnIpDeleteInterface = NULL;
  731. g_pfnIpBindComplete = NULL;
  732. g_pfnIpRcv = NULL;
  733. g_pfnIpRcvComplete = NULL;
  734. g_pfnIpSendComplete = NULL;
  735. g_pfnIpTDComplete = NULL;
  736. g_pfnIpStatus = NULL;
  737. g_pfnIpRcvPkt = NULL;
  738. g_pfnIpPnp = NULL;
  739. g_hIpRegistration = NULL;
  740. TraceLeave(GLOBAL, "WanpDeregisterWithIP");
  741. }
  742. BOOLEAN
  743. EnterDriverCode(
  744. VOID
  745. )
  746. {
  747. KIRQL irql;
  748. BOOLEAN bEnter;
  749. ULONG i;
  750. //
  751. // If we havent received any binds, sleep for 30 seconds
  752. //
  753. i = 0;
  754. while((g_lBindRcvd is 0) and
  755. (i < 3))
  756. {
  757. LARGE_INTEGER liTimeOut;
  758. i++;
  759. //
  760. // Set this to 5,10,15 seconds
  761. //
  762. liTimeOut.QuadPart = (LONGLONG)((i+ 1) * 5 * 1000 * 1000 * 10 * -1);
  763. KeDelayExecutionThread(UserMode,
  764. FALSE,
  765. &liTimeOut);
  766. }
  767. if(g_lBindRcvd is 0)
  768. {
  769. return FALSE;
  770. }
  771. RtAcquireSpinLock(&g_rlStateLock,
  772. &irql);
  773. if(g_dwDriverState is DRIVER_STARTED)
  774. {
  775. g_ulNumThreads++;
  776. bEnter = TRUE;
  777. }
  778. else
  779. {
  780. bEnter = FALSE;
  781. }
  782. RtReleaseSpinLock(&g_rlStateLock,
  783. irql);
  784. return bEnter;
  785. }
  786. VOID
  787. ExitDriverCode(
  788. VOID
  789. )
  790. {
  791. KIRQL irql;
  792. RtAcquireSpinLock(&g_rlStateLock,
  793. &irql);
  794. g_ulNumThreads--;
  795. if((g_dwDriverState is DRIVER_STOPPED) and
  796. (g_ulNumThreads is 0))
  797. {
  798. KeSetEvent(&g_keStateEvent,
  799. 0,
  800. FALSE);
  801. }
  802. RtReleaseSpinLock(&g_rlStateLock,
  803. irql);
  804. }
  805. #pragma alloc_text(PAGE, WanpSetDemandDialCallback)
  806. VOID
  807. WanpSetDemandDialCallback(
  808. BOOLEAN bSetPointer
  809. )
  810. /*++
  811. Routine Description:
  812. Sets the pointer to our demand dial request routine with the IP Stack
  813. Locks:
  814. None, done at INIT time
  815. Arguments:
  816. bSetPointer TRUE: set the pointer
  817. FALSE: remove the pointer
  818. Return Value:
  819. None
  820. --*/
  821. {
  822. PIRP irp;
  823. HANDLE handle;
  824. NTSTATUS nStatus;
  825. KEVENT tempevent;
  826. PFILE_OBJECT fileObject;
  827. PDEVICE_OBJECT deviceObject;
  828. IO_STATUS_BLOCK ioStatusBlock;
  829. UNICODE_STRING usDeviceName;
  830. IP_SET_MAP_ROUTE_HOOK_INFO buffer;
  831. PAGED_CODE();
  832. //
  833. // Open IP driver
  834. //
  835. RtlInitUnicodeString(&usDeviceName,
  836. DD_IP_DEVICE_NAME);
  837. nStatus = IoGetDeviceObjectPointer(&usDeviceName,
  838. SYNCHRONIZE|GENERIC_READ|GENERIC_WRITE,
  839. &fileObject,
  840. &deviceObject);
  841. if(nStatus isnot STATUS_SUCCESS)
  842. {
  843. Trace(CONN, ERROR,
  844. ("SetDemandDialCallback: IoGetDeviceObjectPointer for %S failed with status %x\n",
  845. DD_IP_DEVICE_NAME,
  846. nStatus));
  847. return;
  848. }
  849. //
  850. // Reference the device object.
  851. //
  852. ObReferenceObject(deviceObject);
  853. //
  854. // IoGetDeviceObjectPointer put a reference on the file object.
  855. //
  856. ObDereferenceObject(fileObject);
  857. //
  858. // Allocate event to use for setting callback address
  859. //
  860. KeInitializeEvent(&tempevent,
  861. SynchronizationEvent,
  862. FALSE);
  863. if(bSetPointer)
  864. {
  865. buffer.MapRoutePtr = WanDemandDialRequest;
  866. }
  867. else
  868. {
  869. buffer.MapRoutePtr = NULL;
  870. }
  871. //
  872. // Build the IRP
  873. //
  874. irp = IoBuildDeviceIoControlRequest(IOCTL_IP_SET_MAP_ROUTE_POINTER,
  875. deviceObject,
  876. &buffer,
  877. sizeof(IP_SET_MAP_ROUTE_HOOK_INFO),
  878. NULL,
  879. 0,
  880. FALSE,
  881. &tempevent,
  882. &ioStatusBlock);
  883. if (irp is NULL)
  884. {
  885. ObDereferenceObject(deviceObject);
  886. Trace(GLOBAL, ERROR,
  887. ("SetDemandDialCallback: Couldnt build IRP\n"));
  888. }
  889. else
  890. {
  891. nStatus = IoCallDriver(deviceObject, irp);
  892. if(nStatus is STATUS_PENDING)
  893. {
  894. nStatus = KeWaitForSingleObject(&tempevent,
  895. Executive,
  896. KernelMode,
  897. FALSE,
  898. NULL);
  899. }
  900. //
  901. // "close" handle to IP driver
  902. //
  903. ObDereferenceObject(deviceObject);
  904. }
  905. }
  906. #pragma alloc_text(PAGE, WanpInitializeDriverStructures)
  907. BOOLEAN
  908. WanpInitializeDriverStructures(
  909. VOID
  910. )
  911. /*++
  912. Routine Description:
  913. Initializes the internal driver structures
  914. Locks:
  915. None, called at init time
  916. Arguments:
  917. None
  918. Return Value:
  919. None
  920. --*/
  921. {
  922. ULONG i;
  923. PAGED_CODE();
  924. //
  925. // Lock and event needed to keep track of threads in the driver
  926. //
  927. RtInitializeSpinLock(&g_rlStateLock);
  928. KeInitializeEvent(&g_keStateEvent,
  929. SynchronizationEvent,
  930. FALSE);
  931. KeInitializeEvent(&g_keStartEvent,
  932. NotificationEvent,
  933. FALSE);
  934. KeInitializeEvent(&g_keCloseEvent,
  935. SynchronizationEvent,
  936. FALSE);
  937. WanpInitializeResource(&g_wrBindMutex);
  938. InitRwLock(&g_rwlIfLock);
  939. InitRwLock(&g_rwlAdapterLock);
  940. InitializeListHead(&g_leIfList);
  941. InitializeListHead(&g_lePendingNotificationList);
  942. InitializeListHead(&g_lePendingIrpList);
  943. InitializeListHead(&g_leMappedAdapterList);
  944. InitializeListHead(&g_leChangeAdapterList);
  945. InitializeListHead(&g_leAddedAdapterList);
  946. InitializeListHead(&g_leFreeAdapterList);
  947. //
  948. // Initialize the connection table
  949. //
  950. g_puipConnTable = RtAllocate(NonPagedPool,
  951. WAN_INIT_CONN_TABLE_SIZE * sizeof(ULONG_PTR),
  952. WAN_CONN_TAG);
  953. if(g_puipConnTable is NULL)
  954. {
  955. Trace(GLOBAL, ERROR,
  956. ("InitDriverStructures: Couldnt alloc conn table of %d bytes\n",
  957. WAN_INIT_CONN_TABLE_SIZE * sizeof(ULONG_PTR)));
  958. return FALSE;
  959. }
  960. RtlZeroMemory(g_puipConnTable,
  961. WAN_INIT_CONN_TABLE_SIZE * sizeof(ULONG_PTR));
  962. g_ulConnTableSize = WAN_INIT_CONN_TABLE_SIZE;
  963. //
  964. // The first slot is never used
  965. //
  966. g_puipConnTable[0] = (ULONG_PTR)-1;
  967. g_ulNextConnIndex = 1;
  968. RtInitializeSpinLock(&g_rlConnTableLock);
  969. //
  970. // Initialize the lookaside list for connection entries
  971. //
  972. ExInitializeNPagedLookasideList(&g_llConnBlocks,
  973. NULL,
  974. NULL,
  975. 0,
  976. sizeof(CONN_ENTRY),
  977. WAN_CONN_TAG,
  978. WANARP_CONN_LOOKASIDE_DEPTH);
  979. ExInitializeNPagedLookasideList(&g_llNotificationBlocks,
  980. NULL,
  981. NULL,
  982. 0,
  983. sizeof(PENDING_NOTIFICATION),
  984. WAN_NOTIFICATION_TAG,
  985. WANARP_NOTIFICATION_LOOKASIDE_DEPTH);
  986. //
  987. // Create the buffer pools
  988. //
  989. InitBufferPool(&g_bpHeaderBufferPool,
  990. HEADER_BUFFER_SIZE,
  991. 0,
  992. 20,
  993. 0,
  994. TRUE,
  995. WAN_HEADER_TAG);
  996. InitBufferPool(&g_bpDataBufferPool,
  997. DATA_BUFFER_SIZE,
  998. 0,
  999. 10,
  1000. 0,
  1001. TRUE,
  1002. WAN_DATA_TAG);
  1003. g_bPoolsInitialized = TRUE;
  1004. return TRUE;
  1005. }
  1006. #pragma alloc_text(PAGE, WanpInitializeNdis)
  1007. NDIS_STATUS
  1008. WanpInitializeNdis(
  1009. VOID
  1010. )
  1011. {
  1012. NDIS_STATUS nsStatus;
  1013. NDIS_PROTOCOL_CHARACTERISTICS npcWanChar;
  1014. TraceEnter(GLOBAL, "InitializeNdis");
  1015. PAGED_CODE();
  1016. RtlZeroMemory(&npcWanChar,
  1017. sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
  1018. npcWanChar.MajorNdisVersion = 4;
  1019. npcWanChar.MinorNdisVersion = 0;
  1020. npcWanChar.Flags = 0;
  1021. npcWanChar.OpenAdapterCompleteHandler = WanNdisOpenAdapterComplete;
  1022. npcWanChar.CloseAdapterCompleteHandler = WanNdisCloseAdapterComplete;
  1023. npcWanChar.SendCompleteHandler = WanNdisSendComplete;
  1024. npcWanChar.TransferDataCompleteHandler = WanNdisTransferDataComplete;
  1025. npcWanChar.ResetCompleteHandler = WanNdisResetComplete;
  1026. npcWanChar.RequestCompleteHandler = WanNdisRequestComplete;
  1027. npcWanChar.ReceiveHandler = WanNdisReceive;
  1028. npcWanChar.ReceiveCompleteHandler = WanNdisReceiveComplete;
  1029. npcWanChar.StatusHandler = WanNdisStatus;
  1030. npcWanChar.StatusCompleteHandler = WanNdisStatusComplete;
  1031. npcWanChar.ReceivePacketHandler = WanNdisReceivePacket;
  1032. //
  1033. // No bind handler needed
  1034. //
  1035. npcWanChar.BindAdapterHandler = WanNdisBindAdapter;
  1036. npcWanChar.UnbindAdapterHandler = WanNdisUnbindAdapter;
  1037. npcWanChar.PnPEventHandler = WanNdisPnPEvent;
  1038. npcWanChar.UnloadHandler = WanNdisUnload;
  1039. //
  1040. // Allocate the Packet Pool
  1041. //
  1042. g_nhPacketPool = (NDIS_HANDLE)WAN_PACKET_TAG;
  1043. NdisAllocatePacketPoolEx(&nsStatus,
  1044. &g_nhPacketPool,
  1045. WAN_PACKET_POOL_COUNT,
  1046. WAN_PACKET_POOL_OVERFLOW,
  1047. sizeof(struct PCCommon));
  1048. if(nsStatus isnot NDIS_STATUS_SUCCESS)
  1049. {
  1050. Trace(GLOBAL, ERROR,
  1051. ("InitializeNdis: Unable to allocate packet pool. %x\n",
  1052. nsStatus));
  1053. g_nhPacketPool = NULL;
  1054. return nsStatus;
  1055. }
  1056. NdisSetPacketPoolProtocolId(g_nhPacketPool,
  1057. NDIS_PROTOCOL_ID_TCP_IP);
  1058. RtlInitUnicodeString(&npcWanChar.Name,
  1059. WANARP_NDIS_NAME);
  1060. //
  1061. // THIS MUST BE THE LAST THING DONE
  1062. //
  1063. NdisRegisterProtocol(&nsStatus,
  1064. &g_nhWanarpProtoHandle,
  1065. &npcWanChar,
  1066. sizeof(npcWanChar));
  1067. TraceLeave(GLOBAL, "InitializeNdis");
  1068. return nsStatus;
  1069. }
  1070. #pragma alloc_text(PAGE, WanpDeinitializeNdis)
  1071. VOID
  1072. WanpDeinitializeNdis(
  1073. VOID
  1074. )
  1075. {
  1076. NTSTATUS nStatus;
  1077. LARGE_INTEGER liTimeOut;
  1078. PAGED_CODE();
  1079. WanpAcquireResource(&g_wrBindMutex);
  1080. if(g_nhNdiswanBinding isnot NULL)
  1081. {
  1082. WanpCloseNdisWan(NULL);
  1083. }
  1084. else
  1085. {
  1086. WanpReleaseResource(&g_wrBindMutex);
  1087. }
  1088. //
  1089. // wait on the close event
  1090. //
  1091. nStatus = KeWaitForSingleObject(&g_keCloseEvent,
  1092. Executive,
  1093. KernelMode,
  1094. FALSE,
  1095. NULL);
  1096. //
  1097. // Wait for a 5 secs to let the ndis thread finish its stuff
  1098. //
  1099. /*liTimeOut.QuadPart = (LONGLONG)(5 * 1000 * 1000 * 10 * -1);
  1100. KeDelayExecutionThread(UserMode,
  1101. FALSE,
  1102. &liTimeOut);
  1103. */
  1104. if(g_nhPacketPool isnot NULL)
  1105. {
  1106. NdisFreePacketPool(g_nhPacketPool);
  1107. g_nhPacketPool = NULL;
  1108. }
  1109. NdisDeregisterProtocol(&nStatus,
  1110. g_nhWanarpProtoHandle);
  1111. g_nhWanarpProtoHandle = NULL;
  1112. }
  1113. VOID
  1114. WanNdisUnload(
  1115. VOID
  1116. )
  1117. {
  1118. return;
  1119. }
  1120. #pragma alloc_text(PAGE, OpenRegKey)
  1121. NTSTATUS
  1122. OpenRegKey(
  1123. OUT PHANDLE phHandle,
  1124. IN PUNICODE_STRING pusKeyName
  1125. )
  1126. {
  1127. NTSTATUS Status;
  1128. OBJECT_ATTRIBUTES ObjectAttributes;
  1129. PAGED_CODE();
  1130. RtlZeroMemory(&ObjectAttributes,
  1131. sizeof(OBJECT_ATTRIBUTES));
  1132. InitializeObjectAttributes(&ObjectAttributes,
  1133. pusKeyName,
  1134. OBJ_CASE_INSENSITIVE,
  1135. NULL,
  1136. NULL);
  1137. Status = ZwOpenKey(phHandle,
  1138. KEY_READ,
  1139. &ObjectAttributes);
  1140. return Status;
  1141. }
  1142. #pragma alloc_text(PAGE, GetRegDWORDValue)
  1143. NTSTATUS
  1144. GetRegDWORDValue(
  1145. HANDLE KeyHandle,
  1146. PWCHAR ValueName,
  1147. PULONG ValueData
  1148. )
  1149. {
  1150. NTSTATUS status;
  1151. ULONG resultLength;
  1152. PKEY_VALUE_FULL_INFORMATION keyValueFullInformation;
  1153. UCHAR keybuf[128];
  1154. UNICODE_STRING UValueName;
  1155. PAGED_CODE();
  1156. RtlInitUnicodeString(&UValueName, ValueName);
  1157. keyValueFullInformation = (PKEY_VALUE_FULL_INFORMATION)keybuf;
  1158. RtlZeroMemory(keyValueFullInformation, sizeof(keyValueFullInformation));
  1159. status = ZwQueryValueKey(KeyHandle,
  1160. &UValueName,
  1161. KeyValueFullInformation,
  1162. keyValueFullInformation,
  1163. 128,
  1164. &resultLength);
  1165. if (NT_SUCCESS(status)) {
  1166. if (keyValueFullInformation->Type != REG_DWORD) {
  1167. status = STATUS_INVALID_PARAMETER_MIX;
  1168. } else {
  1169. *ValueData = *((ULONG UNALIGNED *)((PCHAR)keyValueFullInformation +
  1170. keyValueFullInformation->DataOffset));
  1171. }
  1172. }
  1173. return status;
  1174. }
  1175. BOOLEAN
  1176. IsEntryOnList(
  1177. PLIST_ENTRY pleHead,
  1178. PLIST_ENTRY pleEntry
  1179. )
  1180. {
  1181. PLIST_ENTRY pleNode;
  1182. for(pleNode = pleHead->Flink;
  1183. pleNode isnot pleHead;
  1184. pleNode = pleNode->Flink)
  1185. {
  1186. if(pleNode is pleEntry)
  1187. {
  1188. return TRUE;
  1189. }
  1190. }
  1191. return FALSE;
  1192. }
  1193. VOID
  1194. WanpInitializeResource(
  1195. IN PWAN_RESOURCE pLock
  1196. )
  1197. {
  1198. pLock->lWaitCount = 0;
  1199. KeInitializeEvent(&(pLock->keEvent),
  1200. SynchronizationEvent,
  1201. FALSE);
  1202. }
  1203. VOID
  1204. WanpAcquireResource(
  1205. IN PWAN_RESOURCE pLock
  1206. )
  1207. {
  1208. LONG lNumWaiters;
  1209. NTSTATUS nStatus;
  1210. lNumWaiters = InterlockedIncrement(&(pLock->lWaitCount));
  1211. RtAssert(lNumWaiters >= 1);
  1212. if(lNumWaiters isnot 1)
  1213. {
  1214. nStatus = KeWaitForSingleObject(&(pLock->keEvent),
  1215. Executive,
  1216. KernelMode,
  1217. FALSE,
  1218. NULL);
  1219. }
  1220. }
  1221. VOID
  1222. WanpReleaseResource(
  1223. IN PWAN_RESOURCE pLock
  1224. )
  1225. {
  1226. LONG lNumWaiters;
  1227. lNumWaiters = InterlockedDecrement(&(pLock->lWaitCount));
  1228. RtAssert(lNumWaiters >= 0);
  1229. if(lNumWaiters isnot 0)
  1230. {
  1231. KeSetEvent(&(pLock->keEvent),
  1232. 0,
  1233. FALSE);
  1234. }
  1235. }
  1236. VOID
  1237. WanpClearPendingIrps(
  1238. VOID
  1239. )
  1240. /*++
  1241. Routine Description:
  1242. Called at cleanup time to return any pending IRPs
  1243. Locks:
  1244. Acquires the IoCancelSpinLock since it controls the pending irp list
  1245. Arguments:
  1246. None
  1247. Return Value:
  1248. None
  1249. --*/
  1250. {
  1251. KIRQL irql;
  1252. TraceEnter(GLOBAL, "ClearPendingIrps");
  1253. IoAcquireCancelSpinLock (&irql);
  1254. while(!IsListEmpty(&g_lePendingIrpList))
  1255. {
  1256. PLIST_ENTRY pleNode;
  1257. PIRP pIrp;
  1258. pleNode = RemoveHeadList(&g_lePendingIrpList);
  1259. pIrp = CONTAINING_RECORD(pleNode,
  1260. IRP,
  1261. Tail.Overlay.ListEntry);
  1262. IoSetCancelRoutine(pIrp,
  1263. NULL);
  1264. pIrp->IoStatus.Status = STATUS_NO_SUCH_DEVICE;
  1265. pIrp->IoStatus.Information = 0;
  1266. //
  1267. // release lock to complete the IRP
  1268. //
  1269. IoReleaseCancelSpinLock(irql);
  1270. IoCompleteRequest(pIrp,
  1271. IO_NETWORK_INCREMENT);
  1272. //
  1273. // Reaquire the lock
  1274. //
  1275. IoAcquireCancelSpinLock(&irql);
  1276. }
  1277. IoReleaseCancelSpinLock(irql);
  1278. }