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.

1102 lines
29 KiB

  1. //
  2. // UIOTEST.C
  3. //
  4. // Test program for tunmp.sys
  5. //
  6. // usage: UIOTEST [options] <devicename>
  7. //
  8. // options:
  9. // -e: Enumerate devices
  10. // -r: Read
  11. // -w: Write (default)
  12. // -l <length>: length of each packet (default: %d)\n", PacketLength
  13. // -n <count>: number of packets (defaults to infinity)
  14. // -m <MAC address> (defaults to local MAC)
  15. //
  16. #include <windows.h>
  17. #include <winioctl.h>
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include <memory.h>
  22. #include <ctype.h>
  23. #include <malloc.h>
  24. #include <winerror.h>
  25. #include <winsock.h>
  26. #include <ntddndis.h>
  27. #include "tunuser.h"
  28. #include "nuiouser.h"
  29. #include <ndisguid.h>
  30. #include <wmium.h>
  31. #ifndef NDIS_STATUS
  32. #define NDIS_STATUS ULONG
  33. #endif
  34. #if DBG
  35. #define DEBUGP(stmt) printf stmt
  36. #else
  37. #define DEBUGP(stmt)
  38. #endif
  39. #define PRINTF(stmt) printf stmt
  40. #ifndef MAC_ADDR_LEN
  41. #define MAC_ADDR_LEN 6
  42. #endif
  43. #define MAX_NDIS_DEVICE_NAME_LEN 256
  44. #define MAX_ADAPTER_NAME_LENGTH 512
  45. #define DEVICE_PREFIX L"\\Device\\"
  46. //DEFINE_GUID(GUID_NDIS_NOTIFY_DEVICE_POWER_ON, 0x5f81cfd0, 0xf046, 0x4342, 0xaf, 0x61, 0x89, 0x5a, 0xce, 0xda, 0xef, 0xd9);
  47. //DEFINE_GUID(GUID_NDIS_NOTIFY_DEVICE_POWER_OFF, 0x81bc8189, 0xb026, 0x46ab, 0xb9, 0x64, 0xf1, 0x82, 0xe3, 0x42, 0x93, 0x4e);
  48. //#include <initguid.h>
  49. //DEFINE_GUID(GUID_NDIS_NOTIFY_DEVICE_POWER_ON_X, 0x5f81cfd0, 0xf046, 0x4342, 0xaf, 0x61, 0x89, 0x5a, 0xce, 0xda, 0xef, 0xd9);
  50. //DEFINE_GUID(GUID_NDIS_NOTIFY_DEVICE_POWER_OFF_X, 0x81bc8189, 0xb026, 0x46ab, 0xb9, 0x64, 0xf1, 0x82, 0xe3, 0x42, 0x93, 0x4e);
  51. LPGUID WmiEvent[] = {
  52. (LPGUID) &GUID_NDIS_NOTIFY_ADAPTER_ARRIVAL,
  53. (LPGUID) &GUID_NDIS_NOTIFY_ADAPTER_REMOVAL,
  54. (LPGUID) &GUID_NDIS_NOTIFY_DEVICE_POWER_ON,
  55. (LPGUID) &GUID_NDIS_NOTIFY_DEVICE_POWER_OFF
  56. };
  57. CHAR NdisuioDevice[] = "\\\\.\\\\Ndisuio";
  58. CHAR * pNdisuioDevice = &NdisuioDevice[0];
  59. CHAR TunDevice[] = "\\\\.\\\\Tun0";
  60. CHAR * pTunDevice = &TunDevice[0];
  61. BOOLEAN DoEnumerate = FALSE;
  62. BOOLEAN DoReads = FALSE;
  63. INT NumberOfPackets = -1;
  64. ULONG PacketLength = 100;
  65. UCHAR SrcMacAddr[MAC_ADDR_LEN];
  66. UCHAR DstMacAddr[MAC_ADDR_LEN];
  67. BOOLEAN bDstMacSpecified = FALSE;
  68. CHAR * pNdisDeviceName = "JUNK";
  69. USHORT EthType = 0x8e88;
  70. HANDLE UioDeviceHandle, TunDeviceHandle;
  71. BOOLEAN UioDeviceClosed = FALSE;
  72. BOOLEAN TunDeviceClosed = FALSE;
  73. VOID CALLBACK
  74. UioIoCompletion(
  75. DWORD dwErrorCode, // completion code
  76. DWORD dwNumberOfBytesTransfered, // number of bytes transferred
  77. LPOVERLAPPED lpOverlapped // I/O information buffer
  78. );
  79. VOID CALLBACK
  80. TunIoCompletion(
  81. DWORD dwErrorCode, // completion code
  82. DWORD dwNumberOfBytesTransfered, // number of bytes transferred
  83. LPOVERLAPPED lpOverlapped // I/O information buffer
  84. );
  85. /*
  86. typedef struct _OVERLAPPED {
  87. ULONG_PTR Internal;
  88. ULONG_PTR InternalHigh;
  89. DWORD Offset;
  90. DWORD OffsetHigh;
  91. HANDLE hEvent;
  92. } OVERLAPPED;
  93. */
  94. DWORD
  95. __inline
  96. EnableWmiEvent(
  97. IN LPGUID EventGuid,
  98. IN BOOLEAN Enable
  99. );
  100. VOID
  101. __inline
  102. DeregisterWmiEventNotification(
  103. VOID
  104. );
  105. DWORD
  106. __inline
  107. RegisterWmiEventNotification(
  108. VOID
  109. );
  110. VOID
  111. WINAPI
  112. WmiEventNotification(
  113. IN PWNODE_HEADER Event,
  114. IN UINT_PTR Context
  115. );
  116. typedef enum _TEST_IO_TYPE
  117. {
  118. TestIoTypeRead,
  119. TestIoTypeWrite
  120. } TEST_IO_TYPE;
  121. typedef struct _TEST_IO_COMPLETION
  122. {
  123. OVERLAPPED OverLappedIo;
  124. TEST_IO_TYPE Type;
  125. PVOID Buffer;
  126. } TEST_IO_COMPLETION, *PTEST_IO_COMPLETION;
  127. TEST_IO_COMPLETION UioOverlappedIo[5];
  128. TEST_IO_COMPLETION TunOverlappedIo[5];
  129. PVOID ReadUioBuffer[5], ReadTunBuffer[5];
  130. #include <pshpack1.h>
  131. typedef struct _ETH_HEADER
  132. {
  133. UCHAR DstAddr[MAC_ADDR_LEN];
  134. UCHAR SrcAddr[MAC_ADDR_LEN];
  135. USHORT EthType;
  136. } ETH_HEADER, *PETH_HEADER;
  137. #include <poppack.h>
  138. VOID
  139. PrintUsage()
  140. {
  141. PRINTF(("usage: TUNTEST [options] <devicename>\n"));
  142. PRINTF(("options:\n"));
  143. PRINTF((" -e: Enumerate devices\n"));
  144. PRINTF((" -r: Read\n"));
  145. PRINTF((" -w: Write (default)\n"));
  146. PRINTF((" -l <length>: length of each packet (default: %d)\n", PacketLength));
  147. PRINTF((" -n <count>: number of packets (defaults to infinity)\n"));
  148. PRINTF((" -m <MAC address> (defaults to local MAC)\n"));
  149. }
  150. BOOL
  151. GetOptions(
  152. INT argc,
  153. CHAR *argv[]
  154. )
  155. {
  156. BOOL bOkay;
  157. INT i, j, increment;
  158. CHAR *pOption;
  159. ULONG DstMacAddrUlong[MAC_ADDR_LEN];
  160. bOkay = TRUE;
  161. do
  162. {
  163. if (argc < 2)
  164. {
  165. PRINTF(("Missing <devicename> argument\n"));
  166. bOkay = FALSE;
  167. break;
  168. }
  169. i = 1;
  170. while (i < argc)
  171. {
  172. increment = 1;
  173. pOption = argv[i];
  174. if ((*pOption == '-') || (*pOption == '/'))
  175. {
  176. pOption++;
  177. if (*pOption == '\0')
  178. {
  179. DEBUGP(("Badly formed option\n"));
  180. return (FALSE);
  181. }
  182. }
  183. else
  184. {
  185. break;
  186. }
  187. switch (*pOption)
  188. {
  189. case 'e':
  190. DoEnumerate = TRUE;
  191. break;
  192. case 'r':
  193. DoReads = TRUE;
  194. break;
  195. case 'w':
  196. DoReads = FALSE;
  197. break;
  198. case 'l':
  199. if (i+1 < argc-1)
  200. {
  201. sscanf(argv[i+1], "%d", &PacketLength);
  202. DEBUGP((" Option: PacketLength = %d\n", PacketLength));
  203. increment = 2;
  204. }
  205. else
  206. {
  207. PRINTF(("Option l needs PacketLength parameter\n"));
  208. return (FALSE);
  209. }
  210. break;
  211. case 'n':
  212. if (i+1 < argc-1)
  213. {
  214. sscanf(argv[i+1], "%d", &NumberOfPackets);
  215. DEBUGP((" Option: NumberOfPackets = %d\n", NumberOfPackets));
  216. increment = 2;
  217. }
  218. else
  219. {
  220. PRINTF(("Option n needs NumberOfPackets parameter\n"));
  221. return (FALSE);
  222. }
  223. break;
  224. case 'm':
  225. if (i+1 < argc-1)
  226. {
  227. sscanf(argv[i+1], "%2x:%2x:%2x:%2x:%2x:%2x",
  228. &DstMacAddrUlong[0],
  229. &DstMacAddrUlong[1],
  230. &DstMacAddrUlong[2],
  231. &DstMacAddrUlong[3],
  232. &DstMacAddrUlong[4],
  233. &DstMacAddrUlong[5]);
  234. for (j = 0; j < MAC_ADDR_LEN; j++)
  235. {
  236. DstMacAddr[j] = (UCHAR)DstMacAddrUlong[j];
  237. }
  238. DEBUGP((" Option: Dest MAC Addr: %02x:%02x:%02x:%02x:%02x:%02x\n",
  239. DstMacAddr[0],
  240. DstMacAddr[1],
  241. DstMacAddr[2],
  242. DstMacAddr[3],
  243. DstMacAddr[4],
  244. DstMacAddr[5]));
  245. bDstMacSpecified = TRUE;
  246. increment = 2;
  247. }
  248. else
  249. {
  250. PRINTF(("Option m needs MAC address parameter\n"));
  251. return (FALSE);
  252. }
  253. break;
  254. case '?':
  255. return (FALSE);
  256. default:
  257. PRINTF(("Unknown option %c\n", *pOption));
  258. return (FALSE);
  259. }
  260. i+= increment;
  261. }
  262. pNdisDeviceName = argv[argc-1];
  263. break;
  264. }
  265. while (FALSE);
  266. return (bOkay);
  267. }
  268. HANDLE
  269. OpenHandle(
  270. CHAR *pDeviceName,
  271. BOOLEAN fWaitForBind
  272. )
  273. {
  274. DWORD DesiredAccess;
  275. DWORD ShareMode;
  276. LPSECURITY_ATTRIBUTES lpSecurityAttributes = NULL;
  277. DWORD CreationDistribution;
  278. DWORD FlagsAndAttributes;
  279. HANDLE TemplateFile;
  280. HANDLE Handle;
  281. DWORD BytesReturned;
  282. DesiredAccess = GENERIC_READ|GENERIC_WRITE;
  283. ShareMode = 0;
  284. CreationDistribution = OPEN_EXISTING;
  285. FlagsAndAttributes = FILE_FLAG_OVERLAPPED;
  286. TemplateFile = (HANDLE)INVALID_HANDLE_VALUE;
  287. Handle = CreateFile(
  288. pDeviceName,
  289. DesiredAccess,
  290. ShareMode,
  291. lpSecurityAttributes,
  292. CreationDistribution,
  293. FlagsAndAttributes,
  294. TemplateFile
  295. );
  296. if ((Handle != INVALID_HANDLE_VALUE) && fWaitForBind)
  297. {
  298. //
  299. // Wait for the driver to finish binding.
  300. //
  301. if (!DeviceIoControl(
  302. Handle,
  303. IOCTL_NDISUIO_BIND_WAIT,
  304. NULL,
  305. 0,
  306. NULL,
  307. 0,
  308. &BytesReturned,
  309. NULL))
  310. {
  311. DEBUGP(("IOCTL_NDISIO_BIND_WAIT failed, error %x\n", GetLastError()));
  312. CloseHandle(Handle);
  313. Handle = INVALID_HANDLE_VALUE;
  314. }
  315. }
  316. return (Handle);
  317. }
  318. BOOL
  319. OpenNdisDevice(
  320. HANDLE Handle,
  321. CHAR *pDeviceName
  322. )
  323. {
  324. WCHAR wNdisDeviceName[MAX_NDIS_DEVICE_NAME_LEN];
  325. INT wNameLength;
  326. INT NameLength = strlen(pDeviceName);
  327. DWORD BytesReturned;
  328. INT i;
  329. //
  330. // Convert to unicode string - non-localized...
  331. //
  332. wNameLength = 0;
  333. for (i = 0; i < NameLength && i < MAX_NDIS_DEVICE_NAME_LEN-1; i++)
  334. {
  335. wNdisDeviceName[i] = (WCHAR)pDeviceName[i];
  336. wNameLength++;
  337. }
  338. wNdisDeviceName[i] = L'\0';
  339. DEBUGP(("Trying to access NDIS Device: %ws\n", wNdisDeviceName));
  340. return (DeviceIoControl(
  341. Handle,
  342. IOCTL_NDISUIO_OPEN_DEVICE,
  343. (LPVOID)&wNdisDeviceName[0],
  344. wNameLength*sizeof(WCHAR),
  345. NULL,
  346. 0,
  347. &BytesReturned,
  348. NULL));
  349. }
  350. BOOL
  351. GetSrcMac(
  352. HANDLE Handle,
  353. PUCHAR pSrcMacAddr
  354. )
  355. {
  356. DWORD BytesReturned;
  357. BOOLEAN bSuccess;
  358. UCHAR QueryBuffer[sizeof(NDISUIO_QUERY_OID) + MAC_ADDR_LEN];
  359. PNDISUIO_QUERY_OID pQueryOid;
  360. DEBUGP(("Trying to get src mac address\n"));
  361. pQueryOid = (PNDISUIO_QUERY_OID)&QueryBuffer[0];
  362. pQueryOid->Oid = OID_802_3_CURRENT_ADDRESS;
  363. bSuccess = (BOOLEAN)DeviceIoControl(
  364. Handle,
  365. IOCTL_NDISUIO_QUERY_OID_VALUE,
  366. (LPVOID)&QueryBuffer[0],
  367. sizeof(QueryBuffer),
  368. (LPVOID)&QueryBuffer[0],
  369. sizeof(QueryBuffer),
  370. &BytesReturned,
  371. NULL);
  372. if (bSuccess)
  373. {
  374. DEBUGP(("GetSrcMac: IoControl success, BytesReturned = %d\n",
  375. BytesReturned));
  376. memcpy(pSrcMacAddr, pQueryOid->Data, MAC_ADDR_LEN);
  377. }
  378. else
  379. {
  380. DEBUGP(("GetSrcMac: IoControl failed: %d\n", GetLastError()));
  381. }
  382. return (bSuccess);
  383. }
  384. BOOL
  385. SetPacketFilter(
  386. HANDLE Handle,
  387. ULONG FilterValue
  388. )
  389. {
  390. BOOLEAN bSuccess;
  391. UCHAR SetBuffer[sizeof(NDISUIO_SET_OID)];
  392. PNDISUIO_SET_OID pSetOid;
  393. DWORD BytesReturned;
  394. DEBUGP(("Trying to set packet filter to %x\n", FilterValue));
  395. pSetOid = (PNDISUIO_SET_OID)&SetBuffer[0];
  396. pSetOid->Oid = OID_GEN_CURRENT_PACKET_FILTER;
  397. memcpy(&pSetOid->Data[0], &FilterValue, sizeof(FilterValue));
  398. bSuccess = (BOOLEAN)DeviceIoControl(
  399. Handle,
  400. IOCTL_NDISUIO_SET_OID_VALUE,
  401. (LPVOID)&SetBuffer[0],
  402. sizeof(SetBuffer),
  403. (LPVOID)&SetBuffer[0],
  404. 0,
  405. &BytesReturned,
  406. NULL);
  407. if (bSuccess)
  408. {
  409. DEBUGP(("SetPacketFilter: IoControl success\n"));
  410. }
  411. else
  412. {
  413. DEBUGP(("SetPacketFilter: IoControl failed %x\n", GetLastError()));
  414. }
  415. return (bSuccess);
  416. }
  417. VOID
  418. EnumerateDevices(
  419. HANDLE Handle
  420. )
  421. {
  422. CHAR Buf[1024];
  423. DWORD BufLength = sizeof(Buf);
  424. DWORD BytesWritten;
  425. DWORD i;
  426. PNDISUIO_QUERY_BINDING pQueryBinding;
  427. pQueryBinding = (PNDISUIO_QUERY_BINDING)Buf;
  428. i = 0;
  429. for (pQueryBinding->BindingIndex = i;
  430. /* NOTHING */;
  431. pQueryBinding->BindingIndex = ++i)
  432. {
  433. if (DeviceIoControl(
  434. Handle,
  435. IOCTL_NDISUIO_QUERY_BINDING,
  436. pQueryBinding,
  437. sizeof(NDISUIO_QUERY_BINDING),
  438. Buf,
  439. BufLength,
  440. &BytesWritten,
  441. NULL))
  442. {
  443. PRINTF(("%2d. %ws\n - %ws\n",
  444. pQueryBinding->BindingIndex,
  445. (PUCHAR)pQueryBinding + pQueryBinding->DeviceNameOffset,
  446. (PUCHAR)pQueryBinding + pQueryBinding->DeviceDescrOffset));
  447. memset(Buf, 0, BufLength);
  448. }
  449. else
  450. {
  451. ULONG rc = GetLastError();
  452. if (rc != ERROR_NO_MORE_ITEMS)
  453. {
  454. PRINTF(("EnumerateDevices: terminated abnormally, error %d\n", rc));
  455. }
  456. break;
  457. }
  458. }
  459. }
  460. VOID __cdecl
  461. main(
  462. INT argc,
  463. CHAR *argv[]
  464. )
  465. {
  466. ULONG FilterValue;
  467. UINT i;
  468. DWORD BytesWritten, BytesRead;
  469. DWORD ErrorCode;
  470. BOOLEAN bSuccess;
  471. //
  472. // test wmi
  473. //
  474. {
  475. if ((ErrorCode = RegisterWmiEventNotification()) != NO_ERROR)
  476. {
  477. printf("error %d calling RegisterWmiEventNotification.\n", ErrorCode);
  478. return;
  479. }
  480. while (_fgetchar() != 'q')
  481. {
  482. Sleep(1000);
  483. }
  484. DeregisterWmiEventNotification();
  485. return;
  486. }
  487. UioDeviceHandle = TunDeviceHandle = INVALID_HANDLE_VALUE;
  488. do
  489. {
  490. for (i = 0; i < 5; i++)
  491. {
  492. ReadUioBuffer[i] = ReadTunBuffer[i] = NULL;
  493. }
  494. if (!GetOptions(argc, argv))
  495. {
  496. PrintUsage();
  497. break;
  498. }
  499. UioDeviceHandle = OpenHandle(pNdisuioDevice, TRUE);
  500. if (UioDeviceHandle == INVALID_HANDLE_VALUE)
  501. {
  502. PRINTF(("Failed to open %s\n", pNdisuioDevice));
  503. break;
  504. }
  505. if (DoEnumerate)
  506. {
  507. EnumerateDevices(UioDeviceHandle);
  508. break;
  509. }
  510. TunDeviceHandle = OpenHandle(TunDevice, FALSE);
  511. if (TunDeviceHandle == INVALID_HANDLE_VALUE)
  512. {
  513. PRINTF(("Failed to open %s\n", pTunDevice));
  514. break;
  515. }
  516. {
  517. WCHAR wTunMiniportName[MAX_NDIS_DEVICE_NAME_LEN];
  518. UCHAR MiniportName[MAX_NDIS_DEVICE_NAME_LEN];
  519. INT wNameLength;
  520. DWORD BytesReturned;
  521. memset((LPVOID)wTunMiniportName, 0, MAX_NDIS_DEVICE_NAME_LEN);
  522. if (DeviceIoControl(
  523. TunDeviceHandle,
  524. IOCTL_TUN_GET_MINIPORT_NAME,
  525. NULL,
  526. 0,
  527. (LPVOID)&wTunMiniportName[0],
  528. MAX_NDIS_DEVICE_NAME_LEN,
  529. &BytesReturned,
  530. NULL))
  531. {
  532. printf("Tun Miniport Name: %ws\n", (PUCHAR)wTunMiniportName + sizeof(USHORT));
  533. /*
  534. NameLength = *(PUSHORT)wTunMiniportName;
  535. for (i = 0; i < NameLength && i < MAX_NDIS_DEVICE_NAME_LEN-1; i++)
  536. {
  537. wNdisDeviceName[i] = (WCHAR)pDeviceName[i];
  538. wNameLength++;
  539. }
  540. wNdisDeviceName[i] = L'\0';
  541. */
  542. }
  543. else
  544. {
  545. printf("failed to get the miniport name.\n");
  546. }
  547. }
  548. if (!OpenNdisDevice(UioDeviceHandle, pNdisDeviceName))
  549. {
  550. PRINTF(("Failed to access %s\n", pNdisDeviceName));
  551. break;
  552. }
  553. DEBUGP(("Opened device %s successfully!\n", pNdisDeviceName));
  554. if (!GetSrcMac(UioDeviceHandle, SrcMacAddr))
  555. {
  556. PRINTF(("Failed to obtain local MAC address\n"));
  557. break;
  558. }
  559. FilterValue = NDIS_PACKET_TYPE_DIRECTED |
  560. NDIS_PACKET_TYPE_BROADCAST |
  561. NDIS_PACKET_TYPE_ALL_MULTICAST;
  562. DEBUGP(("Got local MAC: %02x:%02x:%02x:%02x:%02x:%02x\n",
  563. SrcMacAddr[0],
  564. SrcMacAddr[1],
  565. SrcMacAddr[2],
  566. SrcMacAddr[3],
  567. SrcMacAddr[4],
  568. SrcMacAddr[5]));
  569. if (!bDstMacSpecified)
  570. {
  571. memcpy(DstMacAddr, SrcMacAddr, MAC_ADDR_LEN);
  572. }
  573. if (!SetPacketFilter(UioDeviceHandle, FilterValue))
  574. {
  575. PRINTF(("Failed to set packet filter\n"));
  576. break;
  577. }
  578. for (i = 0; i < 5; i++)
  579. {
  580. if ((ReadUioBuffer[i] = malloc(1512)) == NULL)
  581. {
  582. PRINTF(("Failed to allocate memory for reading Uio device.\n"));
  583. break;
  584. }
  585. memset((PUCHAR)&UioOverlappedIo[i], 0, sizeof (TEST_IO_COMPLETION));
  586. UioOverlappedIo[i].Buffer = ReadUioBuffer[i];
  587. UioOverlappedIo[i].Type = TestIoTypeRead;
  588. if ((ReadTunBuffer[i] = malloc(1512)) == NULL)
  589. {
  590. PRINTF(("Failed to allocate memory for reading Tun device.\n"));
  591. break;
  592. }
  593. memset((PUCHAR)&TunOverlappedIo[i], 0, sizeof (TEST_IO_COMPLETION));
  594. TunOverlappedIo[i].Buffer = ReadTunBuffer[i];
  595. TunOverlappedIo[i].Type = TestIoTypeRead;
  596. }
  597. if (i < 5)
  598. {
  599. break;
  600. }
  601. if (!BindIoCompletionCallback(
  602. UioDeviceHandle,
  603. UioIoCompletion,
  604. 0))
  605. {
  606. break;
  607. }
  608. if (!BindIoCompletionCallback(
  609. TunDeviceHandle,
  610. TunIoCompletion,
  611. 0))
  612. {
  613. break;
  614. }
  615. for (i = 0; i < 5; i++)
  616. {
  617. //
  618. // post reads from ndis uio
  619. //
  620. bSuccess = (BOOLEAN)ReadFile(
  621. UioDeviceHandle,
  622. (LPVOID)UioOverlappedIo[i].Buffer,
  623. 1500,
  624. &BytesRead,
  625. &UioOverlappedIo[i].OverLappedIo);
  626. bSuccess = (BOOLEAN)ReadFile(
  627. TunDeviceHandle,
  628. (LPVOID)TunOverlappedIo[i].Buffer,
  629. 1500,
  630. &BytesRead,
  631. &TunOverlappedIo[i].OverLappedIo);
  632. }
  633. }
  634. while (FALSE);
  635. while (_fgetchar() != 'q')
  636. {
  637. Sleep(1000);
  638. }
  639. if (UioDeviceHandle != INVALID_HANDLE_VALUE)
  640. {
  641. CancelIo(UioDeviceHandle);
  642. UioDeviceClosed = TRUE;
  643. Sleep(1000);
  644. CloseHandle(UioDeviceHandle);
  645. }
  646. if (TunDeviceHandle != INVALID_HANDLE_VALUE)
  647. {
  648. CancelIo(TunDeviceHandle);
  649. TunDeviceClosed = TRUE;
  650. Sleep(1000);
  651. CloseHandle(TunDeviceHandle);
  652. }
  653. for (i = 0; i < 5; i++)
  654. {
  655. if (ReadTunBuffer[i])
  656. free(ReadTunBuffer[i]);
  657. if (ReadUioBuffer[i])
  658. free(ReadUioBuffer[i]);
  659. }
  660. }
  661. VOID CALLBACK
  662. UioIoCompletion(
  663. DWORD dwErrorCode, // completion code
  664. DWORD dwNumberOfBytesTransfered, // number of bytes transferred
  665. LPOVERLAPPED lpOverlapped // I/O information buffer
  666. )
  667. {
  668. PTEST_IO_COMPLETION pTestIoComp = (PTEST_IO_COMPLETION)lpOverlapped;
  669. DWORD BytesWritten, BytesRead;
  670. BOOLEAN bSuccess;
  671. if (UioDeviceClosed || TunDeviceClosed)
  672. return;
  673. //
  674. // determine if this was a read or write
  675. //
  676. if (pTestIoComp->Type == TestIoTypeRead)
  677. {
  678. if (dwErrorCode == 0)
  679. {
  680. //
  681. // a read to uio device got completed. post a write to
  682. // Tun device with the same data.
  683. //
  684. pTestIoComp->Type = TestIoTypeWrite;
  685. bSuccess = (BOOLEAN)WriteFile(
  686. TunDeviceHandle,
  687. pTestIoComp->Buffer,
  688. dwNumberOfBytesTransfered,
  689. &BytesWritten,
  690. lpOverlapped);
  691. }
  692. else
  693. {
  694. //
  695. // post another read
  696. //
  697. bSuccess = (BOOLEAN)ReadFile(
  698. UioDeviceHandle,
  699. (LPVOID)pTestIoComp->Buffer,
  700. 1500,
  701. &BytesRead,
  702. lpOverlapped);
  703. }
  704. }
  705. else
  706. {
  707. //
  708. // a write to uio device just got completed.
  709. // post a read to Tun device.
  710. //
  711. pTestIoComp->Type = TestIoTypeRead;
  712. bSuccess = (BOOLEAN)ReadFile(
  713. TunDeviceHandle,
  714. (LPVOID)pTestIoComp->Buffer,
  715. 1500,
  716. &BytesRead,
  717. lpOverlapped);
  718. }
  719. }
  720. VOID CALLBACK
  721. TunIoCompletion(
  722. DWORD dwErrorCode, // completion code
  723. DWORD dwNumberOfBytesTransfered, // number of bytes transferred
  724. LPOVERLAPPED lpOverlapped // I/O information buffer
  725. )
  726. {
  727. PTEST_IO_COMPLETION pTestIoComp = (PTEST_IO_COMPLETION)lpOverlapped;
  728. DWORD BytesWritten, BytesRead;
  729. BOOLEAN bSuccess;
  730. if (UioDeviceClosed || TunDeviceClosed)
  731. return;
  732. //
  733. // determine if this was a read or write
  734. //
  735. if (pTestIoComp->Type == TestIoTypeRead)
  736. {
  737. if (dwErrorCode == 0)
  738. {
  739. //
  740. // a read to Tun device got completed. post a write to
  741. // uio device with the same data.
  742. //
  743. pTestIoComp->Type = TestIoTypeWrite;
  744. bSuccess = (BOOLEAN)WriteFile(
  745. UioDeviceHandle,
  746. pTestIoComp->Buffer,
  747. dwNumberOfBytesTransfered,
  748. &BytesWritten,
  749. lpOverlapped);
  750. }
  751. else
  752. {
  753. //
  754. // post another read
  755. //
  756. bSuccess = (BOOLEAN)ReadFile(
  757. TunDeviceHandle,
  758. (LPVOID)pTestIoComp->Buffer,
  759. 1500,
  760. &BytesRead,
  761. lpOverlapped);
  762. }
  763. }
  764. else
  765. {
  766. //
  767. // a write to Tun device just got completed.
  768. // post a read to Uio device.
  769. //
  770. pTestIoComp->Type = TestIoTypeRead;
  771. bSuccess = (BOOLEAN)ReadFile(
  772. UioDeviceHandle,
  773. (LPVOID)pTestIoComp->Buffer,
  774. 1500,
  775. &BytesRead,
  776. lpOverlapped);
  777. }
  778. }
  779. DWORD
  780. __inline
  781. EnableWmiEvent(
  782. IN LPGUID EventGuid,
  783. IN BOOLEAN Enable
  784. )
  785. {
  786. return WmiNotificationRegistrationW(
  787. EventGuid, // Event Type.
  788. Enable, // Enable or Disable.
  789. WmiEventNotification, // Callback.
  790. 0, // Context.
  791. NOTIFICATION_CALLBACK_DIRECT); // Notification Flags.
  792. }
  793. VOID
  794. __inline
  795. DeregisterWmiEventNotification(
  796. VOID
  797. )
  798. {
  799. int i;
  800. for (i = 0; i < (sizeof(WmiEvent) / sizeof(LPGUID)); i++) {
  801. (VOID) EnableWmiEvent(WmiEvent[i], FALSE);
  802. }
  803. }
  804. DWORD
  805. __inline
  806. RegisterWmiEventNotification(
  807. VOID
  808. )
  809. {
  810. DWORD Error;
  811. int i;
  812. for (i = 0; i < (sizeof(WmiEvent) / sizeof(LPGUID)); i++) {
  813. Error = EnableWmiEvent(WmiEvent[i], TRUE);
  814. if (Error != NO_ERROR) {
  815. goto Bail;
  816. }
  817. }
  818. return NO_ERROR;
  819. Bail:
  820. DeregisterWmiEventNotification();
  821. return Error;
  822. }
  823. VOID
  824. WINAPI
  825. WmiEventNotification(
  826. IN PWNODE_HEADER Event,
  827. IN UINT_PTR Context
  828. )
  829. /*++
  830. Routine Description:
  831. Process a WMI event (specifically adapter arrival or removal).
  832. Arguments:
  833. Event - Supplies event specific information.
  834. Context - Supplies the context registered.
  835. Return Value:
  836. None.
  837. --*/
  838. {
  839. PWNODE_SINGLE_INSTANCE Instance = (PWNODE_SINGLE_INSTANCE) Event;
  840. USHORT AdapterNameLength;
  841. WCHAR AdapterName[MAX_ADAPTER_NAME_LENGTH], *AdapterGuid;
  842. USHORT AdapterInstanceNameLength;
  843. WCHAR AdapterInstanceName[MAX_ADAPTER_NAME_LENGTH];
  844. if (Instance == NULL) {
  845. return;
  846. }
  847. //
  848. // WNODE_SINGLE_INSTANCE is organized thus...
  849. // +-----------------------------------------------------------+
  850. // |<--- DataBlockOffset --->| AdapterNameLength | AdapterName |
  851. // +-----------------------------------------------------------+
  852. //
  853. // AdapterName is defined as "\DEVICE\"AdapterGuid
  854. //
  855. AdapterNameLength =
  856. *((PUSHORT) (((PUCHAR) Instance) + Instance->DataBlockOffset));
  857. RtlCopyMemory(
  858. AdapterName,
  859. ((PUCHAR) Instance) + Instance->DataBlockOffset + sizeof(USHORT),
  860. AdapterNameLength);
  861. AdapterName[AdapterNameLength / sizeof(WCHAR)] = L'\0';
  862. AdapterGuid = AdapterName + wcslen(DEVICE_PREFIX);
  863. AdapterInstanceNameLength =
  864. *((PUSHORT) (((PUCHAR) Instance) + Instance->OffsetInstanceName));
  865. RtlCopyMemory(
  866. AdapterInstanceName,
  867. ((PUCHAR) Instance) + Instance->OffsetInstanceName + sizeof(USHORT),
  868. AdapterInstanceNameLength);
  869. if (AdapterInstanceNameLength < MAX_ADAPTER_NAME_LENGTH - 1)
  870. {
  871. AdapterInstanceName[AdapterInstanceNameLength / sizeof(WCHAR)] = L'\0';
  872. }
  873. else
  874. {
  875. AdapterInstanceName[MAX_ADAPTER_NAME_LENGTH - 1] = L'\0';
  876. }
  877. if (memcmp(
  878. &(Event->Guid),
  879. &GUID_NDIS_NOTIFY_ADAPTER_ARRIVAL,
  880. sizeof(GUID)) == 0) {
  881. //
  882. // Adapter arrival.
  883. //
  884. printf("adapter arrival. %ws\n", AdapterGuid);
  885. }
  886. if (memcmp(
  887. &(Event->Guid),
  888. &GUID_NDIS_NOTIFY_ADAPTER_REMOVAL,
  889. sizeof(GUID)) == 0) {
  890. //
  891. // Adapter removal.
  892. //
  893. printf("adapter removal. %ws\n", AdapterGuid);
  894. }
  895. if (memcmp(
  896. &(Event->Guid),
  897. (PVOID)&GUID_NDIS_NOTIFY_DEVICE_POWER_ON,
  898. sizeof(GUID)) == 0) {
  899. //
  900. // Adapter powered on
  901. //
  902. printf("adapter powered on. %ws\n", AdapterInstanceName );
  903. }
  904. if (memcmp(
  905. &(Event->Guid),
  906. (PVOID)&GUID_NDIS_NOTIFY_DEVICE_POWER_OFF,
  907. sizeof(GUID)) == 0) {
  908. //
  909. // Adapter powered off
  910. //
  911. printf("adapter powered off. %ws\n", AdapterInstanceName );
  912. }
  913. }