Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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