From 97cf5197cf5b882b2c689d8dc2b555f2edf8f418 Mon Sep 17 00:00:00 2001 From: Dave Wilson Date: Tue, 17 Mar 2015 19:50:07 -0700 Subject: Initial publish --- nfp/net/exe/NetNfpControl.cpp | 579 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 579 insertions(+) create mode 100644 nfp/net/exe/NetNfpControl.cpp (limited to 'nfp/net/exe/NetNfpControl.cpp') diff --git a/nfp/net/exe/NetNfpControl.cpp b/nfp/net/exe/NetNfpControl.cpp new file mode 100644 index 00000000..b101d19e --- /dev/null +++ b/nfp/net/exe/NetNfpControl.cpp @@ -0,0 +1,579 @@ +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// Module Name: NetNfpControl.cpp +// Abstract: Windows Near-field Proximity Test tool. Designed for simulating proximity hardware. +// +// NetNfpControl console app allows control of the NetNfpProvider test driver. +// Both the local and remote machine must have the NetNfpProvider driver installed. +// +// *USAGE* +// NetNfpControl.exe [/e] +// NetNfpControl.exe [] [/k] +// NetNfpControl.exe /q +// +// Example: NetNfpControl.exe John-PC1 +// The first operating mode allows the user to specify a remote machine name (or IPv6 address) +// that the local machine should connect to and simulate proximity with. After it's connected, +// a simple key-press ends the simulated proximity link. The console app then exits. +// If the option /e is specified, rather than the waiting for a key to be pressed, the tool +// waits for the QUIT_NAMED_EVENT named event to be set. The named event can be set by running +// NetNfpControl.exe /q. +// +// Example: NetNfpControl.exe John-PC1 /k +// A second operating mode keeps the console app running with a Ctrl-F1 hotkey registered. +// This hot key remains registered and functional even when the app is in the background. +// When the hot key is intercepted, a near-field proximity event is simulated directly with +// the specified remote machine. +// Note: The console app needs to be running (only one one machine) to intercept the system hot key. +// +// Example: NetNfpControl.exe /k +// A third operating mode also keeps the console app running with a Ctrl-F1 hotkey registered. +// However, you'll have to run this on two or more machines at the same time. Pressing Ctrl-F1 +// on any two machines at the same time causes the machines to exchange their network name via +// a file on a private share with a special file name. +// - The server share used is hard coded to: \\scratch2\scratch\travm\proxrendezvous\ +// - Either create a file server with these folders shared, or change this to match yours. +// - The file has an effective lifetime of 2 seconds. +// - In the event of a collision (two clients posting an event during the same interval), +// only one client 'wins'. +// +// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#pragma region Includes +#include "precomp.h" +#pragma endregion + + +#pragma region Globals +wchar_t g_szMachineName[MAX_PATH]; +PCWSTR g_pszRemoteMachineName = nullptr; +#pragma endregion + +#define QUIT_NAMED_EVENT L"NetNfpControl_Quit_Event" + + +//---------------------------------------------------------------------------------------------------------------------- +// Name: DEVICE_INTERFACE_DETAIL +// Comments: +// +//---------------------------------------------------------------------------------------------------------------------- +///Device interface details. +struct DEVICE_INTERFACE_DETAIL +{ + DWORD cbSize; + wchar_t szSymbolicLink[MAX_PATH*2]; +}; + +//---------------------------------------------------------------------------------------------------------------------- +// Name: BeginProximity +// Comments: +// +//---------------------------------------------------------------------------------------------------------------------- +///Initalizes a proximity event. +/// +/// +HRESULT BeginProximity(_In_ PCWSTR pszName, _Out_ HANDLE* pHandle) +{ + HRESULT hr = S_OK; + LPGUID pGuid = (LPGUID) &GUID_DEVINTERFACE_NETNFP; + + HDEVINFO hDevSet = SetupDiGetClassDevs(pGuid, nullptr, nullptr, (DIGCF_PRESENT | DIGCF_INTERFACEDEVICE)); + if (hDevSet == INVALID_HANDLE_VALUE) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + } + + DEVICE_INTERFACE_DETAIL deviceInterfaceDetail = {}; + if (SUCCEEDED(hr)) + { + SP_DEVICE_INTERFACE_DATA devInterfaceData = {sizeof(devInterfaceData)}; + if (!SetupDiEnumDeviceInterfaces(hDevSet, nullptr, pGuid, 0, &devInterfaceData)) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + } + + if (SUCCEEDED(hr)) + { + PSP_DEVICE_INTERFACE_DETAIL_DATA pDetail = (PSP_DEVICE_INTERFACE_DETAIL_DATA)&deviceInterfaceDetail; + pDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); + if (!SetupDiGetDeviceInterfaceDetail(hDevSet, &devInterfaceData, pDetail, + sizeof(deviceInterfaceDetail), nullptr, nullptr)) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + } + } + + SetupDiDestroyDeviceInfoList(hDevSet); + } + + HANDLE hProximity = INVALID_HANDLE_VALUE; + if (SUCCEEDED(hr)) + { + hProximity = CreateFile(deviceInterfaceDetail.szSymbolicLink, GENERIC_READ, 0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); + if (hProximity == INVALID_HANDLE_VALUE) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + } + } + + BEGIN_PROXIMITY_ARGS args = {}; + if (SUCCEEDED(hr)) + { + hr = StringCchCopy(args.szName, MAX_PATH, pszName); + } + + if (SUCCEEDED(hr)) + { + DWORD ignore; + if (!DeviceIoControl(hProximity, IOCTL_BEGIN_PROXIMITY, &args, sizeof(args), nullptr, 0, &ignore, nullptr)) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + } + } + + if (FAILED(hr)) + { + if (hProximity != INVALID_HANDLE_VALUE) + { + CloseHandle(hProximity); + hProximity = INVALID_HANDLE_VALUE; + } + } + + *pHandle = hProximity; + + return hr; +} + +//---------------------------------------------------------------------------------------------------------------------- +// Name: AcquireFileLock +// Comments: +// +//---------------------------------------------------------------------------------------------------------------------- +///Aquires a lock on a file. +/// +/// +HANDLE AcquireFileLock(PCWSTR pszLockFilePath) +{ + HANDLE hLock = INVALID_HANDLE_VALUE; + for (int i = 0; i < 200; i++) + { + wprintf(L"Attempting to Acquire Lock: %u\n", (DWORD)GetTickCount64()); + hLock = CreateFile(pszLockFilePath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE, NULL); + if (hLock == INVALID_HANDLE_VALUE) + { + Sleep(50); + } + else + { + wprintf(L"Proximity Lock Acquired: %u\n", (DWORD)GetTickCount64()); + break; + } + } + + if (hLock == INVALID_HANDLE_VALUE) + { + wprintf(L"Proximity Lock Not Acquired, check network connectivity Error = %u.\n", GetLastError()); + } + + return hLock; +} + +//---------------------------------------------------------------------------------------------------------------------- +// Name: Proximity +// Comments: +// +//---------------------------------------------------------------------------------------------------------------------- +///Initiates a proximity event. +/// +/// +void Proximity() +{ + wprintf(L"Checking For Proximate Device\n"); + + SYSTEMTIME sysTime = {}; + GetLocalTime(&sysTime); + + wchar_t szDirectory[MAX_PATH]; + StringCchPrintf(szDirectory, MAX_PATH, L"\\\\scratch2\\scratch\\travm\\proxrendezvous\\%u%02u%02u-%02u", + sysTime.wYear, sysTime.wMonth, sysTime.wDay, sysTime.wHour); + + CreateDirectory(szDirectory, NULL); + + wchar_t szLockPath[MAX_PATH]; + StringCchPrintf(szLockPath, MAX_PATH, L"%s\\lock.txt", szDirectory); + + HANDLE hLock = AcquireFileLock(szLockPath); + + wchar_t szOtherMachine[MAX_PATH] = {}; + if (hLock != INVALID_HANDLE_VALUE) + { + wprintf(L"looking for available devices in proximity.\n"); + wchar_t szFindPath[MAX_PATH]; + StringCchPrintf(szFindPath, MAX_PATH, L"%s\\*.available", szDirectory); + WIN32_FIND_DATA findData; + HANDLE hFind = FindFirstFile(szFindPath, &findData); + + wchar_t szFilePath[MAX_PATH]; + bool fClient; + if (hFind != INVALID_HANDLE_VALUE) + { + fClient = true; + + wprintf(L"Proximate device found: "); + StringCchPrintf(szFilePath, MAX_PATH, L"%s\\%s", szDirectory, findData.cFileName); + HANDLE hFile = CreateFile(szFilePath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile != INVALID_HANDLE_VALUE) + { + DWORD ignore; + (void)ReadFile(hFile, szOtherMachine, sizeof(szOtherMachine) - sizeof(wchar_t), &ignore, NULL); + szOtherMachine[MAX_PATH-1] = L'\0'; + CloseHandle(hFile); + } + + if (szOtherMachine[0] != L'\0') + { + wprintf(L"%s\n", szOtherMachine); + wchar_t szNewFileName[MAX_PATH]; + StringCchPrintf(szNewFileName, MAX_PATH, L"%s\\%s.%s.%02u%02u", szDirectory, szOtherMachine, g_szMachineName, sysTime.wMinute, sysTime.wSecond); + MoveFile(szFilePath, szNewFileName); + } + } + else + { + fClient = false; + + wprintf(L"No proximate device found yet. Placing proximity marker on share...\n"); + StringCchPrintf(szFilePath, MAX_PATH, L"%s\\%s.available", szDirectory, g_szMachineName); + HANDLE hFile = CreateFile(szFilePath, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); + DWORD ignore; + WriteFile(hFile, g_szMachineName, sizeof(g_szMachineName), &ignore, NULL); + CloseHandle(hFile); + } + + FindClose(hFind); + hFind = INVALID_HANDLE_VALUE; + + CloseHandle(hLock); + DeleteFile(szLockPath); + + if (fClient) + { + HANDLE hProximity; + HRESULT hr = BeginProximity(szOtherMachine, &hProximity); + if (SUCCEEDED(hr)) + { + wprintf(L"In Proximity for 1 second...\n"); + Sleep(1000); + CloseHandle(hProximity); + wprintf(L"Proximity Complete.\n"); + } + else + { + wprintf(L"ERROR: BeginProximity() failed: 0x%x\n", hr); + } + } + else + { + wprintf(L"Other machine will initiate proximity...\n"); + Sleep(2000); + + bool fCompleted = true; + hLock = AcquireFileLock(szLockPath); + if (hLock != INVALID_HANDLE_VALUE) + { + wchar_t szNewFileName[MAX_PATH]; + StringCchPrintf(szNewFileName, MAX_PATH, L"%s\\%s.%02u%02u.expired", szDirectory, g_szMachineName, sysTime.wMinute, sysTime.wSecond); + if (MoveFile(szFilePath, szNewFileName)) + { + fCompleted = false; + } + + CloseHandle(hLock); + DeleteFile(szLockPath); + } + + if (fCompleted) + { + wprintf(L"Proximity Successful!\n"); + } + else + { + wprintf(L"ERROR: Proximity Unsuccessful. No proximate device found!\n"); + } + } + } +} + +//---------------------------------------------------------------------------------------------------------------------- +// Name: WndProc +// Comments: +// +//---------------------------------------------------------------------------------------------------------------------- +///Windows call-back procedure. +/// +///Used to receive call-backs for the Windows system-wide Hot Key's +/// +LRESULT CALLBACK WndProc( + HWND hwnd, // handle to window + UINT uMsg, // message identifier + WPARAM wParam, // first message parameter + LPARAM lParam) // second message parameter +{ + switch (uMsg) + { + case WM_HOTKEY: + { + if (g_pszRemoteMachineName != nullptr) + { + HANDLE hProximity; + HRESULT hr = BeginProximity(g_pszRemoteMachineName, &hProximity); + if (SUCCEEDED(hr)) + { + wprintf(L"In Proximity for 1 second...\n"); + Sleep(1000); + CloseHandle(hProximity); + wprintf(L"Proximity Complete.\n"); + } + else + { + wprintf(L"ERROR: BeginProximity() failed: 0x%x\n", hr); + } + } + else // No machine name specified, need to check for a name on the share + { + Proximity(); + } + } + return 0; + + case WM_DESTROY: + PostQuitMessage(0); + return 0; + + // + // Process other messages. + // + default: + return DefWindowProc(hwnd, uMsg, wParam, lParam); + } +} + +__analysis_noreturn void Usage() +{ + wprintf(L"Usage: \n"); + wprintf(L" NetNfpControl.exe \n"); + wprintf(L" NetNfpControl.exe /e \n"); + wprintf(L" NetNfpControl.exe /q\n"); + wprintf(L" NetNfpControl.exe /k\n"); + wprintf(L" NetNfpControl.exe /k \n"); + wprintf(L"\n"); + wprintf(L"The /k option registers a hotkey for entering proximity while selfhosting\n"); + wprintf(L"The /e option keeps NetNfpControl.exe running until NetNfpControl.exe /q is called\n" + L" (or until the named event %s is set)\n", QUIT_NAMED_EVENT); + wprintf(L"The /q option sets the the named event %s (and exits), causing \n" + L" all the outstanding instances of 'NetNfpControl.exe /e' to exit\n", QUIT_NAMED_EVENT); + + exit(1); +} + +//---------------------------------------------------------------------------------------------------------------------- +// Name: wmain +// Comments: Main application entry point. +// +//---------------------------------------------------------------------------------------------------------------------- +///wmain. +/// +///Main application entry point. +/// +int _cdecl wmain(_In_ int argc, _In_reads_(argc) PWSTR* argv) +{ + wprintf(L"\n*** Network NearFieldProvider Control Executable ***\n\n"); + if (argc < 2) + { + Usage(); + } + + bool fUseHotKey = false; + bool fWaitOnNamedEvent = false; + bool fQuitGlobalEventWaiters = false; + + for (int i = 1; i < argc; i++) + { + if ((argv[i][0] == L'/') || (argv[i][0] == L'-')) + { + if ((argv[i][1] == L'k') || (argv[i][1] == L'K')) + { + fUseHotKey = true; + } + else if ((argv[i][1] == L'e') || (argv[i][1] == L'E')) + { + fWaitOnNamedEvent = true; + } + else if ((argv[i][1] == L'q') || (argv[i][1] == L'Q')) + { + fQuitGlobalEventWaiters = true; + } + else + { + wprintf(L"*** Unknown command line argument: '%ws' ***\n\n", argv[i]); + Usage(); + } + } + else + { + if (g_pszRemoteMachineName != nullptr) + { + wprintf(L"*** Can't specify two machine names ***\n\n"); + Usage(); + } + g_pszRemoteMachineName = argv[i]; + } + } + + if (fUseHotKey) + { + if (g_pszRemoteMachineName != nullptr) + { + wprintf(L"Press Ctrl-F1 on this machine to initiate proximity with: '%ws'.\n\n", g_pszRemoteMachineName); + } + else + { + // Dynamic Keyboard hotkey version + wprintf(L"Press Ctrl-F1 on two machines at the same time to initiate proximity.\n\n"); + + DWORD cchMachineName = MAX_PATH; + if (!GetComputerNameEx(ComputerNameNetBIOS, g_szMachineName, &cchMachineName)) + { + return FALSE; + } + } + + // Register the window class for the main window. + WNDCLASS wc = {}; + wc.lpfnWndProc = (WNDPROC)WndProc; + wc.hInstance = GetModuleHandle(NULL); + wc.lpszMenuName = L"MainMenu"; + wc.lpszClassName = L"MainWndClass"; + + if (!RegisterClass(&wc)) + { + return FALSE; + } + + // Create the main window. + HWND hwndMain = CreateWindow(L"MainWndClass", L"Sample", + WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, + CW_USEDEFAULT, CW_USEDEFAULT, (HWND) NULL, + (HMENU) NULL, GetModuleHandle(NULL), (LPVOID) NULL); + + // If the main window cannot be created, terminate + // the application. + if (!hwndMain) + { + return FALSE; + } + + if (!RegisterHotKey(hwndMain, 264334, MOD_CONTROL, VK_F1)) + { + wprintf(L"ERROR: Ctrl-F1 Hotkey already registered!\n"); + return FALSE; + } + + // Start the message loop. + + MSG msg; + BOOL bRet; + while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0) + { + if (bRet == -1) + { + // handle the error and possibly exit + } + else + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + // Return the exit code to the system. + + return (int)msg.wParam; + + } + else if (fQuitGlobalEventWaiters) + { + HANDLE hEvent = CreateEventW(NULL, TRUE, FALSE, QUIT_NAMED_EVENT); + if (NULL != hEvent) + { + wprintf(L"Quitting running instances of NetNfpControl.exe /e \n"); + + BOOL bSetErr = SetEvent(hEvent); + if (!bSetErr) + { + wprintf(L"Failed to set named event %s (Err=0x%x)...\n", QUIT_NAMED_EVENT, GetLastError()); + } + + CloseHandle(hEvent); + } + else + { + wprintf(L"Failed to open named event %s (Err=0x%x)...\n", QUIT_NAMED_EVENT, GetLastError()); + } + } + else + { + if (NULL == g_pszRemoteMachineName) + { + Usage(); + } + + wprintf(L"Attempting connect: '%ws' ...\n\n", g_pszRemoteMachineName); + + HANDLE hProximity; + HRESULT hr = BeginProximity(g_pszRemoteMachineName, &hProximity); + if (SUCCEEDED(hr)) + { + if (fWaitOnNamedEvent) + { + wprintf(L"run NetNfpControl.exe /q to end Proximity (or Set the named event %s)\n", QUIT_NAMED_EVENT); + + HANDLE hEvent = CreateEventW(NULL, TRUE, FALSE, QUIT_NAMED_EVENT); + if (NULL != hEvent) + { + DWORD dwWaitErr = WaitForSingleObject(hEvent, INFINITE); + if (WAIT_OBJECT_0 != dwWaitErr) + { + dwWaitErr = (WAIT_FAILED == dwWaitErr ? GetLastError() : dwWaitErr); + wprintf(L"Failed to wait on named event %s (Err=0x%x)...\n", QUIT_NAMED_EVENT, dwWaitErr); + } + + CloseHandle(hEvent); + } + else + { + wprintf(L"Failed to create/open named event %s (Err=0x%x)...\n", QUIT_NAMED_EVENT, GetLastError()); + } + } + else + { + wprintf(L"Press Any Key to End Proximity.\n"); + (void) _getch(); + wprintf(L"Ending Proximity...\n"); + } + + CloseHandle(hProximity); + } + else + { + wprintf(L"BeginProximity() failed: 0x%x\n", hr); + } + } + + return 0; +} + -- cgit v1.3.1