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.

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