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.

635 lines
15 KiB

  1. //
  2. // UIOTEST.C
  3. //
  4. // Test program for ndisuio.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 "nuiouser.h"
  28. #ifndef NDIS_STATUS
  29. #define NDIS_STATUS ULONG
  30. #endif
  31. #if DBG
  32. #define DEBUGP(stmt) printf stmt
  33. #else
  34. #define DEBUGP(stmt)
  35. #endif
  36. #define PRINTF(stmt) printf stmt
  37. #ifndef MAC_ADDR_LEN
  38. #define MAC_ADDR_LEN 6
  39. #endif
  40. #define MAX_NDIS_DEVICE_NAME_LEN 256
  41. CHAR NdisuioDevice[] = "\\\\.\\\\Ndisuio";
  42. CHAR * pNdisuioDevice = &NdisuioDevice[0];
  43. BOOLEAN DoEnumerate = FALSE;
  44. BOOLEAN DoReads = FALSE;
  45. INT NumberOfPackets = -1;
  46. ULONG PacketLength = 100;
  47. UCHAR SrcMacAddr[MAC_ADDR_LEN];
  48. UCHAR DstMacAddr[MAC_ADDR_LEN];
  49. BOOLEAN bDstMacSpecified = FALSE;
  50. CHAR * pNdisDeviceName = "JUNK";
  51. USHORT EthType = 0x8e88;
  52. BOOLEAN bUseFakeAddress = FALSE;
  53. UCHAR FakeSrcMacAddr[MAC_ADDR_LEN] = {0};
  54. #include <pshpack1.h>
  55. typedef struct _ETH_HEADER
  56. {
  57. UCHAR DstAddr[MAC_ADDR_LEN];
  58. UCHAR SrcAddr[MAC_ADDR_LEN];
  59. USHORT EthType;
  60. } ETH_HEADER, *PETH_HEADER;
  61. #include <poppack.h>
  62. VOID
  63. PrintUsage()
  64. {
  65. PRINTF(("usage: UIOTEST [options] <devicename>\n"));
  66. PRINTF(("options:\n"));
  67. PRINTF((" -e: Enumerate devices\n"));
  68. PRINTF((" -r: Read\n"));
  69. PRINTF((" -w: Write (default)\n"));
  70. PRINTF((" -l <length>: length of each packet (default: %d)\n", PacketLength));
  71. PRINTF((" -n <count>: number of packets (defaults to infinity)\n"));
  72. PRINTF((" -m <MAC address> (defaults to local MAC)\n"));
  73. PRINTF((" -f Use a fake address to send out the packets.\n"));
  74. }
  75. BOOL
  76. GetOptions(
  77. INT argc,
  78. CHAR *argv[]
  79. )
  80. {
  81. BOOL bOkay;
  82. INT i, j, increment;
  83. CHAR *pOption;
  84. ULONG DstMacAddrUlong[MAC_ADDR_LEN];
  85. bOkay = TRUE;
  86. do
  87. {
  88. if (argc < 2)
  89. {
  90. PRINTF(("Missing <devicename> argument\n"));
  91. bOkay = FALSE;
  92. break;
  93. }
  94. i = 1;
  95. while (i < argc)
  96. {
  97. increment = 1;
  98. pOption = argv[i];
  99. if ((*pOption == '-') || (*pOption == '/'))
  100. {
  101. pOption++;
  102. if (*pOption == '\0')
  103. {
  104. DEBUGP(("Badly formed option\n"));
  105. return (FALSE);
  106. }
  107. }
  108. else
  109. {
  110. break;
  111. }
  112. switch (*pOption)
  113. {
  114. case 'e':
  115. DoEnumerate = TRUE;
  116. break;
  117. case 'f':
  118. bUseFakeAddress = TRUE;
  119. break;
  120. case 'r':
  121. DoReads = TRUE;
  122. break;
  123. case 'w':
  124. DoReads = FALSE;
  125. break;
  126. case 'l':
  127. if (i+1 < argc-1)
  128. {
  129. sscanf(argv[i+1], "%d", &PacketLength);
  130. DEBUGP((" Option: PacketLength = %d\n", PacketLength));
  131. increment = 2;
  132. }
  133. else
  134. {
  135. PRINTF(("Option l needs PacketLength parameter\n"));
  136. return (FALSE);
  137. }
  138. break;
  139. case 'n':
  140. if (i+1 < argc-1)
  141. {
  142. sscanf(argv[i+1], "%d", &NumberOfPackets);
  143. DEBUGP((" Option: NumberOfPackets = %d\n", NumberOfPackets));
  144. increment = 2;
  145. }
  146. else
  147. {
  148. PRINTF(("Option n needs NumberOfPackets parameter\n"));
  149. return (FALSE);
  150. }
  151. break;
  152. case 'm':
  153. if (i+1 < argc-1)
  154. {
  155. sscanf(argv[i+1], "%2x:%2x:%2x:%2x:%2x:%2x",
  156. &DstMacAddrUlong[0],
  157. &DstMacAddrUlong[1],
  158. &DstMacAddrUlong[2],
  159. &DstMacAddrUlong[3],
  160. &DstMacAddrUlong[4],
  161. &DstMacAddrUlong[5]);
  162. for (j = 0; j < MAC_ADDR_LEN; j++)
  163. {
  164. DstMacAddr[j] = (UCHAR)DstMacAddrUlong[j];
  165. }
  166. DEBUGP((" Option: Dest MAC Addr: %02x:%02x:%02x:%02x:%02x:%02x\n",
  167. DstMacAddr[0],
  168. DstMacAddr[1],
  169. DstMacAddr[2],
  170. DstMacAddr[3],
  171. DstMacAddr[4],
  172. DstMacAddr[5]));
  173. bDstMacSpecified = TRUE;
  174. increment = 2;
  175. }
  176. else
  177. {
  178. PRINTF(("Option m needs MAC address parameter\n"));
  179. return (FALSE);
  180. }
  181. break;
  182. case '?':
  183. return (FALSE);
  184. default:
  185. PRINTF(("Unknown option %c\n", *pOption));
  186. return (FALSE);
  187. }
  188. i+= increment;
  189. }
  190. pNdisDeviceName = argv[argc-1];
  191. break;
  192. }
  193. while (FALSE);
  194. return (bOkay);
  195. }
  196. HANDLE
  197. OpenHandle(
  198. CHAR *pDeviceName
  199. )
  200. {
  201. DWORD DesiredAccess;
  202. DWORD ShareMode;
  203. LPSECURITY_ATTRIBUTES lpSecurityAttributes = NULL;
  204. DWORD CreationDistribution;
  205. DWORD FlagsAndAttributes;
  206. HANDLE TemplateFile;
  207. HANDLE Handle;
  208. DWORD BytesReturned;
  209. DesiredAccess = GENERIC_READ|GENERIC_WRITE;
  210. ShareMode = 0;
  211. CreationDistribution = OPEN_EXISTING;
  212. FlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
  213. TemplateFile = (HANDLE)INVALID_HANDLE_VALUE;
  214. Handle = CreateFile(
  215. pDeviceName,
  216. DesiredAccess,
  217. ShareMode,
  218. lpSecurityAttributes,
  219. CreationDistribution,
  220. FlagsAndAttributes,
  221. TemplateFile
  222. );
  223. //
  224. // Wait for the driver to finish binding.
  225. //
  226. if (!DeviceIoControl(
  227. Handle,
  228. IOCTL_NDISUIO_BIND_WAIT,
  229. NULL,
  230. 0,
  231. NULL,
  232. 0,
  233. &BytesReturned,
  234. NULL))
  235. {
  236. DEBUGP(("IOCTL_NDISIO_BIND_WAIT failed, error %x\n", GetLastError()));
  237. CloseHandle(Handle);
  238. Handle = INVALID_HANDLE_VALUE;
  239. }
  240. return (Handle);
  241. }
  242. BOOL
  243. OpenNdisDevice(
  244. HANDLE Handle,
  245. CHAR *pDeviceName
  246. )
  247. {
  248. WCHAR wNdisDeviceName[MAX_NDIS_DEVICE_NAME_LEN];
  249. INT wNameLength;
  250. INT NameLength = strlen(pDeviceName);
  251. DWORD BytesReturned;
  252. INT i;
  253. //
  254. // Convert to unicode string - non-localized...
  255. //
  256. wNameLength = 0;
  257. for (i = 0; i < NameLength && i < MAX_NDIS_DEVICE_NAME_LEN-1; i++)
  258. {
  259. wNdisDeviceName[i] = (WCHAR)pDeviceName[i];
  260. wNameLength++;
  261. }
  262. wNdisDeviceName[i] = L'\0';
  263. DEBUGP(("Trying to access NDIS Device: %ws\n", wNdisDeviceName));
  264. return (DeviceIoControl(
  265. Handle,
  266. IOCTL_NDISUIO_OPEN_DEVICE,
  267. (LPVOID)&wNdisDeviceName[0],
  268. wNameLength*sizeof(WCHAR),
  269. NULL,
  270. 0,
  271. &BytesReturned,
  272. NULL));
  273. }
  274. BOOL
  275. GetSrcMac(
  276. HANDLE Handle,
  277. PUCHAR pSrcMacAddr
  278. )
  279. {
  280. DWORD BytesReturned;
  281. BOOLEAN bSuccess;
  282. UCHAR QueryBuffer[sizeof(NDISUIO_QUERY_OID) + MAC_ADDR_LEN];
  283. PNDISUIO_QUERY_OID pQueryOid;
  284. DEBUGP(("Trying to get src mac address\n"));
  285. pQueryOid = (PNDISUIO_QUERY_OID)&QueryBuffer[0];
  286. pQueryOid->Oid = OID_802_3_CURRENT_ADDRESS;
  287. bSuccess = (BOOLEAN)DeviceIoControl(
  288. Handle,
  289. IOCTL_NDISUIO_QUERY_OID_VALUE,
  290. (LPVOID)&QueryBuffer[0],
  291. sizeof(QueryBuffer),
  292. (LPVOID)&QueryBuffer[0],
  293. sizeof(QueryBuffer),
  294. &BytesReturned,
  295. NULL);
  296. if (bSuccess)
  297. {
  298. DEBUGP(("GetSrcMac: IoControl success, BytesReturned = %d\n",
  299. BytesReturned));
  300. memcpy(pSrcMacAddr, pQueryOid->Data, MAC_ADDR_LEN);
  301. }
  302. else
  303. {
  304. DEBUGP(("GetSrcMac: IoControl failed: %d\n", GetLastError()));
  305. }
  306. return (bSuccess);
  307. }
  308. VOID
  309. DoReadProc(
  310. HANDLE Handle
  311. )
  312. {
  313. PUCHAR pReadBuf = NULL;
  314. INT ReadCount = 0;
  315. BOOLEAN bSuccess;
  316. ULONG BytesRead;
  317. DEBUGP(("DoReadProc\n"));
  318. do
  319. {
  320. pReadBuf = malloc(PacketLength);
  321. if (pReadBuf == NULL)
  322. {
  323. PRINTF(("DoReadProc: failed to alloc %d bytes\n", PacketLength));
  324. break;
  325. }
  326. for (ReadCount = 1; /* NOTHING */; ReadCount++)
  327. {
  328. bSuccess = (BOOLEAN)ReadFile(
  329. Handle,
  330. (LPVOID)pReadBuf,
  331. PacketLength,
  332. &BytesRead,
  333. NULL);
  334. if (!bSuccess)
  335. {
  336. PRINTF(("DoReadProc: ReadFile failed on Handle %p, error %x\n",
  337. Handle, GetLastError()));
  338. break;
  339. }
  340. DEBUGP(("DoReadProc: read pkt # %d, %d bytes\n", ReadCount, BytesRead));
  341. if ((NumberOfPackets != -1) && (ReadCount == NumberOfPackets))
  342. {
  343. break;
  344. }
  345. }
  346. }
  347. while (FALSE);
  348. if (pReadBuf)
  349. {
  350. free(pReadBuf);
  351. }
  352. PRINTF(("DoReadProc finished: read %d packets\n", ReadCount));
  353. }
  354. VOID
  355. DoWriteProc(
  356. HANDLE Handle
  357. )
  358. {
  359. PUCHAR pWriteBuf = NULL;
  360. PUCHAR pData;
  361. UINT i;
  362. INT SendCount;
  363. PETH_HEADER pEthHeader;
  364. DWORD BytesWritten;
  365. BOOLEAN bSuccess;
  366. DEBUGP(("DoWriteProc\n"));
  367. SendCount = 0;
  368. do
  369. {
  370. pWriteBuf = malloc(PacketLength);
  371. if (pWriteBuf == NULL)
  372. {
  373. DEBUGP(("DoWriteProc: Failed to malloc %d bytes\n", PacketLength));
  374. break;
  375. }
  376. pEthHeader = (PETH_HEADER)pWriteBuf;
  377. pEthHeader->EthType = EthType;
  378. if (bUseFakeAddress)
  379. {
  380. memcpy(pEthHeader->SrcAddr, FakeSrcMacAddr, MAC_ADDR_LEN);
  381. }
  382. else
  383. {
  384. memcpy(pEthHeader->SrcAddr, SrcMacAddr, MAC_ADDR_LEN);
  385. }
  386. memcpy(pEthHeader->DstAddr, DstMacAddr, MAC_ADDR_LEN);
  387. pData = (PUCHAR)(pEthHeader + 1);
  388. for (i = 0; i < PacketLength - sizeof(ETH_HEADER); i++)
  389. {
  390. *pData++ = (UCHAR)i;
  391. }
  392. for (SendCount = 1; /* NOTHING */; SendCount++)
  393. {
  394. bSuccess = (BOOLEAN)WriteFile(
  395. Handle,
  396. pWriteBuf,
  397. PacketLength,
  398. &BytesWritten,
  399. NULL);
  400. if (!bSuccess)
  401. {
  402. PRINTF(("DoWriteProc: WriteFile failed on Handle %p\n", Handle));
  403. break;
  404. }
  405. DEBUGP(("DoWriteProc: sent %d bytes\n", BytesWritten));
  406. if ((NumberOfPackets != -1) && (SendCount == NumberOfPackets))
  407. {
  408. break;
  409. }
  410. }
  411. }
  412. while (FALSE);
  413. if (pWriteBuf)
  414. {
  415. free(pWriteBuf);
  416. }
  417. PRINTF(("DoWriteProc: finished sending %d packets of %d bytes each\n",
  418. SendCount, PacketLength));
  419. }
  420. VOID
  421. EnumerateDevices(
  422. HANDLE Handle
  423. )
  424. {
  425. CHAR Buf[1024];
  426. DWORD BufLength = sizeof(Buf);
  427. DWORD BytesWritten;
  428. DWORD i;
  429. PNDISUIO_QUERY_BINDING pQueryBinding;
  430. pQueryBinding = (PNDISUIO_QUERY_BINDING)Buf;
  431. i = 0;
  432. for (pQueryBinding->BindingIndex = i;
  433. /* NOTHING */;
  434. pQueryBinding->BindingIndex = ++i)
  435. {
  436. if (DeviceIoControl(
  437. Handle,
  438. IOCTL_NDISUIO_QUERY_BINDING,
  439. pQueryBinding,
  440. sizeof(NDISUIO_QUERY_BINDING),
  441. Buf,
  442. BufLength,
  443. &BytesWritten,
  444. NULL))
  445. {
  446. PRINTF(("%2d. %ws\n - %ws\n",
  447. pQueryBinding->BindingIndex,
  448. (PUCHAR)pQueryBinding + pQueryBinding->DeviceNameOffset,
  449. (PUCHAR)pQueryBinding + pQueryBinding->DeviceDescrOffset));
  450. memset(Buf, 0, BufLength);
  451. }
  452. else
  453. {
  454. ULONG rc = GetLastError();
  455. if (rc != ERROR_NO_MORE_ITEMS)
  456. {
  457. PRINTF(("EnumerateDevices: terminated abnormally, error %d\n", rc));
  458. }
  459. break;
  460. }
  461. }
  462. }
  463. VOID __cdecl
  464. main(
  465. INT argc,
  466. CHAR *argv[]
  467. )
  468. {
  469. HANDLE DeviceHandle;
  470. DeviceHandle = INVALID_HANDLE_VALUE;
  471. do
  472. {
  473. if (!GetOptions(argc, argv))
  474. {
  475. PrintUsage();
  476. break;
  477. }
  478. DeviceHandle = OpenHandle(pNdisuioDevice);
  479. if (DeviceHandle == INVALID_HANDLE_VALUE)
  480. {
  481. PRINTF(("Failed to open %s\n", pNdisuioDevice));
  482. break;
  483. }
  484. if (DoEnumerate)
  485. {
  486. EnumerateDevices(DeviceHandle);
  487. break;
  488. }
  489. if (!OpenNdisDevice(DeviceHandle, pNdisDeviceName))
  490. {
  491. PRINTF(("Failed to access %s\n", pNdisDeviceName));
  492. break;
  493. }
  494. DEBUGP(("Opened device %s successfully!\n", pNdisDeviceName));
  495. if (!GetSrcMac(DeviceHandle, SrcMacAddr))
  496. {
  497. PRINTF(("Failed to obtain local MAC address\n"));
  498. break;
  499. }
  500. DEBUGP(("Got local MAC: %02x:%02x:%02x:%02x:%02x:%02x\n",
  501. SrcMacAddr[0],
  502. SrcMacAddr[1],
  503. SrcMacAddr[2],
  504. SrcMacAddr[3],
  505. SrcMacAddr[4],
  506. SrcMacAddr[5]));
  507. if (!bDstMacSpecified)
  508. {
  509. memcpy(DstMacAddr, SrcMacAddr, MAC_ADDR_LEN);
  510. }
  511. if (DoReads)
  512. {
  513. DoReadProc(DeviceHandle);
  514. }
  515. else
  516. {
  517. DoWriteProc(DeviceHandle);
  518. DoReadProc(DeviceHandle);
  519. }
  520. }
  521. while (FALSE);
  522. if (DeviceHandle != INVALID_HANDLE_VALUE)
  523. {
  524. CloseHandle(DeviceHandle);
  525. }
  526. }