summaryrefslogtreecommitdiff
path: root/nfp/net/exe/NetNfpControl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'nfp/net/exe/NetNfpControl.cpp')
-rw-r--r--nfp/net/exe/NetNfpControl.cpp579
1 files changed, 579 insertions, 0 deletions
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 <remoteMachine> [/e]
+// NetNfpControl.exe [<remoteMachine>] [/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:
+//
+//----------------------------------------------------------------------------------------------------------------------
+///<summary>Device interface details.</summary>
+struct DEVICE_INTERFACE_DETAIL
+{
+ DWORD cbSize;
+ wchar_t szSymbolicLink[MAX_PATH*2];
+};
+
+//----------------------------------------------------------------------------------------------------------------------
+// Name: BeginProximity
+// Comments:
+//
+//----------------------------------------------------------------------------------------------------------------------
+///<summary>Initalizes a proximity event.</summary>
+///<remarks>
+///</remarks>
+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:
+//
+//----------------------------------------------------------------------------------------------------------------------
+///<summary>Aquires a lock on a file.</summary>
+///<remarks>
+///</remarks>
+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:
+//
+//----------------------------------------------------------------------------------------------------------------------
+///<summary>Initiates a proximity event.</summary>
+///<remarks>
+///</remarks>
+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:
+//
+//----------------------------------------------------------------------------------------------------------------------
+///<summary>Windows call-back procedure.</summary>
+///<remarks>
+///Used to receive call-backs for the Windows system-wide Hot Key's
+///</remarks>
+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 <Machine Name or IP>\n");
+ wprintf(L" NetNfpControl.exe /e <Machine Name or IP>\n");
+ wprintf(L" NetNfpControl.exe /q\n");
+ wprintf(L" NetNfpControl.exe /k\n");
+ wprintf(L" NetNfpControl.exe /k <Machine Name or IP>\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.
+//
+//----------------------------------------------------------------------------------------------------------------------
+///<summary>wmain.</summary>
+///<remarks>
+///Main application entry point.
+///</remarks>
+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 <machinename>\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;
+}
+