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.

820 lines
26 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation. All rights reserved.
  3. THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  4. KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  5. IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  6. PURPOSE.
  7. Module Name: testapp.c
  8. Abstract:
  9. Author:
  10. Eliyas Yakub Dec 15, 2002
  11. Environment:
  12. User mode only.
  13. Revision History:
  14. --*/
  15. #define UNICODE 1
  16. #define INITGUID
  17. #include <windows.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <setupapi.h>
  21. #include <dbt.h>
  22. #include <winioctl.h>
  23. #include <ntddndis.h> // for IOCTL_NDIS_QUERY_GLOBAL_STATS
  24. #include <ndisguid.h> // for GUID_NDIS_LAN_CLASS
  25. #include "testapp.h"
  26. #include "public.h" // for IOCTL_NETVMINI_HELLO
  27. //
  28. // Global variables
  29. //
  30. HINSTANCE hInst;
  31. HWND hWndList;
  32. TCHAR szTitle[]=TEXT("NETVMINI's IOCTL Test Application");
  33. LIST_ENTRY ListHead;
  34. HDEVNOTIFY hInterfaceNotification;
  35. TCHAR OutText[500];
  36. UINT ListBoxIndex = 0;
  37. GUID InterfaceGuid;// = GUID_NDIS_LAN_CLASS;
  38. _inline VOID Display(PWCHAR Format, PWCHAR Str)
  39. {
  40. if(Str) {
  41. wsprintf(OutText, Format, Str);
  42. } else {
  43. wcscpy(OutText, Format);
  44. }
  45. SendMessage(hWndList, LB_INSERTSTRING, ListBoxIndex++, (LPARAM)OutText);
  46. }
  47. int PASCAL WinMain (HINSTANCE hInstance,
  48. HINSTANCE hPrevInstance,
  49. LPSTR lpszCmdParam,
  50. int nCmdShow)
  51. {
  52. static TCHAR szAppName[]=TEXT("NETVMINI TESTAPP");
  53. HWND hWnd;
  54. MSG msg;
  55. WNDCLASS wndclass;
  56. InterfaceGuid = GUID_NDIS_LAN_CLASS;
  57. hInst=hInstance;
  58. if (!hPrevInstance)
  59. {
  60. wndclass.style = CS_HREDRAW | CS_VREDRAW;
  61. wndclass.lpfnWndProc = WndProc;
  62. wndclass.cbClsExtra = 0;
  63. wndclass.cbWndExtra = 0;
  64. wndclass.hInstance = hInstance;
  65. wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION);
  66. wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
  67. wndclass.hbrBackground= GetStockObject(WHITE_BRUSH);
  68. wndclass.lpszMenuName = TEXT("GenericMenu");
  69. wndclass.lpszClassName= szAppName;
  70. RegisterClass(&wndclass);
  71. }
  72. hWnd = CreateWindow (szAppName,
  73. szTitle,
  74. WS_OVERLAPPEDWINDOW,
  75. CW_USEDEFAULT,
  76. CW_USEDEFAULT,
  77. CW_USEDEFAULT,
  78. CW_USEDEFAULT,
  79. NULL,
  80. NULL,
  81. hInstance,
  82. NULL);
  83. ShowWindow (hWnd,nCmdShow);
  84. UpdateWindow(hWnd);
  85. while (GetMessage (&msg, NULL, 0,0))
  86. {
  87. TranslateMessage(&msg);
  88. DispatchMessage(&msg);
  89. }
  90. return (0);
  91. }
  92. LRESULT FAR PASCAL
  93. WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  94. {
  95. DWORD nEventType = (DWORD)wParam;
  96. PDEV_BROADCAST_HDR p = (PDEV_BROADCAST_HDR) lParam;
  97. DEV_BROADCAST_DEVICEINTERFACE filter;
  98. switch (message)
  99. {
  100. case WM_COMMAND:
  101. HandleCommands(hWnd, message, wParam, lParam);
  102. return 0;
  103. case WM_CREATE:
  104. hWndList = CreateWindow (TEXT("listbox"),
  105. NULL,
  106. WS_CHILD|WS_VISIBLE|LBS_NOTIFY |
  107. WS_VSCROLL | WS_BORDER,
  108. CW_USEDEFAULT,
  109. CW_USEDEFAULT,
  110. CW_USEDEFAULT,
  111. CW_USEDEFAULT,
  112. hWnd,
  113. (HMENU)ID_EDIT,
  114. hInst,
  115. NULL);
  116. filter.dbcc_size = sizeof(filter);
  117. filter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
  118. filter.dbcc_classguid = InterfaceGuid;
  119. hInterfaceNotification = RegisterDeviceNotification(hWnd, &filter, 0);
  120. InitializeListHead(&ListHead);
  121. EnumExistingDevices(hWnd);
  122. return 0;
  123. case WM_SIZE:
  124. MoveWindow(hWndList, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);
  125. return 0;
  126. case WM_SETFOCUS:
  127. SetFocus(hWndList);
  128. return 0;
  129. case WM_DEVICECHANGE:
  130. //
  131. // All the events we're interested in come with lParam pointing to
  132. // a structure headed by a DEV_BROADCAST_HDR. This is denoted by
  133. // bit 15 of wParam being set, and bit 14 being clear.
  134. //
  135. if((wParam & 0xC000) == 0x8000) {
  136. if (!p)
  137. return 0;
  138. if (p->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
  139. HandleDeviceInterfaceChange(hWnd, nEventType, (PDEV_BROADCAST_DEVICEINTERFACE) p);
  140. } else if (p->dbch_devicetype == DBT_DEVTYP_HANDLE) {
  141. HandleDeviceChange(hWnd, nEventType, (PDEV_BROADCAST_HANDLE) p);
  142. }
  143. }
  144. return 0;
  145. case WM_CLOSE:
  146. Cleanup(hWnd);
  147. UnregisterDeviceNotification(hInterfaceNotification);
  148. return DefWindowProc(hWnd,message, wParam, lParam);
  149. case WM_DESTROY:
  150. PostQuitMessage(0);
  151. return 0;
  152. }
  153. return DefWindowProc(hWnd,message, wParam, lParam);
  154. }
  155. LRESULT
  156. HandleCommands(
  157. HWND hWnd,
  158. UINT uMsg,
  159. WPARAM wParam,
  160. LPARAM lParam
  161. )
  162. {
  163. switch (wParam) {
  164. case IDM_OPEN:
  165. Cleanup(hWnd); // close all open handles
  166. EnumExistingDevices(hWnd);
  167. break;
  168. case IDM_CLOSE:
  169. Cleanup(hWnd);
  170. break;
  171. case IDM_CTL_IOCTL:
  172. {
  173. PDEVICE_INFO deviceInfo = NULL;
  174. PLIST_ENTRY thisEntry;
  175. BOOLEAN found = FALSE;
  176. //
  177. // Find the Virtual miniport driver
  178. // We need the deviceInfo to get the handle to the device.
  179. //
  180. for(thisEntry = ListHead.Flink; thisEntry != &ListHead;
  181. thisEntry = thisEntry->Flink)
  182. {
  183. deviceInfo = CONTAINING_RECORD(thisEntry, DEVICE_INFO, ListEntry);
  184. if(deviceInfo &&
  185. deviceInfo->hDevice != INVALID_HANDLE_VALUE &&
  186. wcsstr(deviceInfo->DeviceName, TEXT("Microsoft Virtual Ethernet Adapter"))) {
  187. found = TRUE;
  188. SendIoctlToControlDevice(deviceInfo);
  189. }
  190. }
  191. if(!found) {
  192. Display(TEXT("Didn't find any NETVMINI device"), NULL);
  193. }
  194. }
  195. break;
  196. case IDM_CLEAR:
  197. SendMessage(hWndList, LB_RESETCONTENT, 0, 0);
  198. ListBoxIndex = 0;
  199. break;
  200. case IDM_EXIT:
  201. PostQuitMessage(0);
  202. break;
  203. default:
  204. break;
  205. }
  206. return TRUE;
  207. }
  208. BOOL
  209. HandleDeviceInterfaceChange(
  210. HWND hWnd,
  211. DWORD evtype,
  212. PDEV_BROADCAST_DEVICEINTERFACE dip
  213. )
  214. {
  215. DEV_BROADCAST_HANDLE filter;
  216. PDEVICE_INFO deviceInfo = NULL;
  217. switch (evtype)
  218. {
  219. case DBT_DEVICEARRIVAL:
  220. //
  221. // New device arrived. Open handle to the device
  222. // and register notification of type DBT_DEVTYP_HANDLE
  223. //
  224. deviceInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DEVICE_INFO));
  225. if(!deviceInfo)
  226. return FALSE;
  227. InitializeListHead(&deviceInfo->ListEntry);
  228. InsertTailList(&ListHead, &deviceInfo->ListEntry);
  229. if(!GetDeviceDescription(dip->dbcc_name, deviceInfo->DeviceName,
  230. NULL)) {
  231. MessageBox(hWnd, TEXT("GetDeviceDescription failed"), TEXT("Error!"), MB_OK);
  232. }
  233. Display(TEXT("New device Arrived (Interface Change Notification): %ws"),
  234. deviceInfo->DeviceName);
  235. wcscpy(deviceInfo->DevicePath, dip->dbcc_name);
  236. deviceInfo->hDevice = CreateFile(dip->dbcc_name,
  237. GENERIC_READ |GENERIC_WRITE, 0, NULL,
  238. OPEN_EXISTING, 0, NULL);
  239. if(deviceInfo->hDevice == INVALID_HANDLE_VALUE) {
  240. Display(TEXT("Failed to open the device: %ws"),
  241. deviceInfo->DeviceName);
  242. break;
  243. }
  244. Display(TEXT("Opened handled to the device: %ws"),
  245. deviceInfo->DeviceName);
  246. memset (&filter, 0, sizeof(filter)); //zero the structure
  247. filter.dbch_size = sizeof(filter);
  248. filter.dbch_devicetype = DBT_DEVTYP_HANDLE;
  249. filter.dbch_handle = deviceInfo->hDevice;
  250. deviceInfo->hHandleNotification =
  251. RegisterDeviceNotification(hWnd, &filter, 0);
  252. break;
  253. case DBT_DEVICEREMOVECOMPLETE:
  254. Display(TEXT("Remove Complete (Interface Change Notification)"), NULL);
  255. break;
  256. //
  257. // Device Removed.
  258. //
  259. default:
  260. Display(TEXT("Unknown (Interface Change Notification)"), NULL);
  261. break;
  262. }
  263. return TRUE;
  264. }
  265. BOOL
  266. HandleDeviceChange(
  267. HWND hWnd,
  268. DWORD evtype,
  269. PDEV_BROADCAST_HANDLE dhp
  270. )
  271. {
  272. UINT i;
  273. DEV_BROADCAST_HANDLE filter;
  274. PDEVICE_INFO deviceInfo = NULL;
  275. PLIST_ENTRY thisEntry;
  276. HANDLE tempHandle;
  277. //
  278. // Walk the list to get the deviceInfo for this device
  279. // by matching the handle given in the notification.
  280. //
  281. for(thisEntry = ListHead.Flink; thisEntry != &ListHead;
  282. thisEntry = thisEntry->Flink)
  283. {
  284. deviceInfo = CONTAINING_RECORD(thisEntry, DEVICE_INFO, ListEntry);
  285. if(dhp->dbch_handle == deviceInfo->hDevice) {
  286. break;
  287. }
  288. deviceInfo = NULL;
  289. }
  290. if(!deviceInfo) {
  291. MessageBox(hWnd, TEXT("Unknown Device"), TEXT("Error"), MB_OK);
  292. return FALSE;
  293. }
  294. switch (evtype)
  295. {
  296. case DBT_DEVICEQUERYREMOVE:
  297. Display(TEXT("Query Remove (Handle Notification)"),
  298. deviceInfo->DeviceName);
  299. //
  300. // Close the handle so that target device can
  301. // get removed. Do not unregister the notification
  302. // at this point, because you want to know whether
  303. // the device is successfully removed or not.
  304. //
  305. tempHandle = deviceInfo->hDevice;
  306. CloseDeviceHandles(deviceInfo);
  307. //
  308. // Since we use the handle to locate the deviceinfo, we
  309. // will reset the handle to the original value and
  310. // clear it in the the remove_pending message callback.
  311. // ugly hack..
  312. //
  313. deviceInfo->hDevice = tempHandle;
  314. break;
  315. case DBT_DEVICEREMOVECOMPLETE:
  316. Display(TEXT("Remove Complete (Handle Notification):%ws"),
  317. deviceInfo->DeviceName);
  318. //
  319. // Device is removed so close the handle if it's there
  320. // and unregister the notification
  321. //
  322. if (deviceInfo->hHandleNotification) {
  323. UnregisterDeviceNotification(deviceInfo->hHandleNotification);
  324. deviceInfo->hHandleNotification = NULL;
  325. }
  326. CloseDeviceHandles(deviceInfo);
  327. //
  328. // Unlink this deviceInfo from the list and free the memory
  329. //
  330. RemoveEntryList(&deviceInfo->ListEntry);
  331. HeapFree (GetProcessHeap(), 0, deviceInfo);
  332. break;
  333. case DBT_DEVICEREMOVEPENDING:
  334. Display(TEXT("Remove Pending (Handle Notification):%ws"),
  335. deviceInfo->DeviceName);
  336. //
  337. // Device is removed so close the handle if it's there
  338. // and unregister the notification
  339. //
  340. if (deviceInfo->hHandleNotification) {
  341. UnregisterDeviceNotification(deviceInfo->hHandleNotification);
  342. deviceInfo->hHandleNotification = NULL;
  343. deviceInfo->hDevice = INVALID_HANDLE_VALUE;
  344. }
  345. //
  346. // Unlink this deviceInfo from the list and free the memory
  347. //
  348. RemoveEntryList(&deviceInfo->ListEntry);
  349. HeapFree (GetProcessHeap(), 0, deviceInfo);
  350. break;
  351. case DBT_DEVICEQUERYREMOVEFAILED :
  352. Display(TEXT("Remove failed (Handle Notification):%ws"),
  353. deviceInfo->DeviceName);
  354. //
  355. // Remove failed. So reopen the device and register for
  356. // notification on the new handle. But first we should unregister
  357. // the previous notification.
  358. //
  359. if (deviceInfo->hHandleNotification) {
  360. UnregisterDeviceNotification(deviceInfo->hHandleNotification);
  361. deviceInfo->hHandleNotification = NULL;
  362. }
  363. deviceInfo->hDevice = CreateFile(deviceInfo->DevicePath,
  364. GENERIC_READ | GENERIC_WRITE,
  365. 0, NULL, OPEN_EXISTING, 0, NULL);
  366. if(deviceInfo->hDevice == INVALID_HANDLE_VALUE) {
  367. Display(TEXT("Failed to reopen the device: %ws"),
  368. deviceInfo->DeviceName);
  369. //
  370. // Unlink this deviceInfo from the list and free the memory
  371. //
  372. RemoveEntryList(&deviceInfo->ListEntry);
  373. HeapFree (GetProcessHeap(), 0, deviceInfo);
  374. break;
  375. }
  376. //
  377. // Register handle based notification to receive pnp
  378. // device change notification on the handle.
  379. //
  380. memset (&filter, 0, sizeof(filter)); //zero the structure
  381. filter.dbch_size = sizeof(filter);
  382. filter.dbch_devicetype = DBT_DEVTYP_HANDLE;
  383. filter.dbch_handle = deviceInfo->hDevice;
  384. deviceInfo->hHandleNotification =
  385. RegisterDeviceNotification(hWnd, &filter, 0);
  386. Display(TEXT("Reopened device %ws"), deviceInfo->DeviceName);
  387. break;
  388. default:
  389. Display(TEXT("Unknown (Handle Notification)"),
  390. deviceInfo->DeviceName);
  391. break;
  392. }
  393. return TRUE;
  394. }
  395. BOOLEAN
  396. EnumExistingDevices(
  397. HWND hWnd
  398. )
  399. {
  400. HDEVINFO hardwareDeviceInfo;
  401. SP_DEVICE_INTERFACE_DATA deviceInterfaceData;
  402. PSP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceDetailData = NULL;
  403. ULONG predictedLength = 0;
  404. ULONG requiredLength = 0, bytes=0;
  405. DWORD dwRegType, error;
  406. DEV_BROADCAST_HANDLE filter;
  407. PDEVICE_INFO deviceInfo =NULL;
  408. UINT i=0;
  409. hardwareDeviceInfo = SetupDiGetClassDevs (
  410. (LPGUID)&InterfaceGuid,
  411. NULL, // Define no enumerator (global)
  412. NULL, // Define no
  413. (DIGCF_PRESENT | // Only Devices present
  414. DIGCF_DEVICEINTERFACE)); // Function class devices.
  415. if(INVALID_HANDLE_VALUE == hardwareDeviceInfo)
  416. {
  417. goto Error;
  418. }
  419. //
  420. // Enumerate devices of toaster class
  421. //
  422. deviceInterfaceData.cbSize = sizeof(deviceInterfaceData);
  423. for(i=0; SetupDiEnumDeviceInterfaces (hardwareDeviceInfo,
  424. 0, // No care about specific PDOs
  425. (LPGUID)&InterfaceGuid,
  426. i, //
  427. &deviceInterfaceData); i++ ) {
  428. //
  429. // Allocate a function class device data structure to
  430. // receive the information about this particular device.
  431. //
  432. //
  433. // First find out required length of the buffer
  434. //
  435. if(deviceInterfaceDetailData)
  436. HeapFree (GetProcessHeap(), 0, deviceInterfaceDetailData);
  437. if(!SetupDiGetDeviceInterfaceDetail (
  438. hardwareDeviceInfo,
  439. &deviceInterfaceData,
  440. NULL, // probing so no output buffer yet
  441. 0, // probing so output buffer length of zero
  442. &requiredLength,
  443. NULL) && (error = GetLastError()) != ERROR_INSUFFICIENT_BUFFER)
  444. {
  445. goto Error;
  446. }
  447. predictedLength = requiredLength;
  448. deviceInterfaceDetailData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
  449. predictedLength);
  450. deviceInterfaceDetailData->cbSize =
  451. sizeof (SP_DEVICE_INTERFACE_DETAIL_DATA);
  452. if (! SetupDiGetDeviceInterfaceDetail (
  453. hardwareDeviceInfo,
  454. &deviceInterfaceData,
  455. deviceInterfaceDetailData,
  456. predictedLength,
  457. &requiredLength,
  458. NULL)) {
  459. goto Error;
  460. }
  461. deviceInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
  462. sizeof(DEVICE_INFO));
  463. if(!deviceInfo)
  464. goto Error;
  465. InitializeListHead(&deviceInfo->ListEntry);
  466. InsertTailList(&ListHead, &deviceInfo->ListEntry);
  467. //
  468. // Get the device details such as friendly name and SerialNo
  469. //
  470. if(!GetDeviceDescription(deviceInterfaceDetailData->DevicePath,
  471. deviceInfo->DeviceName,
  472. NULL)){
  473. goto Error;
  474. }
  475. Display(TEXT("Found device %ws"), deviceInfo->DeviceName );
  476. wcscpy(deviceInfo->DevicePath, deviceInterfaceDetailData->DevicePath);
  477. //
  478. // Open an handle to the device.
  479. //
  480. deviceInfo->hDevice = CreateFile (
  481. deviceInterfaceDetailData->DevicePath,
  482. GENERIC_READ | GENERIC_WRITE,
  483. 0,
  484. NULL, // no SECURITY_ATTRIBUTES structure
  485. OPEN_EXISTING, // No special create flags
  486. 0, // No special attributes
  487. NULL);
  488. if (INVALID_HANDLE_VALUE == deviceInfo->hDevice) {
  489. Display(TEXT("Failed to open the device: %ws"),
  490. deviceInfo->DeviceName);
  491. continue;
  492. }
  493. Display(TEXT("Opened handled to the device: %ws"),
  494. deviceInfo->DeviceName);
  495. //
  496. // Register handle based notification to receive pnp
  497. // device change notification on the handle.
  498. //
  499. memset (&filter, 0, sizeof(filter)); //zero the structure
  500. filter.dbch_size = sizeof(filter);
  501. filter.dbch_devicetype = DBT_DEVTYP_HANDLE;
  502. filter.dbch_handle = deviceInfo->hDevice;
  503. deviceInfo->hHandleNotification = RegisterDeviceNotification(hWnd, &filter, 0);
  504. }
  505. if(deviceInterfaceDetailData)
  506. HeapFree (GetProcessHeap(), 0, deviceInterfaceDetailData);
  507. SetupDiDestroyDeviceInfoList (hardwareDeviceInfo);
  508. return 0;
  509. Error:
  510. error = GetLastError();
  511. MessageBox(hWnd, TEXT("EnumExisting Devices failed"), TEXT("Error!"), MB_OK);
  512. if(deviceInterfaceDetailData)
  513. HeapFree (GetProcessHeap(), 0, deviceInterfaceDetailData);
  514. SetupDiDestroyDeviceInfoList (hardwareDeviceInfo);
  515. Cleanup(hWnd);
  516. return 0;
  517. }
  518. BOOLEAN Cleanup(HWND hWnd)
  519. {
  520. PDEVICE_INFO deviceInfo =NULL;
  521. PLIST_ENTRY thisEntry;
  522. while (!IsListEmpty(&ListHead)) {
  523. thisEntry = RemoveHeadList(&ListHead);
  524. deviceInfo = CONTAINING_RECORD(thisEntry, DEVICE_INFO, ListEntry);
  525. if (deviceInfo->hHandleNotification) {
  526. UnregisterDeviceNotification(deviceInfo->hHandleNotification);
  527. deviceInfo->hHandleNotification = NULL;
  528. }
  529. CloseDeviceHandles(deviceInfo);
  530. HeapFree (GetProcessHeap(), 0, deviceInfo);
  531. }
  532. return TRUE;
  533. }
  534. VOID CloseDeviceHandles(
  535. IN PDEVICE_INFO deviceInfo)
  536. {
  537. if(!deviceInfo) return;
  538. if (deviceInfo->hDevice != INVALID_HANDLE_VALUE &&
  539. deviceInfo->hDevice != NULL) {
  540. CloseHandle(deviceInfo->hDevice);
  541. deviceInfo->hDevice = INVALID_HANDLE_VALUE;
  542. //
  543. // If there is a valid control device handle, close
  544. // that also. We aren't going to get any notification
  545. // on the control-device because it's not known to PNP
  546. // subsystem.
  547. //
  548. if (deviceInfo->hControlDevice != INVALID_HANDLE_VALUE &&
  549. deviceInfo->hControlDevice != NULL) {
  550. CloseHandle(deviceInfo->hControlDevice);
  551. deviceInfo->hControlDevice = INVALID_HANDLE_VALUE;
  552. }
  553. Display(TEXT("Closed handle to device %ws"), deviceInfo->DeviceName );
  554. }
  555. }
  556. BOOL
  557. GetDeviceDescription(
  558. LPTSTR DevPath,
  559. LPTSTR OutBuffer,
  560. PULONG Unused
  561. )
  562. {
  563. HDEVINFO hardwareDeviceInfo;
  564. SP_DEVICE_INTERFACE_DATA deviceInterfaceData;
  565. SP_DEVINFO_DATA deviceInfoData;
  566. DWORD dwRegType, error;
  567. hardwareDeviceInfo = SetupDiCreateDeviceInfoList(NULL, NULL);
  568. if(INVALID_HANDLE_VALUE == hardwareDeviceInfo)
  569. {
  570. goto Error;
  571. }
  572. //
  573. // Enumerate devices of toaster class
  574. //
  575. deviceInterfaceData.cbSize = sizeof(deviceInterfaceData);
  576. SetupDiOpenDeviceInterface (hardwareDeviceInfo, DevPath,
  577. 0, //
  578. &deviceInterfaceData);
  579. deviceInfoData.cbSize = sizeof(deviceInfoData);
  580. if(!SetupDiGetDeviceInterfaceDetail (
  581. hardwareDeviceInfo,
  582. &deviceInterfaceData,
  583. NULL, // probing so no output buffer yet
  584. 0, // probing so output buffer length of zero
  585. NULL,
  586. &deviceInfoData) && (error = GetLastError()) != ERROR_INSUFFICIENT_BUFFER)
  587. {
  588. goto Error;
  589. }
  590. //
  591. // Get the friendly name for this instance, if that fails
  592. // try to get the device description.
  593. //
  594. if(!SetupDiGetDeviceRegistryProperty(hardwareDeviceInfo, &deviceInfoData,
  595. SPDRP_FRIENDLYNAME,
  596. &dwRegType,
  597. (BYTE*) OutBuffer,
  598. MAX_PATH,
  599. NULL))
  600. {
  601. if(!SetupDiGetDeviceRegistryProperty(hardwareDeviceInfo, &deviceInfoData,
  602. SPDRP_DEVICEDESC,
  603. &dwRegType,
  604. (BYTE*) OutBuffer,
  605. MAX_PATH,
  606. NULL)){
  607. goto Error;
  608. }
  609. }
  610. SetupDiDestroyDeviceInfoList (hardwareDeviceInfo);
  611. return TRUE;
  612. Error:
  613. error = GetLastError();
  614. SetupDiDestroyDeviceInfoList (hardwareDeviceInfo);
  615. return FALSE;
  616. }
  617. BOOLEAN
  618. SendIoctlToControlDevice(
  619. IN PDEVICE_INFO deviceInfo)
  620. {
  621. BOOLEAN result = FALSE;
  622. UINT bytes;
  623. //
  624. // Open handle to the control device, if it's not already opened. Please
  625. // note that even a non-admin user can open handle to the device with
  626. // FILE_READ_ATTRIBUTES | SYNCHRONIZE DesiredAccess and send IOCTLs if the
  627. // IOCTL is defined with FILE_ANY_ACCESS. So for better security avoid
  628. // specifying FILE_ANY_ACCESS in your IOCTL defintions.
  629. // If you open the device with GENERIC_READ, you can send IOCTL with
  630. // FILE_READ_DATA access rights. If you open the device with GENERIC_WRITE,
  631. // you can sedn ioctl with FILE_WRITE_DATA access rights.
  632. //
  633. //
  634. if(deviceInfo->hControlDevice != INVALID_HANDLE_VALUE) {
  635. deviceInfo->hControlDevice = CreateFile (
  636. TEXT("\\\\.\\NETVMINI"),
  637. GENERIC_READ | GENERIC_WRITE,//FILE_READ_ATTRIBUTES | SYNCHRONIZE,
  638. FILE_SHARE_READ,
  639. NULL, // no SECURITY_ATTRIBUTES structure
  640. OPEN_EXISTING, // No special create flags
  641. FILE_ATTRIBUTE_NORMAL, // No special attributes
  642. NULL);
  643. if (INVALID_HANDLE_VALUE == deviceInfo->hControlDevice) {
  644. Display(TEXT("Failed to open the control device: %ws"),
  645. deviceInfo->DeviceName);
  646. return result;
  647. }
  648. }
  649. //
  650. // send ioclt requests
  651. //
  652. if(!DeviceIoControl (deviceInfo->hControlDevice,
  653. IOCTL_NETVMINI_READ_DATA,
  654. NULL, 0,
  655. NULL, 0,
  656. &bytes, NULL)) {
  657. Display(TEXT("Read IOCTL to %ws failed"), deviceInfo->DeviceName);
  658. } else {
  659. Display(TEXT("Read IOCTL to %ws succeeded"), deviceInfo->DeviceName);
  660. result = TRUE;
  661. }
  662. if(!DeviceIoControl (deviceInfo->hControlDevice,
  663. IOCTL_NETVMINI_WRITE_DATA,
  664. NULL, 0,
  665. NULL, 0,
  666. &bytes, NULL)) {
  667. Display(TEXT("Write IOCTL to %ws failed"), deviceInfo->DeviceName);
  668. } else {
  669. Display(TEXT("Write IOCTL to %ws succeeded"), deviceInfo->DeviceName);
  670. result = TRUE;
  671. }
  672. return result;
  673. }