diff options
| author | Dave Wilson <[email protected]> | 2015-03-17 19:50:07 -0700 |
|---|---|---|
| committer | Dave Wilson <[email protected]> | 2015-03-17 19:50:07 -0700 |
| commit | 97cf5197cf5b882b2c689d8dc2b555f2edf8f418 (patch) | |
| tree | 46f3701832d70b420eb0fc0eb93261f9da45db3f /general/pcidrv/test/testapp.c | |
| parent | ef1905bf1e8825bb31120dfb27e0daf3154d859a (diff) | |
Initial publish
Diffstat (limited to 'general/pcidrv/test/testapp.c')
| -rw-r--r-- | general/pcidrv/test/testapp.c | 1224 |
1 files changed, 1224 insertions, 0 deletions
diff --git a/general/pcidrv/test/testapp.c b/general/pcidrv/test/testapp.c new file mode 100644 index 00000000..cd83f633 --- /dev/null +++ b/general/pcidrv/test/testapp.c @@ -0,0 +1,1224 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +Module Name: Testapp.c + + +Abstract: + + Testapp for PCIDRV + +Environment: + + User mode only. + +--*/ + +#include "testapp.h" + + +// +// Global variables +// +HINSTANCE HWndInstance; +HWND HWndList; // handle to the embedded list box +TCHAR WindowTitle[]=TEXT("MyPing - Test Application for PCIDRV"); +LIST_ENTRY ListHead; +HDEVNOTIFY InterfaceNotificationHandle; +TCHAR OutText[500]; +UINT ListBoxIndex = 0; +GUID InterfaceGuid;// = GUID_DEVINTERFACE_PCIDRV; +ULONG DeviceIndex; +BOOLEAN Verbose = FALSE; + + +VOID +Display( + _In_ LPWSTR pstrFormat, // @parm A printf style format string + ... // @parm | ... | Variable paramters based on <p pstrFormat> + ) +{ + HRESULT hr; + va_list va; + + va_start(va, pstrFormat); + // + // Truncation is acceptable. + // + hr = StringCbVPrintf(OutText, sizeof(OutText)-sizeof(WCHAR), pstrFormat, va); + va_end(va); + + if(FAILED(hr)){ + return; + } + + SendMessage(HWndList, LB_INSERTSTRING, ListBoxIndex, (LPARAM)OutText); + SendMessage(HWndList, LB_SETCURSEL, ListBoxIndex, 0); + ListBoxIndex++; + +} + +_Use_decl_annotations_ +int +PASCAL +WinMain ( + HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpCmdLine, + int nShowCmd + ) +{ + static TCHAR szAppName[]=TEXT("MYPING"); + HWND hWnd; + MSG msg; + WNDCLASS wndclass; + + InterfaceGuid = GUID_DEVINTERFACE_PCIDRV; + HWndInstance=hInstance; + + if (!hPrevInstance) + { + wndclass.style = CS_HREDRAW | CS_VREDRAW; + wndclass.lpfnWndProc = WndProc; + wndclass.cbClsExtra = 0; + wndclass.cbWndExtra = 0; + wndclass.hInstance = hInstance; + wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION); + wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); + wndclass.hbrBackground= GetStockObject(WHITE_BRUSH); + wndclass.lpszMenuName = TEXT("GenericMenu"); + wndclass.lpszClassName= szAppName; + + RegisterClass(&wndclass); + } + + hWnd = CreateWindow (szAppName, + WindowTitle, + WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + NULL, + NULL, + hInstance, + NULL); + + ShowWindow (hWnd, nShowCmd); + UpdateWindow(hWnd); + + while (GetMessage (&msg, NULL, 0,0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + return (0); +} + + +LRESULT FAR PASCAL +WndProc (HWND hWnd, + UINT message, + WPARAM wParam, + LPARAM lParam + ) +{ + DWORD nEventType = (DWORD)wParam; + PDEV_BROADCAST_HDR p = (PDEV_BROADCAST_HDR) lParam; + DEV_BROADCAST_DEVICEINTERFACE filter; + WSADATA wsd; + + switch (message) + { + + case WM_COMMAND: + HandleCommands(hWnd, message, wParam, lParam); + return 0; + + case WM_CREATE: + + // Load Winsock + if (WSAStartup(MAKEWORD(2,2), &wsd) != 0) + { + MessageBox(hWnd, TEXT("WSAStartup failed"), TEXT("Error"), MB_OK); + exit(0); + } + + HWndList = CreateWindow (TEXT("listbox"), + NULL, + WS_CHILD|WS_VISIBLE|LBS_NOTIFY | + WS_VSCROLL | WS_BORDER, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + hWnd, + (HMENU)ID_EDIT, + HWndInstance, + NULL); + + filter.dbcc_size = sizeof(filter); + filter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; + filter.dbcc_classguid = InterfaceGuid; + InterfaceNotificationHandle = RegisterDeviceNotification(hWnd, &filter, 0); + + InitializeListHead(&ListHead); + EnumExistingDevices(hWnd); + + return 0; + + case WM_SIZE: + + MoveWindow(HWndList, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE); + return 0; + + case WM_SETFOCUS: + SetFocus(HWndList); + return 0; + + case WM_DEVICECHANGE: + + // + // The DBT_DEVNODES_CHANGED broadcast message is sent + // everytime a device is added or removed. This message + // is typically handled by Device Manager kind of apps, + // which uses it to refresh window whenever something changes. + // The lParam is always NULL in this case. + // + if(DBT_DEVNODES_CHANGED == wParam) { + DisplayV(TEXT("Received DBT_DEVNODES_CHANGED broadcast message")); + return 0; + } + + // + // All the events we're interested in come with lParam pointing to + // a structure headed by a DEV_BROADCAST_HDR. This is denoted by + // bit 15 of wParam being set, and bit 14 being clear. + // + if((wParam & 0xC000) == 0x8000) { + + if (!p) + return 0; + + if (p->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) { + + HandleDeviceInterfaceChange(hWnd, nEventType, (PDEV_BROADCAST_DEVICEINTERFACE) p); + } else if (p->dbch_devicetype == DBT_DEVTYP_HANDLE) { + + HandleDeviceChange(hWnd, nEventType, (PDEV_BROADCAST_HANDLE) p); + } + } + return 0; + + case WM_POWERBROADCAST: + HandlePowerBroadcast(hWnd, wParam, lParam); + return 0; + + case WM_CLOSE: + Cleanup(hWnd); + UnregisterDeviceNotification(InterfaceNotificationHandle); + return DefWindowProc(hWnd,message, wParam, lParam); + + case WM_DESTROY: + PostQuitMessage(0); + return 0; + } + return DefWindowProc(hWnd,message, wParam, lParam); + } + + +LRESULT +HandleCommands( + HWND hWnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam + ) + +{ + PDIALOG_RESULT result = NULL; + PDEVICE_INFO deviceInfo = NULL; + + switch (wParam) { + + case IDM_CLOSE: + Cleanup(hWnd); + Display(TEXT("Handle to the device closed")); + EnableMenuItem(GetMenu(hWnd), IDM_PING, MF_BYCOMMAND|MF_GRAYED); + EnableMenuItem(GetMenu(hWnd), IDM_CLOSE, MF_BYCOMMAND|MF_GRAYED); + break; + + case IDM_ENUMERATE: + // + // First cleanup everything, and then reenumerate all the devices. + Cleanup(hWnd); + EnumExistingDevices(hWnd); + EnableMenuItem(GetMenu(hWnd), IDM_PING, MF_BYCOMMAND|MF_ENABLED); + break; + + case IDM_PING: + + result = (PDIALOG_RESULT)DialogBox(HWndInstance, MAKEINTRESOURCE(IDD_DIALOG), hWnd, DlgProc); + if(result) { + deviceInfo = FindDeviceInfo(result); + if(!deviceInfo){ + MessageBox(hWnd, TEXT("FindDeviceInfo failed"), TEXT("Error"), MB_OK); + break; + } + + if(!OpenDevice(hWnd, deviceInfo)){ + MessageBox(hWnd, TEXT("OpenDevice failed"), TEXT("Error"), MB_OK); + break; + } + + if (!CreatePingThread(deviceInfo)) { + MessageBox(hWnd, TEXT("CreatePingThread failed"), TEXT("Error"), MB_OK); + break; + } + + EnableMenuItem(GetMenu(hWnd), IDM_PING, MF_BYCOMMAND|MF_GRAYED); + EnableMenuItem(GetMenu(hWnd), IDM_CLOSE, MF_BYCOMMAND|MF_ENABLED); + + } + break; + + case IDM_CLEAR: + SendMessage(HWndList, LB_RESETCONTENT, 0, 0); + ListBoxIndex = 0; + break; + + case IDM_VERBOSE: { + + HMENU hMenu = GetMenu(hWnd); + Verbose = !Verbose; + if(Verbose) { + CheckMenuItem(hMenu, (UINT)wParam, MF_CHECKED); + } else { + CheckMenuItem(hMenu, (UINT)wParam, MF_UNCHECKED); + } + } + break; + + case IDM_EXIT: + Cleanup(hWnd); + PostQuitMessage(0); + break; + + default: + break; + } + + if(result) { + HeapFree (GetProcessHeap(), 0, result); + } + return TRUE; +} + +INT_PTR CALLBACK +DlgProc( + HWND hDlg, + UINT message, + WPARAM wParam, + LPARAM lParam +) +{ + BOOL success; + PDIALOG_RESULT dialogResult = NULL; + ULONG value; + WCHAR SourceIP[80]; + WCHAR DestinationIP[80]; + DWORD SourceIPLen = sizeof(SourceIP); + + switch(message) + { + case WM_INITDIALOG: + // + // Set default values. + // + if(GetRegistryInfo(SourceIP, &SourceIPLen, DestinationIP, &SourceIPLen)) { + SetDlgItemText(hDlg, IDC_SOURCE_IP, SourceIP); + SetDlgItemText(hDlg, IDC_DESTINATION_IP, DestinationIP); + } else { + SetDlgItemText(hDlg, IDC_SOURCE_IP, DEF_SOURCE_IP); + SetDlgItemText(hDlg, IDC_DESTINATION_IP, DEF_DEST_IP); + + } + + SetDlgItemInt(hDlg, IDC_PACKET_SIZE, MAX_PAYLOAD_SIZE, FALSE); + return TRUE; + + case WM_COMMAND: + switch( wParam) + { + case ID_OK: + // + // Allocate memory to store the input values. + // + dialogResult = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + sizeof(DIALOG_RESULT)); + if(dialogResult) { + + dialogResult->DeviceIndex = GetDlgItemInt(hDlg, + IDC_DEVICE_INDEX, &success, FALSE ); + if(!success){ + break; + } + value = GetDlgItemText(hDlg, IDC_SOURCE_IP, + dialogResult->SourceIp, MAX_LEN-1 ); + if(!value){ + break; + } + + + GetDlgItemText(hDlg, IDC_DESTINATION_IP, + dialogResult->DestIp, MAX_LEN-1 ); + if(!value){ + break; + } + + value = GetDlgItemInt(hDlg,IDC_PACKET_SIZE, &success, FALSE ); + if(success){ + value = min(value, MAX_PAYLOAD_SIZE); + value = max(value, MIN_PAYLOAD_SIZE); + + } else { + value = MIN_PAYLOAD_SIZE; + } + + dialogResult->PacketSize = value; + + SetRegistryInfo(dialogResult->SourceIp, + sizeof(dialogResult->SourceIp), + dialogResult->DestIp, + sizeof(dialogResult->DestIp)); + + } + EndDialog(hDlg, (UINT_PTR)dialogResult); + return TRUE; + case ID_CANCEL: + EndDialog(hDlg, 0); + return TRUE; + + } + break; + + } + return FALSE; +} + + +BOOL +HandleDeviceInterfaceChange( + HWND hWnd, + DWORD evtype, + PDEV_BROADCAST_DEVICEINTERFACE dip + ) +{ + switch (evtype) + { + case DBT_DEVICEARRIVAL: + // + // New device arrived. Create a devicinfo structure and record + // information about the device. + // + Display(TEXT("New device Arrived (Interface Change Notification)")); + + if(!CreateDeviceInfo(dip->dbcc_name)) { + return FALSE; + } + + break; + + case DBT_DEVICEREMOVECOMPLETE: + // + // Device Removed. + // + Display(TEXT("Remove Complete (Interface Change Notification)"), NULL); + break; + + default: + DisplayV(TEXT("Unknown (Interface Change Notification)"), NULL); + break; + } + return TRUE; +} + +BOOL +HandleDeviceChange( + HWND hWnd, + DWORD evtype, + PDEV_BROADCAST_HANDLE dhp + ) +{ + PDEVICE_INFO deviceInfo = NULL; + PLIST_ENTRY thisEntry; + + // + // Walk the list to get the deviceInfo for this device + // by matching the notification handle saved in our deviceInfo + // and the one provided as part of the message. + // + for(thisEntry = ListHead.Flink; thisEntry != &ListHead; + thisEntry = thisEntry->Flink) + { + deviceInfo = CONTAINING_RECORD(thisEntry, DEVICE_INFO, ListEntry); + if(dhp->dbch_hdevnotify == deviceInfo->hHandleNotification) { + break; + } + deviceInfo = NULL; + } + + if(!deviceInfo) { + Display(TEXT("Error: spurious message Event Type %x, Device Type %x"), + evtype, dhp->dbch_devicetype); + return FALSE; + } + + switch (evtype) + { + + case DBT_DEVICEQUERYREMOVE: + + Display(TEXT("Query Remove (Handle Notification): %ws"), + deviceInfo->DeviceName); + // User is trying to disable, uninstall, or eject our device. + // Terminate the ping thread and close the handle + // to the device so that the target device can + // get removed. Do not unregister the notification + // at this point, because we want to know whether + // the device is successfully removed or not. + // + TerminatePingThread(deviceInfo); + break; + + case DBT_DEVICEREMOVECOMPLETE: + + Display(TEXT("Remove Complete (Handle Notification):%ws"), + deviceInfo->DeviceName); + // + // Device is getting surprise removed. So terminate the + // ping thread to close the handle to device and + // unregister the PNP notification. + // + TerminatePingThread(deviceInfo); + + if (deviceInfo->hHandleNotification) { + UnregisterDeviceNotification(deviceInfo->hHandleNotification); + deviceInfo->hHandleNotification = NULL; + } + + // + // Unlink this deviceInfo from the list and free the memory + // + RemoveEntryList(&deviceInfo->ListEntry); + HeapFree (GetProcessHeap(), 0, deviceInfo); + + break; + + case DBT_DEVICEREMOVEPENDING: + + Display(TEXT("Remove Pending (Handle Notification):%ws"), + deviceInfo->DeviceName); + // + // Device is successfully removed so unregister the notification + // and free the memory. + // + FreeDeviceInfo(deviceInfo); + + break; + + case DBT_DEVICEQUERYREMOVEFAILED : + Display(TEXT("Remove failed (Handle Notification):%ws"), + deviceInfo->DeviceName); + // + // Remove failed. So reopen the device and register for + // notification on the new handle. But first we should unregister + // the previous notification. + // + if (deviceInfo->hHandleNotification) { + UnregisterDeviceNotification(deviceInfo->hHandleNotification); + deviceInfo->hHandleNotification = NULL; + } + + if(!OpenDevice(hWnd, deviceInfo)) { + Display(TEXT("Failed to reopen the device: %ws"), + deviceInfo->DeviceName); + FreeDeviceInfo(deviceInfo); + break; + } + + Display(TEXT("Reopened device %ws"), deviceInfo->DeviceName); + // + // Restart the ping operation. + // + if(CreatePingThread(deviceInfo)){ + FreeDeviceInfo(deviceInfo); + break; + } + + break; + + default: + Display(TEXT("Unknown (Handle Notification)")); + break; + + } + return TRUE; +} + + +BOOLEAN +EnumExistingDevices( + HWND hWnd +) +{ + HDEVINFO hardwareDeviceInfo; + SP_DEVICE_INTERFACE_DATA deviceInterfaceData; + PSP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceDetailData = NULL; + ULONG predictedLength = 0; + ULONG requiredLength = 0, i; + DWORD error; + PDEVICE_INFO deviceInfo =NULL; + + DisplayV(TEXT("Entered EnumExistingDevices")); + + // + // Make sure the list is empty + // + if(!IsListEmpty(&ListHead) ){ + MessageBox(hWnd, TEXT("ListHead should be empty"), TEXT("Error!"), MB_OK); + return FALSE; + } + + DeviceIndex = 0; + + hardwareDeviceInfo = SetupDiGetClassDevs ( + (LPGUID)&InterfaceGuid, + NULL, // Define no enumerator (global) + NULL, // Define no + (DIGCF_PRESENT | // Only Devices present + DIGCF_DEVICEINTERFACE)); // Function class devices. + if(INVALID_HANDLE_VALUE == hardwareDeviceInfo) + { + goto Error; + } + + // + // Enumerate devices of a specific interface class + // + deviceInterfaceData.cbSize = sizeof(deviceInterfaceData); + + for(i=0; SetupDiEnumDeviceInterfaces (hardwareDeviceInfo, + 0, // No care about specific PDOs + (LPGUID)&InterfaceGuid, + i, // + &deviceInterfaceData); i++ ) { + + // + // Allocate a function class device data structure to + // receive the information about this particular device. + // + + // + // First find out required length of the buffer + // + if (deviceInterfaceDetailData) { + HeapFree (GetProcessHeap(), 0, deviceInterfaceDetailData); + deviceInterfaceDetailData = NULL; + } + + if(!SetupDiGetDeviceInterfaceDetail ( + hardwareDeviceInfo, + &deviceInterfaceData, + NULL, // probing so no output buffer yet + 0, // probing so output buffer length of zero + &requiredLength, + NULL) && (error = GetLastError()) != ERROR_INSUFFICIENT_BUFFER) + { + goto Error; + } + predictedLength = requiredLength; + + deviceInterfaceDetailData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + predictedLength); + if (deviceInterfaceDetailData == NULL) { + goto Error; + } + + deviceInterfaceDetailData->cbSize = + sizeof (SP_DEVICE_INTERFACE_DETAIL_DATA); + + + if (! SetupDiGetDeviceInterfaceDetail ( + hardwareDeviceInfo, + &deviceInterfaceData, + deviceInterfaceDetailData, + predictedLength, + &requiredLength, + NULL)) { + goto Error; + } + + deviceInfo = CreateDeviceInfo(deviceInterfaceDetailData->DevicePath); + + if(!deviceInfo) + goto Error; + + + } + + if(deviceInterfaceDetailData) { + HeapFree (GetProcessHeap(), 0, deviceInterfaceDetailData); + } + + SetupDiDestroyDeviceInfoList (hardwareDeviceInfo); + return 0; + +Error: + + error = GetLastError(); + MessageBox(hWnd, TEXT("EnumExisting Devices failed"), TEXT("Error!"), MB_OK); + if(deviceInterfaceDetailData) + HeapFree (GetProcessHeap(), 0, deviceInterfaceDetailData); + + SetupDiDestroyDeviceInfoList (hardwareDeviceInfo); + Cleanup(hWnd); + return 0; +} + +PDEVICE_INFO +FindDeviceInfo( + PDIALOG_RESULT InputInfo + ) +{ + PLIST_ENTRY thisEntry, listHead; + PDEVICE_INFO deviceInfo = NULL, result = NULL; + + listHead = &ListHead; + + for(thisEntry = listHead->Flink; + thisEntry != listHead; + thisEntry = thisEntry->Flink){ + + deviceInfo = CONTAINING_RECORD(thisEntry, DEVICE_INFO, ListEntry); + + if(deviceInfo->DeviceIndex == InputInfo->DeviceIndex){ + + if(deviceInfo->IsANetworkMiniport){ + Display(TEXT("You can't use this app on a device installed as a network device")); + break; + } + + if(deviceInfo->hDevice && + deviceInfo->hDevice != INVALID_HANDLE_VALUE){ + Display(TEXT("%ws device is already in use"), + deviceInfo->DeviceName); + break; + } + + + deviceInfo->DeviceIndex = InputInfo->DeviceIndex; + deviceInfo->PacketSize = InputInfo->PacketSize; + memcpy(deviceInfo->UnicodeSourceIp, InputInfo->SourceIp, MAX_LEN); + memcpy(deviceInfo->UnicodeDestIp, InputInfo->DestIp, MAX_LEN); + // + // Convert the unicode source and destination IP string + // to ANSI and store it. + // + WideCharToMultiByte(CP_ACP, //ANSI code page + 0, deviceInfo->UnicodeSourceIp, -1, + deviceInfo->SourceIp, MAX_LEN, NULL, NULL); + + // + // Convert Unicode string to ANSI. + // + WideCharToMultiByte(CP_ACP, 0, deviceInfo->UnicodeDestIp, -1, + deviceInfo->DestIp, MAX_LEN, NULL, NULL); + + + result = deviceInfo; + break; + } + + } + + return result; + +} + +PDEVICE_INFO +CreateDeviceInfo( + _In_ LPWSTR DevicePath + ) +{ + PDEVICE_INFO deviceInfo = NULL; + HRESULT hr; + + DisplayV(TEXT("Entered CreateDeviceInfo")); + + deviceInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DEVICE_INFO)); + if(!deviceInfo) { + goto Error; + } + + + if(!GetDeviceDescription(DevicePath, + deviceInfo->DeviceName, + sizeof(deviceInfo->DeviceName), + &deviceInfo->IsANetworkMiniport + )) { + Display(TEXT("GetDeviceDescription failed %x"), GetLastError()); + goto Error; + } + + + // + // Copy the device path so that we can open the device using CreateFile. + // + hr = StringCchCopy(deviceInfo->DevicePath, MAX_PATH, DevicePath); + if(FAILED(hr)){ + goto Error; + } + + DeviceIndex++; + deviceInfo->DeviceIndex = DeviceIndex; + + // + // Link this to the global list of devices. + // + InitializeListHead(&deviceInfo->ListEntry); + InsertTailList(&ListHead, &deviceInfo->ListEntry); + + Display(TEXT("Device %d is %ws"), DeviceIndex, deviceInfo->DeviceName); + + return deviceInfo; + +Error: + + if(deviceInfo) { + HeapFree (GetProcessHeap(), 0, deviceInfo); + } + return NULL; + +} + +VOID +FreeDeviceInfo( + _In_ PDEVICE_INFO DeviceInfo + ) +{ + DisplayV(TEXT("Entered FreeDeviceInfo")); + + if (DeviceInfo->hHandleNotification) { + UnregisterDeviceNotification(DeviceInfo->hHandleNotification); + DeviceInfo->hHandleNotification = NULL; + } + if (DeviceInfo->hDevice != INVALID_HANDLE_VALUE && + DeviceInfo->hDevice != NULL) { + CloseHandle(DeviceInfo->hDevice); + DeviceInfo->hDevice = INVALID_HANDLE_VALUE; + Display(TEXT("Closed handle to device %ws"), DeviceInfo->DeviceName ); + } + + RemoveEntryList(&DeviceInfo->ListEntry); + + HeapFree (GetProcessHeap(), 0, DeviceInfo); + + return; +} + +BOOL +SetRegistryInfo( + _In_reads_bytes_(SourceIPLen) LPWSTR SourceIP, + _In_ DWORD SourceIPLen, + _In_reads_bytes_(DestinationIPLen) LPWSTR DestinationIP, + _In_ DWORD DestinationIPLen + ) +{ + HKEY hKey; + BOOL ret = FALSE; + size_t srcStrLen, destStrLen; + + if (FAILED(StringCbLengthW(SourceIP, SourceIPLen, &srcStrLen))) { + return ret; + } + + if (FAILED(StringCbLengthW(DestinationIP, DestinationIPLen, &destStrLen))) { + return ret; + } + + // + // RegSetValueEx takes a DWORD, in the rare case that size_t is larger than + // a DWORD return an error. + // + if (srcStrLen > (DWORD_MAX - sizeof(WCHAR))|| + destStrLen > (DWORD_MAX - sizeof(WCHAR))) { + return ret; + } + + if (RegOpenKey(HKEY_LOCAL_MACHINE, REG_PATH, &hKey)) { + + if (ERROR_SUCCESS != RegCreateKey(HKEY_LOCAL_MACHINE, REG_PATH, &hKey)) { + Display(TEXT("RegCreateKey failed: %x"), GetLastError()); + return ret; + } + } + + if (ERROR_SUCCESS == RegSetValueEx(hKey, L"SourceIP", 0, REG_SZ, + (LPBYTE)SourceIP, (DWORD) srcStrLen+sizeof(WCHAR))) { + + if (ERROR_SUCCESS == RegSetValueEx(hKey, L"DestinationIP", 0, REG_SZ, + (LPBYTE)DestinationIP, (DWORD) destStrLen+sizeof(WCHAR))) { + ret = TRUE; + } + } + + RegCloseKey(hKey); + return ret; +} + +_Success_(return) +BOOL +GetRegistryInfo( + _Out_writes_bytes_(* SourceIPLen) PWSTR SourceIP, + _Inout_ LPDWORD SourceIPLen, + _Out_writes_bytes_(* DestinationIPLen) PWSTR DestinationIP, + _Inout_ LPDWORD DestinationIPLen + ) +{ + HKEY hKey; + DWORD dwType = REG_SZ; + BOOL ret = FALSE; + + if(ERROR_SUCCESS == RegOpenKey(HKEY_LOCAL_MACHINE, REG_PATH, &hKey)) { + + if(ERROR_SUCCESS == RegQueryValueEx(hKey, L"SourceIP", NULL, &dwType, + (LPBYTE)SourceIP, SourceIPLen)){ + + if(ERROR_SUCCESS == RegQueryValueEx(hKey, L"DestinationIP", NULL, &dwType, + (LPBYTE)DestinationIP, DestinationIPLen)){ + + ret = TRUE; + } + + } + RegCloseKey(hKey); + } + + return ret; +} + + + +BOOLEAN +OpenDevice( + _In_ HWND HWnd, + _In_ PDEVICE_INFO DeviceInfo + ) +{ + DEV_BROADCAST_HANDLE filter; + HANDLE hDevice; + + DisplayV(TEXT("Entered OpenDevice")); + + // + // Open an handle to the device. + // + hDevice = CreateFile ( + DeviceInfo->DevicePath, + GENERIC_READ | GENERIC_WRITE, + 0, + NULL, // no SECURITY_ATTRIBUTES structure + OPEN_EXISTING, // No special create flags + FILE_FLAG_OVERLAPPED, + NULL); + + if (INVALID_HANDLE_VALUE == hDevice) { + Display(TEXT("Failed to open the device: %ws"), + DeviceInfo->DeviceName); + return FALSE; + } + + Display(TEXT("Opened handled to the device: %ws"), + DeviceInfo->DeviceName); + // + // Register handle based notification to receive pnp + // device change notification on the handle. + // + + memset (&filter, 0, sizeof(filter)); //zero the structure + filter.dbch_size = sizeof(filter); + filter.dbch_devicetype = DBT_DEVTYP_HANDLE; + filter.dbch_handle = hDevice; + + DeviceInfo->hHandleNotification = RegisterDeviceNotification(HWnd, &filter, 0); + if(!DeviceInfo->hHandleNotification){ + Display(TEXT("Failed to register notification: %ws"), + DeviceInfo->DeviceName); + CloseHandle(hDevice); + return FALSE; + } + + DeviceInfo->hDevice = hDevice; + + return TRUE; + +} + + +BOOL +CreatePingThread( + PDEVICE_INFO DeviceInfo + ) +{ + ULONG id; + + DisplayV(TEXT("CreatePingThread")); + + DeviceInfo->ExitThread = FALSE; + + // + // Start the ping operation in a separate thread. + // + DeviceInfo->ThreadHandle = CreateThread( NULL, // security attributes + 0, // initial stack size + (LPTHREAD_START_ROUTINE) PingThread, // Main() function + DeviceInfo, // arg to Reader thread + 0, // creation flags + (LPDWORD)&id); // returned thread id + + if ( NULL == DeviceInfo->ThreadHandle) { + Display(TEXT("CreateThread failed %x"), GetLastError()); + return FALSE; + } + + return TRUE; +} + +VOID +TerminatePingThread( + PDEVICE_INFO DeviceInfo + ) +{ + DWORD status; + + DisplayV(TEXT("TerminatePingThread")); + + if(DeviceInfo->ThreadHandle){ + + DeviceInfo->ExitThread = TRUE; + // + // Wait for the thread to exit + // + status = WaitForSingleObjectEx(DeviceInfo->ThreadHandle, 1000, TRUE ); + if(status == WAIT_FAILED){ + Display(TEXT("Wait failed %x"), GetLastError()); + } + CloseHandle(DeviceInfo->ThreadHandle); + DeviceInfo->ThreadHandle = NULL; + } + +} + +BOOLEAN +Cleanup( + HWND hWnd + ) +/*++ + + This routine walks the global list of currently enumerated devices + and close all handles and frees the memory. + --*/ +{ + PDEVICE_INFO deviceInfo =NULL; + PLIST_ENTRY thisEntry; + + DisplayV(TEXT("Entered Cleanup")); + + while (!IsListEmpty(&ListHead)) { + thisEntry = ListHead.Flink; + deviceInfo = CONTAINING_RECORD(thisEntry, DEVICE_INFO, ListEntry); + // + // First let us make sure the PingThread is not running. + // + TerminatePingThread(deviceInfo); + FreeDeviceInfo(deviceInfo); + } + return TRUE; +} + + +_Success_(return != FALSE) +BOOL +GetDeviceDescription( + _In_ LPTSTR DevPath, + _Out_writes_bytes_all_(OutBufferLen) LPTSTR OutBuffer, + _In_ ULONG OutBufferLen, + BOOL *NetClassDevice +) +{ + HDEVINFO hardwareDeviceInfo = NULL; + SP_DEVICE_INTERFACE_DATA deviceInterfaceData; + SP_DEVINFO_DATA deviceInfoData; + DWORD dwRegType, error; + TCHAR classGuidString[MAX_GUID_STRING_LEN]; + HRESULT hr; + GUID classGuid; + BOOL ret = FALSE; + + DisplayV(TEXT("GetDeviceDescription")); + + hardwareDeviceInfo = SetupDiCreateDeviceInfoList(NULL, NULL); + if(INVALID_HANDLE_VALUE == hardwareDeviceInfo) + { + Display(TEXT("Couldn't create DeviceInfoList: %x"), GetLastError()); + goto Error; + } + + // + // Enumerate devices of toaster class + // + deviceInterfaceData.cbSize = sizeof(deviceInterfaceData); + + SetupDiOpenDeviceInterface (hardwareDeviceInfo, DevPath, + 0, // + &deviceInterfaceData); + + deviceInfoData.cbSize = sizeof(deviceInfoData); + if(!SetupDiGetDeviceInterfaceDetail ( + hardwareDeviceInfo, + &deviceInterfaceData, + NULL, // probing so no output buffer yet + 0, // probing so output buffer length of zero + NULL, + &deviceInfoData) && (error = GetLastError()) != ERROR_INSUFFICIENT_BUFFER) + { + Display(TEXT("Couldn't get interface detail: %x"), GetLastError()); + goto Error; + } + // + // Get the friendly name for this instance, if that fails + // try to get the device description. + // + + if(!SetupDiGetDeviceRegistryProperty(hardwareDeviceInfo, &deviceInfoData, + SPDRP_FRIENDLYNAME, + &dwRegType, + (BYTE*) OutBuffer, + OutBufferLen, + NULL)) + { + if(!SetupDiGetDeviceRegistryProperty(hardwareDeviceInfo, &deviceInfoData, + SPDRP_DEVICEDESC, + &dwRegType, + (BYTE*) OutBuffer, + OutBufferLen, + NULL)){ + Display(TEXT("Couldn't get friendlyname: %x"), GetLastError()); + goto Error; + + } + + + } + + // + // Get the class guid of the device and find out whether this is a + // network miniport. + // + if(!SetupDiGetDeviceRegistryProperty(hardwareDeviceInfo, + &deviceInfoData, + SPDRP_CLASSGUID, + &dwRegType, + (BYTE*) classGuidString, + sizeof(classGuidString), + NULL)) { + Display(TEXT("Class guid is not available for device: %ws"), OutBuffer ); + } + + hr = CLSIDFromString(classGuidString, &classGuid); + if(FAILED(hr)) { + goto Error; + } + + if(IsEqualGUID(&classGuid, &GUID_DEVCLASS_NET)){ + *NetClassDevice = TRUE; + } else { + *NetClassDevice = FALSE; + } + + ret = TRUE; + +Error: + + if(hardwareDeviceInfo) { + SetupDiDestroyDeviceInfoList (hardwareDeviceInfo); + } + return ret; +} + + +BOOL +HandlePowerBroadcast( + HWND hWnd, + WPARAM wParam, + LPARAM lParam) +{ + BOOL fRet = TRUE; + + switch (wParam) + { + case PBT_APMQUERYSTANDBY: + DisplayV(TEXT("PBT_APMQUERYSTANDBY")); + break; + case PBT_APMQUERYSUSPEND: + DisplayV(TEXT("PBT_APMQUERYSUSPEND")); + break; + case PBT_APMSTANDBY : + DisplayV(TEXT("PBT_APMSTANDBY")); + break; + case PBT_APMSUSPEND : + DisplayV(TEXT("PBT_APMSUSPEND")); + break; + case PBT_APMQUERYSTANDBYFAILED: + DisplayV(TEXT("PBT_APMQUERYSTANDBYFAILED")); + break; + case PBT_APMRESUMESTANDBY: + DisplayV(TEXT("PBT_APMRESUMESTANDBY")); + break; + case PBT_APMQUERYSUSPENDFAILED: + DisplayV(TEXT("PBT_APMQUERYSUSPENDFAILED")); + break; + case PBT_APMRESUMESUSPEND: + DisplayV(TEXT("PBT_APMRESUMESUSPEND")); + break; + case PBT_APMBATTERYLOW: + DisplayV(TEXT("PBT_APMBATTERYLOW")); + break; + case PBT_APMOEMEVENT: + DisplayV(TEXT("PBT_APMOEMEVENT")); + break; + case PBT_APMRESUMEAUTOMATIC: + DisplayV(TEXT("PBT_APMRESUMEAUTOMATIC")); + break; + case PBT_APMRESUMECRITICAL: + DisplayV(TEXT("PBT_APMRESUMECRITICAL")); + break; + case PBT_APMPOWERSTATUSCHANGE: + DisplayV(TEXT("PBT_APMPOWERSTATUSCHANGE")); + break; + default: + DisplayV(TEXT("Default")); + break; + } + return fRet; +} + + |
