From 04a778f8901e1d8809e43299b99b3ddf99aa4729 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Fri, 21 Feb 2025 21:12:56 +0100 Subject: [PATCH 1/6] Added vcpkg as submodules --- .gitmodules | 3 +++ Directory.Build.props | 3 +++ Directory.Build.targets | 9 +++++++++ vcpkg | 1 + 4 files changed, 16 insertions(+) create mode 100644 .gitmodules create mode 100644 Directory.Build.props create mode 100644 Directory.Build.targets create mode 160000 vcpkg diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..a0a57f3 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "vcpkg"] + path = vcpkg + url = https://github.com/microsoft/vcpkg.git diff --git a/Directory.Build.props b/Directory.Build.props new file mode 100644 index 0000000..313e48a --- /dev/null +++ b/Directory.Build.props @@ -0,0 +1,3 @@ + + + diff --git a/Directory.Build.targets b/Directory.Build.targets new file mode 100644 index 0000000..2df1563 --- /dev/null +++ b/Directory.Build.targets @@ -0,0 +1,9 @@ + + + + + $(MSBuildThisFileDirectory)vcpkg\bootstrap-vcpkg.bat + Bootstrap vcpkg + + + diff --git a/vcpkg b/vcpkg new file mode 160000 index 0000000..8d88de0 --- /dev/null +++ b/vcpkg @@ -0,0 +1 @@ +Subproject commit 8d88de013751588c7361735aa748490619775058 From 0a50401d81a320c0509df551b7288891dac60fe5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Fri, 21 Feb 2025 21:41:14 +0100 Subject: [PATCH 2/6] Implemented new commands: - --enable-bluetooth-service - --disable-bluetooth-service --- NefConUtil.sln.DotSettings | 1 + NefConUtil.vcxproj | 1 + NefConUtil.vcxproj.filters | 3 ++ src/LibraryHelper.hpp | 55 +++++++++++++++++++++++++++ src/NefConUtil.cpp | 77 +++++++++++++++++++++++++++++++++++++- src/NefConUtil.h | 2 + src/NefConUtil.rc | 10 ++--- 7 files changed, 142 insertions(+), 7 deletions(-) create mode 100644 src/LibraryHelper.hpp diff --git a/NefConUtil.sln.DotSettings b/NefConUtil.sln.DotSettings index a3ed424..ab84466 100644 --- a/NefConUtil.sln.DotSettings +++ b/NefConUtil.sln.DotSettings @@ -1,5 +1,6 @@  True + True True True True diff --git a/NefConUtil.vcxproj b/NefConUtil.vcxproj index 9ff2ee8..eab13a7 100644 --- a/NefConUtil.vcxproj +++ b/NefConUtil.vcxproj @@ -540,6 +540,7 @@ + diff --git a/NefConUtil.vcxproj.filters b/NefConUtil.vcxproj.filters index d0536ff..30fa989 100644 --- a/NefConUtil.vcxproj.filters +++ b/NefConUtil.vcxproj.filters @@ -35,6 +35,9 @@ Header Files + + Header Files + diff --git a/src/LibraryHelper.hpp b/src/LibraryHelper.hpp new file mode 100644 index 0000000..9ab95af --- /dev/null +++ b/src/LibraryHelper.hpp @@ -0,0 +1,55 @@ +#pragma once + +#include +#include + +#include + +class ProcPtr { +public: + explicit ProcPtr(FARPROC ptr) : _ptr(ptr) {} + + template >> + operator T* () const { + return reinterpret_cast(_ptr); + } + +private: + FARPROC _ptr; +}; + +class DllHelper { +public: + explicit DllHelper(LPCTSTR filename) : _module(LoadLibrary(filename)) {} + + ~DllHelper() { FreeLibrary(_module); } + + ProcPtr operator[](LPCSTR proc_name) const { + return ProcPtr(GetProcAddress(_module, proc_name)); + } + + static HMODULE _parent_module; + +private: + HMODULE _module; +}; + + +class Bthprops { + DllHelper _dll{ L"BluetoothApis.dll" }; + +public: + decltype(BluetoothFindFirstRadio)* pBluetoothFindFirstRadio = _dll["BluetoothFindFirstRadio"]; + decltype(BluetoothFindRadioClose)* pBluetoothFindRadioClose = _dll["BluetoothFindRadioClose"]; + decltype(BluetoothSetLocalServiceInfo)* pBluetoothSetLocalServiceInfo = _dll["BluetoothSetLocalServiceInfo"]; +}; + +class Newdev { + DllHelper _dll{ L"Newdev.dll" }; + +public: + decltype(DiUninstallDriverW)* pDiUninstallDriverW = _dll["DiUninstallDriverW"]; + decltype(DiInstallDriverW)* pDiInstallDriverW = _dll["DiInstallDriverW"]; + decltype(DiUninstallDevice)* pDiUninstallDevice = _dll["DiUninstallDevice"]; +}; + diff --git a/src/NefConUtil.cpp b/src/NefConUtil.cpp index 7e15d21..9d45791 100644 --- a/src/NefConUtil.cpp +++ b/src/NefConUtil.cpp @@ -49,10 +49,10 @@ int main(int argc, char* argv[]) "--class-guid", "--service-name", "--position", - "--service-name", "--display-name", "--bin-path", - "--file-path" + "--file-path", + "--service-guid" }); auto cliArgs = nefarius::winapi::cli::GetCommandLineArgs(); @@ -719,6 +719,79 @@ int main(int argc, char* argv[]) return EXIT_SUCCESS; } + constexpr PCSTR ENABLE_BLUETOOTH_SERVICE = "--enable-bluetooth-service"; + constexpr PCSTR DISABLE_BLUETOOTH_SERVICE = "--disable-bluetooth-service"; + + if (cmdl[{ENABLE_BLUETOOTH_SERVICE}] || cmdl[{DISABLE_BLUETOOTH_SERVICE}]) + { + // + // Sanity check + // + if (cmdl[{ENABLE_BLUETOOTH_SERVICE}] && cmdl[{DISABLE_BLUETOOTH_SERVICE}]) + { + logger->error("You must either specify 'enable' or 'disable' action, not both together"); + return EXIT_FAILURE; + } + + const bool enable = cmdl[{ENABLE_BLUETOOTH_SERVICE}]; + + auto bthServiceName = cmdl({"--service-name"}).str(); + auto bthServiceGuid = cmdl({"--service-guid"}).str(); + + if (bthServiceName.empty()) + { + logger->error("Service name missing"); + return EXIT_FAILURE; + } + + if (bthServiceGuid.empty()) + { + logger->error("Service GUID missing"); + return EXIT_FAILURE; + } + + const auto guid = nefarius::winapi::GUIDFromString(bthServiceGuid); + + if (!guid) + { + logger->error( + "GUID format invalid, expected format (with or without brackets): xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"); + return EXIT_FAILURE; + } + + if (auto ret = nefarius::winapi::security::AdjustProcessPrivileges(); !ret) + { + logger->error("Failed to modify process privileges, error: %v", ret.error().getErrorMessageA()); + return ret.error().getErrorCode(); + } + + auto serviceNameWide = nefarius::utilities::ConvertAnsiToWide(bthServiceName); + + BLUETOOTH_LOCAL_SERVICE_INFO svcInfo = {}; + wcscpy_s(svcInfo.szName, sizeof(svcInfo.szName) / sizeof(WCHAR), serviceNameWide.c_str()); + + svcInfo.Enabled = enable ? TRUE : FALSE; + Bthprops bth; + + if (DWORD err; ERROR_SUCCESS != (err = bth.pBluetoothSetLocalServiceInfo( + nullptr, //callee would select the first found radio + &guid.value(), + 0, + &svcInfo + ))) + { + auto error = nefarius::utilities::Win32Error(err); + logger->error("Failed to {} local service, error: %v", + enable ? "enable" : "disable", + error.getErrorMessageA()); + return error.getErrorCode(); + } + + logger->info("Service {} successfully", enable ? "enabled" : "disabled"); + + return EXIT_SUCCESS; + } + #pragma endregion #pragma region Version diff --git a/src/NefConUtil.h b/src/NefConUtil.h index cef6b01..1eddefb 100644 --- a/src/NefConUtil.h +++ b/src/NefConUtil.h @@ -12,6 +12,7 @@ #include #include #include +#include // // Device class interfaces @@ -45,6 +46,7 @@ // Internal // #include "ColorLogging.hpp" +#include "LibraryHelper.hpp" // // neflib diff --git a/src/NefConUtil.rc b/src/NefConUtil.rc index c7a45cd..1953fa1 100644 --- a/src/NefConUtil.rc +++ b/src/NefConUtil.rc @@ -51,8 +51,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,11,1,0 - PRODUCTVERSION 1,11,1,0 + FILEVERSION 1,12,0,0 + PRODUCTVERSION 1,12,0,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -69,12 +69,12 @@ BEGIN BEGIN VALUE "CompanyName", "Nefarius Software Solutions e.U." VALUE "FileDescription", "Nefarius' Device Console Utility" - VALUE "FileVersion", "1.11.1.0" + VALUE "FileVersion", "1.12.0.0" VALUE "InternalName", "nefcon.exe" - VALUE "LegalCopyright", "Copyright (C) 2022-2024 Nefarius Software Solutions e.U." + VALUE "LegalCopyright", "Copyright (C) 2022-2025 Nefarius Software Solutions e.U." VALUE "OriginalFilename", "nefcon.exe" VALUE "ProductName", "nefcon" - VALUE "ProductVersion", "1.11.1.0" + VALUE "ProductVersion", "1.12.0.0" END END BLOCK "VarFileInfo" From c95e082b1096ae98935b5447d50afe0536065343 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Fri, 21 Feb 2025 21:44:17 +0100 Subject: [PATCH 3/6] Updated usage text --- src/NefConUtil.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/NefConUtil.cpp b/src/NefConUtil.cpp index 9d45791..24d9960 100644 --- a/src/NefConUtil.cpp +++ b/src/NefConUtil.cpp @@ -851,6 +851,12 @@ int main(int argc, char* argv[]) std::cout << " --find-hwid Shows one or more devices matching a partial Hardware ID" << '\n'; std::cout << " ---hardware-id (Partial) Hardware ID of the device to match against (required)" << '\n'; + std::cout << " --enable-bluetooth-service Enables a local Bluetooth service" << '\n'; + std::cout << " --service-name The service name" << '\n'; + std::cout << " --service-guid The service GUID" << '\n'; + std::cout << " --disable-bluetooth-service Disables a local Bluetooth service" << '\n'; + std::cout << " --service-name The service name" << '\n'; + std::cout << " --service-guid The service GUID" << '\n'; std::cout << " -v, --version Display version of this utility" << '\n'; std::cout << '\n'; std::cout << " logging:" << '\n'; From 526535d69e37d2a6735220155b537f871ed50852 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Fri, 21 Feb 2025 21:48:23 +0100 Subject: [PATCH 4/6] Update msbuild.yml --- .github/workflows/msbuild.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/msbuild.yml b/.github/workflows/msbuild.yml index 94ef96e..eb23fbf 100644 --- a/.github/workflows/msbuild.yml +++ b/.github/workflows/msbuild.yml @@ -29,14 +29,12 @@ jobs: steps: - uses: actions/checkout@v4 + with: + submodules: recursive - name: Add MSBuild to PATH uses: microsoft/setup-msbuild@v2.0.0 - - name: Restore vcpkg packages - working-directory: ${{env.GITHUB_WORKSPACE}} - run: vcpkg integrate install - - name: Build Console Edition working-directory: ${{env.GITHUB_WORKSPACE}} # Add additional options to the MSBuild command line here (like platform or verbosity level). From 2463a965267953f247aaed964dd7c53f10cc36e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Fri, 21 Feb 2025 21:54:15 +0100 Subject: [PATCH 5/6] CI changes --- .github/workflows/msbuild.yml | 6 ++++-- Directory.Build.props | 2 +- Directory.Build.targets | 4 ++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/.github/workflows/msbuild.yml b/.github/workflows/msbuild.yml index eb23fbf..94ef96e 100644 --- a/.github/workflows/msbuild.yml +++ b/.github/workflows/msbuild.yml @@ -29,12 +29,14 @@ jobs: steps: - uses: actions/checkout@v4 - with: - submodules: recursive - name: Add MSBuild to PATH uses: microsoft/setup-msbuild@v2.0.0 + - name: Restore vcpkg packages + working-directory: ${{env.GITHUB_WORKSPACE}} + run: vcpkg integrate install + - name: Build Console Edition working-directory: ${{env.GITHUB_WORKSPACE}} # Add additional options to the MSBuild command line here (like platform or verbosity level). diff --git a/Directory.Build.props b/Directory.Build.props index 313e48a..2db43cb 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,3 +1,3 @@ - + diff --git a/Directory.Build.targets b/Directory.Build.targets index 2df1563..8d3297b 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -1,6 +1,6 @@ - - + + $(MSBuildThisFileDirectory)vcpkg\bootstrap-vcpkg.bat Bootstrap vcpkg From 322dfd7afe53bc6bff8931ab1108e8da017456e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Fri, 21 Feb 2025 22:26:15 +0100 Subject: [PATCH 6/6] Added admin check Fixed wrong format specifier in logging instruction --- src/NefConUtil.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/NefConUtil.cpp b/src/NefConUtil.cpp index 24d9960..6cad2b4 100644 --- a/src/NefConUtil.cpp +++ b/src/NefConUtil.cpp @@ -757,7 +757,13 @@ int main(int argc, char* argv[]) logger->error( "GUID format invalid, expected format (with or without brackets): xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"); return EXIT_FAILURE; - } + } + + int errorCode; + if (!IsAdmin(errorCode)) + { + return errorCode; + } if (auto ret = nefarius::winapi::security::AdjustProcessPrivileges(); !ret) { @@ -781,13 +787,13 @@ int main(int argc, char* argv[]) ))) { auto error = nefarius::utilities::Win32Error(err); - logger->error("Failed to {} local service, error: %v", + logger->error("Failed to %v local service, error: %v", enable ? "enable" : "disable", error.getErrorMessageA()); return error.getErrorCode(); } - logger->info("Service {} successfully", enable ? "enabled" : "disabled"); + logger->info("Service %v successfully", enable ? "enabled" : "disabled"); return EXIT_SUCCESS; }