diff --git a/.pipelines/pipeline.user.windows.yml b/.pipelines/pipeline.user.windows.yml index c851d2f1a..21a982792 100644 --- a/.pipelines/pipeline.user.windows.yml +++ b/.pipelines/pipeline.user.windows.yml @@ -116,6 +116,11 @@ build: - 'modules\Microsoft.Launcher.dll' - 'modules\PowerRename\PowerRenameExt.dll' - 'modules\ShortcutGuide\ShortcutGuide.dll' + - 'modules\VideoConference\VideoConferenceModule.dll' + - 'modules\VideoConference\VideoConferenceVirtualDriver\VideoConferenceVirtualDriver.dll' + - 'modules\VideoConference\VideoConferenceVirtualDriver\VideoConferenceCustomMediaSource.dll' + - 'modules\VideoConference\VideoConferenceVirtualDriver\videoconferencevirtualdriver.cat' + - 'modules\VideoConference\VideoConferenceVirtualDriver\VideoConferenceVirtualDriver.inf' - 'Notifications.dll' - 'os-detection.dll' - 'PowerToys.exe' diff --git a/.pipelines/restore.cmd b/.pipelines/restore.cmd index fd630aea5..22eb393aa 100644 --- a/.pipelines/restore.cmd +++ b/.pipelines/restore.cmd @@ -1,3 +1,12 @@ cd /D "%~dp0" nuget restore ../PowerToys.sln || exit /b 1 + +powershell.exe -Command "Invoke-WebRequest -OutFile %tmp%\wdksetup.exe https://go.microsoft.com/fwlink/p/?linkid=2085767" +%tmp%\wdksetup.exe /q + +copy "C:\Program Files (x86)\Windows Kits\10\Vsix\VS2019\WDK.vsix" %tmp%\wdkvsix.zip +powershell Expand-Archive %tmp%\wdkvsix.zip -DestinationPath %tmp%\wdkvsix -Force + +robocopy /e %tmp%\wdkvsix\$MSBuild\Microsoft\VC\v160 "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Microsoft\VC\v160" || IF %ERRORLEVEL% LEQ 7 EXIT 0 +robocopy /e %tmp%\wdkvsix\$VCTargets "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\VC\VCTargets" || IF %ERRORLEVEL% LEQ 7 EXIT 0 diff --git a/PowerToys.sln b/PowerToys.sln index 7812aa19d..4e13c7705 100644 --- a/PowerToys.sln +++ b/PowerToys.sln @@ -265,6 +265,19 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Plugin.Uri.UnitTe EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.PowerToys.Settings.UI.UnitTests", "src\core\Microsoft.PowerToys.Settings.UI.UnitTests\Microsoft.PowerToys.Settings.UI.UnitTests.csproj", "{0F85E674-34AE-443D-954C-8321EB8B93B1}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "VideoConference", "VideoConference", "{05BE6150-D5B3-48F0-AEB9-C44096950C6D}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VideoConferenceCustomMediaSource", "src\modules\videoconference\VideoConferenceCustomMediaSource\VideoConferenceCustomMediaSource.vcxproj", "{43AD9BF7-E765-48FE-9826-71A8F2CB12DD}" + ProjectSection(ProjectDependencies) = postProject + {459E0768-7EBD-4C41-BBA1-6DB3B3815E0A} = {459E0768-7EBD-4C41-BBA1-6DB3B3815E0A} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VideoConferenceModule", "src\modules\videoconference\VideoConferenceModule\Video Conference.vcxproj", "{FD2CAFFC-D682-4ED9-A06B-5FC88AE0A193}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VideoConferenceShared", "src\modules\videoconference\VideoConferenceShared\VideoConferenceShared.vcxproj", "{459E0768-7EBD-4C41-BBA1-6DB3B3815E0A}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VideoConferenceVirtualDriver", "src\modules\videoconference\VideoConferenceVirtualDriver\VideoConferenceVirtualDriver.vcxproj", "{3098C6BF-E96E-4793-A70E-FB09B741580A}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 @@ -531,6 +544,24 @@ Global {0F85E674-34AE-443D-954C-8321EB8B93B1}.Debug|x64.Build.0 = Debug|x64 {0F85E674-34AE-443D-954C-8321EB8B93B1}.Release|x64.ActiveCfg = Release|x64 {0F85E674-34AE-443D-954C-8321EB8B93B1}.Release|x64.Build.0 = Release|x64 + {43AD9BF7-E765-48FE-9826-71A8F2CB12DD}.Debug|x64.ActiveCfg = Debug|x64 + {43AD9BF7-E765-48FE-9826-71A8F2CB12DD}.Debug|x64.Build.0 = Debug|x64 + {43AD9BF7-E765-48FE-9826-71A8F2CB12DD}.Release|x64.ActiveCfg = Release|x64 + {43AD9BF7-E765-48FE-9826-71A8F2CB12DD}.Release|x64.Build.0 = Release|x64 + {FD2CAFFC-D682-4ED9-A06B-5FC88AE0A193}.Debug|x64.ActiveCfg = Debug|x64 + {FD2CAFFC-D682-4ED9-A06B-5FC88AE0A193}.Debug|x64.Build.0 = Debug|x64 + {FD2CAFFC-D682-4ED9-A06B-5FC88AE0A193}.Release|x64.ActiveCfg = Release|x64 + {FD2CAFFC-D682-4ED9-A06B-5FC88AE0A193}.Release|x64.Build.0 = Release|x64 + {459E0768-7EBD-4C41-BBA1-6DB3B3815E0A}.Debug|x64.ActiveCfg = Debug|x64 + {459E0768-7EBD-4C41-BBA1-6DB3B3815E0A}.Debug|x64.Build.0 = Debug|x64 + {459E0768-7EBD-4C41-BBA1-6DB3B3815E0A}.Release|x64.ActiveCfg = Release|x64 + {459E0768-7EBD-4C41-BBA1-6DB3B3815E0A}.Release|x64.Build.0 = Release|x64 + {3098C6BF-E96E-4793-A70E-FB09B741580A}.Debug|x64.ActiveCfg = Debug|x64 + {3098C6BF-E96E-4793-A70E-FB09B741580A}.Debug|x64.Build.0 = Debug|x64 + {3098C6BF-E96E-4793-A70E-FB09B741580A}.Debug|x64.Deploy.0 = Debug|x64 + {3098C6BF-E96E-4793-A70E-FB09B741580A}.Release|x64.ActiveCfg = Release|x64 + {3098C6BF-E96E-4793-A70E-FB09B741580A}.Release|x64.Build.0 = Release|x64 + {3098C6BF-E96E-4793-A70E-FB09B741580A}.Release|x64.Deploy.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -607,6 +638,11 @@ Global {03276A39-D4E9-417C-8FFD-200B0EE5E871} = {4AFC9975-2456-4C70-94A4-84073C1CED93} {B81FB7B6-D30E-428F-908A-41422EFC1172} = {4AFC9975-2456-4C70-94A4-84073C1CED93} {0F85E674-34AE-443D-954C-8321EB8B93B1} = {C3081D9A-1586-441A-B5F4-ED815B3719C1} + {05BE6150-D5B3-48F0-AEB9-C44096950C6D} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC} + {43AD9BF7-E765-48FE-9826-71A8F2CB12DD} = {05BE6150-D5B3-48F0-AEB9-C44096950C6D} + {FD2CAFFC-D682-4ED9-A06B-5FC88AE0A193} = {05BE6150-D5B3-48F0-AEB9-C44096950C6D} + {459E0768-7EBD-4C41-BBA1-6DB3B3815E0A} = {05BE6150-D5B3-48F0-AEB9-C44096950C6D} + {3098C6BF-E96E-4793-A70E-FB09B741580A} = {05BE6150-D5B3-48F0-AEB9-C44096950C6D} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {C3A2F9D1-7930-4EF4-A6FC-7EE0A99821D0} diff --git a/installer/PowerToysSetup/PowerToysSetup.wixproj b/installer/PowerToysSetup/PowerToysSetup.wixproj index 8c5ad9d3d..7f3bc6951 100644 --- a/installer/PowerToysSetup/PowerToysSetup.wixproj +++ b/installer/PowerToysSetup/PowerToysSetup.wixproj @@ -2,8 +2,9 @@ + - Version=$(Version); + Version=$(Version);HasWDK=$(HasWDK) Release diff --git a/installer/PowerToysSetup/Product.wxs b/installer/PowerToysSetup/Product.wxs index dee4bedd4..c0279b9c3 100644 --- a/installer/PowerToysSetup/Product.wxs +++ b/installer/PowerToysSetup/Product.wxs @@ -9,6 +9,7 @@ + @@ -87,6 +88,20 @@ NOT Installed and CREATESCHEDULEDTASK = 1 + + + + NOT Installed + + + + NOT Installed + + + + Installed + + @@ -204,6 +219,44 @@ DllEntry="DetectPrevInstallPathCA" /> + + + + + + + + + + + + + + @@ -240,6 +293,11 @@ + + + + + @@ -612,6 +670,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -793,6 +881,10 @@ + + + + diff --git a/installer/PowerToysSetup/publish.cmd b/installer/PowerToysSetup/publish.cmd index b52cdc0bb..5b766039b 100644 --- a/installer/PowerToysSetup/publish.cmd +++ b/installer/PowerToysSetup/publish.cmd @@ -31,7 +31,6 @@ echo ^ >> !settingsPublishProfile! rem In case of Release we should not use Debug CRT in VCRT forwarders msbuild !PTRoot!\src\core\Microsoft.PowerToys.Settings.UI.Runner\Microsoft.PowerToys.Settings.UI.Runner.csproj -t:Publish -p:Configuration="Release" -p:Platform="x64" -p:AppxBundle=Never -p:VCRTForwarders-IncludeDebugCRT=false -p:PublishProfile=!settingsProfileFileName! - rem Publish Launcher SET launcherProfileFolderName=!PTRoot!\src\modules\launcher\PowerLauncher\Properties\PublishProfiles\ diff --git a/installer/PowerToysSetupCustomActions/CustomAction.cpp b/installer/PowerToysSetupCustomActions/CustomAction.cpp index 99d915d55..96993a74f 100644 --- a/installer/PowerToysSetupCustomActions/CustomAction.cpp +++ b/installer/PowerToysSetupCustomActions/CustomAction.cpp @@ -3,6 +3,11 @@ #include #include "../../src/common/updating/updating.h" +#include + +#include + +#pragma comment (lib, "crypt32.lib") using namespace std; @@ -16,6 +21,7 @@ TRACELOGGING_DEFINE_PROVIDER( const DWORD USERNAME_DOMAIN_LEN = DNLEN + UNLEN + 2; // Domain Name + '\' + User Name + '\0' const DWORD USERNAME_LEN = UNLEN + 1; // User Name + '\0' +static const wchar_t* POWERTOYS_EXE_COMPONENT = L"{A2C66D91-3485-4D00-B04D-91844E6B345B}"; static const wchar_t* POWERTOYS_UPGRADE_CODE = L"{42B84BF7-5FBF-473B-9C8B-049DC16F7708}"; // Creates a Scheduled Task to run at logon for the current user. @@ -564,6 +570,8 @@ LExit: return WcaFinalize(er); } + + UINT __stdcall DetectPrevInstallPathCA(MSIHANDLE hInstall) { HRESULT hr = S_OK; @@ -662,6 +670,165 @@ UINT __stdcall TerminateProcessesCA(MSIHANDLE hInstall) return WcaFinalize(er); } +UINT __stdcall CertifyVirtualCameraDriverCA(MSIHANDLE hInstall) +{ +#ifdef CIBuild // On pipeline we are using microsoft certification + WcaInitialize(hInstall, "CertifyVirtualCameraDriverCA"); + return WcaFinalize(ERROR_SUCCESS); +#else + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + LPWSTR certificatePath = NULL; + HCERTSTORE hCertStore = NULL; + HANDLE hfile = NULL; + DWORD size = INVALID_FILE_SIZE; + + hr = WcaInitialize(hInstall, "CertifyVirtualCameraDriverCA"); + ExitOnFailure(hr, "Failed to initialize", hr); + + hr = WcaGetProperty(L"CustomActionData", &certificatePath); + ExitOnFailure(hr, "Failed to get install preperty", hr); + + hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL, CERT_SYSTEM_STORE_LOCAL_MACHINE, L"AuthRoot"); + if (!hCertStore) + { + hr = GetLastError(); + ExitOnFailure(hr, "Cannot put principal run level: %x", hr); + } + + hfile = CreateFile(certificatePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (hfile == INVALID_HANDLE_VALUE) + { + hr = GetLastError(); + ExitOnFailure(hr, "Certificate file open failed", hr); + } + + size = GetFileSize(hfile, NULL); + if (size == INVALID_FILE_SIZE) + { + hr = GetLastError(); + ExitOnFailure(hr, "Certificate file size not valid", hr); + } + + char* pFileContent = (char*)malloc(size); + + DWORD sizeread; + if (!ReadFile(hfile, pFileContent, size, &sizeread, NULL)) + { + hr = GetLastError(); + ExitOnFailure(hr, "Certificate file read failed", hr); + } + + if (!CertAddEncodedCertificateToStore(hCertStore, + X509_ASN_ENCODING, + (const BYTE*)pFileContent, + size, + CERT_STORE_ADD_ALWAYS, + NULL)) + { + hr = GetLastError(); + ExitOnFailure(hr, "Adding certificate failed", hr); + } + + free(pFileContent); + +LExit: + ReleaseStr(certificatePath); + if (hCertStore) + { + CertCloseStore(hCertStore, 0); + } + if (hfile) + { + CloseHandle(hfile); + } + + if (!SUCCEEDED(hr)) + { + PMSIHANDLE hRecord = MsiCreateRecord(0); + MsiRecordSetString(hRecord, 0, TEXT("Failed to add certificate to store")); + MsiProcessMessage(hInstall, INSTALLMESSAGE(INSTALLMESSAGE_WARNING + MB_OK), hRecord); + } + + + er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +#endif +} + + +UINT __stdcall InstallVirtualCameraDriverCA(MSIHANDLE hInstall) +{ + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + hr = WcaInitialize(hInstall, "InstallVirtualCameraDriverCA"); + ExitOnFailure(hr, "Failed to initialize"); + + LPWSTR driverPath = NULL; + + hr = WcaGetProperty(L"CustomActionData", &driverPath); + ExitOnFailure(hr, "Failed to get install preperty"); + + BOOL requiresReboot; + DiInstallDriverW(GetConsoleWindow(), driverPath, DIIRFLAG_FORCE_INF, &requiresReboot); + + hr = GetLastError(); + ExitOnFailure(hr, "Failed to install driver"); + +LExit: + + if (!SUCCEEDED(hr)) + { + PMSIHANDLE hRecord = MsiCreateRecord(0); + MsiRecordSetString(hRecord, 0, TEXT("Failed to install virtual camera driver")); + MsiProcessMessage(hInstall, INSTALLMESSAGE(INSTALLMESSAGE_WARNING + MB_OK), hRecord); + } + + er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} + +UINT __stdcall UninstallVirtualCameraDriverCA(MSIHANDLE hInstall) +{ + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + hr = WcaInitialize(hInstall, "UninstallVirtualCameraDriverCA"); + ExitOnFailure(hr, "Failed to initialize"); + + LPWSTR driverPath = NULL; + + hr = WcaGetProperty(L"CustomActionData", &driverPath); + ExitOnFailure(hr, "Failed to get uninstall preperty"); + + BOOL requiresReboot; + DiUninstallDriverW(GetConsoleWindow(), driverPath, 0, &requiresReboot); + + switch (GetLastError()) + { + case ERROR_ACCESS_DENIED: + case ERROR_FILE_NOT_FOUND: + case ERROR_INVALID_FLAGS: + case ERROR_IN_WOW64: + { + hr = GetLastError(); + ExitOnFailure(hr, "Failed to uninstall driver"); + break; + } + } + +LExit: + + if (!SUCCEEDED(hr)) + { + PMSIHANDLE hRecord = MsiCreateRecord(0); + MsiRecordSetString(hRecord, 0, TEXT("Filed to iminstall virtual camera driver")); + MsiProcessMessage(hInstall, INSTALLMESSAGE(INSTALLMESSAGE_WARNING + MB_OK), hRecord); + } + + er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} + // DllMain - Initialize and cleanup WiX custom action utils. extern "C" BOOL WINAPI DllMain(__in HINSTANCE hInst, __in ULONG ulReason, __in LPVOID) diff --git a/installer/PowerToysSetupCustomActions/CustomAction.def b/installer/PowerToysSetupCustomActions/CustomAction.def index 3e8a2ab72..0f90c2e4d 100644 --- a/installer/PowerToysSetupCustomActions/CustomAction.def +++ b/installer/PowerToysSetupCustomActions/CustomAction.def @@ -12,4 +12,7 @@ EXPORTS TelemetryLogUninstallFailCA TelemetryLogRepairCancelCA TelemetryLogRepairFailCA - TerminateProcessesCA \ No newline at end of file + TerminateProcessesCA + CertifyVirtualCameraDriverCA + InstallVirtualCameraDriverCA + UninstallVirtualCameraDriverCA diff --git a/installer/PowerToysSetupCustomActions/PowerToysSetupCustomActions.vcxproj b/installer/PowerToysSetupCustomActions/PowerToysSetupCustomActions.vcxproj index e0a23ec46..fbec536dd 100644 --- a/installer/PowerToysSetupCustomActions/PowerToysSetupCustomActions.vcxproj +++ b/installer/PowerToysSetupCustomActions/PowerToysSetupCustomActions.vcxproj @@ -60,7 +60,7 @@ true - Psapi.lib;Pathcch.lib;comsupp.lib;taskschd.lib;Secur32.lib;msi.lib;dutil.lib;wcautil.lib;Version.lib;..\..\$(PlatformShortName)\$(Configuration)\common.lib;..\..\$(PlatformShortName)\$(Configuration)\updating.lib;%(AdditionalDependencies) + Psapi.lib;Pathcch.lib;comsupp.lib;taskschd.lib;Secur32.lib;msi.lib;dutil.lib;wcautil.lib;Version.lib;Newdev.lib;..\..\$(PlatformShortName)\$(Configuration)\common.lib;..\..\$(PlatformShortName)\$(Configuration)\updating.lib;%(AdditionalDependencies) $(WIX)sdk\$(WixPlatformToolset)\lib\x64;$(SolutionDir)\packages\WiX.3.11.2\tools\sdk\vs2017\lib\x64;%(AdditionalLibraryDirectories) CustomAction.def true @@ -81,8 +81,11 @@ stdcpplatest true + + /DCIBuild + - Psapi.lib;Pathcch.lib;comsupp.lib;taskschd.lib;Secur32.lib;msi.lib;dutil.lib;wcautil.lib;Version.lib;..\..\$(PlatformShortName)\$(Configuration)\common.lib;..\..\$(PlatformShortName)\$(Configuration)\updating.lib;%(AdditionalDependencies) + Psapi.lib;Pathcch.lib;comsupp.lib;taskschd.lib;Secur32.lib;msi.lib;dutil.lib;wcautil.lib;Version.lib;Newdev.lib;..\..\$(PlatformShortName)\$(Configuration)\common.lib;..\..\$(PlatformShortName)\$(Configuration)\updating.lib;%(AdditionalDependencies) $(WIX)sdk\$(WixPlatformToolset)\lib\x64;$(SolutionDir)\packages\WiX.3.11.2\tools\sdk\vs2017\lib\x64;%(AdditionalLibraryDirectories) CustomAction.def true diff --git a/src/common/common.vcxproj b/src/common/common.vcxproj index 97a46b404..41e78013b 100644 --- a/src/common/common.vcxproj +++ b/src/common/common.vcxproj @@ -132,6 +132,7 @@ + @@ -141,6 +142,7 @@ + @@ -171,6 +173,7 @@ + @@ -185,6 +188,7 @@ + diff --git a/src/common/common.vcxproj.filters b/src/common/common.vcxproj.filters index c9abbe7cb..b1d35cdce 100644 --- a/src/common/common.vcxproj.filters +++ b/src/common/common.vcxproj.filters @@ -141,6 +141,12 @@ Header Files + + Header Files + + + Header Files + @@ -222,8 +228,14 @@ Source Files + + Source Files + + + Source Files + - \ No newline at end of file + diff --git a/src/common/monitors.cpp b/src/common/monitors.cpp index 1ad10aaff..e96b065bf 100644 --- a/src/common/monitors.cpp +++ b/src/common/monitors.cpp @@ -72,3 +72,23 @@ MonitorInfo MonitorInfo::GetPrimaryMonitor() EnumDisplayMonitors(NULL, NULL, GetPrimaryDisplayEnumCb, reinterpret_cast(&primary)); return primary; } + +MonitorInfo MonitorInfo::GetFromWindow(HWND hwnd) +{ + auto monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST); + return GetFromHandle(monitor); +} + +MonitorInfo MonitorInfo::GetFromPoint(POINT p) +{ + auto monitor = MonitorFromPoint(p, MONITOR_DEFAULTTONEAREST); + return GetFromHandle(monitor); +} + +MonitorInfo MonitorInfo::GetFromHandle(HMONITOR monitor) +{ + MONITORINFOEX monitor_info; + monitor_info.cbSize = sizeof(MONITORINFOEX); + GetMonitorInfo(monitor, &monitor_info); + return MonitorInfo(monitor, monitor_info.rcWork); +} diff --git a/src/common/monitors.h b/src/common/monitors.h index 7771e843d..6af6de74a 100644 --- a/src/common/monitors.h +++ b/src/common/monitors.h @@ -33,6 +33,9 @@ struct MonitorInfo : ScreenSize // Returns monitor rects ordered from left to right static std::vector GetMonitors(bool includeNonWorkingArea); static MonitorInfo GetPrimaryMonitor(); + static MonitorInfo GetFromWindow(HWND hwnd); + static MonitorInfo GetFromPoint(POINT p); + static MonitorInfo GetFromHandle(HMONITOR monitor); }; bool operator==(const ScreenSize& lhs, const ScreenSize& rhs); diff --git a/src/common/naming.cpp b/src/common/naming.cpp new file mode 100644 index 000000000..70d2af9b1 --- /dev/null +++ b/src/common/naming.cpp @@ -0,0 +1,20 @@ +#include "pch.h" +#include "naming.h" + +#include "user.h" + +std::wstring ObtainStableGlobalNameForKernelObject(const std::wstring_view name, const bool restricted) +{ + static const std::optional username = ObtainActiveUserName(); + std::wstring result = L"Global\\"; + if (restricted) + { + result += L"Restricted\\"; + } + if (username) + { + result += *username; + } + result += name; + return result; +} diff --git a/src/common/naming.h b/src/common/naming.h new file mode 100644 index 000000000..8d127b062 --- /dev/null +++ b/src/common/naming.h @@ -0,0 +1,5 @@ +#pragma once +#include +#include + +std::wstring ObtainStableGlobalNameForKernelObject(const std::wstring_view name, const bool restricted); \ No newline at end of file diff --git a/src/common/settings_helpers.h b/src/common/settings_helpers.h index 754ab0237..1b9b21192 100644 --- a/src/common/settings_helpers.h +++ b/src/common/settings_helpers.h @@ -7,6 +7,7 @@ namespace PTSettingsHelper { std::wstring get_module_save_folder_location(std::wstring_view powertoy_name); + std::wstring get_module_save_file_location(std::wstring_view powertoy_name); std::wstring get_root_save_folder_location(); void save_module_settings(std::wstring_view powertoy_name, json::JsonObject& settings); diff --git a/src/common/settings_objects.h b/src/common/settings_objects.h index 52f654b96..f3cc37493 100644 --- a/src/common/settings_objects.h +++ b/src/common/settings_objects.h @@ -202,7 +202,7 @@ namespace PowerToysSettings if (output_bytes == 1 && output[0] >= 'a' && output[0] <= 'z') { // Make Latin letters keys capital, as it looks better - output[0] = toupper(output[0]); + output[0] = static_cast(toupper(output[0])); } return output.data(); } diff --git a/src/common/timeutil.h b/src/common/timeutil.h index 348eb7ab9..cd1a101da 100644 --- a/src/common/timeutil.h +++ b/src/common/timeutil.h @@ -26,6 +26,13 @@ namespace timeutil return std::nullopt; } } + inline time_t from_filetime(const FILETIME& ft) + { + ULARGE_INTEGER ull; + ull.LowPart = ft.dwLowDateTime; + ull.HighPart = ft.dwHighDateTime; + return ull.QuadPart / 10000000ULL - 11644473600ULL; + } inline std::time_t now() { diff --git a/src/common/user.cpp b/src/common/user.cpp new file mode 100644 index 000000000..1e3f1d56d --- /dev/null +++ b/src/common/user.cpp @@ -0,0 +1,20 @@ +#include "pch.h" +#include "user.h" + +#include + +std::optional ObtainActiveUserName() +{ + const DWORD sessionId = WTSGetActiveConsoleSessionId(); + WCHAR* pUserName; + DWORD _ = 0; + + if (!WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, sessionId, WTSUserName, &pUserName, &_)) + { + return std::nullopt; + } + WTSGetActiveConsoleSessionId(); + std::wstring result{ pUserName }; + WTSFreeMemory(pUserName); + return result; +} diff --git a/src/common/user.h b/src/common/user.h new file mode 100644 index 000000000..dcbefec38 --- /dev/null +++ b/src/common/user.h @@ -0,0 +1,9 @@ +#pragma once + +#include +#include +#include + +std::optional ObtainActiveUserName(); + +std::wstring ObtainStableGlobalNameForKernelObject(const std::wstring_view name, const bool restricted); \ No newline at end of file diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/EnabledModules.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/EnabledModules.cs index 835b9a726..db2c112a7 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI.Lib/EnabledModules.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/EnabledModules.cs @@ -80,6 +80,22 @@ namespace Microsoft.PowerToys.Settings.UI.Lib } } + private bool videoConference = true; + + [JsonPropertyName("Video Conference")] + public bool VideoConference + { + get => this.videoConference; + set + { + if (this.videoConference != value) + { + LogTelemetryEvent(value); + this.videoConference = value; + } + } + } + private bool powerRename = true; public bool PowerRename diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/SettingsUtils.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/SettingsUtils.cs index abc6c1cd9..f70c5fdb8 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI.Lib/SettingsUtils.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/SettingsUtils.cs @@ -56,6 +56,22 @@ namespace Microsoft.PowerToys.Settings.UI.Lib return JsonSerializer.Deserialize(jsonSettingsString); } + public static T GetOrCreateSettings(string powertoy = DefaultModuleName, string fileName = DefaultFileName) + where T : new() + { + try + { + var jsonSettingsString = File.ReadAllText(GetSettingsPath(powertoy, fileName)); + return JsonSerializer.Deserialize(jsonSettingsString); + } + catch + { + var settings = new T(); + SaveSettings(JsonSerializer.Serialize(settings), powertoy, fileName); + return settings; + } + } + // Save settings to a json file. public static void SaveSettings(string jsonSettings, string powertoy = DefaultModuleName, string fileName = DefaultFileName) { diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/SndVideoConferenceSettings.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/SndVideoConferenceSettings.cs new file mode 100644 index 000000000..166835ac8 --- /dev/null +++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/SndVideoConferenceSettings.cs @@ -0,0 +1,28 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Text; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Microsoft.PowerToys.Settings.UI.Lib +{ + public class SndVideoConferenceSettings + { + [JsonPropertyName("Video Conference")] + public VideoConferenceSettings VideoConference { get; set; } + + public SndVideoConferenceSettings(VideoConferenceSettings settings) + { + this.VideoConference = settings; + } + + public string ToJsonString() + { + return JsonSerializer.Serialize(this); + } + } +} diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/StringProperty.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/StringProperty.cs index 6165d7544..fb44f2479 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI.Lib/StringProperty.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/StringProperty.cs @@ -29,5 +29,10 @@ namespace Microsoft.PowerToys.Settings.UI.Lib { return JsonSerializer.Serialize(this); } + + public static implicit operator StringProperty(string v) + { + return new StringProperty(v); + } } } diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/VideoConferenceConfigProperties.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/VideoConferenceConfigProperties.cs new file mode 100644 index 000000000..49eff76b4 --- /dev/null +++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/VideoConferenceConfigProperties.cs @@ -0,0 +1,85 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Microsoft.PowerToys.Settings.UI.Lib +{ + public class VideoConferenceConfigProperties + { + public VideoConferenceConfigProperties() + { + this.MuteCameraAndMicrophoneHotkey = new KeyboardKeysProperty( + new HotkeySettings() + { + Win = true, + Ctrl = false, + Alt = false, + Shift = false, + Key = "N", + Code = 78, + }); + + this.MuteMicrophoneHotkey = new KeyboardKeysProperty( + new HotkeySettings() + { + Win = true, + Ctrl = false, + Alt = false, + Shift = true, + Key = "A", + Code = 65, + }); + + this.MuteCameraHotkey = new KeyboardKeysProperty( + new HotkeySettings() + { + Win = true, + Ctrl = false, + Alt = false, + Shift = true, + Key = "O", + Code = 79, + }); + + Theme = new StringProperty("light"); + + this.HideOverlayWhenUnmuted = new BoolProperty(true); + } + + [JsonPropertyName("mute_camera_and_microphone_hotkey")] + public KeyboardKeysProperty MuteCameraAndMicrophoneHotkey { get; set; } + + [JsonPropertyName("mute_microphone_hotkey")] + public KeyboardKeysProperty MuteMicrophoneHotkey { get; set; } + + [JsonPropertyName("mute_camera_hotkey")] + public KeyboardKeysProperty MuteCameraHotkey { get; set; } + + [JsonPropertyName("selected_camera")] + public StringProperty SelectedCamera { get; set; } = string.Empty; + + [JsonPropertyName("overlay_position")] + public StringProperty OverlayPosition { get; set; } = "Top right corner"; + + [JsonPropertyName("overlay_monitor")] + public StringProperty OverlayMonitor { get; set; } = "Main monitor"; + + [JsonPropertyName("camera_overlay_image_path")] + public StringProperty CameraOverlayImagePath { get; set; } = string.Empty; + + [JsonPropertyName("theme")] + public StringProperty Theme { get; set; } + + [JsonPropertyName("hide_overlay_when_unmuted")] + public BoolProperty HideOverlayWhenUnmuted { get; set; } + + // converts the current to a json string. + public string ToJsonString() + { + return JsonSerializer.Serialize(this); + } + } +} diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/VideoConferenceSettings.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/VideoConferenceSettings.cs new file mode 100644 index 000000000..ff434176b --- /dev/null +++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/VideoConferenceSettings.cs @@ -0,0 +1,36 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Text; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Microsoft.PowerToys.Settings.UI.Lib +{ + public class VideoConferenceSettings + { + public VideoConferenceSettings() + { + this.Version = "1.0"; + this.Name = "Video Conference"; + this.Properties = new VideoConferenceConfigProperties(); + } + + [JsonPropertyName("version")] + public string Version { get; set; } + + [JsonPropertyName("name")] + public string Name { get; set; } + + [JsonPropertyName("properties")] + public VideoConferenceConfigProperties Properties { get; set; } + + public string ToJsonString() + { + return JsonSerializer.Serialize(this); + } + } +} diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/VideoConferenceSettingsIPCMessage.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/VideoConferenceSettingsIPCMessage.cs new file mode 100644 index 000000000..a188e5ce3 --- /dev/null +++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/VideoConferenceSettingsIPCMessage.cs @@ -0,0 +1,29 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Microsoft.PowerToys.Settings.UI.Lib +{ + public class VideoConferenceSettingsIPCMessage + { + [JsonPropertyName("powertoys")] + public SndVideoConferenceSettings Powertoys { get; set; } + + public VideoConferenceSettingsIPCMessage() + { + } + + public VideoConferenceSettingsIPCMessage(SndVideoConferenceSettings settings) + { + this.Powertoys = settings; + } + + public string ToJsonString() + { + return JsonSerializer.Serialize(this); + } + } +} diff --git a/src/core/Microsoft.PowerToys.Settings.UI/Microsoft.PowerToys.Settings.UI.csproj b/src/core/Microsoft.PowerToys.Settings.UI/Microsoft.PowerToys.Settings.UI.csproj index 051bec93f..c965f16e1 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI/Microsoft.PowerToys.Settings.UI.csproj +++ b/src/core/Microsoft.PowerToys.Settings.UI/Microsoft.PowerToys.Settings.UI.csproj @@ -111,6 +111,7 @@ + ColorPickerPage.xaml @@ -141,6 +142,9 @@ ShortcutGuidePage.xaml + + VideoConference.xaml + @@ -182,7 +186,7 @@ 6.1.0 - 6.1.1 + 6.1.2 2.5.0-prerelease.200708003 @@ -275,6 +279,10 @@ Designer MSBuild:Compile + + MSBuild:Compile + Designer + @@ -298,12 +306,6 @@ false false - - 8.0 - - - 8.0 -