diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index f2eb897a4d56..37ba10bc4d85 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -77,9 +77,9 @@ body: - Shortcut Guide - System tray interaction - TextExtractor - - Video Conference Mute - Workspaces - Welcome / PowerToys Tour window + - ZoomIt validations: required: true diff --git a/.github/ISSUE_TEMPLATE/translation_issue.yml b/.github/ISSUE_TEMPLATE/translation_issue.yml index 69787a3ed685..ffddacb9aac8 100644 --- a/.github/ISSUE_TEMPLATE/translation_issue.yml +++ b/.github/ISSUE_TEMPLATE/translation_issue.yml @@ -51,9 +51,9 @@ body: - Shortcut Guide - System tray interaction - TextExtractor - - Video Conference Mute - Workspaces - Welcome / PowerToys Tour window + - ZoomIt validations: required: true - type: input diff --git a/.github/actions/spell-check/allow/code.txt b/.github/actions/spell-check/allow/code.txt index 8c53e5282757..787715190015 100644 --- a/.github/actions/spell-check/allow/code.txt +++ b/.github/actions/spell-check/allow/code.txt @@ -97,6 +97,7 @@ EXSEL HOLDENTER HOLDESC HOLDSPACE +HOLDBACKSPACE KBDLLHOOKSTRUCT keyevent LAlt diff --git a/.github/actions/spell-check/allow/names.txt b/.github/actions/spell-check/allow/names.txt index fb7ff648b2bc..4941c62e13ce 100644 --- a/.github/actions/spell-check/allow/names.txt +++ b/.github/actions/spell-check/allow/names.txt @@ -23,7 +23,6 @@ registrypreview rooler scoobe shortcutguide -videoconference # USERS @@ -34,6 +33,7 @@ Adoumie Advaith alekhyareddy Aleks +amihaiuc angularsen Anirudha arjunbalgovind @@ -68,6 +68,7 @@ Essey Feng ethanfangg ferraridavide +foxmsft frankychen Gaarden gaardmark @@ -115,6 +116,7 @@ martinchrzan martinmoene Melman Mengyuan +Mihaiuc Mikhayelyan msft Mykhailo @@ -142,6 +144,7 @@ ricardosantos riri ritchielawrence robmikh +Russinovich Rutkas ryanbodrug saahmedm @@ -186,6 +189,7 @@ Zykova Bilibili BVID +capturevideosample cmdow Controlz cortana diff --git a/.github/actions/spell-check/excludes.txt b/.github/actions/spell-check/excludes.txt index 80fee9ff244b..912d72d472ec 100644 --- a/.github/actions/spell-check/excludes.txt +++ b/.github/actions/spell-check/excludes.txt @@ -16,6 +16,7 @@ (?:|$^ 92.31% - excluded 12/13)/editor/[^/]+$ /images/launcher/[^/]+$ /TestFiles/ +[^/]\.cur$ [^/]\.gcode$ [^/]\.rgs$ \.a$ @@ -119,5 +120,6 @@ ^src/modules/MouseWithoutBorders/App/Helper/.*\.resx$ ^src/modules/previewpane/UnitTests-MarkdownPreviewHandler/HelperFiles/MarkdownWithHTMLImageTag\.txt$ ^src/Monaco/ +^src/common/sysinternals/Eula/ ^tools/Verification scripts/Check preview handler registration\.ps1$ ignore$ diff --git a/.github/actions/spell-check/expect.txt b/.github/actions/spell-check/expect.txt index 39b2cd26dca9..fa9c77d5a411 100644 --- a/.github/actions/spell-check/expect.txt +++ b/.github/actions/spell-check/expect.txt @@ -4,17 +4,16 @@ abgr ABlocked ABOUTBOX Abug -accctrl Acceleratorkeys ACCEPTFILES ACCESSDENIED ACCESSTOKEN -aclapi AClient AColumn acrt ACTIVATEAPP activationaction +ADDSTRING ADDUNDORECORD ADifferent adml @@ -27,8 +26,10 @@ AGGREGATABLE ahk AHybrid akv +ALIGNRIGHT ALarger ALLAPPS +ALLCHILDREN ALLINPUT ALLOWUNDO ALLVIEW @@ -39,6 +40,7 @@ AMPROPSETID amr ANDSCANS animatedvisuals +Animnate ansicolor ANull AOC @@ -51,12 +53,9 @@ APIIs apng Apm APPBARDATA -appdata APPEXECLINK -Appium APPLICATIONFRAMEHOST appmanifest -appmodel APPNAME appref appsettings @@ -70,6 +69,7 @@ ARemapped ARPINSTALLLOCATION ARPPRODUCTICON ARRAYSIZE +ARROWKEYS asf AShortcut ASingle @@ -79,17 +79,18 @@ ASSOCSTR ASYNCWINDOWPLACEMENT ASYNCWINDOWPOS atl -atlbase -atlcom atleast -atlfile -atlstr ATRIOX aumid Authenticode +AUTOBUDDY +AUTOCHECKBOX AUTOHIDE +AUTOHSCROLL AUTOMATIONPROPERTIES +AUTORADIOBUTTON Autorun +AUTOTICKS AUTOUPDATE AValid awakeness @@ -106,12 +107,17 @@ BIF bigbar bigobj binlog +binres BITMAPFILEHEADER bitmapimage BITMAPINFO BITMAPINFOHEADER +Bitmaps +BITSPERPEL BITSPIXEL bla +BLACKFRAME +BLENDFUNCTION Blockquotes blogs Blt @@ -121,7 +127,6 @@ bmi bms BNumber BODGY -bootstrapper BOOTSTRAPPERINSTALLFOLDER bostrot BOTTOMALIGN @@ -144,11 +149,11 @@ BVal BValue byapp BYPOSITION +CALCRECT CALG callbackptr calpwstr Cangjie -caniuse CANRENAME CAPTUREBLT CAPTURECHANGED @@ -163,7 +168,6 @@ CDeclaration CDEF CElems CENTERALIGN -ceq certlm certmgr cfp @@ -173,6 +177,7 @@ CHANGECBCHAIN changecursor CHILDACTIVATE CHILDWINDOW +CHOOSEFONT cidl cim CImage @@ -192,55 +197,49 @@ CLSCTX Clusion cmder CMDNOTFOUNDMODULEINTERFACE -Cmds CMIC CMINVOKECOMMANDINFO CMINVOKECOMMANDINFOEX CMock CMONITORS cmph -cne CNF coclass codereview Codespaces -codicon COINIT colorconv colorformat colorhistory colorhistorylimit COLORKEY +comctl comdef comdlg comexp cominterop -commandline -commctrl -commdlg compmgmt COMPOSITIONFULL -comutil CONFIGW CONFLICTINGMODIFIERKEY CONFLICTINGMODIFIERSHORTCUT CONOUT -consts -contentdialog contentfiles CONTEXTHELP CONTEXTMENUHANDLER CONTROLL CONTROLPARENT copiedcolorrepresentation +COPYPEN COREWINDOW cotaskmem COULDNOT countof cph +cplusplus CPower -cppwinrt createdump +CREATEPROCESS CREATESCHEDULEDTASK CREATESTRUCT CREATEWINDOWFAILED @@ -248,14 +247,14 @@ CRECT CRH critsec Crossdevice -CRSEL -crx CSearch CSettings cso CSRW CStyle CTest +CTEXT +CTLCOLORSTATIC currentculture CURRENTDIR CURSORINFO @@ -285,11 +284,8 @@ DBLEPSILON DCapture DCBA DCOM -dcommon -dcomp DComposition DCR -DCs ddd DDEIf DDevice @@ -315,14 +311,15 @@ DELA DELETEDKEYIMAGE DELETESCANS deletethis +DEMOTYPE DENORMAL depersist deprioritized DESELECTOTHERS +DESIGNINFO DESKTOPABSOLUTEEDITING DESKTOPABSOLUTEPARSING desktopshorcutinstalled -desktopwindowxamlsource devblogs devdocs devenum @@ -330,15 +327,19 @@ devmgmt DEVMODE DEVMODEW DEVMON -devpkey DEVSOURCE DGR +DIALOGEX DIIRFLAG dimm DISABLEASACTIONKEY +DISABLENOSCROLL diskmgmt DISPLAYCHANGE DISPLAYCONFIG +DISPLAYFLAGS +DISPLAYFREQUENCY +DISPLAYORIENTATION displayname divyan Dlg @@ -362,8 +363,11 @@ DRAWFRAME drawingcolor dreamsofameaningfullife drivedetectionwarning +DROPFILES dshow DSTINVERT +DSurface +DTexture DUMMYUNIONNAME Dutil DVASPECT @@ -392,23 +396,21 @@ DWORDLONG dworigin dwrite dxgi -dxgidebug -dxgiformat easeofaccess ecount EData Edid EDITKEYBOARD EDITSHORTCUTS +EDITTEXT EFile ekus -emmintrin -Emoji ENABLEDELAYEDEXPANSION ENABLEDPOPUP +ENABLETAB +ENABLETEMPLATE encodedlaunch encryptor -endpointvolume ENDSESSION ENSUREVISIBLE ENTERSIZEMOVE @@ -425,12 +427,13 @@ ERRORTITLE erwrite ESettings esrp +ETDT etl etw +eula eurochange eventlog eventvwr -evntrace evt EWXFORCE EWXFORCEIFHUNG @@ -442,7 +445,6 @@ examplehandler examplepowertoy EXAND EXCLUDEFROMCAPTURE -exdisp executionpolicy exename EXITSIZEMOVE @@ -456,6 +458,7 @@ exsb exstyle EXTENDEDKEY EXTENDEDVERBS +EXTRALIGHT EXTRINSICPROPERTIES eyetracker FANCYZONESDRAWLAYOUTTEST @@ -466,12 +469,14 @@ fff FILEEXPLORER FILEFLAGS FILEFLAGSMASK +FILEINFOSIG FILELOCKSMITH FILELOCKSMITHCONTEXTMENU FILELOCKSMITHEXT FILELOCKSMITHLIBINTEROP FILEMUSTEXIST FILEOP +FILEOPENDIALOGOPTIONS FILEOS FILESUBTYPE FILESYSPATH @@ -479,9 +484,11 @@ Filetime FILEVERSION Filtergraph Filterkeyboard +FILTERMODE Filterx findfast FIXEDFILEINFO +FIXEDSYS flac flyouts FMask @@ -489,7 +496,10 @@ FOF FOFX FOLDERID folderpath +FONTTYPE +FORCEFILESYSTEM FORCEMINIMIZE +FORMATDLGORD formatetc FORPARSING FRAMECHANGED @@ -497,7 +507,6 @@ frm Froml FROMTOUCH fsmgmt -Functiondiscoverykeys FZE gacutil Gaeilge @@ -506,18 +515,23 @@ GC'ed GCLP gdi gdiplus +GDIPVER GDISCALED GEmoji GETCLIENTAREAANIMATION +GETCURSEL GETDESKWALLPAPER GETDLGCODE GETDPISCALEDSIZE getfilesiginforedist GETICON +GETHOTKEY GETMINMAXINFO +GETNONCLIENTMETRICS GETPROPERTYSTOREFLAGS GETSCREENSAVERRUNNING GETSECKEY +GETSTICKYKEYS GETTEXTLENGTH GHND GMEM @@ -527,10 +541,10 @@ gpo GPOCA gpp gpu +gradians GSM gtm guiddata -guiddef GUITHREADINFO GValue gwl @@ -550,6 +564,7 @@ hbm hbmp hbr HBRBACKGROUND +hbrush hcblack HCERTSTORE HCRYPTHASH @@ -557,6 +572,7 @@ HCRYPTPROV hcursor hcwhite hdc +hdr hdrop hdwwiz Helpline @@ -569,18 +585,20 @@ Hiber Hiberboot HIBYTE hicon +HIDEREADONLY HIDEWINDOW Hif HIMAGELIST himl hinst -hinstance HIWORD HKCC +HKCOMB HKCR HKCU hkey HKLM +HKM HKPD HKU HMD @@ -588,9 +606,11 @@ hmenu hmodule hmonitor homljgmgpmcbpjbnjpfijnhipfkiclkd +HORZRES HORZSIZE Hostbackdropbrush hotkeycontrol +HOTKEYF hotkeys hotlight hotspot @@ -603,7 +623,6 @@ hrgn hsb HSCROLL hsi -hstring HTCLIENT hthumbnail HTOUCHINPUT @@ -618,15 +637,19 @@ hwnd HWNDFIRST HWNDLAST HWNDNEXT +HWNDPARENT HWNDPREV hyjiacan IAI IBeam ICONERROR ICONLOCATION +idc +IDCANCEL IDD idl idlist +IDOK IDR IDXGI ietf @@ -647,11 +670,15 @@ imageresizerinput imageresizersettings imagingdevices ime +INCONTACT +Indo inetcpl Infobar INFOEXAMPLE Infotip +INITDIALOG INITGUID +INITTOLOGFONTSTRUCT inorder INPC inproc @@ -673,14 +700,12 @@ installscopeperuser INSTALLSTARTMENUSHORTCUT INSTALLSTATE Inste -Intelli Interlop INTRESOURCE INVALIDARG invalidoperatioexception ipcmanager IPREVIEW -ipreviewhandlervisualssetfont irprops isbi ISearch @@ -724,7 +749,6 @@ keyvault KILLFOCUS killrunner kmph -Knownfolders KSPROPERTY Kybd lastcodeanalysissucceeded @@ -735,22 +759,26 @@ lcb LCIDTo Lclean Ldone +Ldr ldx LEFTSCROLLBAR +LEFTTEXT LError LEVELID LExit lhwnd LIBID +LIMITSIZE +LIMITTEXT lindex linkid LINKOVERLAY LINQTo listview +LIVEZOOM lld LLKH llkhf -lmcons LMEM LMENU lnks @@ -764,13 +792,17 @@ LOGFONT LOGFONTW logon LOGPIXELSX +LOGPIXELSY longdate LONGLONG +LONGNAMES lowlevel LOWORD lparam LPBITMAPINFOHEADER +LPCFHOOKPROC LPCITEMIDLIST +LPCLSID lpcmi LPCMINVOKECOMMANDINFO LPCREATESTRUCT @@ -789,7 +821,6 @@ lprc LPSAFEARRAY lpstr lpsz -lpt LPTHREAD LPTOP lptpm @@ -798,12 +829,15 @@ LPTSTR LPW lpwcx lpwndpl +lpv LReader LRESULT LSTATUS lstrcmp lstrcmpi +lstrcpyn lstrlen +LTEXT LTRB LTRREADING luid @@ -813,12 +847,16 @@ LVal LWA lwin LZero +MAGTRANSFORM majortype makecab MAKEINTRESOURCE MAKEINTRESOURCEA MAKEINTRESOURCEW MAKELANGID +MAKELONG +MAKELPARAM +MAKEWPARAM manifestdependency MAPPEDTOSAMEKEY MAPTOSAMESHORTCUT @@ -841,23 +879,19 @@ MERGECOPY MERGEPAINT Metadatas metafile -mfapi mfc -mfidl -mfobjects mfplat -mftransform Mgmt mic midl mii mindaro -Minimatch Minimizable MINIMIZEBOX MINIMIZEEND MINIMIZESTART miniz +MINMAXINFO Mip Miracast mjpg @@ -866,11 +900,10 @@ mlcfg mmc mmcexe MMdd -mmdeviceapi mmi mmsys -mmsystem mockapi +MODALFRAME MODESPRUNED MONITORENUMPROC MONITORINFO @@ -892,13 +925,14 @@ MRT mru msc mscorlib +msctls msdata MSDL -msedge MSGFLT msiexec MSIFASTINSTALL MSIHANDLE +Msimg msiquery MSIRESTARTMANAGERCONTROL msixbundle @@ -910,6 +944,7 @@ msrc msstore mst msvcp +msvsmon MTND MULTIPLEUSE multizone @@ -946,7 +981,6 @@ netframework netsetup netsh newcolor -newdev NEWDIALOGSTYLE NEWFILE newitem @@ -959,33 +993,39 @@ newsgroups NIF NLog NLSTEXT +NMAKE NNN NOACTIVATE NOAGGREGATION NOASYNC +NOCLIP NOCLOSEPROCESS NOCOALESCE NOCOMM NOCONFIRMMKDIR NOCOPYBITS NOCOPYSECURITYATTRIBS +NOCRLF nodeca -nodoc NODRAWCAPTION NODRAWICON NOINHERITLAYOUT NOINTERFACE +NOINVERT NOLINKINFO NOMCX NOMINMAX NOMIRRORBITMAP NOMOVE +NONANTIALIASED nonclient +NONCLIENTMETRICSW NONELEVATED NONINFRINGEMENT nonstd NOOWNERZORDER NOPARENTNOTIFY +NOPREFIX NOREDIRECTIONBITMAP NOREDRAW NOREMOVE @@ -998,15 +1038,17 @@ NORMALUSER NOSEARCH NOSENDCHANGING NOSIZE +NOTHOUSANDS +NOTICKS NOTIFICATIONSDLL NOTIFYICONDATA NOTIFYICONDATAW NOTIMPL -notlike NOTOPMOST NOTRACK NOTSRCCOPY NOTSRCERASE +NOTXORPEN NOZORDER NPH npmjs @@ -1014,16 +1056,16 @@ NResize nsunt NTAPI ntdll -ntfs NTSTATUS +NTSYSAPI +NULLCURSOR nullonfailure numberbox nwc -Objbase -objidl ocr Ocrsettings odbccp +OEMCONVERT officehubintl OFN ofs @@ -1043,18 +1085,21 @@ ORPHANEDDIALOGTITLE ORSCANS oss ostr +OSVERSIONINFO OSVERSIONINFOEX OSVERSIONINFOEXW +OSVERSIONINFOW osvi OUTOFCONTEXT outpin Outptr -outputtype outsettings OVERLAPPEDWINDOW overlaywindow Oversampling +OVERWRITEPROMPT OWNDC +OWNERDRAWFIXED Packagemanager PACL PAINTSTRUCT @@ -1066,7 +1111,6 @@ PARENTRELATIVEPARSING parray PARTIALCONFIRMATIONDIALOGTITLE PATCOPY -pathcch PATHMUSTEXIST PATINVERT PATPAINT @@ -1083,7 +1127,9 @@ PCIDLIST PCTSTR PCWSTR pdbs +PDEVMODE pdisp +PDLL pdo pdto pdtobj @@ -1091,6 +1137,8 @@ pdw Peb PElems Pels +PELSHEIGHT +PELSWIDTH PERCEIVEDFLAG perfmon pesi @@ -1119,9 +1167,13 @@ ploc ploca plocm pluginsmodel +PMAGTRANSFORM PMSIHANDLE pnid +PNMLINK Pnp +POINTERID +POINTERUPDATE Popups POPUPWINDOW POSITIONITEM @@ -1149,7 +1201,6 @@ pptal ppv prc Prefixer -Preinstalled prependpath prevhost previewer @@ -1166,8 +1217,8 @@ prm proactively PROCESSENTRY PROCESSKEY -processthreadsapi PROCESSTRACE +procmon PRODEXT PRODUCTVERSION Progman @@ -1175,9 +1226,9 @@ programdata projectname PROPBAG PROPERTYKEY -propkey PROPVARIANT propvarutil +PRTL prvpane psapi pscid @@ -1189,13 +1240,14 @@ psrm psrree pstatstg pstm -pstr +PStr pstream pstrm PSYSTEM psz ptb ptc +PTCHAR ptd PTOKEN PToy @@ -1219,6 +1271,7 @@ QUEUESYNC QUNS RAII RAlt +randi Rasterize RAWINPUTDEVICE RAWINPUTHEADER @@ -1226,6 +1279,8 @@ RAWMODE RAWPATH rbhid rclsid +RCZOOMIT +RDW READMODE READOBJECTS recents @@ -1234,7 +1289,6 @@ rectp RECTSOURCE recyclebin Redist -redistributable reencode reencoded REFCLSID @@ -1263,10 +1317,8 @@ remoteip Removelnk renamable RENAMEONCOLLISION -Renamer reparented reparenting -reparse reportfileaccesses requery requerying @@ -1278,7 +1330,6 @@ RESIZETOFIT resmimetype RESOURCEID RESTORETOMAXIMIZED -restrictederrorinfo resultlist RETURNONLYFSDIRS RGBQUAD @@ -1294,7 +1345,6 @@ riid ringbuffer RKey RNumber -roadmap rop ROUNDSMALL rpcrt @@ -1307,14 +1357,12 @@ rstringalpha rstringdigit RTB RTLREADING -ruleset runas rundll rungameid RUNLEVEL runtimeclass runtimepack -runtimes ruuid rvm rwin @@ -1329,6 +1377,7 @@ SCID Scip scipbe Scode +SCREENFONTS screensaver screenshots scrollviewer @@ -1337,16 +1386,27 @@ SDKDDK sdns searchterm SEARCHUI +SECONDARYDISPLAY secpol +SELCHANGE SENDCHANGE sendvirtualinput serverside +SETBUDDYINT SETCONTEXT +SETCURSEL setcursor SETFOCUS SETFOREGROUND +SETHOTKEY SETICON +SETLOWPOWERACTIVE +SETPOWEROFFACTIVE +SETRANGE SETREDRAW +SETRULES +SETSCREENSAVEACTIVE +SETSTICKYKEYS SETTEXT SETTINGCHANGE SETTINGSCHANGED @@ -1356,27 +1416,24 @@ setvariable SETWORKAREA sfgao SFGAOF +SHACF SHANDLE sharpkeys SHCNE SHCNF SHCONTF Shcore -shellapi SHELLDETAILS SHELLDLL shellex SHELLEXECUTEINFO SHELLEXECUTEINFOW -shellscalingapi SHFILEINFO SHFILEOPSTRUCT SHGDN SHGDNF SHGFI shinfo -shldisp -shlobj shlwapi shmem SHNAMEMAPPING @@ -1393,6 +1450,7 @@ shortsplit showcolorname SHOWDEFAULT SHOWELEVATIONPROMPT +SHOWMAGNIFIEDCURSOR SHOWMAXIMIZED SHOWMINIMIZED SHOWMINNOACTIVE @@ -1467,6 +1525,7 @@ STATICEDGE STATSTG stdafx STDAPI +stdc stdcpplatest STDMETHODCALLTYPE STDMETHODIMP @@ -1474,8 +1533,10 @@ STGC STGM STGMEDIUM sticpl +STICKYKEYS stl storelogo +stprintf streamjsonrpc STRINGIZE stringtable @@ -1484,12 +1545,14 @@ Strm strret strsafe strutil +stscanf sttngs Stubless STYLECHANGED STYLECHANGING subkeys sublang +SUBMODULEUPDATE subquery Superbar sut @@ -1498,7 +1561,6 @@ SVGIn SVGIO svgz SVSI -SWC SWFO SWP SWRESTORE @@ -1520,9 +1582,8 @@ SYSKEYUP SYSLIB SYSMENU SYSTEMAPPS +SYSTEMMODAL SYSTEMTIME -tailwindcss -tapp TApplication TApplied targ @@ -1534,9 +1595,18 @@ targetver taskkill taskschd TCHAR +TCIF +TCITEM +TCN Tcollab tcs +tcscat +tcschr +tcscmp tcscpy +tcsdup +tcslen +tcsrchr TCustom tdbuild TDefault @@ -1547,39 +1617,38 @@ testprocess TEXCOORD TEXTEXTRACTOR TEXTINCLUDE +tfopen tgz themeresources THH THICKFRAME THISCOMPONENT THotkey -thumbcache TILEDWINDOW TILLSON timedate timediff timeunion timeutil +TITLEBARINFO Titlecase tkcontrols tkconverters TLayout tlb tlbimp -tlhelp TMPVAR TNP Toolhelp toolkitconverters -Toolset toolwindow TOPDOWNDIB TOUCHEVENTF TOUCHINPUT -touchpad TRACEHANDLE tracelogging tracerpt +trackbar trafficmanager traies transicc @@ -1588,8 +1657,8 @@ triaging trl trx tsa -Tsd TServer +tstoi TStr tweakme TWF @@ -1598,8 +1667,10 @@ TYPEKEYBOARD TYPEMOUSE TYPESHORTCUT UAC +UACUI UAL uap +UBR UCallback udit uefi @@ -1613,6 +1684,7 @@ ums uncompilable UNCPRIORITY UNDNAME +unhiding UNICODETEXT uninstaller uninstantiated @@ -1620,31 +1692,31 @@ uniquifier Uniquifies unitconverter unittests -Unknwn UNLEN UNORM -unregistering unremapped unvirtualized unwide +unzoom UOffset UOI Updatelayout +UPDATENOW +UPDATEREGISTRY +updown UPGRADINGPRODUCTCODE Uptool urld -urlmon Usb USEDEFAULT USEFILEATTRIBUTES -USERDATA USESHOWWINDOW USESTDHANDLES USRDLL UType uuidv uwp -Uxtheme +uxtheme vabdq validmodulename valuegenerator @@ -1653,9 +1725,9 @@ vcamp vcdl vcgtq VCINSTALLDIR -vcm Vcpkg VCRT +VCENTER vcruntime vcvars VDesktop @@ -1664,18 +1736,18 @@ vdupq VERBSONLY VERBW VERIFYCONTEXT -verrsrc VERSIONINFO +VERTRES VERTSIZE VFT vget vgetq vid VIDCAP -videoconferencevirtualdriver VIDEOINFOHEADER viewmodel vih +VIRTKEY VIRTUALDESK VISEGRADRELAY visiblecolorformats @@ -1702,6 +1774,7 @@ vsonline vstemplate vstest VSTHRD +vstprintf VSTT vswhere Vtbl @@ -1711,7 +1784,6 @@ Wagnerp wbem WBounds Wca -wcautil WCE wcex WClass @@ -1719,6 +1791,7 @@ wcsicmp wcsncpy wcsnicmp WDA +wdm wdp wdupenv webbrowsers @@ -1732,29 +1805,21 @@ wifi wil winapi winappsdk -wincodec -Wincodecsdk wincolor -windef windir WINDOWCREATED WINDOWEDGE +WINDOWINFO WINDOWNAME WINDOWPLACEMENT WINDOWPOSCHANGED WINDOWPOSCHANGING -windowsapp WINDOWSBUILDNUMBER windowssearch windowssettings WINDOWSTYLES WINDOWSTYLESICON -windowsx -winerror WINEVENT -winevt -winexe -winforms winget wingetcreate Winhook @@ -1765,9 +1830,7 @@ WINNT winres winrt winsdk -winsdkver winsta -winternl WINTHRESHOLD WINVER winxamlmanager @@ -1813,14 +1876,12 @@ wrl wscui wsf wsh -wsl wstr wsz WTA WTNCA wtoi WTS -wtsapi WTSAT Wubi WVC @@ -1855,4 +1916,7 @@ ZEROINIT zonable zoneset Zoneszonabletester +Zoomin +zoomit +ZOOMITX zzz diff --git a/.github/actions/spell-check/patterns.txt b/.github/actions/spell-check/patterns.txt index 90ec1de43b9a..00725cb50ff1 100644 --- a/.github/actions/spell-check/patterns.txt +++ b/.github/actions/spell-check/patterns.txt @@ -239,3 +239,7 @@ CRC(32|64)(Decimal|Hex) # WSL paths \/mnt\/.* + +# ZoomIt menu items with accelerator keys +E&xit +St&yle diff --git a/.pipelines/ESRPSigning_core.json b/.pipelines/ESRPSigning_core.json index f4216069f944..60741d41242e 100644 --- a/.pipelines/ESRPSigning_core.json +++ b/.pipelines/ESRPSigning_core.json @@ -17,7 +17,6 @@ "PowerToys.FilePreviewCommon.dll", "PowerToys.Interop.dll", "Tools\\PowerToys.BugReportTool.exe", - "WebcamReportTool\\PowerToys.WebcamReportTool.exe", "StylesReportTool\\PowerToys.StylesReportTool.exe", "Telemetry.dll", "PowerToys.ManagedTelemetry.dll", @@ -110,6 +109,7 @@ "FileLocksmithContextMenuPackage.msix", "WinUI3Apps\\Peek.Common.dll", + "WinUI3Apps\\Peek.Helpers.dll", "WinUI3Apps\\Peek.FilePreviewer.dll", "WinUI3Apps\\Powertoys.Peek.UI.dll", "WinUI3Apps\\Powertoys.Peek.UI.exe", @@ -226,10 +226,9 @@ "PowerToys.ShortcutGuide.exe", "PowerToys.ShortcutGuideModuleInterface.dll", - "PowerToys.VideoConferenceModule.dll", - "PowerToys.VideoConferenceProxyFilter_x86.dll", - "PowerToys.VideoConferenceProxyFilter_x64.dll", - "PowerToys.VideoConferenceProxyFilter_arm64.dll", + "PowerToys.ZoomIt.exe", + "PowerToys.ZoomItModuleInterface.dll", + "PowerToys.ZoomItSettingsInterop.dll", "WinUI3Apps\\PowerToys.Settings.dll", "WinUI3Apps\\PowerToys.Settings.exe" @@ -346,7 +345,12 @@ "ColorCode.UWP.dll", "UnitsNet.dll", "UtfUnknown.dll", - "Wpf.Ui.dll" + "Wpf.Ui.dll", + "WinUI3Apps\\Microsoft.WindowsAPICodePack.Core.dll", + "WinUI3Apps\\Microsoft.WindowsAPICodePack.ExtendedLinguisticServices.dll", + "WinUI3Apps\\Microsoft.WindowsAPICodePack.Sensors.dll", + "WinUI3Apps\\Microsoft.WindowsAPICodePack.Shell.dll", + "WinUI3Apps\\Microsoft.WindowsAPICodePack.ShellExtensions.dll" ], "SigningInfo": { "Operations": [ diff --git a/.pipelines/ESRPSigning_vcm.json b/.pipelines/ESRPSigning_vcm.json deleted file mode 100644 index e9f2309cc413..000000000000 --- a/.pipelines/ESRPSigning_vcm.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "Version": "1.0.0", - "UseMinimatch": false, - "SignBatches": [ - { - "MatchedPath": [ - "PowerToys.VideoConferenceProxyFilter_x86.dll" - ], - "SigningInfo": { - "Operations": [ - { - "KeyCode": "CP-230012", - "OperationSetCode": "SigntoolSign", - "Parameters": [ - { - "parameterName": "OpusName", - "parameterValue": "Microsoft" - }, - { - "parameterName": "OpusInfo", - "parameterValue": "http://www.microsoft.com" - }, - { - "parameterName": "FileDigest", - "parameterValue": "/fd \"SHA256\"" - }, - { - "parameterName": "PageHash", - "parameterValue": "/NPH" - }, - { - "parameterName": "TimeStamp", - "parameterValue": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256" - } - ], - "ToolName": "sign", - "ToolVersion": "1.0" - }, - { - "KeyCode": "CP-230012", - "OperationSetCode": "SigntoolVerify", - "Parameters": [], - "ToolName": "sign", - "ToolVersion": "1.0" - } - ] - } - } - ] -} diff --git a/.pipelines/loc/loc.yml b/.pipelines/loc/loc.yml index 2087e300eaf1..8d582c48305c 100644 --- a/.pipelines/loc/loc.yml +++ b/.pipelines/loc/loc.yml @@ -32,9 +32,9 @@ steps: TDBuildServiceConnection: $(TouchdownServiceConnection) authType: SubjectNameIssuer resourceFilePath: | - **\Resources.resx - **\Resource.resx - **\Resources.resw + src\**\Resources.resx + src\**\Resource.resx + src\**\Resources.resw outputDirectoryRoot: LocOutput appendRelativeDir: true pseudoSetting: Included diff --git a/.pipelines/v2/templates/job-build-project.yml b/.pipelines/v2/templates/job-build-project.yml index 653e8cc9fd96..5a3b787ede41 100644 --- a/.pipelines/v2/templates/job-build-project.yml +++ b/.pipelines/v2/templates/job-build-project.yml @@ -172,7 +172,6 @@ jobs: - pwsh: |- & '.pipelines/verifyArm64Configuration.ps1' -solution '$(build.sourcesdirectory)\PowerToys.sln' & '.pipelines/verifyArm64Configuration.ps1' -solution '$(build.sourcesdirectory)\tools\BugReportTool\BugReportTool.sln' - & '.pipelines/verifyArm64Configuration.ps1' -solution '$(build.sourcesdirectory)\tools\WebcamReportTool\WebcamReportTool.sln' & '.pipelines/verifyArm64Configuration.ps1' -solution '$(build.sourcesdirectory)\tools\StylesReportTool\StylesReportTool.sln' & '.pipelines/verifyArm64Configuration.ps1' -solution '$(build.sourcesdirectory)\installer\PowerToysSetup.sln' displayName: Verify ARM64 configurations @@ -361,27 +360,6 @@ jobs: env: SYSTEM_ACCESSTOKEN: $(System.AccessToken) - - task: VSBuild@1 - displayName: Build WebcamReportTool - inputs: - solution: '**/tools/WebcamReportTool/WebcamReportTool.sln' - vsVersion: 17.0 - msbuildArgs: >- - -restore -graph - /p:RestorePackagesConfig=true - /p:CIBuild=true - /bl:$(LogOutputDirectory)\build-webcam-report.binlog - ${{ parameters.additionalBuildOptions }} - $(MSBuildCacheParameters) - $(RestoreAdditionalProjectSourcesArg) - platform: $(BuildPlatform) - configuration: $(BuildConfiguration) - msbuildArchitecture: x64 - maximumCpuCount: true - ${{ if eq(parameters.enableMsBuildCaching, true) }}: - env: - SYSTEM_ACCESSTOKEN: $(System.AccessToken) - - task: VSBuild@1 displayName: Build StylesReportTool inputs: @@ -484,7 +462,7 @@ jobs: displayName: Sign Core PowerToys signingIdentity: ${{ parameters.signingIdentity }} inputs: - FolderPath: '$(BuildPlatform)/$(BuildConfiguration)' # Video conf uses x86 and x64. + FolderPath: '$(BuildPlatform)/$(BuildConfiguration)' signType: batchSigning batchSignPolicyFile: '$(build.sourcesdirectory)\.pipelines\ESRPSigning_core.json' ciPolicyFile: '$(build.sourcesdirectory)\.pipelines\CIPolicy.xml' @@ -499,16 +477,6 @@ jobs: batchSignPolicyFile: '$(build.sourcesdirectory)\.pipelines\ESRPSigning_DSC.json' ciPolicyFile: '$(build.sourcesdirectory)\.pipelines\CIPolicy.xml' - - template: steps-esrp-signing.yml - parameters: - displayName: Sign x86 DirectShow VCM - signingIdentity: ${{ parameters.signingIdentity }} - inputs: - FolderPath: 'x86/$(BuildConfiguration)' # Video conf uses x86 and x64. - signType: batchSigning - batchSignPolicyFile: '$(build.sourcesdirectory)\.pipelines\ESRPSigning_vcm.json' - ciPolicyFile: '$(build.sourcesdirectory)\.pipelines\CIPolicy.xml' - - template: steps-build-installer.yml parameters: codeSign: ${{ parameters.codeSign }} diff --git a/COMMUNITY.md b/COMMUNITY.md index 64d77c9f37c8..8b3d7035da08 100644 --- a/COMMUNITY.md +++ b/COMMUNITY.md @@ -15,15 +15,21 @@ Christian contributed New+ utility ### [@CleanCodeDeveloper](https://github.com/CleanCodeDeveloper) CleanCodeDeveloper helped do massive amounts of code stability and image resizer work. +### [@plante-msft](https://github.com/plante-msft) - Connor Plante +Connor was the creator of Workspaces and helped create PowerToys Run v2 + ### [@damienleroy](https://github.com/damienleroy) - [Damien Leroy](https://www.linkedin.com/in/Damien-Leroy-b2734416a/) Damien has helped out by developing and contributing the Quick Accent utility. -### [@daverayment ](https://github.com/daverayment ) - [David Rayment](https://www.linkedin.com/in/david-rayment-168b5251/) +### [@daverayment ](https://github.com/daverayment) - [David Rayment](https://www.linkedin.com/in/david-rayment-168b5251/) Dave has helped improve the experience inside of Peek by adding in new features and fixing bugs. ### [@davidegiacometti](https://github.com/davidegiacometti) - [Davide Giacometti](https://www.linkedin.com/in/davidegiacometti/) Davide has helped fix multiple bugs, added new utilities, features, as well as help us with the ARM64 effort by porting applications to .NET Core. +### [@ethanfangg](https://github.com/ethanfangg) - Ethan Fang +Ethan helped run PowerToys and worked on improving and prototyping out next generation PowerToys + ### [@franky920920](https://github.com/franky920920) - [Franky Chen](https://frankychen.net) Franky has helped triaging, discussing, and creating a substantial number of issues and contributed features/fixes to PowerToys. @@ -39,6 +45,9 @@ Jeff added in multiple new features into Keyboard manager, such as key chord sup ### [@TheJoeFin](https://github.com/TheJoeFin) - [Joe Finney](https://joefinapps.com) Joe has helped triaging, discussing, issues as well as fixing bugs and building features for Text Extractor. +### [@joadoumie](https://github.com/joadoumie) - Jordi Adoumie +Jordi helped innovate amazing new features into Advanced Paste and helped create PowerToys Run v2 + ### [@jsoref](https://github.com/jsoref) - [Josh Soref](https://check-spelling.dev/) Helping keep our spelling correct :) @@ -121,6 +130,8 @@ Find My Mouse is based on Raymond Chen's SuperSonar. Crop And Lock is based on the original work of Robert Mikhayelyan, with Program Manager support from [@kevinguo305](https://github.com/kevinguo305) - Kevin Guo. +ZoomIt's Video Recording Session code is based on Robert Mikhayelyan's https://github.com/robmikh/capturevideosample code. + ### Microsoft InVEST team This amazing team helped PowerToys develop PowerToys Run and Keyboard manager as well as update our Settings to v2. @alekhyareddy28, @arjunbalgovind, @jyuwono @laviusmotileng-ms, @ryanbodrug-microsoft, @saahmedm, @somil55, @traies, @udit3333 @@ -160,14 +171,19 @@ Other contributors: * Paul Schmitt - WWL * And many other Users! +## ZoomIt original contributors + +ZoomIt source code was originally implemented by [Sysinternals](https://sysinternals.com): + +- [@markrussinovich](https://github.com/markrussinovich) - Mark Russinovich +- [@foxmsft](https://github.com/foxmsft) - Alex Mihaiuc +- [@johnstep](https://github.com/johnstep) - John Stephens + ## PowerToys core team - [@crutkas](https://github.com/crutkas/) - Clint Rutkas - Lead - [@cinnamon-msft](https://github.com/cinnamon-msft) - Kayla Cinnamon - Lead -- [@ethanfangg](https://github.com/ethanfangg) - Ethan Fang - Product Manager -- [@plante-msft](https://github.com/plante-msft) - Connor Plante - Product Manager - [@nguyen-dows](https://github.com/nguyen-dows) - Christopher Nguyen - Product Manager -- [@joadoumie](https://github.com/joadoumie) - Jordi Adoumie - Product Manager - [@jaimecbernardo](https://github.com/jaimecbernardo) - Jaime Bernardo - Dev lead - [@dhowett](https://github.com/dhowett) - Dustin Howett - Dev lead - [@yeelam-gordon](https://github.com/yeelam-gordon) - Gordon Lam - Dev lead @@ -193,6 +209,9 @@ Other contributors: # Former PowerToys core team members - [@indierawk2k2](https://github.com/indierawk2k2) - Mike Harsh - Product Manager +- [@ethanfangg](https://github.com/ethanfangg) - Ethan Fang - Product Manager +- [@plante-msft](https://github.com/plante-msft) - Connor Plante - Product Manager +- [@joadoumie](https://github.com/joadoumie) - Jordi Adoumie - Product Manager - [@enricogior](https://github.com/enricogior) - Enrico Giordani - Dev Lead - [@bzoz](https://github.com/bzoz) - Bartosz Sosnowski - Dev - [@ivan100sic](https://github.com/ivan100sic) - Ivan Stošić - Dev diff --git a/DATA_AND_PRIVACY.md b/DATA_AND_PRIVACY.md index 5570729c202a..92711f00ddef 100644 --- a/DATA_AND_PRIVACY.md +++ b/DATA_AND_PRIVACY.md @@ -941,26 +941,6 @@ _If you want to find diagnostic data events in the source code, these two links -### Video Conference Mute - - - - - - - - - - - - - - - - - -
Event NameDescription
Microsoft.PowerToys.VideoConference_CameraMutedTriggered when the camera is turned off by Video Conference Mute.
Microsoft.PowerToys.VideoConference_EnableVideoConferenceOccurs when Video Conference Mute is enabled.
Microsoft.PowerToys.VideoConference_MicrophoneMutedOccurs when the microphone is muted by Video Conference Mute.
- ### Workspaces @@ -997,6 +977,50 @@ _If you want to find diagnostic data events in the source code, these two links
+### ZoomIt + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Event NameDescription
Microsoft.PowerToys.ZoomIt_EnableZoomItTriggered when ZoomIt is enabled/disabled.
Microsoft.PowerToys.ZoomIt_StartedTriggered when the ZoomIt process starts.
Microsoft.PowerToys.ZoomIt_ActivateBreakTriggered when the Break mode is entered.
Microsoft.PowerToys.ZoomIt_ActivateDrawTriggered when the Draw mode is entered.
Microsoft.PowerToys.ZoomIt_ActivateZoomTriggered when the Zoom mode is entered.
Microsoft.PowerToys.ZoomIt_ActivateLiveZoomTriggered when the Live Zoom mode is entered.
Microsoft.PowerToys.ZoomIt_ActivateDemoTypeTriggered when the DemoType mode is entered.
Microsoft.PowerToys.ZoomIt_ActivateRecordTriggered when the Record mode is entered.
Microsoft.PowerToys.ZoomIt_ActivateSnipTriggered when the Snip mode is entered.
+ - + - + - - - - - + + + + + - - + + - + - - - + + + - + - - + + - - + + - - - - + + + + diff --git a/NOTICE.md b/NOTICE.md index c2498495032a..20e810e2b6a9 100644 --- a/NOTICE.md +++ b/NOTICE.md @@ -1331,24 +1331,24 @@ EXHIBIT A -Mozilla Public License. - hyjiacan.pinyin4net 4.1.1 - Interop.Microsoft.Office.Interop.OneNote 1.1.0.2 - LazyCache 2.4.0 -- Mages 2.0.2 +- Mages 3.0.0 - Markdig.Signed 0.34.0 - MessagePack 2.5.187 -- Microsoft.Bcl.AsyncInterfaces 9.0.0 +- Microsoft.Bcl.AsyncInterfaces 9.0.1 - Microsoft.CodeAnalysis.NetAnalyzers 9.0.0 -- Microsoft.Data.Sqlite 9.0.0 +- Microsoft.Data.Sqlite 9.0.1 - Microsoft.Diagnostics.Tracing.TraceEvent 3.1.16 -- Microsoft.Extensions.DependencyInjection 9.0.0 -- Microsoft.Extensions.Hosting 9.0.0 -- Microsoft.Extensions.Hosting.WindowsServices 9.0.0 -- Microsoft.Extensions.Logging 9.0.0 -- Microsoft.Extensions.Logging.Abstractions 9.0.0 +- Microsoft.Extensions.DependencyInjection 9.0.1 +- Microsoft.Extensions.Hosting 9.0.1 +- Microsoft.Extensions.Hosting.WindowsServices 9.0.1 +- Microsoft.Extensions.Logging 9.0.1 +- Microsoft.Extensions.Logging.Abstractions 9.0.1 - Microsoft.NET.ILLink.Tasks (A) - Microsoft.SemanticKernel 1.15.0 - Microsoft.Toolkit.Uwp.Notifications 7.1.2 - Microsoft.Web.WebView2 1.0.2739.15 -- Microsoft.Win32.SystemEvents 9.0.0 -- Microsoft.Windows.Compatibility 9.0.0 +- Microsoft.Win32.SystemEvents 9.0.1 +- Microsoft.Windows.Compatibility 9.0.1 - Microsoft.Windows.CsWin32 0.2.46-beta - Microsoft.Windows.CsWinRT 2.1.5 - Microsoft.Windows.SDK.BuildTools 10.0.22621.2428 @@ -1366,24 +1366,24 @@ EXHIBIT A -Mozilla Public License. - SharpCompress 0.37.2 - StreamJsonRpc 2.19.27 - StyleCop.Analyzers 1.2.0-beta.556 -- System.CodeDom 9.0.0 +- System.CodeDom 9.0.1 - System.CommandLine 2.0.0-beta4.22272.1 -- System.ComponentModel.Composition 9.0.0 -- System.Configuration.ConfigurationManager 9.0.0 -- System.Data.OleDb 9.0.0 +- System.ComponentModel.Composition 9.0.1 +- System.Configuration.ConfigurationManager 9.0.1 +- System.Data.OleDb 9.0.1 - System.Data.SqlClient 4.8.6 -- System.Diagnostics.EventLog 9.0.0 -- System.Diagnostics.PerformanceCounter 9.0.0 -- System.Drawing.Common 9.0.0 +- System.Diagnostics.EventLog 9.0.1 +- System.Diagnostics.PerformanceCounter 9.0.1 +- System.Drawing.Common 9.0.1 - System.IO.Abstractions 21.0.29 - System.IO.Abstractions.TestingHelpers 21.0.29 -- System.IO.Hashing 9.0.0 -- System.Management 9.0.0 +- System.IO.Hashing 9.0.1 +- System.Management 9.0.1 - System.Reactive 6.0.1 -- System.Runtime.Caching 9.0.0 -- System.ServiceProcess.ServiceController 9.0.0 -- System.Text.Encoding.CodePages 9.0.0 -- System.Text.Json 9.0.0 +- System.Runtime.Caching 9.0.1 +- System.ServiceProcess.ServiceController 9.0.1 +- System.Text.Encoding.CodePages 9.0.1 +- System.Text.Json 9.0.1 - UnicodeInformation 2.6.0 - UnitsNet 5.56.0 - UTF.Unknown 2.5.1 diff --git a/PowerToys.sln b/PowerToys.sln index 1093e3b4d1e9..5cfc9332132e 100644 --- a/PowerToys.sln +++ b/PowerToys.sln @@ -179,7 +179,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Directory.Build.targets = Directory.Build.targets Directory.Packages.props = Directory.Packages.props src\Monaco.props = src\Monaco.props - Solution.props = Solution.props + src\Solution.props = src\Solution.props src\Version.props = src\Version.props EndProjectSection EndProject @@ -349,17 +349,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerToys.Update", "src\Upd EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.PowerToys.Run.Plugin.WindowsSettings", "src\modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.WindowsSettings\Microsoft.PowerToys.Run.Plugin.WindowsSettings.csproj", "{5043CECE-E6A7-4867-9CBE-02D27D83747A}" 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}") = "VideoConferenceModule", "src\modules\videoconference\VideoConferenceModule\VideoConference.vcxproj", "{5ABA70DE-3A3F-41F6-A1F5-D1F74F54F9BB}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VideoConferenceProxyFilter", "src\modules\videoconference\VideoConferenceProxyFilter\VideoConferenceProxyFilter.vcxproj", "{AC2857B4-103D-4D6D-9740-926EBF785042}" - ProjectSection(ProjectDependencies) = postProject - {459E0768-7EBD-4C41-BBA1-6DB3B3815E0A} = {459E0768-7EBD-4C41-BBA1-6DB3B3815E0A} - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "VideoConference", "VideoConference", "{470FBAF9-E1F8-4F3E-8786-198A1C81C8A8}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PdfThumbnailProvider", "src\modules\previewpane\PdfThumbnailProvider\PdfThumbnailProvider.csproj", "{11491FD8-F921-48BF-880C-7FEA185B80A1}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTests-PdfThumbnailProvider", "src\modules\previewpane\UnitTests-PdfThumbnailProvider\UnitTests-PdfThumbnailProvider.csproj", "{F40C3397-1834-4530-B2D9-8F8B8456BCDF}" @@ -672,6 +661,14 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AdvancedPaste.UnitTests", " EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AdvancedPaste.FuzzTests", "src\modules\AdvancedPaste\AdvancedPaste.FuzzTests\AdvancedPaste.FuzzTests.csproj", "{7F5B9557-5878-4438-A721-3E28296BA193}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ZoomIt", "ZoomIt", "{DD6E12FE-5509-4ABC-ACC2-3D6DC98A238C}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZoomIt", "src\modules\ZoomIt\ZoomIt\ZoomIt.vcxproj", "{0A84F764-3A88-44CD-AA96-41BDBD48627B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZoomItModuleInterface", "src\modules\ZoomIt\ZoomItModuleInterface\ZoomItModuleInterface.vcxproj", "{E4585179-2AC1-4D5F-A3FF-CFC5392F694C}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZoomItSettingsInterop", "src\modules\ZoomIt\ZoomItSettingsInterop\ZoomItSettingsInterop.vcxproj", "{CA7D8106-30B9-4AEC-9D05-B69B31B8C461}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|ARM64 = Debug|ARM64 @@ -1542,40 +1539,6 @@ Global {5043CECE-E6A7-4867-9CBE-02D27D83747A}.Release|x64.ActiveCfg = Release|x64 {5043CECE-E6A7-4867-9CBE-02D27D83747A}.Release|x64.Build.0 = Release|x64 {5043CECE-E6A7-4867-9CBE-02D27D83747A}.Release|x86.ActiveCfg = Release|x64 - {459E0768-7EBD-4C41-BBA1-6DB3B3815E0A}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {459E0768-7EBD-4C41-BBA1-6DB3B3815E0A}.Debug|ARM64.Build.0 = Debug|ARM64 - {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}.Debug|x86.ActiveCfg = Debug|Win32 - {459E0768-7EBD-4C41-BBA1-6DB3B3815E0A}.Debug|x86.Build.0 = Debug|Win32 - {459E0768-7EBD-4C41-BBA1-6DB3B3815E0A}.Release|ARM64.ActiveCfg = Release|ARM64 - {459E0768-7EBD-4C41-BBA1-6DB3B3815E0A}.Release|ARM64.Build.0 = Release|ARM64 - {459E0768-7EBD-4C41-BBA1-6DB3B3815E0A}.Release|x64.ActiveCfg = Release|x64 - {459E0768-7EBD-4C41-BBA1-6DB3B3815E0A}.Release|x64.Build.0 = Release|x64 - {459E0768-7EBD-4C41-BBA1-6DB3B3815E0A}.Release|x86.ActiveCfg = Release|Win32 - {459E0768-7EBD-4C41-BBA1-6DB3B3815E0A}.Release|x86.Build.0 = Release|Win32 - {5ABA70DE-3A3F-41F6-A1F5-D1F74F54F9BB}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {5ABA70DE-3A3F-41F6-A1F5-D1F74F54F9BB}.Debug|ARM64.Build.0 = Debug|ARM64 - {5ABA70DE-3A3F-41F6-A1F5-D1F74F54F9BB}.Debug|x64.ActiveCfg = Debug|x64 - {5ABA70DE-3A3F-41F6-A1F5-D1F74F54F9BB}.Debug|x64.Build.0 = Debug|x64 - {5ABA70DE-3A3F-41F6-A1F5-D1F74F54F9BB}.Debug|x86.ActiveCfg = Debug|x64 - {5ABA70DE-3A3F-41F6-A1F5-D1F74F54F9BB}.Release|ARM64.ActiveCfg = Release|ARM64 - {5ABA70DE-3A3F-41F6-A1F5-D1F74F54F9BB}.Release|ARM64.Build.0 = Release|ARM64 - {5ABA70DE-3A3F-41F6-A1F5-D1F74F54F9BB}.Release|x64.ActiveCfg = Release|x64 - {5ABA70DE-3A3F-41F6-A1F5-D1F74F54F9BB}.Release|x64.Build.0 = Release|x64 - {5ABA70DE-3A3F-41F6-A1F5-D1F74F54F9BB}.Release|x86.ActiveCfg = Release|x64 - {AC2857B4-103D-4D6D-9740-926EBF785042}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {AC2857B4-103D-4D6D-9740-926EBF785042}.Debug|ARM64.Build.0 = Debug|ARM64 - {AC2857B4-103D-4D6D-9740-926EBF785042}.Debug|x64.ActiveCfg = Debug|x64 - {AC2857B4-103D-4D6D-9740-926EBF785042}.Debug|x64.Build.0 = Debug|x64 - {AC2857B4-103D-4D6D-9740-926EBF785042}.Debug|x86.ActiveCfg = Debug|Win32 - {AC2857B4-103D-4D6D-9740-926EBF785042}.Debug|x86.Build.0 = Debug|Win32 - {AC2857B4-103D-4D6D-9740-926EBF785042}.Release|ARM64.ActiveCfg = Release|ARM64 - {AC2857B4-103D-4D6D-9740-926EBF785042}.Release|ARM64.Build.0 = Release|ARM64 - {AC2857B4-103D-4D6D-9740-926EBF785042}.Release|x64.ActiveCfg = Release|x64 - {AC2857B4-103D-4D6D-9740-926EBF785042}.Release|x64.Build.0 = Release|x64 - {AC2857B4-103D-4D6D-9740-926EBF785042}.Release|x86.ActiveCfg = Release|Win32 - {AC2857B4-103D-4D6D-9740-926EBF785042}.Release|x86.Build.0 = Release|Win32 {11491FD8-F921-48BF-880C-7FEA185B80A1}.Debug|ARM64.ActiveCfg = Debug|ARM64 {11491FD8-F921-48BF-880C-7FEA185B80A1}.Debug|ARM64.Build.0 = Debug|ARM64 {11491FD8-F921-48BF-880C-7FEA185B80A1}.Debug|x64.ActiveCfg = Debug|x64 @@ -3024,6 +2987,42 @@ Global {7F5B9557-5878-4438-A721-3E28296BA193}.Release|x64.Build.0 = Release|x64 {7F5B9557-5878-4438-A721-3E28296BA193}.Release|x86.ActiveCfg = Release|x64 {7F5B9557-5878-4438-A721-3E28296BA193}.Release|x86.Build.0 = Release|x64 + {0A84F764-3A88-44CD-AA96-41BDBD48627B}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {0A84F764-3A88-44CD-AA96-41BDBD48627B}.Debug|ARM64.Build.0 = Debug|ARM64 + {0A84F764-3A88-44CD-AA96-41BDBD48627B}.Debug|x64.ActiveCfg = Debug|x64 + {0A84F764-3A88-44CD-AA96-41BDBD48627B}.Debug|x64.Build.0 = Debug|x64 + {0A84F764-3A88-44CD-AA96-41BDBD48627B}.Debug|x86.ActiveCfg = Debug|x64 + {0A84F764-3A88-44CD-AA96-41BDBD48627B}.Debug|x86.Build.0 = Debug|x64 + {0A84F764-3A88-44CD-AA96-41BDBD48627B}.Release|ARM64.ActiveCfg = Release|ARM64 + {0A84F764-3A88-44CD-AA96-41BDBD48627B}.Release|ARM64.Build.0 = Release|ARM64 + {0A84F764-3A88-44CD-AA96-41BDBD48627B}.Release|x64.ActiveCfg = Release|x64 + {0A84F764-3A88-44CD-AA96-41BDBD48627B}.Release|x64.Build.0 = Release|x64 + {0A84F764-3A88-44CD-AA96-41BDBD48627B}.Release|x86.ActiveCfg = Release|x64 + {0A84F764-3A88-44CD-AA96-41BDBD48627B}.Release|x86.Build.0 = Release|x64 + {E4585179-2AC1-4D5F-A3FF-CFC5392F694C}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {E4585179-2AC1-4D5F-A3FF-CFC5392F694C}.Debug|ARM64.Build.0 = Debug|ARM64 + {E4585179-2AC1-4D5F-A3FF-CFC5392F694C}.Debug|x64.ActiveCfg = Debug|x64 + {E4585179-2AC1-4D5F-A3FF-CFC5392F694C}.Debug|x64.Build.0 = Debug|x64 + {E4585179-2AC1-4D5F-A3FF-CFC5392F694C}.Debug|x86.ActiveCfg = Debug|x64 + {E4585179-2AC1-4D5F-A3FF-CFC5392F694C}.Debug|x86.Build.0 = Debug|x64 + {E4585179-2AC1-4D5F-A3FF-CFC5392F694C}.Release|ARM64.ActiveCfg = Release|ARM64 + {E4585179-2AC1-4D5F-A3FF-CFC5392F694C}.Release|ARM64.Build.0 = Release|ARM64 + {E4585179-2AC1-4D5F-A3FF-CFC5392F694C}.Release|x64.ActiveCfg = Release|x64 + {E4585179-2AC1-4D5F-A3FF-CFC5392F694C}.Release|x64.Build.0 = Release|x64 + {E4585179-2AC1-4D5F-A3FF-CFC5392F694C}.Release|x86.ActiveCfg = Release|x64 + {E4585179-2AC1-4D5F-A3FF-CFC5392F694C}.Release|x86.Build.0 = Release|x64 + {CA7D8106-30B9-4AEC-9D05-B69B31B8C461}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {CA7D8106-30B9-4AEC-9D05-B69B31B8C461}.Debug|ARM64.Build.0 = Debug|ARM64 + {CA7D8106-30B9-4AEC-9D05-B69B31B8C461}.Debug|x64.ActiveCfg = Debug|x64 + {CA7D8106-30B9-4AEC-9D05-B69B31B8C461}.Debug|x64.Build.0 = Debug|x64 + {CA7D8106-30B9-4AEC-9D05-B69B31B8C461}.Debug|x86.ActiveCfg = Debug|x64 + {CA7D8106-30B9-4AEC-9D05-B69B31B8C461}.Debug|x86.Build.0 = Debug|x64 + {CA7D8106-30B9-4AEC-9D05-B69B31B8C461}.Release|ARM64.ActiveCfg = Release|ARM64 + {CA7D8106-30B9-4AEC-9D05-B69B31B8C461}.Release|ARM64.Build.0 = Release|ARM64 + {CA7D8106-30B9-4AEC-9D05-B69B31B8C461}.Release|x64.ActiveCfg = Release|x64 + {CA7D8106-30B9-4AEC-9D05-B69B31B8C461}.Release|x64.Build.0 = Release|x64 + {CA7D8106-30B9-4AEC-9D05-B69B31B8C461}.Release|x86.ActiveCfg = Release|x64 + {CA7D8106-30B9-4AEC-9D05-B69B31B8C461}.Release|x86.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -3127,10 +3126,6 @@ Global {48804216-2A0E-4168-A6D8-9CD068D14227} = {D1D6BC88-09AE-4FB4-AD24-5DED46A791DD} {FF1D7936-842A-4BBB-8BEA-E9FE796DE700} = {D1D6BC88-09AE-4FB4-AD24-5DED46A791DD} {5043CECE-E6A7-4867-9CBE-02D27D83747A} = {4AFC9975-2456-4C70-94A4-84073C1CED93} - {459E0768-7EBD-4C41-BBA1-6DB3B3815E0A} = {470FBAF9-E1F8-4F3E-8786-198A1C81C8A8} - {5ABA70DE-3A3F-41F6-A1F5-D1F74F54F9BB} = {470FBAF9-E1F8-4F3E-8786-198A1C81C8A8} - {AC2857B4-103D-4D6D-9740-926EBF785042} = {470FBAF9-E1F8-4F3E-8786-198A1C81C8A8} - {470FBAF9-E1F8-4F3E-8786-198A1C81C8A8} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC} {11491FD8-F921-48BF-880C-7FEA185B80A1} = {2F305555-C296-497E-AC20-5FA1B237996A} {F40C3397-1834-4530-B2D9-8F8B8456BCDF} = {2F305555-C296-497E-AC20-5FA1B237996A} {A2D583F0-B70C-4462-B1F0-8E81AFB7BA85} = {4AFC9975-2456-4C70-94A4-84073C1CED93} @@ -3274,6 +3269,10 @@ Global {0DB0F63A-D2F8-4DA3-A650-2D0B8724218E} = {CA716AE6-FE5C-40AC-BB8F-2C87912687AC} {D5E5F5EA-1B6C-4A73-88BE-304F36C9E4EE} = {9873BA05-4C41-4819-9283-CF45D795431B} {7F5B9557-5878-4438-A721-3E28296BA193} = {9873BA05-4C41-4819-9283-CF45D795431B} + {DD6E12FE-5509-4ABC-ACC2-3D6DC98A238C} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC} + {0A84F764-3A88-44CD-AA96-41BDBD48627B} = {DD6E12FE-5509-4ABC-ACC2-3D6DC98A238C} + {E4585179-2AC1-4D5F-A3FF-CFC5392F694C} = {DD6E12FE-5509-4ABC-ACC2-3D6DC98A238C} + {CA7D8106-30B9-4AEC-9D05-B69B31B8C461} = {DD6E12FE-5509-4ABC-ACC2-3D6DC98A238C} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {C3A2F9D1-7930-4EF4-A6FC-7EE0A99821D0} diff --git a/README.md b/README.md index df5b8acb1033..11646244adef 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Microsoft PowerToys -![Hero image for Microsoft PowerToys](doc/images/overview/PT_holiday_hero_image.png) +![Hero image for Microsoft PowerToys](doc/images/overview/PT_hero_image.png) [How to use PowerToys][usingPowerToys-docs-link] | [Downloads & Release notes][github-release-link] | [Contributing to PowerToys](#contributing) | [What's Happening](#whats-happening) | [Roadmap](#powertoys-roadmap) @@ -18,13 +18,7 @@ Microsoft PowerToys is a set of utilities for power users to tune and streamline | [New+](https://aka.ms/PowerToysOverview_NewPlus) | [Peek](https://aka.ms/PowerToysOverview_Peek) | [Paste as Plain Text](https://aka.ms/PowerToysOverview_PastePlain) | | [PowerRename](https://aka.ms/PowerToysOverview_PowerRename) | [PowerToys Run](https://aka.ms/PowerToysOverview_PowerToysRun) | [Quick Accent](https://aka.ms/PowerToysOverview_QuickAccent) | | [Registry Preview](https://aka.ms/PowerToysOverview_RegistryPreview) | [Screen Ruler](https://aka.ms/PowerToysOverview_ScreenRuler) | [Shortcut Guide](https://aka.ms/PowerToysOverview_ShortcutGuide) | -| [Text Extractor](https://aka.ms/PowerToysOverview_TextExtractor) | [Video Conference Mute](https://aka.ms/PowerToysOverview_VideoConference) | [Workspaces](https://aka.ms/PowerToysOverview_Workspaces) | - -## 🎁⭐ PowerToys Advent calendar ⭐🎁 - -We will be highlighting a cool utility each day for 24 days in December! To follow along, check out these threads: -- https://bsky.app/profile/kaylacinnamon.bsky.social/post/3lcb7iljxck2o -- https://x.com/cinnamon_msft/status/1863284610773246257 +| [Text Extractor](https://aka.ms/PowerToysOverview_TextExtractor) | [Workspaces](https://aka.ms/PowerToysOverview_Workspaces) | [ZoomIt](https://aka.ms/PowerToysOverview_PowerToysOverview_ZoomIt) | ## Installing and running Microsoft PowerToys @@ -232,6 +226,5 @@ The application logs basic diagnostic data (telemetry). For more information on [winget-link]: https://github.com/microsoft/winget-cli#installing-the-client [roadmap]: https://github.com/microsoft/PowerToys/wiki/Roadmap [privacy-link]: http://go.microsoft.com/fwlink/?LinkId=521839 -[vidConfOverview]: https://aka.ms/PowerToysOverview_VideoConference [loc-bug]: https://github.com/microsoft/PowerToys/issues/new?assignees=&labels=&template=translation_issue.md&title= [usingPowerToys-docs-link]: https://aka.ms/powertoys-docs diff --git a/doc/devdocs/akaLinks.md b/doc/devdocs/akaLinks.md index 6b0dcac1d895..eae60c1161e2 100644 --- a/doc/devdocs/akaLinks.md +++ b/doc/devdocs/akaLinks.md @@ -29,7 +29,6 @@ | PowerToysOverview_PowerRename | https://learn.microsoft.com/windows/powertoys/powerrename | | PowerToysOverview_PowerToysRun | https://learn.microsoft.com/windows/powertoys/run | | PowerToysOverview_ShortcutGuide | https://learn.microsoft.com/windows/powertoys/shortcut-guide | -| PowerToysOverview_VideoConference | https://learn.microsoft.com/windows/powertoys/video-conference-mute | | powerToysPowerLauncherImageSmall | https://github.com/microsoft/PowerToys/wiki/images/overview/PowerLauncher_small.png | | powerToysPowerLauncherSettingImage | https://raw.githubusercontent.com/microsoft/PowerToys/main/doc/images/overview/PowerLauncher_large.png | | powerToysPowerPreviewImageSmall | https://github.com/microsoft/PowerToys/wiki/images/overview/PowerPreview_small.png | @@ -42,6 +41,4 @@ | powerToysRequestFeature | https://github.com/microsoft/PowerToys/issues/new?assignees=&labels=&template=feature_request.md&title= | | powerToysShortcutGuideImageSmall | https://github.com/microsoft/PowerToys/wiki/images/overview/ShortcutGuide_small.png | | powerToysShortcutGuideSettingImage | https://raw.githubusercontent.com/microsoft/PowerToys/main/doc/images/overview/ShortcutGuide_large.png | -| powerToysVideoConferenceImageSmall | https://github.com/microsoft/PowerToys/wiki/images/overview/VideoConference_small.png | -| powerToysVideoConferenceSettingImage | https://github.com/microsoft/PowerToys/wiki/images/overview/VideoConference_large.png | | powertoyswiki | https://github.com/microsoft/PowerToys/wiki | diff --git a/doc/devdocs/modules/launcher/new-plugin-checklist.md b/doc/devdocs/modules/launcher/new-plugin-checklist.md index 7287e4305e6c..e1bb7fae098e 100644 --- a/doc/devdocs/modules/launcher/new-plugin-checklist.md +++ b/doc/devdocs/modules/launcher/new-plugin-checklist.md @@ -16,7 +16,7 @@ "Author": string, "Version": "1.0.0", // For future compatibility "Language": "csharp", // So far we support only csharp - "Website": "https://aka.ms/powertoys", + "Website": "https://aka.ms/powertoys", // Has to be an absolute uri starting with "http://" or "https://". "ExecuteFileName": string, // Should be {Type}.PowerToys.Run.Plugin.{PluginName}.dll "IcoPathDark": string, // Path to dark theme icon. The path is relative to the root plugin folder "IcoPathLight": string // Path to light theme icon. The path is relative to the root plugin folder @@ -42,3 +42,4 @@ In the PR that adds a new plugin, reference a new issue to track the work for fu - [ ] Add the resource folder to https://github.com/microsoft/PowerToys/blob/21247c0bb09a1bee3d14d6efa53d0c247f7236af/installer/PowerToysSetup/Product.wxs#L825 - [ ] Add the resource files under the section https://github.com/microsoft/PowerToys/blob/21247c0bb09a1bee3d14d6efa53d0c247f7236af/installer/PowerToysSetup/Product.wxs#L882 +- [ ] Your plugin's executable file (DLL) has to have correct version informations after building it. (This version information will be shown on the settings page.) diff --git a/doc/devdocs/modules/launcher/readme.md b/doc/devdocs/modules/launcher/readme.md index 75b62ecb3c35..984d82833c6f 100644 --- a/doc/devdocs/modules/launcher/readme.md +++ b/doc/devdocs/modules/launcher/readme.md @@ -1,19 +1,24 @@ # Table of Contents 1. [Architecture](/doc/devdocs/modules/launcher/architecture.md) 2. [Debugging](/doc/devdocs/modules/launcher/debugging.md) -3. [Project Structure](/doc/devdocs/modules/launcher/project_structure.md) -4. [Telemetry](/doc/devdocs/modules/launcher/telemetry.md) -5. Plugins +3. [New Plugin Checklist](/doc/devdocs/modules/launcher/new-plugin-checklist.md) +4. [Project Structure](/doc/devdocs/modules/launcher/project_structure.md) +5. [Telemetry](/doc/devdocs/modules/launcher/telemetry.md) +6. Plugins - [Overview](/doc/devdocs/modules/launcher/plugins/overview.md) - [Calculator](/doc/devdocs/modules/launcher/plugins/calculator.md) - [Folder](/doc/devdocs/modules/launcher/plugins/folder.md) + - [History](/doc/devdocs/modules/launcher/plugins/history.md) - [Indexer](/doc/devdocs/modules/launcher/plugins/indexer.md) - [OneNote](/doc/devdocs/modules/launcher/plugins/onenote.md) - [Program](/doc/devdocs/modules/launcher/plugins/program.md) - [Registry](/doc/devdocs/modules/launcher/plugins/registry.md) - [Shell](/doc/devdocs/modules/launcher/plugins/shell.md) - [Time and Date](/doc/devdocs/modules/launcher/plugins/timedate.md) - - [Windows System Commands](/doc/devdocs/modules/launcher/plugins/system.md) + - [Unit Converter](/doc/devdocs/modules/launcher/plugins/community.unitconverter.md) - [Uri](/doc/devdocs/modules/launcher/plugins/uri.md) - - [Window Walker](/doc/devdocs/modules/launcher/plugins/windowwalker.md) + - [Value Generator](/doc/devdocs/modules/launcher/plugins/community.valuegenerator.md) - [Web Search](/doc/devdocs/modules/launcher/plugins/WebSearch.md) + - [Windows Settings](/doc/devdocs/modules/launcher/plugins/windowssettings.md) + - [Windows System Commands](/doc/devdocs/modules/launcher/plugins/system.md) + - [Window Walker](/doc/devdocs/modules/launcher/plugins/windowwalker.md) diff --git a/doc/devdocs/readme.md b/doc/devdocs/readme.md index 558cb5aa4962..50912c5b3fe1 100644 --- a/doc/devdocs/readme.md +++ b/doc/devdocs/readme.md @@ -73,7 +73,6 @@ The installer can only be compiled in `Release` mode; steps 1 and 2 must be perf 1. Compile `PowerToys.sln`. Instructions are listed above. 1. Compile `BugReportTool.sln` tool. Path from root: `tools\BugReportTool\BugReportTool.sln` (details listed below) -1. Compile `WebcamReportTool.sln` tool. Path from root: `tools\WebcamReportTool\WebcamReportTool.sln` (details listed below) 1. Compile `StylesReportTool.sln` tool. Path from root: `tools\StylesReportTool\StylesReportTool.sln` (details listed below) 1. Compile `PowerToysSetup.sln` Path from root: `installer\PowerToysSetup.sln` (details listed below) @@ -95,9 +94,6 @@ The installer can only be compiled in `Release` mode; steps 1 and 2 must be perf nuget restore .\tools\BugReportTool\BugReportTool.sln msbuild -p:Platform=x64 -p:Configuration=Release .\tools\BugReportTool\BugReportTool.sln -nuget restore .\tools\WebcamReportTool\WebcamReportTool.sln -msbuild -p:Platform=x64 -p:Configuration=Release .\tools\WebcamReportTool\WebcamReportTool.sln - nuget restore .\tools\StylesReportTool\StylesReportTool.sln msbuild -p:Platform=x64 -p:Configuration=Release .\tools\StylesReportTool\StylesReportTool.sln ``` @@ -109,9 +105,6 @@ If you prefer, you can alternatively build prerequisite projects for the install 1. Open `tools\BugReportTool\BugReportTool.sln` 1. In Visual Studio, in the `Solutions Configuration` drop-down menu select `Release` 1. From the `Build` menu, choose `Build Solution`. -1. Open `tools\WebcamReportTool\WebcamReportTool.sln` -1. In Visual Studio, in the `Solutions Configuration` drop-down menu select `Release` -1. From the `Build` menu, choose `Build Solution`. 1. Open `tools\StylesReportTool\StylesReportTool.sln` 1. In Visual Studio, in the `Solutions Configuration` drop-down menu select `Release` 1. From the `Build` menu, choose `Build Solution`. diff --git a/doc/devdocs/tools/build-tools.md b/doc/devdocs/tools/build-tools.md index dfa4e251b20d..b8acaa3273d1 100644 --- a/doc/devdocs/tools/build-tools.md +++ b/doc/devdocs/tools/build-tools.md @@ -25,7 +25,3 @@ This script is used by the pipeline to move the .resw files to the correct locat ## [versionSetting.ps1](/tools/build/versionSetting.ps1) Sets `version.props` file with the version number. - -## [video_conference_make_cab.ps1](/tools/build/video_conference_make_cab.ps1) - -This script creates a cab file for the Video Conference Mute driver. diff --git a/doc/devdocs/tools/readme.md b/doc/devdocs/tools/readme.md index 1bf19d610b55..a2640bda7a97 100644 --- a/doc/devdocs/tools/readme.md +++ b/doc/devdocs/tools/readme.md @@ -18,4 +18,3 @@ Following tools are currently available: * [project template](/tools/project_template/README.md) - A Visual Studio project template for a new PowerToys project. * [StylesReportTool](styles-report-tool.md) - A tool to collect information about an open window. * [Verification scripts](verification-scripts.md) - A set of scripts that help verifying the PowerToys installation. -* [WebcamReportTool](webcam-report-tool.md) - A tool to collect information about the connected webcams. diff --git a/doc/devdocs/tools/webcam-report-tool.md b/doc/devdocs/tools/webcam-report-tool.md deleted file mode 100644 index efa6d47da3ee..000000000000 --- a/doc/devdocs/tools/webcam-report-tool.md +++ /dev/null @@ -1,6 +0,0 @@ -# [WebcamReportTool](/tools/WebcamReportTool/) - -This command line application generates a report about the connected webcams on the desktop called "WebcamReport.txt". The report contains the following information about every webcam: - -* Name -* Supported formats diff --git a/doc/images/overview/Original/VideoConference.png b/doc/images/overview/Original/VideoConference.png deleted file mode 100644 index 3a71531361c3..000000000000 Binary files a/doc/images/overview/Original/VideoConference.png and /dev/null differ diff --git a/doc/images/overview/PT_holiday_hero_image.png b/doc/images/overview/PT_holiday_hero_image.png deleted file mode 100644 index 77351927fdb3..000000000000 Binary files a/doc/images/overview/PT_holiday_hero_image.png and /dev/null differ diff --git a/doc/images/overview/VideoConference_large.png b/doc/images/overview/VideoConference_large.png deleted file mode 100644 index 028d98889c62..000000000000 Binary files a/doc/images/overview/VideoConference_large.png and /dev/null differ diff --git a/doc/images/overview/VideoConference_small.png b/doc/images/overview/VideoConference_small.png deleted file mode 100644 index 8e2030e92d63..000000000000 Binary files a/doc/images/overview/VideoConference_small.png and /dev/null differ diff --git a/installer/PowerToysSetup/Common.wxi b/installer/PowerToysSetup/Common.wxi index 4b34cfd6abef..adf4a0d906d1 100644 --- a/installer/PowerToysSetup/Common.wxi +++ b/installer/PowerToysSetup/Common.wxi @@ -8,7 +8,6 @@ - diff --git a/installer/PowerToysSetup/FileActionsMenu.wxs b/installer/PowerToysSetup/FileActionsMenu.wxs index 32d5dac84e56..00303295ddf9 100644 --- a/installer/PowerToysSetup/FileActionsMenu.wxs +++ b/installer/PowerToysSetup/FileActionsMenu.wxs @@ -21,7 +21,7 @@ - + diff --git a/installer/PowerToysSetup/PowerToysInstaller.wixproj b/installer/PowerToysSetup/PowerToysInstaller.wixproj index 4bad4b72b368..30ff303c241f 100644 --- a/installer/PowerToysSetup/PowerToysInstaller.wixproj +++ b/installer/PowerToysSetup/PowerToysInstaller.wixproj @@ -52,7 +52,6 @@ call powershell.exe -NonInteractive -executionpolicy Unrestricted -File $(MSBuil call move /Y ..\..\..\Settings.wxs.bk ..\..\..\Settings.wxs call move /Y ..\..\..\ShortcutGuide.wxs.bk ..\..\..\ShortcutGuide.wxs call move /Y ..\..\..\Tools.wxs.bk ..\..\..\Tools.wxs - call move /Y ..\..\..\VideoConference.wxs.bk ..\..\..\VideoConference.wxs call move /Y ..\..\..\WinAppSDK.wxs.bk ..\..\..\WinAppSDK.wxs call move /Y ..\..\..\WinUI3Applications.wxs.bk ..\..\..\WinUI3Applications.wxs call move /Y ..\..\..\Workspaces.wxs.bk ..\..\..\Workspaces.wxs @@ -121,7 +120,6 @@ call powershell.exe -NonInteractive -executionpolicy Unrestricted -File $(MSBuil - diff --git a/installer/PowerToysSetup/Product.wxs b/installer/PowerToysSetup/Product.wxs index 9185a6300da6..aa35b09310d9 100644 --- a/installer/PowerToysSetup/Product.wxs +++ b/installer/PowerToysSetup/Product.wxs @@ -70,7 +70,6 @@ - @@ -197,6 +196,9 @@ NOT Installed + + NOT Installed + + + - - - - - - @@ -34,7 +28,6 @@ - diff --git a/installer/PowerToysSetup/VideoConference.wxs b/installer/PowerToysSetup/VideoConference.wxs deleted file mode 100644 index 04bdb1e5066e..000000000000 --- a/installer/PowerToysSetup/VideoConference.wxs +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - WINDOWSBUILDNUMBER >= 19041 - - - - - - - - - - - - - WINDOWSBUILDNUMBER >= 19041 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/installer/PowerToysSetupCustomActions/CustomAction.cpp b/installer/PowerToysSetupCustomActions/CustomAction.cpp index d011156a0d57..82eb8023c4f6 100644 --- a/installer/PowerToysSetupCustomActions/CustomAction.cpp +++ b/installer/PowerToysSetupCustomActions/CustomAction.cpp @@ -11,6 +11,7 @@ #include "../../src/common/updating/installer.h" #include "../../src/common/version/version.h" #include "../../src/common/Telemetry/EtwTrace/EtwTrace.h" +#include "../../src/common/utils/clean_video_conference.h" #include #include @@ -328,6 +329,19 @@ UINT __stdcall CheckGPOCA(MSIHANDLE hInstall) return WcaFinalize(er); } +// We've deprecated Video Conference Mute. This Custom Action cleans up any stray registry entry for the driver dll. +UINT __stdcall CleanVideoConferenceRegistryCA(MSIHANDLE hInstall) +{ + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + hr = WcaInitialize(hInstall, "CleanVideoConferenceRegistry"); + ExitOnFailure(hr, "Failed to initialize"); + clean_video_conference(); +LExit: + er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return WcaFinalize(er); +} + UINT __stdcall ApplyModulesRegistryChangeSetsCA(MSIHANDLE hInstall) { HRESULT hr = S_OK; @@ -1026,164 +1040,6 @@ UINT __stdcall DetectPrevInstallPathCA(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 = nullptr; - HCERTSTORE hCertStore = nullptr; - HANDLE hfile = nullptr; - DWORD size = INVALID_FILE_SIZE; - char* pFileContent = nullptr; - - hr = WcaInitialize(hInstall, "CertifyVirtualCameraDriverCA"); - ExitOnFailure(hr, "Failed to initialize", hr); - - hr = WcaGetProperty(L"CustomActionData", &certificatePath); - ExitOnFailure(hr, "Failed to get install property", hr); - - hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, 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, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); - if (hfile == INVALID_HANDLE_VALUE) - { - hr = GetLastError(); - ExitOnFailure(hr, "Certificate file open failed", hr); - } - - size = GetFileSize(hfile, nullptr); - if (size == INVALID_FILE_SIZE) - { - hr = GetLastError(); - ExitOnFailure(hr, "Certificate file size not valid", hr); - } - - pFileContent = static_cast(malloc(size)); - - DWORD sizeread; - if (!ReadFile(hfile, pFileContent, size, &sizeread, nullptr)) - { - hr = GetLastError(); - ExitOnFailure(hr, "Certificate file read failed", hr); - } - - if (!CertAddEncodedCertificateToStore(hCertStore, - X509_ASN_ENCODING, - reinterpret_cast(pFileContent), - size, - CERT_STORE_ADD_ALWAYS, - nullptr)) - { - 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, static_cast(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; - LPWSTR driverPath = nullptr; - - hr = WcaInitialize(hInstall, "InstallVirtualCameraDriverCA"); - ExitOnFailure(hr, "Failed to initialize"); - - hr = WcaGetProperty(L"CustomActionData", &driverPath); - ExitOnFailure(hr, "Failed to get install property"); - - 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, static_cast(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; - LPWSTR driverPath = nullptr; - - hr = WcaInitialize(hInstall, "UninstallVirtualCameraDriverCA"); - ExitOnFailure(hr, "Failed to initialize"); - - hr = WcaGetProperty(L"CustomActionData", &driverPath); - ExitOnFailure(hr, "Failed to get uninstall property"); - - 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("Failed to uninstall virtual camera driver")); - MsiProcessMessage(hInstall, static_cast(INSTALLMESSAGE_WARNING + MB_OK), hRecord); - } - - er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; - return WcaFinalize(er); -} - UINT __stdcall UnRegisterContextMenuPackagesCA(MSIHANDLE hInstall) { using namespace winrt::Windows::Foundation; @@ -1272,7 +1128,7 @@ UINT __stdcall TerminateProcessesCA(MSIHANDLE hInstall) } processes.resize(bytes / sizeof(processes[0])); - std::array processesToTerminate = { + std::array processesToTerminate = { L"PowerToys.PowerLauncher.exe", L"PowerToys.Settings.exe", L"PowerToys.AdvancedPaste.exe", @@ -1310,6 +1166,7 @@ UINT __stdcall TerminateProcessesCA(MSIHANDLE hInstall) L"PowerToys.WorkspacesLauncherUI.exe", L"PowerToys.WorkspacesEditor.exe", L"PowerToys.WorkspacesWindowArranger.exe", + L"PowerToys.ZoomIt.exe", L"PowerToys.exe", }; diff --git a/installer/PowerToysSetupCustomActions/CustomAction.def b/installer/PowerToysSetupCustomActions/CustomAction.def index f685a0be1dfc..d9ed0d0f04ee 100644 --- a/installer/PowerToysSetupCustomActions/CustomAction.def +++ b/installer/PowerToysSetupCustomActions/CustomAction.def @@ -3,6 +3,7 @@ LIBRARY "PowerToysSetupCustomActions" EXPORTS LaunchPowerToysCA CheckGPOCA + CleanVideoConferenceRegistryCA ApplyModulesRegistryChangeSetsCA DetectPrevInstallPathCA RemoveScheduledTasksCA @@ -15,12 +16,9 @@ EXPORTS TelemetryLogRepairCancelCA TelemetryLogRepairFailCA TerminateProcessesCA - CertifyVirtualCameraDriverCA - InstallVirtualCameraDriverCA InstallEmbeddedMSIXCA InstallDSCModuleCA UnApplyModulesRegistryChangeSetsCA - UninstallVirtualCameraDriverCA UnRegisterContextMenuPackagesCA UninstallEmbeddedMSIXCA UninstallDSCModuleCA diff --git a/installer/PowerToysSetupCustomActions/PowerToysSetupCustomActions.vcxproj b/installer/PowerToysSetupCustomActions/PowerToysSetupCustomActions.vcxproj index 56ff9b808a27..11088e0b9034 100644 --- a/installer/PowerToysSetupCustomActions/PowerToysSetupCustomActions.vcxproj +++ b/installer/PowerToysSetupCustomActions/PowerToysSetupCustomActions.vcxproj @@ -74,7 +74,6 @@ call cmd /C "copy ""$(ProjectDir)..\PowerToysSetup\Settings.wxs"" ""$(ProjectDir)..\PowerToysSetup\Settings.wxs.bk"""" call cmd /C "copy ""$(ProjectDir)..\PowerToysSetup\ShortcutGuide.wxs"" ""$(ProjectDir)..\PowerToysSetup\ShortcutGuide.wxs.bk"""" call cmd /C "copy ""$(ProjectDir)..\PowerToysSetup\Tools.wxs"" ""$(ProjectDir)..\PowerToysSetup\Tools.wxs.bk"""" - call cmd /C "copy ""$(ProjectDir)..\PowerToysSetup\VideoConference.wxs"" ""$(ProjectDir)..\PowerToysSetup\VideoConference.wxs.bk"""" call cmd /C "copy ""$(ProjectDir)..\PowerToysSetup\WinAppSDK.wxs"" ""$(ProjectDir)..\PowerToysSetup\WinAppSDK.wxs.bk"""" call cmd /C "copy ""$(ProjectDir)..\PowerToysSetup\WinUI3Applications.wxs"" ""$(ProjectDir)..\PowerToysSetup\WinUI3Applications.wxs.bk"""" call cmd /C "copy ""$(ProjectDir)..\PowerToysSetup\Workspaces.wxs"" ""$(ProjectDir)..\PowerToysSetup\Workspaces.wxs.bk"""" diff --git a/src/Monaco/index.html b/src/Monaco/index.html index 020c4c3c3342..54f7524225bf 100644 --- a/src/Monaco/index.html +++ b/src/Monaco/index.html @@ -9,17 +9,19 @@ // `theme` can be "vs" for light theme or "vs-dark" for dark theme // `lang` is the language of the file // `wrap` if the editor is wrapping or not + // `minimap` if the minimap is shown + // `contextMenu` whether to use the Monaco context menu. The built-in context menu + // doesn't work in Peek, so we set this to false and create a custom one var theme = ("[[PT_THEME]]" == "dark") ? "vs-dark" : "vs"; + var wrap = [[PT_WRAP]]; + var minimap = [[PT_MINIMAP]]; + var stickyScroll = [[PT_STICKY_SCROLL]]; + var fontSize = [[PT_FONT_SIZE]]; + var lang = "[[PT_LANG]]"; - var wrap = ([[PT_WRAP]] == 1) ? true : false; - var base64code = "[[PT_CODE]]"; - - var stickyScroll = ([[PT_STICKY_SCROLL]] == 1) ? true : false; - - var fontSize = [[PT_FONT_SIZE]]; - var contextMenu = ([[PT_CONTEXTMENU]] == 1) ? true : false; + var contextMenu = [[PT_CONTEXTMENU]]; var editor; @@ -29,12 +31,13 @@ }).join('')); function runToggleTextWrapCommand() { - if (wrap) { - editor.updateOptions({ wordWrap: 'off' }) - } else { - editor.updateOptions({ wordWrap: 'on' }) - } wrap = !wrap; + editor.updateOptions({ wordWrap: wrap ? 'on' : 'off' }); + } + + function runToggleMinimap() { + minimap = !minimap; + editor.updateOptions({minimap: {enabled: minimap}}); } function runCopyCommand() { @@ -99,8 +102,8 @@ language: lang, // Sets language of the code readOnly: true, // Sets to readonly theme: 'theme', // Sets editor theme - minimap: { enabled: false }, // Disables minimap - lineNumbersMinChars: '3', // Width of the line numbers + minimap: { enabled: minimap }, // Controls if minimap is shown + lineNumbersMinChars: 3, // Width of the line numbers contextmenu: contextMenu, scrollbar: { // Deactivate shadows @@ -135,10 +138,20 @@ contextMenuOrder: 100, // Method that will be executed when the action is triggered. - // @param editor The editor instance is passed in as a convenience - run: function (ed) { - runToggleTextWrapCommand(); - } + run: runToggleTextWrapCommand + }); + + editor.addAction({ + id: 'toggle-minimap', + + label: 'Toggle minimap', + + contextMenuGroupId: 'cutcopypaste', + + contextMenuOrder: 100, + + // Method that will be executed when the action is triggered. + run: runToggleMinimap }); onContextMenu(); @@ -166,4 +179,4 @@ } - + \ No newline at end of file diff --git a/src/Monaco/monacoSpecialLanguages.js b/src/Monaco/monacoSpecialLanguages.js index 7039548513a5..5a76713a66cd 100644 --- a/src/Monaco/monacoSpecialLanguages.js +++ b/src/Monaco/monacoSpecialLanguages.js @@ -7,7 +7,7 @@ import { srtDefinition } from './customLanguages/srt.js'; export async function registerAdditionalLanguages(monaco){ await languageDefinitions(); registerAdditionalLanguage("cppExt", [".ino", ".pde"], "cpp", monaco); - registerAdditionalLanguage("xmlExt", [".wsdl", ".csproj", ".vcxproj", ".vbproj", ".fsproj"], "xml", monaco); + registerAdditionalLanguage("xmlExt", [".wsdl", ".csproj", ".vcxproj", ".vbproj", ".fsproj", ".resx", ".resw"], "xml", monaco); registerAdditionalLanguage("txtExt", [".sln", ".log", ".vsconfig", ".env", ".ahk", ".ion"], "txt", monaco); registerAdditionalLanguage("razorExt", [".razor"], "razor", monaco); registerAdditionalLanguage("vbExt", [".vbs"], "vb", monaco); diff --git a/src/Monaco/monaco_languages.json b/src/Monaco/monaco_languages.json index 027e3ffc4250..8f0408dc9b54 100644 --- a/src/Monaco/monaco_languages.json +++ b/src/Monaco/monaco_languages.json @@ -1 +1 @@ -{"list":[{"id":"plaintext","extensions":[".txt"],"aliases":["Plain Text","text"],"mimetypes":["text/plain"]},{"id":"abap","extensions":[".abap"],"aliases":["abap","ABAP"]},{"id":"apex","extensions":[".cls"],"aliases":["Apex","apex"],"mimetypes":["text/x-apex-source","text/x-apex"]},{"id":"azcli","extensions":[".azcli"],"aliases":["Azure CLI","azcli"]},{"id":"bat","extensions":[".bat",".cmd"],"aliases":["Batch","bat"]},{"id":"bicep","extensions":[".bicep"],"aliases":["Bicep"]},{"id":"cameligo","extensions":[".mligo"],"aliases":["Cameligo"]},{"id":"clojure","extensions":[".clj",".cljs",".cljc",".edn"],"aliases":["clojure","Clojure"]},{"id":"coffeescript","extensions":[".coffee"],"aliases":["CoffeeScript","coffeescript","coffee"],"mimetypes":["text/x-coffeescript","text/coffeescript"]},{"id":"c","extensions":[".c",".h"],"aliases":["C","c"]},{"id":"cpp","extensions":[".cpp",".cc",".cxx",".hpp",".hh",".hxx"],"aliases":["C++","Cpp","cpp"]},{"id":"csharp","extensions":[".cs",".csx",".cake"],"aliases":["C#","csharp"]},{"id":"csp","extensions":[],"aliases":["CSP","csp"]},{"id":"css","extensions":[".css"],"aliases":["CSS","css"],"mimetypes":["text/css"]},{"id":"cypher","extensions":[".cypher",".cyp"],"aliases":["Cypher","OpenCypher"]},{"id":"dart","extensions":[".dart"],"aliases":["Dart","dart"],"mimetypes":["text/x-dart-source","text/x-dart"]},{"id":"dockerfile","extensions":[".dockerfile"],"filenames":["Dockerfile"],"aliases":["Dockerfile"]},{"id":"ecl","extensions":[".ecl"],"aliases":["ECL","Ecl","ecl"]},{"id":"elixir","extensions":[".ex",".exs"],"aliases":["Elixir","elixir","ex"]},{"id":"flow9","extensions":[".flow"],"aliases":["Flow9","Flow","flow9","flow"]},{"id":"fsharp","extensions":[".fs",".fsi",".ml",".mli",".fsx",".fsscript"],"aliases":["F#","FSharp","fsharp"]},{"id":"freemarker2","extensions":[".ftl",".ftlh",".ftlx"],"aliases":["FreeMarker2","Apache FreeMarker2"]},{"id":"freemarker2.tag-angle.interpolation-dollar","aliases":["FreeMarker2 (Angle/Dollar)","Apache FreeMarker2 (Angle/Dollar)"]},{"id":"freemarker2.tag-bracket.interpolation-dollar","aliases":["FreeMarker2 (Bracket/Dollar)","Apache FreeMarker2 (Bracket/Dollar)"]},{"id":"freemarker2.tag-angle.interpolation-bracket","aliases":["FreeMarker2 (Angle/Bracket)","Apache FreeMarker2 (Angle/Bracket)"]},{"id":"freemarker2.tag-bracket.interpolation-bracket","aliases":["FreeMarker2 (Bracket/Bracket)","Apache FreeMarker2 (Bracket/Bracket)"]},{"id":"freemarker2.tag-auto.interpolation-dollar","aliases":["FreeMarker2 (Auto/Dollar)","Apache FreeMarker2 (Auto/Dollar)"]},{"id":"freemarker2.tag-auto.interpolation-bracket","aliases":["FreeMarker2 (Auto/Bracket)","Apache FreeMarker2 (Auto/Bracket)"]},{"id":"go","extensions":[".go"],"aliases":["Go"]},{"id":"graphql","extensions":[".graphql",".gql"],"aliases":["GraphQL","graphql","gql"],"mimetypes":["application/graphql"]},{"id":"handlebars","extensions":[".handlebars",".hbs"],"aliases":["Handlebars","handlebars","hbs"],"mimetypes":["text/x-handlebars-template"]},{"id":"hcl","extensions":[".tf",".tfvars",".hcl"],"aliases":["Terraform","tf","HCL","hcl"]},{"id":"html","extensions":[".html",".htm",".shtml",".xhtml",".mdoc",".jsp",".asp",".aspx",".jshtm"],"aliases":["HTML","htm","html","xhtml"],"mimetypes":["text/html","text/x-jshtm","text/template","text/ng-template"]},{"id":"ini","extensions":[".ini",".properties",".gitconfig"],"filenames":["config",".gitattributes",".gitconfig",".editorconfig"],"aliases":["Ini","ini"]},{"id":"java","extensions":[".java",".jav"],"aliases":["Java","java"],"mimetypes":["text/x-java-source","text/x-java"]},{"id":"javascript","extensions":[".js",".es6",".jsx",".mjs",".cjs"],"firstLine":"^#!.*\\bnode","filenames":["jakefile"],"aliases":["JavaScript","javascript","js"],"mimetypes":["text/javascript"]},{"id":"julia","extensions":[".jl"],"aliases":["julia","Julia"]},{"id":"kotlin","extensions":[".kt",".kts"],"aliases":["Kotlin","kotlin"],"mimetypes":["text/x-kotlin-source","text/x-kotlin"]},{"id":"less","extensions":[".less"],"aliases":["Less","less"],"mimetypes":["text/x-less","text/less"]},{"id":"lexon","extensions":[".lex"],"aliases":["Lexon"]},{"id":"lua","extensions":[".lua"],"aliases":["Lua","lua"]},{"id":"liquid","extensions":[".liquid",".html.liquid"],"aliases":["Liquid","liquid"],"mimetypes":["application/liquid"]},{"id":"m3","extensions":[".m3",".i3",".mg",".ig"],"aliases":["Modula-3","Modula3","modula3","m3"]},{"id":"markdown","extensions":[".md",".markdown",".mdown",".mkdn",".mkd",".mdwn",".mdtxt",".mdtext"],"aliases":["Markdown","markdown"]},{"id":"mdx","extensions":[".mdx"],"aliases":["MDX","mdx"]},{"id":"mips","extensions":[".s"],"aliases":["MIPS","MIPS-V"],"mimetypes":["text/x-mips","text/mips","text/plaintext"]},{"id":"msdax","extensions":[".dax",".msdax"],"aliases":["DAX","MSDAX"]},{"id":"mysql","extensions":[],"aliases":["MySQL","mysql"]},{"id":"objective-c","extensions":[".m"],"aliases":["Objective-C"]},{"id":"pascal","extensions":[".pas",".p",".pp"],"aliases":["Pascal","pas"],"mimetypes":["text/x-pascal-source","text/x-pascal"]},{"id":"pascaligo","extensions":[".ligo"],"aliases":["Pascaligo","ligo"]},{"id":"perl","extensions":[".pl",".pm"],"aliases":["Perl","pl"]},{"id":"pgsql","extensions":[],"aliases":["PostgreSQL","postgres","pg","postgre"]},{"id":"php","extensions":[".php",".php4",".php5",".phtml",".ctp"],"aliases":["PHP","php"],"mimetypes":["application/x-php"]},{"id":"pla","extensions":[".pla"]},{"id":"postiats","extensions":[".dats",".sats",".hats"],"aliases":["ATS","ATS/Postiats"]},{"id":"powerquery","extensions":[".pq",".pqm"],"aliases":["PQ","M","Power Query","Power Query M"]},{"id":"powershell","extensions":[".ps1",".psm1",".psd1"],"aliases":["PowerShell","powershell","ps","ps1"]},{"id":"proto","extensions":[".proto"],"aliases":["protobuf","Protocol Buffers"]},{"id":"pug","extensions":[".jade",".pug"],"aliases":["Pug","Jade","jade"]},{"id":"python","extensions":[".py",".rpy",".pyw",".cpy",".gyp",".gypi"],"aliases":["Python","py"],"firstLine":"^#!/.*\\bpython[0-9.-]*\\b"},{"id":"qsharp","extensions":[".qs"],"aliases":["Q#","qsharp"]},{"id":"r","extensions":[".r",".rhistory",".rmd",".rprofile",".rt"],"aliases":["R","r"]},{"id":"razor","extensions":[".cshtml"],"aliases":["Razor","razor"],"mimetypes":["text/x-cshtml"]},{"id":"redis","extensions":[".redis"],"aliases":["redis"]},{"id":"redshift","extensions":[],"aliases":["Redshift","redshift"]},{"id":"restructuredtext","extensions":[".rst"],"aliases":["reStructuredText","restructuredtext"]},{"id":"ruby","extensions":[".rb",".rbx",".rjs",".gemspec",".pp"],"filenames":["rakefile","Gemfile"],"aliases":["Ruby","rb"]},{"id":"rust","extensions":[".rs",".rlib"],"aliases":["Rust","rust"]},{"id":"sb","extensions":[".sb"],"aliases":["Small Basic","sb"]},{"id":"scala","extensions":[".scala",".sc",".sbt"],"aliases":["Scala","scala","SBT","Sbt","sbt","Dotty","dotty"],"mimetypes":["text/x-scala-source","text/x-scala","text/x-sbt","text/x-dotty"]},{"id":"scheme","extensions":[".scm",".ss",".sch",".rkt"],"aliases":["scheme","Scheme"]},{"id":"scss","extensions":[".scss"],"aliases":["Sass","sass","scss"],"mimetypes":["text/x-scss","text/scss"]},{"id":"shell","extensions":[".sh",".bash"],"aliases":["Shell","sh"]},{"id":"sol","extensions":[".sol"],"aliases":["sol","solidity","Solidity"]},{"id":"aes","extensions":[".aes"],"aliases":["aes","sophia","Sophia"]},{"id":"sparql","extensions":[".rq"],"aliases":["sparql","SPARQL"]},{"id":"sql","extensions":[".sql"],"aliases":["SQL"]},{"id":"st","extensions":[".st",".iecst",".iecplc",".lc3lib",".TcPOU",".TcDUT",".TcGVL",".TcIO"],"aliases":["StructuredText","scl","stl"]},{"id":"swift","aliases":["Swift","swift"],"extensions":[".swift"],"mimetypes":["text/swift"]},{"id":"systemverilog","extensions":[".sv",".svh"],"aliases":["SV","sv","SystemVerilog","systemverilog"]},{"id":"verilog","extensions":[".v",".vh"],"aliases":["V","v","Verilog","verilog"]},{"id":"tcl","extensions":[".tcl"],"aliases":["tcl","Tcl","tcltk","TclTk","tcl/tk","Tcl/Tk"]},{"id":"twig","extensions":[".twig"],"aliases":["Twig","twig"],"mimetypes":["text/x-twig"]},{"id":"typescript","extensions":[".ts",".tsx",".cts",".mts"],"aliases":["TypeScript","ts","typescript"],"mimetypes":["text/typescript"]},{"id":"vb","extensions":[".vb"],"aliases":["Visual Basic","vb"]},{"id":"wgsl","extensions":[".wgsl"],"aliases":["WebGPU Shading Language","WGSL","wgsl"]},{"id":"xml","extensions":[".xml",".xsd",".dtd",".ascx",".csproj",".config",".props",".targets",".wxi",".wxl",".wxs",".xaml",".svg",".svgz",".opf",".xslt",".xsl"],"firstLine":"(\\<\\?xml.*)|(\\ public string Format(string value) { @@ -27,8 +30,7 @@ public string Format(string value) using (var jDocument = JsonDocument.Parse(value, new JsonDocumentOptions { CommentHandling = JsonCommentHandling.Skip })) { - FilePreviewJsonSerializerContext context = new(_serializerOptions); - return JsonSerializer.Serialize(jDocument, context.JsonDocument); + return JsonSerializer.Serialize(jDocument, _filePreviewJsonSerializerContext.JsonDocument); } } } diff --git a/src/common/FilePreviewCommon/MonacoHelper.cs b/src/common/FilePreviewCommon/MonacoHelper.cs index 303cacbde287..3aff51fe6ec0 100644 --- a/src/common/FilePreviewCommon/MonacoHelper.cs +++ b/src/common/FilePreviewCommon/MonacoHelper.cs @@ -38,7 +38,11 @@ private static string GetRuntimeMonacoDirectory() { string baseDirectory = AppContext.BaseDirectory ?? string.Empty; + // AppContext.BaseDirectory returns a stray \\ so we want to remove that. + baseDirectory = Path.TrimEndingDirectorySeparator(baseDirectory); + // If the executable is within "WinUI3Apps", correct the path first. + // The idea of GetFileName here is getting the last directory in the path. if (Path.GetFileName(baseDirectory) == "WinUI3Apps") { baseDirectory = Path.Combine(baseDirectory, ".."); diff --git a/src/common/GPOWrapper/GPOWrapper.cpp b/src/common/GPOWrapper/GPOWrapper.cpp index f8afd14073f2..2e6accd48681 100644 --- a/src/common/GPOWrapper/GPOWrapper.cpp +++ b/src/common/GPOWrapper/GPOWrapper.cpp @@ -128,9 +128,9 @@ namespace winrt::PowerToys::GPOWrapper::implementation { return static_cast(powertoys_gpo::getConfiguredAdvancedPasteEnabledValue()); } - GpoRuleConfigured GPOWrapper::GetConfiguredVideoConferenceMuteEnabledValue() + GpoRuleConfigured GPOWrapper::GetConfiguredZoomItEnabledValue() { - return static_cast(powertoys_gpo::getConfiguredVideoConferenceMuteEnabledValue()); + return static_cast(powertoys_gpo::getConfiguredZoomItEnabledValue()); } GpoRuleConfigured GPOWrapper::GetConfiguredMouseWithoutBordersEnabledValue() { diff --git a/src/common/GPOWrapper/GPOWrapper.h b/src/common/GPOWrapper/GPOWrapper.h index fc43ad230990..e4e55385a033 100644 --- a/src/common/GPOWrapper/GPOWrapper.h +++ b/src/common/GPOWrapper/GPOWrapper.h @@ -39,7 +39,7 @@ namespace winrt::PowerToys::GPOWrapper::implementation static GpoRuleConfigured GetConfiguredShortcutGuideEnabledValue(); static GpoRuleConfigured GetConfiguredTextExtractorEnabledValue(); static GpoRuleConfigured GetConfiguredAdvancedPasteEnabledValue(); - static GpoRuleConfigured GetConfiguredVideoConferenceMuteEnabledValue(); + static GpoRuleConfigured GetConfiguredZoomItEnabledValue(); static GpoRuleConfigured GetConfiguredPeekEnabledValue(); static GpoRuleConfigured GetDisableNewUpdateToastValue(); static GpoRuleConfigured GetDisableAutomaticUpdateDownloadValue(); diff --git a/src/common/GPOWrapper/GPOWrapper.idl b/src/common/GPOWrapper/GPOWrapper.idl index 1068896d5d93..ebacf408497c 100644 --- a/src/common/GPOWrapper/GPOWrapper.idl +++ b/src/common/GPOWrapper/GPOWrapper.idl @@ -43,7 +43,7 @@ namespace PowerToys static GpoRuleConfigured GetConfiguredShortcutGuideEnabledValue(); static GpoRuleConfigured GetConfiguredTextExtractorEnabledValue(); static GpoRuleConfigured GetConfiguredAdvancedPasteEnabledValue(); - static GpoRuleConfigured GetConfiguredVideoConferenceMuteEnabledValue(); + static GpoRuleConfigured GetConfiguredZoomItEnabledValue(); static GpoRuleConfigured GetConfiguredPeekEnabledValue(); static GpoRuleConfigured GetDisableNewUpdateToastValue(); static GpoRuleConfigured GetDisableAutomaticUpdateDownloadValue(); diff --git a/src/common/ManagedCommon/ModuleType.cs b/src/common/ManagedCommon/ModuleType.cs index 2bbc467c1e92..4e5904d15160 100644 --- a/src/common/ManagedCommon/ModuleType.cs +++ b/src/common/ManagedCommon/ModuleType.cs @@ -33,5 +33,6 @@ public enum ModuleType ShortcutGuide, PowerOCR, Workspaces, + ZoomIt, } } diff --git a/src/common/ManagedCommon/NativeMethods.cs b/src/common/ManagedCommon/NativeMethods.cs index feffafa94637..998010f10a29 100644 --- a/src/common/ManagedCommon/NativeMethods.cs +++ b/src/common/ManagedCommon/NativeMethods.cs @@ -42,6 +42,9 @@ internal static class NativeMethods [DllImport("user32.dll")] internal static extern uint SendInput(uint nInputs, INPUT[] pInputs, int cbSize); + [DllImport("dwmapi")] + internal static extern IntPtr DwmExtendFrameIntoClientArea(IntPtr hWnd, ref MARGINS pMarInset); + [StructLayout(LayoutKind.Sequential)] public struct INPUT { @@ -100,5 +103,14 @@ internal enum INPUTTYPE : uint INPUT_KEYBOARD = 1, INPUT_HARDWARE = 2, } + + [StructLayout(LayoutKind.Sequential)] + internal struct MARGINS + { + public int cxLeftWidth; + public int cxRightWidth; + public int cyTopHeight; + public int cyBottomHeight; + } } } diff --git a/src/common/Common.UI/OSVersionHelper.cs b/src/common/ManagedCommon/OSVersionHelper.cs similarity index 75% rename from src/common/Common.UI/OSVersionHelper.cs rename to src/common/ManagedCommon/OSVersionHelper.cs index aa2a2a953a4f..6a865b7ae18e 100644 --- a/src/common/Common.UI/OSVersionHelper.cs +++ b/src/common/ManagedCommon/OSVersionHelper.cs @@ -4,10 +4,15 @@ using System; -namespace Common.UI +namespace ManagedCommon { public static class OSVersionHelper { + public static bool IsWindows10() + { + return Environment.OSVersion.Version.Major >= 10 && Environment.OSVersion.Version.Minor < 22000; + } + public static bool IsWindows11() { return Environment.OSVersion.Version.Major >= 10 && Environment.OSVersion.Version.Build >= 22000; diff --git a/src/common/ManagedCommon/WindowHelpers.cs b/src/common/ManagedCommon/WindowHelpers.cs index bd9d3347229b..c5ee13f69cfd 100644 --- a/src/common/ManagedCommon/WindowHelpers.cs +++ b/src/common/ManagedCommon/WindowHelpers.cs @@ -35,5 +35,20 @@ public static void BringToForeground(IntPtr handle) } } } + + /// + /// Workaround for a WinUI bug on Windows 10 in which a window's top border is always + /// black. Calls DwmExtendFrameIntoClientArea() with a cyTopHeight of 2 to force + /// the window's top border to be visible.

+ /// Is a no-op on versions other than Windows 10. + ///
+ public static void ForceTopBorder1PixelInsetOnWindows10(IntPtr handle) + { + if (OSVersionHelper.IsWindows10()) + { + var margins = new NativeMethods.MARGINS { cxLeftWidth = 0, cxRightWidth = 0, cyBottomHeight = 0, cyTopHeight = 2 }; + NativeMethods.DwmExtendFrameIntoClientArea(handle, ref margins); + } + } } } diff --git a/src/common/SettingsAPI/settings_objects.cpp b/src/common/SettingsAPI/settings_objects.cpp index 6f3aa4c792dc..f9a72cee6244 100644 --- a/src/common/SettingsAPI/settings_objects.cpp +++ b/src/common/SettingsAPI/settings_objects.cpp @@ -331,6 +331,15 @@ namespace PowerToysSettings return static_cast(m_json.GetNamedObject(L"properties").GetNamedObject(property_name).GetNamedNumber(L"value")); } + std::optional PowerToyValues::get_uint_value(std::wstring_view property_name) const + { + if (!has_property(m_json, property_name, json::JsonValueType::Number)) + { + return std::nullopt; + } + return static_cast(m_json.GetNamedObject(L"properties").GetNamedObject(property_name).GetNamedNumber(L"value")); + } + std::optional PowerToyValues::get_string_value(std::wstring_view property_name) const { if (!has_property(m_json, property_name, json::JsonValueType::String)) diff --git a/src/common/SettingsAPI/settings_objects.h b/src/common/SettingsAPI/settings_objects.h index 1c84ac19b7d5..84b064d5af55 100644 --- a/src/common/SettingsAPI/settings_objects.h +++ b/src/common/SettingsAPI/settings_objects.h @@ -83,6 +83,7 @@ namespace PowerToysSettings std::optional get_bool_value(std::wstring_view property_name) const; std::optional get_int_value(std::wstring_view property_name) const; + std::optional get_uint_value(std::wstring_view property_name) const; std::optional get_string_value(std::wstring_view property_name) const; std::optional get_json(std::wstring_view property_name) const; json::JsonObject get_raw_json(); diff --git a/src/common/interop/CommonManaged.cpp b/src/common/interop/CommonManaged.cpp index 39ae2967b42c..d59741fef6eb 100644 --- a/src/common/interop/CommonManaged.cpp +++ b/src/common/interop/CommonManaged.cpp @@ -2,8 +2,6 @@ #include "CommonManaged.h" #include "CommonManaged.g.cpp" #include -#include "../../modules/videoconference/VideoConferenceShared/MicrophoneDevice.h" -#include "../../modules/videoconference/VideoConferenceShared/VideoCaptureDeviceList.h" namespace winrt::PowerToys::Interop::implementation { @@ -11,29 +9,4 @@ namespace winrt::PowerToys::Interop::implementation { return hstring{ get_product_version() }; } - winrt::Windows::Foundation::Collections::IVector CommonManaged::GetAllActiveMicrophoneDeviceNames() - { - auto names = std::vector(); - for (const auto& device : MicrophoneDevice::getAllActive()) - { - names.push_back(device->name().data()); - } - return winrt::multi_threaded_vector(std::move(names)); - } - winrt::Windows::Foundation::Collections::IVector CommonManaged::GetAllVideoCaptureDeviceNames() - { - auto names = std::vector(); - VideoCaptureDeviceList vcdl; - vcdl.EnumerateDevices(); - - for (UINT32 i = 0; i < vcdl.Count(); ++i) - { - auto name = vcdl.GetDeviceName(i).data(); - if (name != L"PowerToys VideoConference Mute") - { - names.push_back(name); - } - } - return winrt::multi_threaded_vector(std::move(names)); - } } diff --git a/src/common/interop/CommonManaged.h b/src/common/interop/CommonManaged.h index 96d6f5d8a549..7196699ae996 100644 --- a/src/common/interop/CommonManaged.h +++ b/src/common/interop/CommonManaged.h @@ -8,8 +8,6 @@ namespace winrt::PowerToys::Interop::implementation CommonManaged() = default; static hstring GetProductVersion(); - static winrt::Windows::Foundation::Collections::IVector GetAllActiveMicrophoneDeviceNames(); - static winrt::Windows::Foundation::Collections::IVector GetAllVideoCaptureDeviceNames(); }; } namespace winrt::PowerToys::Interop::factory_implementation diff --git a/src/common/interop/CommonManaged.idl b/src/common/interop/CommonManaged.idl index 0a523e790a52..38e9225bb529 100644 --- a/src/common/interop/CommonManaged.idl +++ b/src/common/interop/CommonManaged.idl @@ -4,8 +4,6 @@ namespace PowerToys { [default_interface] static runtimeclass CommonManaged { static String GetProductVersion(); - static Windows.Foundation.Collections.IVector GetAllActiveMicrophoneDeviceNames(); - static Windows.Foundation.Collections.IVector GetAllVideoCaptureDeviceNames(); } } } \ No newline at end of file diff --git a/src/common/interop/PowerToys.Interop.vcxproj b/src/common/interop/PowerToys.Interop.vcxproj index 88115f9eabc5..aadd8b2ebb97 100644 --- a/src/common/interop/PowerToys.Interop.vcxproj +++ b/src/common/interop/PowerToys.Interop.vcxproj @@ -93,8 +93,6 @@ - - CommonManaged.idl @@ -123,8 +121,6 @@ - - CommonManaged.idl diff --git a/src/common/interop/PowerToys.Interop.vcxproj.filters b/src/common/interop/PowerToys.Interop.vcxproj.filters index 5df4afc36889..6fa51a327571 100644 --- a/src/common/interop/PowerToys.Interop.vcxproj.filters +++ b/src/common/interop/PowerToys.Interop.vcxproj.filters @@ -21,12 +21,6 @@ Header Files - - Header Files - - - Header Files - Header Files @@ -65,12 +59,6 @@ Source Files - - Source Files - - - Source Files - Source Files diff --git a/src/common/interop/shared_constants.h b/src/common/interop/shared_constants.h index c031d5d33628..5f7f911061c4 100644 --- a/src/common/interop/shared_constants.h +++ b/src/common/interop/shared_constants.h @@ -127,6 +127,10 @@ namespace CommonSharedConstants const wchar_t SHOW_ENVIRONMENT_VARIABLES_EVENT[] = L"Local\\PowerToysEnvironmentVariables-ShowEnvironmentVariablesEvent-1021f616-e951-4d64-b231-a8f972159978"; const wchar_t SHOW_ENVIRONMENT_VARIABLES_ADMIN_EVENT[] = L"Local\\PowerToysEnvironmentVariables-EnvironmentVariablesAdminEvent-8c95d2ad-047c-49a2-9e8b-b4656326cfb2"; + // Path to the events used by ZoomIt + const wchar_t ZOOMIT_REFRESH_SETTINGS_EVENT[] = L"Local\\PowerToysZoomIt-RefreshSettingsEvent-f053a563-d519-4b0d-8152-a54489c13324"; + const wchar_t ZOOMIT_EXIT_EVENT[] = L"Local\\PowerToysZoomIt-ExitEvent-36641ce6-df02-4eac-abea-a3fbf9138220"; + // Max DWORD for key code to disable keys. const DWORD VK_DISABLED = 0x100; } diff --git a/src/common/logger/logger_settings.h b/src/common/logger/logger_settings.h index e20bc999d9c5..dab7ad64a22e 100644 --- a/src/common/logger/logger_settings.h +++ b/src/common/logger/logger_settings.h @@ -76,6 +76,7 @@ struct LogSettings inline const static std::wstring workspacesWindowArrangerLogPath = L"workspaces-window-arranger-log.txt"; inline const static std::string workspacesSnapshotToolLoggerName = "workspaces-snapshot-tool"; inline const static std::wstring workspacesSnapshotToolLogPath = L"workspaces-snapshot-tool-log.txt"; + inline const static std::string zoomItLoggerName = "zoom-it"; inline const static int retention = 30; std::wstring logLevel; LogSettings(); diff --git a/src/common/sysinternals/Eula/Eula.txt b/src/common/sysinternals/Eula/Eula.txt new file mode 100644 index 000000000000..8efa71167cc3 --- /dev/null +++ b/src/common/sysinternals/Eula/Eula.txt @@ -0,0 +1,75 @@ +Sysinternals Software License Terms +These license terms are an agreement between Sysinternals (a wholly owned subsidiary of Microsoft Corporation) and you. Please read them. They apply to the software you are downloading from technet.microsoft.com/sysinternals, which includes the media on which you received it, if any. The terms also apply to any Sysinternals +* updates, +* supplements, +* Internet-based services, +* and support services +for this software, unless other terms accompany those items. If so, those terms apply. +BY USING THE SOFTWARE, YOU ACCEPT THESE TERMS. IF YOU DO NOT ACCEPT THEM, DO NOT USE THE SOFTWARE. +If you comply with these license terms, you have the rights below. + +Installation and User Rights + +You may install and use any number of copies of the software on your devices. + +Scope of License + +The software is licensed, not sold. This agreement only gives you some rights to use the software. Sysinternals reserves all other rights. Unless applicable law gives you more rights despite this limitation, you may use the software only as expressly permitted in this agreement. In doing so, you must comply with any technical limitations in the software that only allow you to use it in certain ways. You may not +* work around any technical limitations in the software; +* reverse engineer, decompile or disassemble the software, except and only to the extent that applicable law expressly permits, despite this limitation; +* make more copies of the software than specified in this agreement or allowed by applicable law, despite this limitation; +* publish the software for others to copy; +* rent, lease or lend the software; +* transfer the software or this agreement to any third party; or +* use the software for commercial software hosting services. + +Sensitive Information + +Please be aware that, similar to other debug tools that capture “process state” information, files saved by Sysinternals tools may include personally identifiable or other sensitive information (such as usernames, passwords, paths to files accessed, and paths to registry accessed). By using this software, you acknowledge that you are aware of this and take sole responsibility for any personally identifiable or other sensitive information provided to Microsoft or any other party through your use of the software. + +Documentation + +Any person that has valid access to your computer or internal network may copy and use the documentation for your internal, reference purposes. + +Export Restrictions + +The software is subject to United States export laws and regulations. You must comply with all domestic and international export laws and regulations that apply to the software. These laws include restrictions on destinations, end users and end use. For additional information, see www.microsoft.com/exporting . + +Support Services + +Because this software is "as is," we may not provide support services for it. + +Entire Agreement + +This agreement, and the terms for supplements, updates, Internet-based services and support services that you use, are the entire agreement for the software and support services. + +Applicable Law + +United States . If you acquired the software in the United States , Washington state law governs the interpretation of this agreement and applies to claims for breach of it, regardless of conflict of laws principles. The laws of the state where you live govern all other claims, including claims under state consumer protection laws, unfair competition laws, and in tort. +Outside the United States . If you acquired the software in any other country, the laws of that country apply. + +Legal Effect + +This agreement describes certain legal rights. You may have other rights under the laws of your country. You may also have rights with respect to the party from whom you acquired the software. This agreement does not change your rights under the laws of your country if the laws of your country do not permit it to do so. + +Disclaimer of Warranty + +The software is licensed "as-is." You bear the risk of using it. Sysinternals gives no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this agreement cannot change. To the extent permitted under your local laws, sysinternals excludes the implied warranties of merchantability, fitness for a particular purpose and non-infringement. + +Limitation on and Exclusion of Remedies and Damages + +You can recover from sysinternals and its suppliers only direct damages up to U.S. $5.00. You cannot recover any other damages, including consequential, lost profits, special, indirect or incidental damages. +This limitation applies to +* anything related to the software, services, content (including code) on third party Internet sites, or third party programs; and +* claims for breach of contract, breach of warranty, guarantee or condition, strict liability, negligence, or other tort to the extent permitted by applicable law. + +It also applies even if Sysinternals knew or should have known about the possibility of the damages. The above limitation or exclusion may not apply to you because your country may not allow the exclusion or limitation of incidental, consequential or other damages. +Please note: As this software is distributed in Quebec , Canada , some of the clauses in this agreement are provided below in French. +Remarque : Ce logiciel étant distribué au Québec, Canada, certaines des clauses dans ce contrat sont fournies ci-dessous en français. +EXONÉRATION DE GARANTIE. Le logiciel visé par une licence est offert « tel quel ». Toute utilisation de ce logiciel est à votre seule risque et péril. Sysinternals n'accorde aucune autre garantie expresse. Vous pouvez bénéficier de droits additionnels en vertu du droit local sur la protection dues consommateurs, que ce contrat ne peut modifier. La ou elles sont permises par le droit locale, les garanties implicites de qualité marchande, d'adéquation à un usage particulier et d'absence de contrefaçon sont exclues. +LIMITATION DES DOMMAGES-INTÉRÊTS ET EXCLUSION DE RESPONSABILITÉ POUR LES DOMMAGES. Vous pouvez obtenir de Sysinternals et de ses fournisseurs une indemnisation en cas de dommages directs uniquement à hauteur de 5,00 $ US. Vous ne pouvez prétendre à aucune indemnisation pour les autres dommages, y compris les dommages spéciaux, indirects ou accessoires et pertes de bénéfices. +Cette limitation concerne : +tout ce qui est relié au logiciel, aux services ou au contenu (y compris le code) figurant sur des sites Internet tiers ou dans des programmes tiers ; et +les réclamations au titre de violation de contrat ou de garantie, ou au titre de responsabilité stricte, de négligence ou d'une autre faute dans la limite autorisée par la loi en vigueur. +Elle s'applique également, même si Sysinternals connaissait ou devrait connaître l'éventualité d'un tel dommage. Si votre pays n'autorise pas l'exclusion ou la limitation de responsabilité pour les dommages indirects, accessoires ou de quelque nature que ce soit, il se peut que la limitation ou l'exclusion ci-dessus ne s'appliquera pas à votre égard. +EFFET JURIDIQUE. Le présent contrat décrit certains droits juridiques. Vous pourriez avoir d'autres droits prévus par les lois de votre pays. Le présent contrat ne modifie pas les droits que vous confèrent les lois de votre pays si celles-ci ne le permettent pas. diff --git a/src/common/sysinternals/Eula/eula.c b/src/common/sysinternals/Eula/eula.c new file mode 100644 index 000000000000..eaf35e9be54c --- /dev/null +++ b/src/common/sysinternals/Eula/eula.c @@ -0,0 +1,702 @@ +#pragma once + +#pragma warning( disable: 4996) + +#include +#include +#include +#include +#include +#include +#include +#include "Eula.h" +#include "dll.h" + +#define IDC_TEXT 500 +#define IDC_PRINT 501 +#define IDC_TEXT1 502 + +static const char * EulaText[] = { +"{\\rtf1\\ansi\\ansicpg1252\\deff0\\nouicompat\\deflang1033{\\fonttbl{\\f0\\fswiss\\fprq2\\fcharset0 Tahoma;}{\\f1\\fnil\\fcharset0 Calibri;}}", +"{\\colortbl ;\\red0\\green0\\blue255;\\red0\\green0\\blue0;}", +"{\\*\\generator Riched20 10.0.10240}\\viewkind4\\uc1 ", +"\\pard\\brdrb\\brdrs\\brdrw10\\brsp20 \\sb120\\sa120\\b\\f0\\fs24 SYSINTERNALS SOFTWARE LICENSE TERMS\\fs28\\par", +"\\pard\\sb120\\sa120\\b0\\fs19 These license terms are an agreement between Sysinternals (a wholly owned subsidiary of Microsoft Corporation) and you. Please read them. They apply to the software you are downloading from Sysinternals.com, which includes the media on which you received it, if any. The terms also apply to any Sysinternals\\par", +"\\pard\\fi-363\\li720\\sb120\\sa120\\tx720\\'b7\\tab updates,\\par", +"\\pard\\fi-363\\li720\\sb120\\sa120\\'b7\\tab supplements,\\par", +"\\'b7\\tab Internet-based services, and \\par", +"\\'b7\\tab support services\\par", +"\\pard\\sb120\\sa120 for this software, unless other terms accompany those items. If so, those terms apply.\\par", +"\\b BY USING THE SOFTWARE, YOU ACCEPT THESE TERMS. IF YOU DO NOT ACCEPT THEM, DO NOT USE THE SOFTWARE.\\par", +"\\pard\\brdrt\\brdrs\\brdrw10\\brsp20 \\sb120\\sa120 If you comply with these license terms, you have the rights below.\\par", +"\\pard\\fi-357\\li357\\sb120\\sa120\\tx360\\fs20 1.\\tab\\fs19 INSTALLATION AND USE RIGHTS. \\b0 You may install and use any number of copies of the software on your devices.\\b\\par", +"\\caps\\fs20 2.\\tab\\fs19 Scope of License\\caps0 .\\b0 The software is licensed, not sold. This agreement only gives you some rights to use the software. Sysinternals reserves all other rights. Unless applicable law gives you more rights despite this limitation, you may use the software only as expressly permitted in this agreement. In doing so, you must comply with any technical limitations in the software that only allow you to use it in certain ways. You may not\\b\\par", +"\\pard\\fi-363\\li720\\sb120\\sa120\\tx720\\b0\\'b7\\tab work around any technical limitations in the binary versions of the software;\\par", +"\\pard\\fi-363\\li720\\sb120\\sa120\\'b7\\tab reverse engineer, decompile or disassemble the binary versions of the software, except and only to the extent that applicable law expressly permits, despite this limitation;\\par", +"\\'b7\\tab make more copies of the software than specified in this agreement or allowed by applicable law, despite this limitation;\\par", +"\\'b7\\tab publish the software for others to copy;\\par", +"\\'b7\\tab rent, lease or lend the software;\\par", +"\\'b7\\tab transfer the software or this agreement to any third party; or\\par", +"\\'b7\\tab use the software for commercial software hosting services.\\par", +"\\pard\\fi-357\\li357\\sb120\\sa120\\tx360\\b\\fs20 3.\\tab SENSITIVE INFORMATION. \\b0 Please be aware that, similar to other debug tools that capture \\ldblquote process state\\rdblquote information, files saved by Sysinternals tools may include personally identifiable or other sensitive information (such as usernames, passwords, paths to files accessed, and paths to registry accessed). By using this software, you acknowledge that you are aware of this and take sole responsibility for any personally identifiable or other sensitive information provided to Microsoft or any other party through your use of the software.\\b\\par", +"5. \\tab\\fs19 DOCUMENTATION.\\b0 Any person that has valid access to your computer or internal network may copy and use the documentation for your internal, reference purposes.\\b\\par", +"\\caps\\fs20 6.\\tab\\fs19 Export Restrictions\\caps0 .\\b0 The software is subject to United States export laws and regulations. You must comply with all domestic and international export laws and regulations that apply to the software. These laws include restrictions on destinations, end users and end use. For additional information, see {\\cf1\\ul{\\field{\\*\\fldinst{HYPERLINK www.microsoft.com/exporting }}{\\fldrslt{www.microsoft.com/exporting}}}}\\cf1\\ul\\f0\\fs19 <{{\\field{\\*\\fldinst{HYPERLINK \"http://www.microsoft.com/exporting\"}}{\\fldrslt{http://www.microsoft.com/exporting}}}}\\f0\\fs19 >\\cf0\\ulnone .\\b\\par", +"\\caps\\fs20 7.\\tab\\fs19 SUPPORT SERVICES.\\caps0 \\b0 Because this software is \"as is, \" we may not provide support services for it.\\b\\par", +"\\caps\\fs20 8.\\tab\\fs19 Entire Agreement.\\b0\\caps0 This agreement, and the terms for supplements, updates, Internet-based services and support services that you use, are the entire agreement for the software and support services.\\par", +"\\pard\\keepn\\fi-360\\li360\\sb120\\sa120\\tx360\\cf2\\b\\caps\\fs20 9.\\tab\\fs19 Applicable Law\\caps0 .\\par", +"\\pard\\fi-363\\li720\\sb120\\sa120\\tx720\\cf0\\fs20 a.\\tab\\fs19 United States.\\b0 If you acquired the software in the United States, Washington state law governs the interpretation of this agreement and applies to claims for breach of it, regardless of conflict of laws principles. The laws of the state where you live govern all other claims, including claims under state consumer protection laws, unfair competition laws, and in tort.\\b\\par", +"\\pard\\fi-363\\li720\\sb120\\sa120\\fs20 b.\\tab\\fs19 Outside the United States.\\b0 If you acquired the software in any other country, the laws of that country apply.\\b\\par", +"\\pard\\fi-357\\li357\\sb120\\sa120\\tx360\\caps\\fs20 10.\\tab\\fs19 Legal Effect.\\b0\\caps0 This agreement describes certain legal rights. You may have other rights under the laws of your country. You may also have rights with respect to the party from whom you acquired the software. This agreement does not change your rights under the laws of your country if the laws of your country do not permit it to do so.\\b\\caps\\par", +"\\fs20 11.\\tab\\fs19 Disclaimer of Warranty.\\caps0 \\caps The software is licensed \"as - is.\" You bear the risk of using it. SYSINTERNALS gives no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this agreement cannot change. To the extent permitted under your local laws, SYSINTERNALS excludes the implied warranties of merchantability, fitness for a particular purpose and non-infringement.\\par", +"\\pard\\fi-360\\li360\\sb120\\sa120\\tx360\\fs20 12.\\tab\\fs19 Limitation on and Exclusion of Remedies and Damages. You can recover from SYSINTERNALS and its suppliers only direct damages up to U.S. $5.00. You cannot recover any other damages, including consequential, lost profits, special, indirect or incidental damages.\\par", +"\\pard\\li357\\sb120\\sa120\\b0\\caps0 This limitation applies to\\par", +"\\pard\\fi-363\\li720\\sb120\\sa120\\tx720\\'b7\\tab anything related to the software, services, content (including code) on third party Internet sites, or third party programs; and\\par", +"\\pard\\fi-363\\li720\\sb120\\sa120\\'b7\\tab claims for breach of contract, breach of warranty, guarantee or condition, strict liability, negligence, or other tort to the extent permitted by applicable law.\\par", +"\\pard\\li360\\sb120\\sa120 It also applies even if Sysinternals knew or should have known about the possibility of the damages. The above limitation or exclusion may not apply to you because your country may not allow the exclusion or limitation of incidental, consequential or other damages.\\par", +"\\pard\\b Please note: As this software is distributed in Quebec, Canada, some of the clauses in this agreement are provided below in French.\\par", +"\\pard\\sb240\\lang1036 Remarque : Ce logiciel \\'e9tant distribu\\'e9 au Qu\\'e9bec, Canada, certaines des clauses dans ce contrat sont fournies ci-dessous en fran\\'e7ais.\\par", +"\\pard\\sb120\\sa120 EXON\\'c9RATION DE GARANTIE.\\b0 Le logiciel vis\\'e9 par une licence est offert \\'ab tel quel \\'bb. Toute utilisation de ce logiciel est \\'e0 votre seule risque et p\\'e9ril. Sysinternals n'accorde aucune autre garantie expresse. Vous pouvez b\\'e9n\\'e9ficier de droits additionnels en vertu du droit local sur la protection dues consommateurs, que ce contrat ne peut modifier. La ou elles sont permises par le droit locale, les garanties implicites de qualit\\'e9 marchande, d'ad\\'e9quation \\'e0 un usage particulier et d'absence de contrefa\\'e7on sont exclues.\\par", +"\\pard\\keepn\\sb120\\sa120\\b LIMITATION DES DOMMAGES-INT\\'c9R\\'caTS ET EXCLUSION DE RESPONSABILIT\\'c9 POUR LES DOMMAGES.\\b0 Vous pouvez obtenir de Sysinternals et de ses fournisseurs une indemnisation en cas de dommages directs uniquement \\'e0 hauteur de 5,00 $ US. Vous ne pouvez pr\\'e9tendre \\'e0 aucune indemnisation pour les autres dommages, y compris les dommages sp\\'e9ciaux, indirects ou accessoires et pertes de b\\'e9n\\'e9fices.\\par", +"\\lang1033 Cette limitation concerne :\\par", +"\\pard\\keepn\\fi-360\\li720\\sb120\\sa120\\tx720\\lang1036\\'b7\\tab tout ce qui est reli\\'e9 au logiciel, aux services ou au contenu (y compris le code) figurant sur des sites Internet tiers ou dans des programmes tiers ; et\\par", +"\\pard\\fi-363\\li720\\sb120\\sa120\\tx720\\'b7\\tab les r\\'e9clamations au titre de violation de contrat ou de garantie, ou au titre de responsabilit\\'e9 stricte, de n\\'e9gligence ou d'une autre faute dans la limite autoris\\'e9e par la loi en vigueur.\\par", +"\\pard\\sb120\\sa120 Elle s'applique \\'e9galement, m\\'eame si Sysinternals connaissait ou devrait conna\\'eetre l'\\'e9ventualit\\'e9 d'un tel dommage. Si votre pays n'autorise pas l'exclusion ou la limitation de responsabilit\\'e9 pour les dommages indirects, accessoires ou de quelque nature que ce soit, il se peut que la limitation ou l'exclusion ci-dessus ne s'appliquera pas \\'e0 votre \\'e9gard.\\par", +"\\b EFFET JURIDIQUE.\\b0 Le pr\\'e9sent contrat d\\'e9crit certains droits juridiques. Vous pourriez avoir d'autres droits pr\\'e9vus par les lois de votre pays. Le pr\\'e9sent contrat ne modifie pas les droits que vous conf\\'e8rent les lois de votre pays si celles-ci ne le permettent pas.\\b\\par", +"\\pard\\b0\\fs20\\lang1033\\par", +"\\pard\\sa200\\sl276\\slmult1\\f1\\fs22\\lang9\\par", +"}", +NULL +}; + +static const wchar_t *Raw_EulaText = L"SYSINTERNALS SOFTWARE LICENSE TERMS\nThese license terms are an agreement between Sysinternals(a wholly owned subsidiary of Microsoft Corporation) and you.Please read them.They apply to the software you are downloading from technet.microsoft.com / sysinternals, which includes the media on which you received it, if any.The terms also apply to any Sysinternals\n* updates,\n*supplements,\n*Internet - based services,\n*and support services\nfor this software, unless other terms accompany those items.If so, those terms apply.\nBY USING THE SOFTWARE, YOU ACCEPT THESE TERMS.IF YOU DO NOT ACCEPT THEM, DO NOT USE THE SOFTWARE.\n\nIf you comply with these license terms, you have the rights below.\nINSTALLATION AND USER RIGHTS\nYou may install and use any number of copies of the software on your devices.\n\nSCOPE OF LICENSE\nThe software is licensed, not sold.This agreement only gives you some rights to use the software.Sysinternals reserves all other rights.Unless applicable law gives you more rights despite this limitation, you may use the software only as expressly permitted in this agreement.In doing so, you must comply with any technical limitations in the software that only allow you to use it in certain ways.You may not\n* work around any technical limitations in the software;\n*reverse engineer, decompile or disassemble the software, except and only to the extent that applicable law expressly permits, despite this limitation;\n*make more copies of the software than specified in this agreement or allowed by applicable law, despite this limitation;\n*publish the software for others to copy;\n*rent, lease or lend the software;\n*transfer the software or this agreement to any third party; or\n* use the software for commercial software hosting services.\n\nSENSITIVE INFORMATION\nPlease be aware that, similar to other debug tools that capture “process state” information, files saved by Sysinternals tools may include personally identifiable or other sensitive information(such as usernames, passwords, paths to files accessed, and paths to registry accessed).By using this software, you acknowledge that you are aware of this and take sole responsibility for any personally identifiable or other sensitive information provided to Microsoft or any other party through your use of the software.\n\nDOCUMENTATION\nAny person that has valid access to your computer or internal network may copy and use the documentation for your internal, reference purposes.\n\nEXPORT RESTRICTIONS\nThe software is subject to United States export laws and regulations.You must comply with all domestic and international export laws and regulations that apply to the software.These laws include restrictions on destinations, end users and end use.For additional information, see www.microsoft.com / exporting .\n\nSUPPORT SERVICES\nBecause this software is \"as is, \" we may not provide support services for it.\n\nENTIRE AGREEMENT\nThis agreement, and the terms for supplements, updates, Internet - based services and support services that you use, are the entire agreement for the software and support services.\n\nAPPLICABLE LAW\nUnited States.If you acquired the software in the United States, Washington state law governs the interpretation of this agreement and applies to claims for breach of it, regardless of conflict of laws principles.The laws of the state where you live govern all other claims, including claims under state consumer protection laws, unfair competition laws, and in tort.\nOutside the United States.If you acquired the software in any other country, the laws of that country apply.\n\nLEGAL EFFECT\nThis agreement describes certain legal rights.You may have other rights under the laws of your country.You may also have rights with respect to the party from whom you acquired the software.This agreement does not change your rights under the laws of your country if the laws of your country do not permit it to do so.\n\nDISCLAIMER OF WARRANTY\nThe software is licensed \"as - is.\" You bear the risk of using it.Sysinternals gives no express warranties, guarantees or conditions.You may have additional consumer rights under your local laws which this agreement cannot change.To the extent permitted under your local laws, sysinternals excludes the implied warranties of merchantability, fitness for a particular purpose and non - infringement.\n\nLIMITATION ON AND EXCLUSION OF REMEDIES AND DAMAGES\nYou can recover from sysinternals and its suppliers only direct damages up to U.S.$5.00.You cannot recover any other damages, including consequential, lost profits, special, indirect or incidental damages.\nThis limitation applies to\n* anything related to the software, services, content(including code) on third party Internet sites, or third party programs; and\n* claims for breach of contract, breach of warranty, guarantee or condition, strict liability, negligence, or other tort to the extent permitted by applicable law.\nIt also applies even if Sysinternals knew or should have known about the possibility of the damages.The above limitation or exclusion may not apply to you because your country may not allow the exclusion or limitation of incidental, consequential or other damages.\nPlease note : As this software is distributed in Quebec, Canada, some of the clauses in this agreement are provided below in French.\nRemarque : Ce logiciel étant distribué au Québec, Canada, certaines des clauses dans ce contrat sont fournies ci - dessous en français.\n EXONÉRATION DE GARANTIE.Le logiciel visé par une licence est offert « tel quel ».Toute utilisation de ce logiciel est à votre seule risque et péril.Sysinternals n'accorde aucune autre garantie expresse. Vous pouvez bénéficier de droits additionnels en vertu du droit local sur la protection dues consommateurs, que ce contrat ne peut modifier. La ou elles sont permises par le droit locale, les garanties implicites de qualité marchande, d'adéquation à un usage particulier et d'absence de contrefaçon sont exclues.\n LIMITATION DES DOMMAGES - INTÉRÊTS ET EXCLUSION DE RESPONSABILITÉ POUR LES DOMMAGES.Vous pouvez obtenir de Sysinternals et de ses fournisseurs une indemnisation en cas de dommages directs uniquement à hauteur de 5, 00 $ US.Vous ne pouvez prétendre à aucune indemnisation pour les autres dommages, y compris les dommages spéciaux, indirects ou accessoires et pertes de bénéfices.\n\n Cette limitation concerne :\ntout ce qui est relié au logiciel, aux services ou au contenu(y compris le code) figurant sur des sites Internet tiers ou dans des programmes tiers; et\nles réclamations au titre de violation de contrat ou de garantie, ou au titre de responsabilité stricte, de négligence ou d'une autre faute dans la limite autorisée par la loi en vigueur.\n\nElle s'applique également, même si Sysinternals connaissait ou devrait connaître l'éventualité d'un tel dommage. Si votre pays n'autorise pas l'exclusion ou la limitation de responsabilité pour les dommages indirects, accessoires ou de quelque nature que ce soit, il se peut que la limitation ou l'exclusion ci - dessus ne s'appliquera pas à votre égard.\nEFFET JURIDIQUE.Le présent contrat décrit certains droits juridiques.Vous pourriez avoir d'autres droits prévus par les lois de votre pays. Le présent contrat ne modifie pas les droits que vous confèrent les lois de votre pays si celles-ci ne le permettent pas.\n\n"; + +BOOL IsEulaRegkeyAdded(const TCHAR * ToolName); + +static BOOL EulaCenter( HWND hwndChild, HWND hwndParent ) +{ + RECT rcChild, rcParent; + int cxChild, cyChild, cxParent, cyParent; + int cxScreen, cyScreen, xNew, yNew; + HDC hdc; + + // Get the Height and Width of the child window + GetWindowRect(hwndChild, &rcChild); + cxChild = rcChild.right - rcChild.left; + cyChild = rcChild.bottom - rcChild.top; + + // Get the Height and Width of the parent window + GetWindowRect(hwndParent, &rcParent); + cxParent = rcParent.right - rcParent.left; + cyParent = rcParent.bottom - rcParent.top; + + // Get the display limits + hdc = GetDC(hwndChild); + cxScreen = GetDeviceCaps(hdc, HORZRES); + cyScreen = GetDeviceCaps(hdc, VERTRES); + ReleaseDC(hwndChild, hdc); + + // Calculate new X position, then adjust for screen + xNew = rcParent.left + ((cxParent - cxChild) / 2); + if (xNew < 0) + { + xNew = 0; + } + else if ((xNew + cxChild) > cxScreen) + { + xNew = cxScreen - cxChild; + } + + // Calculate new Y position, then adjust for screen + yNew = rcParent.top + ((cyParent - cyChild) / 2); + if (yNew < 0) + { + yNew = 0; + } + else if ((yNew + cyChild) > cyScreen) + { + yNew = cyScreen - cyChild; + } + + // Set it, and return + return SetWindowPos(hwndChild, + NULL, + xNew, yNew, + 0, 0, + SWP_NOSIZE | SWP_NOZORDER); +} + + + +static BOOL PrintRichedit( HWND hRichedit ) +{ + // Get the printer. + PRINTDLG pd = { 0 }; + + pd.lStructSize = sizeof pd; + pd.hwndOwner = hRichedit; + pd.hInstance = GetModuleHandle(NULL); + pd.Flags = PD_RETURNDC | PD_NOPAGENUMS | PD_NOSELECTION | PD_PRINTSETUP; + if ( !PrintDlg( &pd ) ) + return FALSE; + + { + HCURSOR oldCursor = SetCursor( LoadCursor( NULL, IDC_WAIT ) ); + int nHorzRes = GetDeviceCaps( pd.hDC, HORZRES ); + int nVertRes = GetDeviceCaps( pd.hDC, VERTRES ); + int nLogPixelsX = GetDeviceCaps( pd.hDC, LOGPIXELSX ); + int nLogPixelsY = GetDeviceCaps( pd.hDC, LOGPIXELSY ); + FORMATRANGE fr = { 0 }; + DOCINFO di = { 0 }; + int TotalLength; + + // Ensure the printer DC is in MM_TEXT mode. + SetMapMode( pd.hDC, MM_TEXT ); + + // Rendering to the same DC we are measuring. + fr.hdc = pd.hDC; + fr.hdcTarget = pd.hDC; + + // Set up the page. + fr.rcPage.top = 0; + fr.rcPage.left = 0; + fr.rcPage.bottom = (nVertRes/nLogPixelsY) * 1440; + fr.rcPage.right = (nHorzRes/nLogPixelsX) * 1440; + + // Set up 1" margins all around. + fr.rc = fr.rcPage; + InflateRect( &fr.rc, -1440, -1440 ); + + // Default the range of text to print as the entire document. + fr.chrg.cpMin = 0; + fr.chrg.cpMax = -1; + + // Set up the print job (standard printing stuff here). + di.cbSize = sizeof di; + di.lpszDocName = _T("Sysinternals License"); + + // Start the document. + StartDoc( pd.hDC, &di ); + + // Find out real size of document in characters. + TotalLength = (int) SendMessage ( hRichedit, WM_GETTEXTLENGTH, 0, 0 ); + for (;;) { + int NextPage; + + // Start the page. + StartPage( pd.hDC ); + + // Print as much text as can fit on a page. The return value is + // the index of the first character on the next page. + NextPage = (int) SendMessage( hRichedit, EM_FORMATRANGE, TRUE, (LPARAM)&fr ); + + // Print last page. + EndPage( pd.hDC ); + + if ( NextPage >= TotalLength ) + break; + + // Adjust the range of characters to start printing at the first character of the next page. + fr.chrg.cpMin = NextPage; + fr.chrg.cpMax = -1; + } + + // Tell the control to release cached information. + SendMessage( hRichedit, EM_FORMATRANGE, 0, (LPARAM)NULL ); + EndDoc( pd.hDC ); + + SetCursor( oldCursor ); + } + + return TRUE; +} + +// combine all text strings into a single string +char * GetEulaText() +{ + char * text; + DWORD len = 1; + int i; + for ( i = 0; EulaText[i]; ++i ) + len += (DWORD) strlen( EulaText[i] ); + text = (char *) malloc( len ); + len = 0; + for ( i = 0; EulaText[i]; ++i ) { + strcpy( text+len, EulaText[i] ); + len += (DWORD) strlen( EulaText[i] ); + } + text[len] = 0; + return text; +} + +DWORD CALLBACK StreamCallback( DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG * pcb ) +{ + const char ** ptr = (const char **) dwCookie; + LONG_PTR len = strlen(*ptr); + if ( cb > len ) + cb = (int) len; + memcpy( pbBuff, *ptr, cb ); + *pcb = cb; + *ptr += cb; + return 0; +} + +static INT_PTR CALLBACK EulaProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + switch ( uMsg ) { + case WM_INITDIALOG: + { + TCHAR title[MAX_PATH]; + char * text = GetEulaText(); + char * textptr = text; + EDITSTREAM stream = { 0, 0, StreamCallback }; + stream.dwCookie = (DWORD_PTR) &textptr; + _stprintf_s( title, MAX_PATH, _T("%s License Agreement"), (TCHAR *) lParam ); + SetWindowText( hwndDlg, title ); + + // enter RTF into edit box + SendMessage( GetDlgItem(hwndDlg,IDC_TEXT), EM_EXLIMITTEXT, 0, 1024*1024 ); + SendMessage( GetDlgItem(hwndDlg,IDC_TEXT), EM_STREAMIN, SF_RTF, (LPARAM)&stream ); + free( text ); + } + return TRUE; + + case WM_CTLCOLORSTATIC: + // force background of read-only text window to be white + if ( (HWND)lParam == GetDlgItem( hwndDlg, IDC_TEXT) ) { + return (INT_PTR)GetSysColorBrush( COLOR_WINDOW ); + } + break; + + case WM_COMMAND: + switch( LOWORD( wParam )) { + case IDOK: + EndDialog( hwndDlg, TRUE ); + return TRUE; + case IDCANCEL: + EndDialog( hwndDlg, FALSE ); + return TRUE; + case IDC_PRINT: + PrintRichedit( GetDlgItem(hwndDlg,IDC_TEXT) ); + return TRUE; + } + break; + } + return FALSE; +} + + +static WORD * Align2( WORD * pos ) +{ + return (WORD *)(((DWORD_PTR)pos + 1) & ~((DWORD_PTR) 1)); +} +static WORD * Align4( WORD * pos ) +{ + return (WORD *)(((DWORD_PTR)pos + 3) & ~((DWORD_PTR) 3)); +} + +static int CopyText( WORD * pos, const WCHAR * text ) +{ + int len = (int) wcslen( text ) + 1; + wcscpy( (PWCHAR) pos, text ); + return len; +} + +BOOL ShowEulaInternal( const TCHAR * ToolName, DWORD eulaAccepted ) +{ +#if !defined(SYSMON_SHARED) + HKEY hKey = NULL; + TCHAR keyName[MAX_PATH]; + + _stprintf_s( keyName, MAX_PATH, _T("Software\\Sysinternals\\%s"), ToolName ); + + // + // check the regkey value if no -accepteula switch append + // + if (!eulaAccepted) + { + eulaAccepted = IsEulaRegkeyAdded(ToolName); + } +#endif + + if( !eulaAccepted ) { + if (IsIoTEdition()) + { + eulaAccepted = ShowEulaConsole(); // display Eula to console and prompt for Eula Accepted. + { + } + } + else if (IsRemoteOnlyEdition() || IsRunningRemotely()) // Nano and in remote session will not be able to accept eula from prompt + { + ShowEulaConsoleNoPrompt(); + } + else + { + DLGTEMPLATE * dlg = (DLGTEMPLATE *)LocalAlloc(LPTR, 1000); + WORD * extra = (WORD *)(dlg + 1); + DLGITEMTEMPLATE * item; + +#if defined(SYSMON_SHARED) + printf( "Displaying EULA Gui dialog box ... (use -accepteula to avoid).\n" ); +#endif + + LoadLibrarySafe(_T("Riched32.dll"), DLL_LOAD_LOCATION_SYSTEM ); // Richedit 1.0 library + + // header + dlg->style = DS_MODALFRAME | DS_CENTER | DS_SETFONT | WS_POPUP | WS_CAPTION | WS_SYSMENU | DS_NOFAILCREATE; + dlg->x = 0; + dlg->y = 0; + dlg->cx = 312; + dlg->cy = 180; + dlg->cdit = 0; // number of controls + + *extra++ = 0; // menu + *extra++ = 0; // class + extra += CopyText(extra, L"License Agreement"); + *extra++ = 8; // font size + extra += CopyText(extra, L"MS Shell Dlg"); + + // Command-line message + item = (DLGITEMTEMPLATE *)Align4(extra); + item->x = 7; + item->y = 3; + item->cx = 298; + item->cy = 14; + item->id = IDC_TEXT1; + item->style = WS_CHILD | WS_VISIBLE; + extra = (WORD *)(item + 1); + *extra++ = 0xFFFF; // class is ordinal + *extra++ = 0x0082; // class is static + extra += CopyText(extra, L"You can also use the /accepteula command-line switch to accept the EULA."); + *extra++ = 0; // creation data + dlg->cdit++; + + // Agree button + item = (DLGITEMTEMPLATE *)Align4(extra); + item->x = 201; + item->y = 159; + item->cx = 50; + item->cy = 14; + item->id = IDOK; + item->style = BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP; // | WS_DEFAULT; + extra = (WORD *)(item + 1); + *extra++ = 0xFFFF; // class is ordinal + *extra++ = 0x0080; // class is button + extra += CopyText(extra, L"&Agree"); + *extra++ = 0; // creation data + dlg->cdit++; + + // Decline button + item = (DLGITEMTEMPLATE *)Align4(extra); + item->x = 255; + item->y = 159; + item->cx = 50; + item->cy = 14; + item->id = IDCANCEL; + item->style = BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP; + extra = (WORD *)(item + 1); + *extra++ = 0xFFFF; // class is ordinal + *extra++ = 0x0080; // class is button + extra += CopyText(extra, L"&Decline"); + *extra++ = 0; // creation data + dlg->cdit++; + + // Print button + item = (DLGITEMTEMPLATE *)Align4(extra); + item->x = 7; + item->y = 159; + item->cx = 50; + item->cy = 14; + item->id = IDC_PRINT; + item->style = BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP; + extra = (WORD *)(item + 1); + *extra++ = 0xFFFF; // class is ordinal + *extra++ = 0x0080; // class is button + extra += CopyText(extra, L"&Print"); + *extra++ = 0; // creation data + dlg->cdit++; + + // Edit box + item = (DLGITEMTEMPLATE *)Align4(extra); + item->x = 7; + item->y = 14; + item->cx = 298; + item->cy = 140; + item->id = IDC_TEXT; + item->style = WS_BORDER | ES_MULTILINE | ES_AUTOVSCROLL | ES_WANTRETURN | WS_VSCROLL | ES_READONLY | WS_CHILD | WS_VISIBLE | WS_TABSTOP; + extra = (WORD *)(item + 1); + extra += CopyText(extra, L"RICHEDIT"); + extra += CopyText(extra, L"&Decline"); + *extra++ = 0; // creation data + dlg->cdit++; + + eulaAccepted = (DWORD)DialogBoxIndirectParam(NULL, dlg, NULL, EulaProc, (LPARAM)ToolName); + LocalFree(dlg); + } + } +#if !defined(SYSMON_SHARED) + if ( eulaAccepted ) { + if (RegCreateKey(HKEY_CURRENT_USER, keyName, &hKey) == ERROR_SUCCESS) { + RegSetValueEx(hKey, _T("EulaAccepted"), 0, REG_DWORD, (BYTE *)&eulaAccepted, sizeof(eulaAccepted)); + RegCloseKey(hKey); + } + } +#endif + + return eulaAccepted != 0; +} + +BOOL ShowEulaW( const TCHAR * ToolName, int *argc, PWCHAR argv[] ) +{ + DWORD eulaAccepted = 0; + int i; + + if ( argc == NULL || argv == NULL ) { + typedef LPWSTR * (WINAPI * type_CommandLineToArgvW)( LPCWSTR lpCmdLine, int *pNumArgs ); + type_CommandLineToArgvW pCommandLineToArgvW = (type_CommandLineToArgvW) GetProcAddress( LoadLibrarySafe(_T("Shell32.dll"), DLL_LOAD_LOCATION_SYSTEM), "CommandLineToArgvW" ); + if ( pCommandLineToArgvW ) { + static int argc2; + argc = &argc2; + argv = (*pCommandLineToArgvW)( GetCommandLineW(), argc ); + } else { + argc = NULL; + } + } + + + // + // See if its accepted via command line switch + // + if( argc ) { + + for( i = 0; i < *argc; i++ ) { + + eulaAccepted = (!_wcsicmp( argv[i], L"/accepteula") || + !_wcsicmp( argv[i], L"-accepteula")); + if( eulaAccepted ) { + + for( ; i < *argc - 1; i++ ) { + + argv[i] = argv[i+1]; + } + (*argc)--; + break; + } + } + } + if( ShowEulaInternal( ToolName, eulaAccepted )) { + + eulaAccepted = 1; + } + return eulaAccepted != 0; +} + + +BOOL ShowEula( const TCHAR * ToolName, int *argc, PTCHAR argv[] ) +{ + DWORD eulaAccepted = 0; + int i; + + if ( argc == NULL || argv == NULL ) { + return ShowEulaW( ToolName, NULL, NULL ); + } + + // + // See if its accepted via command line switch + // + if( argc ) { + + for( i = 0; i < *argc; i++ ) { + + eulaAccepted = (!_tcsicmp( argv[i], _T("/accepteula")) || + !_tcsicmp( argv[i], _T("-accepteula"))); + if( eulaAccepted ) { + + for( ; i < *argc - 1; i++ ) { + + argv[i] = argv[i+1]; + } + (*argc)--; + break; + } + } + } + if( ShowEulaInternal( ToolName, eulaAccepted )) { + + eulaAccepted = 1; + } + return eulaAccepted != 0; +} + +// Determine whether we are on the IoT SKU by looking at the ProductName. +BOOL IsIoTEdition() +{ + HKEY hKey = NULL; + wchar_t ProductName[MAX_PATH]; + BOOL bRet = FALSE; // assume "not" IoT Edition + DWORD dwSize = sizeof(ProductName); + DWORD type = 0; + + if (ERROR_SUCCESS == RegOpenKey(HKEY_LOCAL_MACHINE, _T("Software\\Microsoft\\windows nt\\currentversion"), &hKey)) + { + if (ERROR_SUCCESS == RegQueryValueExW(hKey, L"ProductName", 0, &type, (LPBYTE)ProductName, &dwSize)) + { + if (!_wcsicmp(L"iotuap", ProductName)) + bRet = TRUE; + } + RegCloseKey(hKey); + } + + return bRet; +} + +// Determine whether we are on the remote only edition, where we cannot prompt for user input. +BOOL IsRemoteOnlyEdition() +{ + HKEY hKey = NULL; + DWORD dwNanoServer = 0; + BOOL bRet = FALSE; + DWORD dwSize = sizeof(dwNanoServer); + DWORD type = 0; + + // Currently Nano is the only remote only edtion. + if (ERROR_SUCCESS == RegOpenKey(HKEY_LOCAL_MACHINE, _T("Software\\Microsoft\\Windows NT\\CurrentVersion\\Server\\ServerLevels"), &hKey)) + { + if (ERROR_SUCCESS == RegQueryValueEx(hKey, _T("NanoServer"), 0, &type, (LPBYTE)&dwNanoServer, &dwSize)) + { + if (type == REG_DWORD && dwNanoServer == 1) + bRet = TRUE; + } + RegCloseKey(hKey); + } + + return bRet; +} + +BOOL IsRunningRemotely() +{ + // running from a remote session will not support input interaction + DWORD fileType = GetFileType(GetStdHandle(STD_OUTPUT_HANDLE)); + return fileType == FILE_TYPE_PIPE; +} + +DWORD ShowEulaConsole() +{ + DWORD dwRet = 0; + char ch; + BOOLEAN eulaAcknowledged = FALSE; + + wprintf(Raw_EulaText); + + while( eulaAcknowledged != TRUE ) + { + printf("Accept Eula (Y/N)?"); + ch = (char) _getch(); + printf("%c\n", ch); + if ('y' == ch || 'Y' == ch) + { + dwRet = 1; // EULA Accepted. + eulaAcknowledged = TRUE; + } + + if ('n' == ch || 'N' == ch) + { + // EULA not accepted. + eulaAcknowledged = TRUE; + } + } + return dwRet; +} + +void ShowEulaConsoleNoPrompt() +{ + wprintf_s(L"%ls", Raw_EulaText); + wprintf_s(L"This is the first run of this program. You must accept EULA to continue.\n"); + wprintf_s(L"Use -accepteula to accept EULA.\n\n"); + + // exit here to avoid printing the misleading "Eula declined". + exit(1); +} + +BOOL IsEulaAcceptedValueExist(HKEY hKeyRoot, LPCTSTR lpSubKey) +{ + HKEY hKey = NULL; + DWORD length; + DWORD eulaAccepted = 0; + DWORD ret; + + // + // check if it is set by external channel for all tools + // assuming external channel do not set to WOW6432Node + // + if (RegOpenKeyEx(hKeyRoot, lpSubKey, 0, KEY_QUERY_VALUE | KEY_WOW64_64KEY, &hKey) == ERROR_SUCCESS) + { + length = sizeof(eulaAccepted); + ret = RegQueryValueEx(hKey, _T("EulaAccepted"), NULL, NULL, (LPBYTE)&eulaAccepted, &length); + RegCloseKey(hKey); + + if (ret == ERROR_SUCCESS && eulaAccepted) + { + return TRUE; + } + } + + return FALSE; +} + +BOOL IsEulaRegkeyAdded(const TCHAR * ToolName) +{ + TCHAR perToolRegKey[MAX_PATH]; + PTCHAR suiteRegKey = _T("Software\\Sysinternals"); + + _stprintf_s(perToolRegKey, MAX_PATH, _T("%s\\%s"), suiteRegKey, ToolName); + + // + // check if it is set by external channel for all tools + // assuming external channel do not set to WOW6432Node + // + if (IsEulaAcceptedValueExist(HKEY_LOCAL_MACHINE, suiteRegKey) || + IsEulaAcceptedValueExist(HKEY_CURRENT_USER, suiteRegKey)) + { + return TRUE; + } + + // + // per tool check + // + if (IsEulaAcceptedValueExist(HKEY_CURRENT_USER, perToolRegKey)) + { + return TRUE; + } + + return FALSE; +} + +BOOL IsEulaSwitchAppended(int *argc, PTCHAR argv[]) +{ + DWORD eulaAccepted = 0; + int i; + + // + // See if its accepted via command line switch + // + if (*argc > 1) { + for (i = 1; i < *argc; i++) { + eulaAccepted = (!_tcsicmp(argv[i], _T("/accepteula")) || + !_tcsicmp(argv[i], _T("-accepteula"))); + if (eulaAccepted) { + break; + } + } + } + + return eulaAccepted; +} + +// +// Determine if Eula is accepted, either already have regkey added +// or have -accepteula switch appended +// +BOOL IsEulaAccepted(const TCHAR * ToolName, int *argc, PTCHAR argv[]) +{ + return IsEulaRegkeyAdded(ToolName) || IsEulaSwitchAppended(argc, argv); +} diff --git a/src/common/sysinternals/Eula/eula.h b/src/common/sysinternals/Eula/eula.h new file mode 100644 index 000000000000..450031583e95 --- /dev/null +++ b/src/common/sysinternals/Eula/eula.h @@ -0,0 +1,17 @@ +#ifdef __cplusplus +extern "C" { +#endif + + +BOOL ShowEulaW( const TCHAR * ToolName, int *argc, PWCHAR argv[] ); +BOOL ShowEula( const TCHAR * ToolName, int *argc, TCHAR *argv[] ); +DWORD ShowEulaConsole(); +void ShowEulaConsoleNoPrompt(); +BOOL IsIoTEdition(); +BOOL IsRemoteOnlyEdition(); +BOOL IsRunningRemotely(); +BOOL IsEulaAccepted(const TCHAR * ToolName, int *argc, PTCHAR argv[]); + +#ifdef __cplusplus +} +#endif diff --git a/src/common/sysinternals/Eula/eula.rtf b/src/common/sysinternals/Eula/eula.rtf new file mode 100644 index 000000000000..4f8c495bf30d --- /dev/null +++ b/src/common/sysinternals/Eula/eula.rtf @@ -0,0 +1,76 @@ +{\rtf1\ansi\ansicpg1252\deff0\nouicompat\deflang1033{\fonttbl{\f0\fswiss\fprq2\fcharset0 Tahoma;}{\f1\fnil\fcharset0 Calibri;}} +{\colortbl ;\red0\green0\blue255;\red0\green0\blue0;} +{\*\generator Riched20 10.0.10240}\viewkind4\uc1 +\pard\brdrb\brdrs\brdrw10\brsp20 \sb120\sa120\b\f0\fs24 SYSINTERNALS SOFTWARE LICENSE TERMS\fs28\par + +\pard\sb120\sa120\b0\fs19 These license terms are an agreement between Sysinternals (a wholly owned subsidiary of Microsoft Corporation) and you. Please read them. They apply to the software you are downloading from Sysinternals.com, which includes the media on which you received it, if any. The terms also apply to any Sysinternals\par + +\pard\fi-363\li720\sb120\sa120\tx720\'b7\tab updates,\par + +\pard\fi-363\li720\sb120\sa120\'b7\tab supplements,\par +\'b7\tab Internet-based services, and \par +\'b7\tab support services\par + +\pard\sb120\sa120 for this software, unless other terms accompany those items. If so, those terms apply.\par +\b BY USING THE SOFTWARE, YOU ACCEPT THESE TERMS. IF YOU DO NOT ACCEPT THEM, DO NOT USE THE SOFTWARE.\par + +\pard\brdrt\brdrs\brdrw10\brsp20 \sb120\sa120 If you comply with these license terms, you have the rights below.\par + +\pard\fi-357\li357\sb120\sa120\tx360\fs20 1.\tab\fs19 INSTALLATION AND USE RIGHTS. \b0 You may install and use any number of copies of the software on your devices.\b\par +\caps\fs20 2.\tab\fs19 Scope of License\caps0 .\b0 The software is licensed, not sold. This agreement only gives you some rights to use the software. Sysinternals reserves all other rights. Unless applicable law gives you more rights despite this limitation, you may use the software only as expressly permitted in this agreement. In doing so, you must comply with any technical limitations in the software that only allow you to use it in certain ways. You may not\b\par + +\pard\fi-363\li720\sb120\sa120\tx720\b0\'b7\tab work around any technical limitations in the binary versions of the software;\par + +\pard\fi-363\li720\sb120\sa120\'b7\tab reverse engineer, decompile or disassemble the binary versions of the software, except and only to the extent that applicable law expressly permits, despite this limitation;\par +\'b7\tab make more copies of the software than specified in this agreement or allowed by applicable law, despite this limitation;\par +\'b7\tab publish the software for others to copy;\par +\'b7\tab rent, lease or lend the software;\par +\'b7\tab transfer the software or this agreement to any third party; or\par +\'b7\tab use the software for commercial software hosting services.\par + +\pard\fi-357\li357\sb120\sa120\tx360\b\fs20 3.\tab SENSITIVE INFORMATION. \b0 Please be aware that, similar to other debug tools that capture \ldblquote process state\rdblquote information, files saved by Sysinternals tools may include personally identifiable or other sensitive information (such as usernames, passwords, paths to files accessed, and paths to registry accessed). By using this software, you acknowledge that you are aware of this and take sole responsibility for any personally identifiable or other sensitive information provided to Microsoft or any other party through your use of the software.\b\par +5. \tab\fs19 DOCUMENTATION.\b0 Any person that has valid access to your computer or internal network may copy and use the documentation for your internal, reference purposes.\b\par +\caps\fs20 6.\tab\fs19 Export Restrictions\caps0 .\b0 The software is subject to United States export laws and regulations. You must comply with all domestic and international export laws and regulations that apply to the software. These laws include restrictions on destinations, end users and end use. For additional information, see {\cf1\ul{\field{\*\fldinst{HYPERLINK www.microsoft.com/exporting }}{\fldrslt{www.microsoft.com/exporting}}}}\cf1\ul\f0\fs19 <{{\field{\*\fldinst{HYPERLINK "http://www.microsoft.com/exporting"}}{\fldrslt{http://www.microsoft.com/exporting}}}}\f0\fs19 >\cf0\ulnone .\b\par +\caps\fs20 7.\tab\fs19 SUPPORT SERVICES.\caps0 \b0 Because this software is "as is," we may not provide support services for it.\b\par +\caps\fs20 8.\tab\fs19 Entire Agreement.\b0\caps0 This agreement, and the terms for supplements, updates, Internet-based services and support services that you use, are the entire agreement for the software and support services.\par + +\pard\keepn\fi-360\li360\sb120\sa120\tx360\cf2\b\caps\fs20 9.\tab\fs19 Applicable Law\caps0 .\par + +\pard\fi-363\li720\sb120\sa120\tx720\cf0\fs20 a.\tab\fs19 United States.\b0 If you acquired the software in the United States, Washington state law governs the interpretation of this agreement and applies to claims for breach of it, regardless of conflict of laws principles. The laws of the state where you live govern all other claims, including claims under state consumer protection laws, unfair competition laws, and in tort.\b\par + +\pard\fi-363\li720\sb120\sa120\fs20 b.\tab\fs19 Outside the United States.\b0 If you acquired the software in any other country, the laws of that country apply.\b\par + +\pard\fi-357\li357\sb120\sa120\tx360\caps\fs20 10.\tab\fs19 Legal Effect.\b0\caps0 This agreement describes certain legal rights. You may have other rights under the laws of your country. You may also have rights with respect to the party from whom you acquired the software. This agreement does not change your rights under the laws of your country if the laws of your country do not permit it to do so.\b\caps\par +\fs20 11.\tab\fs19 Disclaimer of Warranty.\caps0 \caps The software is licensed "as-is." You bear the risk of using it. SYSINTERNALS gives no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this agreement cannot change. To the extent permitted under your local laws, SYSINTERNALS excludes the implied warranties of merchantability, fitness for a particular purpose and non-infringement.\par + +\pard\fi-360\li360\sb120\sa120\tx360\fs20 12.\tab\fs19 Limitation on and Exclusion of Remedies and Damages. You can recover from SYSINTERNALS and its suppliers only direct damages up to U.S. $5.00. You cannot recover any other damages, including consequential, lost profits, special, indirect or incidental damages.\par + +\pard\li357\sb120\sa120\b0\caps0 This limitation applies to\par + +\pard\fi-363\li720\sb120\sa120\tx720\'b7\tab anything related to the software, services, content (including code) on third party Internet sites, or third party programs; and\par + +\pard\fi-363\li720\sb120\sa120\'b7\tab claims for breach of contract, breach of warranty, guarantee or condition, strict liability, negligence, or other tort to the extent permitted by applicable law.\par + +\pard\li360\sb120\sa120 It also applies even if Sysinternals knew or should have known about the possibility of the damages. The above limitation or exclusion may not apply to you because your country may not allow the exclusion or limitation of incidental, consequential or other damages.\par + +\pard\b Please note: As this software is distributed in Quebec, Canada, some of the clauses in this agreement are provided below in French.\par + +\pard\sb240\lang1036 Remarque : Ce logiciel \'e9tant distribu\'e9 au Qu\'e9bec, Canada, certaines des clauses dans ce contrat sont fournies ci-dessous en fran\'e7ais.\par + +\pard\sb120\sa120 EXON\'c9RATION DE GARANTIE.\b0 Le logiciel vis\'e9 par une licence est offert \'ab tel quel \'bb. Toute utilisation de ce logiciel est \'e0 votre seule risque et p\'e9ril. Sysinternals n'accorde aucune autre garantie expresse. Vous pouvez b\'e9n\'e9ficier de droits additionnels en vertu du droit local sur la protection dues consommateurs, que ce contrat ne peut modifier. La ou elles sont permises par le droit locale, les garanties implicites de qualit\'e9 marchande, d'ad\'e9quation \'e0 un usage particulier et d'absence de contrefa\'e7on sont exclues.\par + +\pard\keepn\sb120\sa120\b LIMITATION DES DOMMAGES-INT\'c9R\'caTS ET EXCLUSION DE RESPONSABILIT\'c9 POUR LES DOMMAGES.\b0 Vous pouvez obtenir de Sysinternals et de ses fournisseurs une indemnisation en cas de dommages directs uniquement \'e0 hauteur de 5,00 $ US. Vous ne pouvez pr\'e9tendre \'e0 aucune indemnisation pour les autres dommages, y compris les dommages sp\'e9ciaux, indirects ou accessoires et pertes de b\'e9n\'e9fices.\par +\lang1033 Cette limitation concerne :\par + +\pard\keepn\fi-360\li720\sb120\sa120\tx720\lang1036\'b7\tab tout ce qui est reli\'e9 au logiciel, aux services ou au contenu (y compris le code) figurant sur des sites Internet tiers ou dans des programmes tiers ; et\par + +\pard\fi-363\li720\sb120\sa120\tx720\'b7\tab les r\'e9clamations au titre de violation de contrat ou de garantie, ou au titre de responsabilit\'e9 stricte, de n\'e9gligence ou d'une autre faute dans la limite autoris\'e9e par la loi en vigueur.\par + +\pard\sb120\sa120 Elle s'applique \'e9galement, m\'eame si Sysinternals connaissait ou devrait conna\'eetre l'\'e9ventualit\'e9 d'un tel dommage. Si votre pays n'autorise pas l'exclusion ou la limitation de responsabilit\'e9 pour les dommages indirects, accessoires ou de quelque nature que ce soit, il se peut que la limitation ou l'exclusion ci-dessus ne s'appliquera pas \'e0 votre \'e9gard.\par +\b EFFET JURIDIQUE.\b0 Le pr\'e9sent contrat d\'e9crit certains droits juridiques. Vous pourriez avoir d'autres droits pr\'e9vus par les lois de votre pays. Le pr\'e9sent contrat ne modifie pas les droits que vous conf\'e8rent les lois de votre pays si celles-ci ne le permettent pas.\b\par + +\pard\b0\fs20\lang1033\par + +\pard\sa200\sl276\slmult1\f1\fs22\lang9\par +} + \ No newline at end of file diff --git a/src/common/sysinternals/WindowsVersions.cpp b/src/common/sysinternals/WindowsVersions.cpp new file mode 100644 index 000000000000..6b12d86d2a80 --- /dev/null +++ b/src/common/sysinternals/WindowsVersions.cpp @@ -0,0 +1,24 @@ +#include + +#include "WindowsVersions.h" + +// Declared in wdm.h +typedef NTSYSAPI NTSTATUS (NTAPI *RtlGetVersionType)( PRTL_OSVERSIONINFOW ); + +DWORD GetWindowsBuild( DWORD* revision ) +{ + if( revision ) { + + DWORD size = sizeof( *revision ); + if( RegGetValueW( HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", L"UBR", RRF_RT_REG_DWORD, NULL, revision, &size ) != ERROR_SUCCESS ) { + + *revision = 0; + } + } + + RtlGetVersionType pRtlGetVersion = reinterpret_cast(GetProcAddress( GetModuleHandleW( L"ntdll.dll" ), "RtlGetVersion" )); + + RTL_OSVERSIONINFOW version; + pRtlGetVersion( &version ); + return version.dwBuildNumber; +} diff --git a/src/common/sysinternals/WindowsVersions.h b/src/common/sysinternals/WindowsVersions.h new file mode 100644 index 000000000000..de06ab7e562f --- /dev/null +++ b/src/common/sysinternals/WindowsVersions.h @@ -0,0 +1,32 @@ +//---------------------------------------------------------------------- +// +// WindowsVersions.h +// +// Provides helpers for Windows builds and versions. +// +//---------------------------------------------------------------------- + +#pragma once + +#define BUILD_WINDOWS_SERVER_2008 6003 +#define BUILD_WINDOWS_SERVER_2008_R2 7601 +#define BUILD_WINDOWS_SERVER_2012 9200 +#define BUILD_WINDOWS_8_1 9600 +#define BUILD_WINDOWS_SERVER_2012_R2 9600 +#define BUILD_WINDOWS_10_1507 10240 +#define BUILD_WINDOWS_10_1607 14393 +#define BUILD_WINDOWS_SERVER_2016 14393 +#define BUILD_WINDOWS_10_1809 17763 +#define BUILD_WINDOWS_SERVER_2019 17763 +#define BUILD_WINDOWS_10_1903 18362 +#define BUILD_WINDOWS_10_1909 18363 +#define BUILD_WINDOWS_10_2004 19041 +#define BUILD_WINDOWS_10_20H2 19042 +#define BUILD_WINDOWS_SERVER_20H2 19042 +#define BUILD_WINDOWS_10_21H1 19043 +#define BUILD_WINDOWS_10_21H2 19044 +#define BUILD_WINDOWS_SERVER_2022 20348 +#define BUILD_WINDOWS_11_21H2 22000 +#define BUILD_WINDOWS_11_22H2 22621 + +DWORD GetWindowsBuild( DWORD* revision ); diff --git a/src/common/sysinternals/dll.c b/src/common/sysinternals/dll.c new file mode 100644 index 000000000000..8498db813c18 --- /dev/null +++ b/src/common/sysinternals/dll.c @@ -0,0 +1,74 @@ +//=========================================================================-== +// +// dll.c +// +// DLL support functions +// +//============================================================================ + +#include +#include +#include +#include +#include "dll.h" + +#ifndef LOAD_LIBRARY_SEARCH_SYSTEM32 + #define LOAD_LIBRARY_SEARCH_SYSTEM32 0x800 +#endif + + +//=========================================================================-== +// +// ExtendedFlagsSupported +// +// Returns TRUE if running on Windows 7 or later and FALSE otherwise +// +//============================================================================ +static BOOLEAN ExtendedFlagsSupported() +{ + OSVERSIONINFO osInfo; + BOOLEAN rc = FALSE; + + ZeroMemory(&osInfo, sizeof(OSVERSIONINFO)); + osInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + +#pragma warning ( disable : 4996 ) // deprecated in favour of version helper functions which we can't use + + if (GetVersionEx(&osInfo) && (osInfo.dwMajorVersion > 6 || (osInfo.dwMajorVersion == 6 && osInfo.dwMinorVersion > 0))) + rc = TRUE; + +#pragma warning ( default : 4996 ) + + return rc; +} + +//=========================================================================-== +// +// LoadLibrarySafe +// +// Loads a DLL from the system folder in a way that mitigates DLL spoofing / +// side-loading attacks +// +//============================================================================ +HMODULE LoadLibrarySafe(LPCTSTR libraryName, DLL_LOAD_LOCATION location) +{ + HMODULE hMod = NULL; + + if (NULL == libraryName || location <= DLL_LOAD_LOCATION_MIN || location >= DLL_LOAD_LOCATION_MAX) { + + SetLastError(ERROR_INVALID_PARAMETER); + return NULL; + } + + // LOAD_LIBRARY_SEARCH_SYSTEM32 is only supported on Window 7 or later. On earlier SKUs we could use a fully + // qualified path to the system folder but specifying a path causes Ldr to skip SxS file redirection. This can + // cause the wrong library to be loaded if the application is using a manifest that defines a specific version + // of Microsoft.Windows.Common-Controls when loading comctl32.dll + if (DLL_LOAD_LOCATION_SYSTEM == location) { + + DWORD flags = ExtendedFlagsSupported() ? LOAD_LIBRARY_SEARCH_SYSTEM32 : 0; + hMod = LoadLibraryEx(libraryName, NULL, flags); + } + + return hMod; +} diff --git a/src/common/sysinternals/dll.h b/src/common/sysinternals/dll.h new file mode 100644 index 000000000000..80c60a72ca07 --- /dev/null +++ b/src/common/sysinternals/dll.h @@ -0,0 +1,26 @@ +//=========================================================================-== +// +// dll.h +// +// DLL support functions +// +//============================================================================ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + + typedef enum + { + DLL_LOAD_LOCATION_MIN = 0, + DLL_LOAD_LOCATION_SYSTEM = 1, + DLL_LOAD_LOCATION_MAX + } DLL_LOAD_LOCATION, *PDLL_LOAD_LOCATION; + + HMODULE LoadLibrarySafe(LPCTSTR libraryName, DLL_LOAD_LOCATION location); + +#ifdef __cplusplus +} +#endif + diff --git a/src/common/utils/clean_video_conference.h b/src/common/utils/clean_video_conference.h new file mode 100644 index 000000000000..f90a3ad1ee2b --- /dev/null +++ b/src/common/utils/clean_video_conference.h @@ -0,0 +1,18 @@ +#pragma once + +// Video Conference Mute was a utility we deprecated. However, this required a manual user disable of the module to remove the camera registration, so we include the disable code here to be able to clean up. +void clean_video_conference() +{ + // 31AD75E9-8C3A-49C8-B9ED-5880D6B4A764 is the CLSID GUID for the 64 video conference mute driver. + // 31AD75E9-8C3A-49C8-B9ED-5880D6B4A732 is the CLSID GUID for the 32 video conference mute driver. + // 860BB310-5D01-11D0-BD3B-00A0C911CE86 is the CLSID GUID for CLSID_VideoInputDeviceCategory. + + // Unregister the 64 bit driver CLSID: + RegDeleteTreeW(HKEY_CLASSES_ROOT, L"CLSID\\{31AD75E9-8C3A-49C8-B9ED-5880D6B4A764}"); + // Unregister the 64 bit driver CLSID from Video Input Devices: + RegDeleteTreeW(HKEY_CLASSES_ROOT, L"CLSID\\{860BB310-5D01-11D0-BD3B-00A0C911CE86}\\Instance\\{31AD75E9-8C3A-49C8-B9ED-5880D6B4A764}"); + // Unregister the 32 bit driver CLSID: + RegDeleteTreeW(HKEY_LOCAL_MACHINE, L"Software\\WOW6432Node\\Classes\\CLSID\\{31AD75E9-8C3A-49C8-B9ED-5880D6B4A732}"); + // Unregister the 32 bit driver CLSID from Video Input Devices: + RegDeleteTreeW(HKEY_LOCAL_MACHINE, L"Software\\WOW6432Node\\Classes\\CLSID\\{860BB310-5D01-11D0-BD3B-00A0C911CE86}\\Instance\\{31AD75E9-8C3A-49C8-B9ED-5880D6B4A732}"); +} diff --git a/src/common/utils/gpo.h b/src/common/utils/gpo.h index 886c4682221f..e0ac054a5ba9 100644 --- a/src/common/utils/gpo.h +++ b/src/common/utils/gpo.h @@ -54,7 +54,7 @@ namespace powertoys_gpo { const std::wstring POLICY_CONFIGURE_ENABLED_SHORTCUT_GUIDE = L"ConfigureEnabledUtilityShortcutGuide"; const std::wstring POLICY_CONFIGURE_ENABLED_TEXT_EXTRACTOR = L"ConfigureEnabledUtilityTextExtractor"; const std::wstring POLICY_CONFIGURE_ENABLED_ADVANCED_PASTE = L"ConfigureEnabledUtilityAdvancedPaste"; - const std::wstring POLICY_CONFIGURE_ENABLED_VIDEO_CONFERENCE_MUTE = L"ConfigureEnabledUtilityVideoConferenceMute"; + const std::wstring POLICY_CONFIGURE_ENABLED_ZOOM_IT = L"ConfigureEnabledUtilityZoomIt"; const std::wstring POLICY_CONFIGURE_ENABLED_REGISTRY_PREVIEW = L"ConfigureEnabledUtilityRegistryPreview"; const std::wstring POLICY_CONFIGURE_ENABLED_MOUSE_WITHOUT_BORDERS = L"ConfigureEnabledUtilityMouseWithoutBorders"; const std::wstring POLICY_CONFIGURE_ENABLED_PEEK = L"ConfigureEnabledUtilityPeek"; @@ -420,9 +420,9 @@ namespace powertoys_gpo { return getUtilityEnabledValue(POLICY_CONFIGURE_ENABLED_WORKSPACES); } - inline gpo_rule_configured_t getConfiguredVideoConferenceMuteEnabledValue() + inline gpo_rule_configured_t getConfiguredZoomItEnabledValue() { - return getUtilityEnabledValue(POLICY_CONFIGURE_ENABLED_VIDEO_CONFERENCE_MUTE); + return getUtilityEnabledValue(POLICY_CONFIGURE_ENABLED_ZOOM_IT); } inline gpo_rule_configured_t getConfiguredMouseWithoutBordersEnabledValue() diff --git a/src/common/version/version.vcxproj b/src/common/version/version.vcxproj index f6ad515137eb..b045d8f5a58d 100644 --- a/src/common/version/version.vcxproj +++ b/src/common/version/version.vcxproj @@ -10,7 +10,7 @@ - + Debug diff --git a/src/dsc/Microsoft.PowerToys.Configure/examples/disableAllModules.dsc.yaml b/src/dsc/Microsoft.PowerToys.Configure/examples/disableAllModules.dsc.yaml index 5324df75ea0d..92986e81071e 100644 --- a/src/dsc/Microsoft.PowerToys.Configure/examples/disableAllModules.dsc.yaml +++ b/src/dsc/Microsoft.PowerToys.Configure/examples/disableAllModules.dsc.yaml @@ -63,8 +63,6 @@ properties: Enabled: false ShortcutGuide: Enabled: false - VideoConference: - Enabled: false MeasureTool: Enabled: false Hosts: diff --git a/src/dsc/Microsoft.PowerToys.Configure/examples/enableAllModules.dsc.yaml b/src/dsc/Microsoft.PowerToys.Configure/examples/enableAllModules.dsc.yaml index 5fa895ddfd32..5ff4dcfe7192 100644 --- a/src/dsc/Microsoft.PowerToys.Configure/examples/enableAllModules.dsc.yaml +++ b/src/dsc/Microsoft.PowerToys.Configure/examples/enableAllModules.dsc.yaml @@ -63,8 +63,6 @@ properties: Enabled: true ShortcutGuide: Enabled: true - VideoConference: - Enabled: true MeasureTool: Enabled: true Hosts: diff --git a/src/gpo/assets/PowerToys.admx b/src/gpo/assets/PowerToys.admx index 68c6f24b58c1..7e870ec70699 100644 --- a/src/gpo/assets/PowerToys.admx +++ b/src/gpo/assets/PowerToys.admx @@ -1,11 +1,11 @@ - + - + @@ -24,6 +24,7 @@ + @@ -46,6 +47,9 @@ + + + @@ -452,8 +456,18 @@ + + + + + + + + + + - + diff --git a/src/gpo/assets/en-US/PowerToys.adml b/src/gpo/assets/en-US/PowerToys.adml index e16a0e3fba3a..19459ee284a0 100644 --- a/src/gpo/assets/en-US/PowerToys.adml +++ b/src/gpo/assets/en-US/PowerToys.adml @@ -1,7 +1,7 @@ - + PowerToys PowerToys @@ -13,6 +13,7 @@ Mouse Without Borders General settings New+ + Deprecated policies PowerToys version 0.64.0 or later PowerToys version 0.68.0 or later @@ -30,6 +31,7 @@ PowerToys version 0.85.0 or later PowerToys version 0.86.0 or later PowerToys version 0.88.0 or later + From PowerToys version 0.64.0 until PowerToys version 0.87.1 This policy configures the enabled state for all PowerToys utilities. @@ -247,6 +249,7 @@ If you don't configure this policy, the user takes control over the setting and Shortcut Guide: Configure enabled state Text Extractor: Configure enabled state Video Conference Mute: Configure enabled state + Zoom It: Configure enabled state Disable per-user installation Disable automatic downloads Do not show the release notes after updates diff --git a/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/Controls/PasteFormatTemplateSelector.cs b/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/Controls/PasteFormatTemplateSelector.cs new file mode 100644 index 000000000000..18f6b86f334f --- /dev/null +++ b/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/Controls/PasteFormatTemplateSelector.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 AdvancedPaste.Models; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Controls.Primitives; + +namespace AdvancedPaste.Controls; + +public sealed partial class PasteFormatTemplateSelector : DataTemplateSelector +{ + public DataTemplate ItemTemplate { get; set; } + + public DataTemplate ItemTemplateDisabled { get; set; } + + protected override DataTemplate SelectTemplateCore(object item, DependencyObject container) + { + bool isEnabled = item is PasteFormat pasteFormat && pasteFormat.IsEnabled; + + if (container is SelectorItem selector) + { + selector.IsEnabled = isEnabled; + } + + return isEnabled ? ItemTemplate : ItemTemplateDisabled; + } +} diff --git a/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/Controls/PromptBox.xaml b/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/Controls/PromptBox.xaml index 79a29ac872d5..69f675d4cb06 100644 --- a/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/Controls/PromptBox.xaml +++ b/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/Controls/PromptBox.xaml @@ -410,6 +410,7 @@ Spacing="2"> @@ -537,6 +539,7 @@ HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ui:VisualExtensions.NormalizedCenterPoint="0.5,0.5" + AutomationProperties.HelpText="{x:Bind ViewModel.CustomAIUnavailableErrorText, Mode=OneWay}" Command="{x:Bind GenerateCustomAICommand}" Content="{ui:FontIcon Glyph=, FontSize=16}" diff --git a/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/MainWindow.xaml.cs b/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/MainWindow.xaml.cs index 18295f231567..7743e6764bb2 100644 --- a/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/MainWindow.xaml.cs +++ b/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/MainWindow.xaml.cs @@ -82,6 +82,7 @@ double GetHeight(int maxCustomActionCount) => }; WindowHelpers.BringToForeground(this.GetWindowHandle()); + WindowHelpers.ForceTopBorder1PixelInsetOnWindows10(this.GetWindowHandle()); } private void OnActivated(object sender, WindowActivatedEventArgs args) diff --git a/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/Pages/MainPage.xaml b/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/Pages/MainPage.xaml index b4e99ebaed94..a37e53f49ea4 100644 --- a/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/Pages/MainPage.xaml +++ b/src/modules/AdvancedPaste/AdvancedPaste/AdvancedPasteXAML/Pages/MainPage.xaml @@ -21,6 +21,77 @@ x:Name="customActionsToMinHeightConverter" ValueIfNonZero="40" ValueIfZero="0" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - @@ -196,10 +216,10 @@ x:Name="PasteOptionsListView" Grid.Row="0" VerticalAlignment="Bottom" - IsItemClickEnabled="False" - ItemContainerStyle="{StaticResource PasteFormatListViewItemStyle}" + IsItemClickEnabled="True" + ItemClick="PasteFormat_ItemClick" ItemContainerTransitions="{x:Null}" - ItemTemplate="{StaticResource PasteFormatTemplate}" + ItemTemplateSelector="{StaticResource PasteFormatTemplateSelector}" ItemsSource="{x:Bind ViewModel.StandardPasteFormats, Mode=OneWay}" ScrollViewer.VerticalScrollBarVisibility="Visible" ScrollViewer.VerticalScrollMode="Auto" @@ -217,10 +237,10 @@ x:Name="CustomActionsListView" Grid.Row="2" VerticalAlignment="Top" - IsItemClickEnabled="False" - ItemContainerStyle="{StaticResource PasteFormatListViewItemStyle}" + IsItemClickEnabled="True" + ItemClick="PasteFormat_ItemClick" ItemContainerTransitions="{x:Null}" - ItemTemplate="{StaticResource PasteFormatTemplate}" + ItemTemplateSelector="{StaticResource PasteFormatTemplateSelector}" ItemsSource="{x:Bind ViewModel.CustomActionPasteFormats, Mode=OneWay}" ScrollViewer.VerticalScrollBarVisibility="Visible" ScrollViewer.VerticalScrollMode="Auto" @@ -232,7 +252,6 @@ Height="1" HorizontalAlignment="Stretch" Fill="{ThemeResource DividerStrokeColorDefaultBrush}" /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 9,6,9,8 - 320 - 1 - - - - - - - - - - - - - - + 16 + + + + IsReadOnly="True"> + + + + + + + + + + + + + + + + diff --git a/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.xaml.cs b/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.xaml.cs index 1687a24293d3..06e435c9f0e4 100644 --- a/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.xaml.cs +++ b/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.xaml.cs @@ -8,6 +8,7 @@ using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Microsoft.Windows.ApplicationModel.Resources; +using Windows.ApplicationModel.DataTransfer; namespace RegistryPreviewUILib { diff --git a/src/modules/registrypreview/RegistryPreviewUILib/RegistryValue.xaml.cs b/src/modules/registrypreview/RegistryPreviewUILib/RegistryValue.xaml.cs index 3e0d16c9328f..1bf403c3fab1 100644 --- a/src/modules/registrypreview/RegistryPreviewUILib/RegistryValue.xaml.cs +++ b/src/modules/registrypreview/RegistryPreviewUILib/RegistryValue.xaml.cs @@ -3,6 +3,10 @@ // See the LICENSE file in the project root for more information. using System; +using System.Windows.Input; +using CommunityToolkit.Mvvm.Input; +using Microsoft.UI.Xaml; +using Windows.ApplicationModel.DataTransfer; namespace RegistryPreviewUILib { @@ -17,12 +21,16 @@ public class RegistryValue private static Uri uriDeleteValue = new Uri("ms-appx:///Assets/RegistryPreview/deleted-value32.png"); private static Uri uriErrorValue = new Uri("ms-appx:///Assets/RegistryPreview/error32.png"); + public string Key { get; set; } + public string Name { get; set; } public string Type { get; set; } public string Value { get; set; } + public string ValueOneLine => Value.Replace('\r', ' '); + public string ToolTipText { get; set; } public Uri ImageUri @@ -46,12 +54,49 @@ public Uri ImageUri } } - public RegistryValue(string name, string type, string value) + public RegistryValue(string name, string type, string value, string key) { this.Name = name; this.Type = type; this.Value = value; this.ToolTipText = string.Empty; + this.Key = key; + } + + // Commands + public ICommand CopyToClipboardEntry_Click => new RelayCommand(CopyToClipboardEntry); + + public ICommand CopyToClipboardWithPath_Click => new RelayCommand(CopyToClipboardEntryWithPath); + + public ICommand CopyToClipboardName_Click => new RelayCommand(CopyToClipboardName); + + public ICommand CopyToClipboardType_Click => new RelayCommand(CopyToClipboardType); + + public ICommand CopyToClipboardData_Click => new RelayCommand(CopyToClipboardData); + + private void CopyToClipboardEntry() + { + ClipboardHelper.CopyToClipboardAction($"{Name}\r\n{Type}\r\n{Value}"); + } + + private void CopyToClipboardEntryWithPath() + { + ClipboardHelper.CopyToClipboardAction($"{Key}\r\n{Name}\r\n{Type}\r\n{Value}"); + } + + private void CopyToClipboardName() + { + ClipboardHelper.CopyToClipboardAction(Name); + } + + private void CopyToClipboardType() + { + ClipboardHelper.CopyToClipboardAction(Type); + } + + private void CopyToClipboardData() + { + ClipboardHelper.CopyToClipboardAction(Value); } } } diff --git a/src/modules/registrypreview/RegistryPreviewUILib/Strings/en-US/Resources.resw b/src/modules/registrypreview/RegistryPreviewUILib/Strings/en-US/Resources.resw index 580d108d9a7b..9401908d216e 100644 --- a/src/modules/registrypreview/RegistryPreviewUILib/Strings/en-US/Resources.resw +++ b/src/modules/registrypreview/RegistryPreviewUILib/Strings/en-US/Resources.resw @@ -257,4 +257,28 @@ (zero-length binary value) + + Copy path + Like "Copy item" + + + Copy name + Like "Copy item" + + + Copy type + Like "Copy item" + + + Copy data + Like "Copy item" + + + Copy value + Like "Copy item" + + + Copy value with key path + Like "Copy item" + \ No newline at end of file diff --git a/src/modules/videoconference/VideoConferenceModule/Assets/VCM/Off-NotInUse Dark.png b/src/modules/videoconference/VideoConferenceModule/Assets/VCM/Off-NotInUse Dark.png deleted file mode 100644 index 08446a20784f..000000000000 Binary files a/src/modules/videoconference/VideoConferenceModule/Assets/VCM/Off-NotInUse Dark.png and /dev/null differ diff --git a/src/modules/videoconference/VideoConferenceModule/Assets/VCM/Off-NotInUse Dark.svg b/src/modules/videoconference/VideoConferenceModule/Assets/VCM/Off-NotInUse Dark.svg deleted file mode 100644 index 4860bbfd3a8d..000000000000 --- a/src/modules/videoconference/VideoConferenceModule/Assets/VCM/Off-NotInUse Dark.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - Camera not in use - - - Microphone off - - diff --git a/src/modules/videoconference/VideoConferenceModule/Assets/VCM/Off-NotInUse Light.png b/src/modules/videoconference/VideoConferenceModule/Assets/VCM/Off-NotInUse Light.png deleted file mode 100644 index 285ea495b860..000000000000 Binary files a/src/modules/videoconference/VideoConferenceModule/Assets/VCM/Off-NotInUse Light.png and /dev/null differ diff --git a/src/modules/videoconference/VideoConferenceModule/Assets/VCM/Off-NotInUse Light.svg b/src/modules/videoconference/VideoConferenceModule/Assets/VCM/Off-NotInUse Light.svg deleted file mode 100644 index a30e909ff116..000000000000 --- a/src/modules/videoconference/VideoConferenceModule/Assets/VCM/Off-NotInUse Light.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - Camera not in use - - - Microphone off - - diff --git a/src/modules/videoconference/VideoConferenceModule/Assets/VCM/Off-Off Dark.png b/src/modules/videoconference/VideoConferenceModule/Assets/VCM/Off-Off Dark.png deleted file mode 100644 index 32d7559e73a1..000000000000 Binary files a/src/modules/videoconference/VideoConferenceModule/Assets/VCM/Off-Off Dark.png and /dev/null differ diff --git a/src/modules/videoconference/VideoConferenceModule/Assets/VCM/Off-Off Dark.svg b/src/modules/videoconference/VideoConferenceModule/Assets/VCM/Off-Off Dark.svg deleted file mode 100644 index c147f2278ef0..000000000000 --- a/src/modules/videoconference/VideoConferenceModule/Assets/VCM/Off-Off Dark.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - Camera off - - - Microphone off - - diff --git a/src/modules/videoconference/VideoConferenceModule/Assets/VCM/Off-Off Light.png b/src/modules/videoconference/VideoConferenceModule/Assets/VCM/Off-Off Light.png deleted file mode 100644 index 7f0477ff8984..000000000000 Binary files a/src/modules/videoconference/VideoConferenceModule/Assets/VCM/Off-Off Light.png and /dev/null differ diff --git a/src/modules/videoconference/VideoConferenceModule/Assets/VCM/Off-Off Light.svg b/src/modules/videoconference/VideoConferenceModule/Assets/VCM/Off-Off Light.svg deleted file mode 100644 index 25eecdd72f2f..000000000000 --- a/src/modules/videoconference/VideoConferenceModule/Assets/VCM/Off-Off Light.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - Camera off - - - Microphone off - - diff --git a/src/modules/videoconference/VideoConferenceModule/Assets/VCM/Off-On Dark.png b/src/modules/videoconference/VideoConferenceModule/Assets/VCM/Off-On Dark.png deleted file mode 100644 index ac33d985c89d..000000000000 Binary files a/src/modules/videoconference/VideoConferenceModule/Assets/VCM/Off-On Dark.png and /dev/null differ diff --git a/src/modules/videoconference/VideoConferenceModule/Assets/VCM/Off-On Dark.svg b/src/modules/videoconference/VideoConferenceModule/Assets/VCM/Off-On Dark.svg deleted file mode 100644 index ea31e3d78db8..000000000000 --- a/src/modules/videoconference/VideoConferenceModule/Assets/VCM/Off-On Dark.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - Camera on - - Microphone off - - - diff --git a/src/modules/videoconference/VideoConferenceModule/Assets/VCM/Off-On Light.png b/src/modules/videoconference/VideoConferenceModule/Assets/VCM/Off-On Light.png deleted file mode 100644 index a43b3cf364b2..000000000000 Binary files a/src/modules/videoconference/VideoConferenceModule/Assets/VCM/Off-On Light.png and /dev/null differ diff --git a/src/modules/videoconference/VideoConferenceModule/Assets/VCM/Off-On Light.svg b/src/modules/videoconference/VideoConferenceModule/Assets/VCM/Off-On Light.svg deleted file mode 100644 index e3c0352bccb2..000000000000 --- a/src/modules/videoconference/VideoConferenceModule/Assets/VCM/Off-On Light.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - Camera on - - Microphone off - - - diff --git a/src/modules/videoconference/VideoConferenceModule/Assets/VCM/On-NotInUse Dark.png b/src/modules/videoconference/VideoConferenceModule/Assets/VCM/On-NotInUse Dark.png deleted file mode 100644 index ff34ff3eb5cd..000000000000 Binary files a/src/modules/videoconference/VideoConferenceModule/Assets/VCM/On-NotInUse Dark.png and /dev/null differ diff --git a/src/modules/videoconference/VideoConferenceModule/Assets/VCM/On-NotInUse Dark.svg b/src/modules/videoconference/VideoConferenceModule/Assets/VCM/On-NotInUse Dark.svg deleted file mode 100644 index 268decd93b08..000000000000 --- a/src/modules/videoconference/VideoConferenceModule/Assets/VCM/On-NotInUse Dark.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - Camera not in use - - Microphone on - - - diff --git a/src/modules/videoconference/VideoConferenceModule/Assets/VCM/On-NotInUse Light.png b/src/modules/videoconference/VideoConferenceModule/Assets/VCM/On-NotInUse Light.png deleted file mode 100644 index b4e5edaea5cb..000000000000 Binary files a/src/modules/videoconference/VideoConferenceModule/Assets/VCM/On-NotInUse Light.png and /dev/null differ diff --git a/src/modules/videoconference/VideoConferenceModule/Assets/VCM/On-NotInUse Light.svg b/src/modules/videoconference/VideoConferenceModule/Assets/VCM/On-NotInUse Light.svg deleted file mode 100644 index d9d340c03418..000000000000 --- a/src/modules/videoconference/VideoConferenceModule/Assets/VCM/On-NotInUse Light.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - Camera not in use - - Microphone on - - - diff --git a/src/modules/videoconference/VideoConferenceModule/Assets/VCM/On-Off Dark.png b/src/modules/videoconference/VideoConferenceModule/Assets/VCM/On-Off Dark.png deleted file mode 100644 index 8492439759f6..000000000000 Binary files a/src/modules/videoconference/VideoConferenceModule/Assets/VCM/On-Off Dark.png and /dev/null differ diff --git a/src/modules/videoconference/VideoConferenceModule/Assets/VCM/On-Off Dark.svg b/src/modules/videoconference/VideoConferenceModule/Assets/VCM/On-Off Dark.svg deleted file mode 100644 index 67080eabdd91..000000000000 --- a/src/modules/videoconference/VideoConferenceModule/Assets/VCM/On-Off Dark.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - Camera off - - Microphone on - - - diff --git a/src/modules/videoconference/VideoConferenceModule/Assets/VCM/On-Off Light.png b/src/modules/videoconference/VideoConferenceModule/Assets/VCM/On-Off Light.png deleted file mode 100644 index b011e944bb27..000000000000 Binary files a/src/modules/videoconference/VideoConferenceModule/Assets/VCM/On-Off Light.png and /dev/null differ diff --git a/src/modules/videoconference/VideoConferenceModule/Assets/VCM/On-Off Light.svg b/src/modules/videoconference/VideoConferenceModule/Assets/VCM/On-Off Light.svg deleted file mode 100644 index f5661655bcb1..000000000000 --- a/src/modules/videoconference/VideoConferenceModule/Assets/VCM/On-Off Light.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - Camera off - - Microphone on - - - diff --git a/src/modules/videoconference/VideoConferenceModule/Assets/VCM/On-On Dark.png b/src/modules/videoconference/VideoConferenceModule/Assets/VCM/On-On Dark.png deleted file mode 100644 index 6f1955d2d2ea..000000000000 Binary files a/src/modules/videoconference/VideoConferenceModule/Assets/VCM/On-On Dark.png and /dev/null differ diff --git a/src/modules/videoconference/VideoConferenceModule/Assets/VCM/On-On Dark.svg b/src/modules/videoconference/VideoConferenceModule/Assets/VCM/On-On Dark.svg deleted file mode 100644 index e539e785a6f3..000000000000 --- a/src/modules/videoconference/VideoConferenceModule/Assets/VCM/On-On Dark.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - Camera on - - Microphone on - - - diff --git a/src/modules/videoconference/VideoConferenceModule/Assets/VCM/On-On Light.png b/src/modules/videoconference/VideoConferenceModule/Assets/VCM/On-On Light.png deleted file mode 100644 index b9fb04c6a6e3..000000000000 Binary files a/src/modules/videoconference/VideoConferenceModule/Assets/VCM/On-On Light.png and /dev/null differ diff --git a/src/modules/videoconference/VideoConferenceModule/Assets/VCM/On-On Light.svg b/src/modules/videoconference/VideoConferenceModule/Assets/VCM/On-On Light.svg deleted file mode 100644 index ff4a5c2e3114..000000000000 --- a/src/modules/videoconference/VideoConferenceModule/Assets/VCM/On-On Light.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - Camera on - - Microphone on - - - diff --git a/src/modules/videoconference/VideoConferenceModule/AudioDeviceNotificationClient.cpp b/src/modules/videoconference/VideoConferenceModule/AudioDeviceNotificationClient.cpp deleted file mode 100644 index 125290718415..000000000000 --- a/src/modules/videoconference/VideoConferenceModule/AudioDeviceNotificationClient.cpp +++ /dev/null @@ -1,78 +0,0 @@ -#include "pch.h" - -#include "AudioDeviceNotificationClient.h" - -AudioDeviceNotificationClient::AudioDeviceNotificationClient() -{ - (void)CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&_deviceEnumerator)); - if (!_deviceEnumerator) - { - return; - } - - if (FAILED(_deviceEnumerator->RegisterEndpointNotificationCallback(this))) - { - _deviceEnumerator->Release(); - _deviceEnumerator = nullptr; - } -} - -AudioDeviceNotificationClient::~AudioDeviceNotificationClient() -{ - if (!_deviceEnumerator) - { - return; - } - - _deviceEnumerator->UnregisterEndpointNotificationCallback(this); - _deviceEnumerator->Release(); -} - -ULONG AudioDeviceNotificationClient::AddRef() -{ - return 1; -} - -ULONG AudioDeviceNotificationClient::Release() -{ - return 1; -} - -HRESULT AudioDeviceNotificationClient::QueryInterface(REFIID, void**) -{ - return S_OK; -} - -HRESULT AudioDeviceNotificationClient::OnPropertyValueChanged(LPCWSTR, const PROPERTYKEY) -{ - _deviceConfigurationChanged = true; - return S_OK; -} - -HRESULT AudioDeviceNotificationClient::OnDeviceAdded(LPCWSTR) -{ - _deviceConfigurationChanged = true; - return S_OK; -} - -HRESULT AudioDeviceNotificationClient::OnDeviceRemoved(LPCWSTR) -{ - _deviceConfigurationChanged = true; - return S_OK; -} - -HRESULT AudioDeviceNotificationClient::OnDeviceStateChanged(LPCWSTR, DWORD) -{ - _deviceConfigurationChanged = true; - return S_OK; -} - -HRESULT AudioDeviceNotificationClient::OnDefaultDeviceChanged(EDataFlow flow, ERole role, LPCWSTR) -{ - if (role == eConsole && (flow == eCapture || flow == eAll)) - { - _deviceConfigurationChanged = true; - } - - return S_OK; -} diff --git a/src/modules/videoconference/VideoConferenceModule/AudioDeviceNotificationClient.h b/src/modules/videoconference/VideoConferenceModule/AudioDeviceNotificationClient.h deleted file mode 100644 index 3fe3f5fd1db2..000000000000 --- a/src/modules/videoconference/VideoConferenceModule/AudioDeviceNotificationClient.h +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -#include - -struct AudioDeviceNotificationClient : IMMNotificationClient -{ - AudioDeviceNotificationClient(); - ~AudioDeviceNotificationClient(); - - bool PullPendingNotifications() - { - const bool result = _deviceConfigurationChanged; - _deviceConfigurationChanged = false; - return result; - } - -private: - ULONG AddRef() override; - ULONG Release() override; - HRESULT QueryInterface(REFIID, void**) override; - HRESULT OnPropertyValueChanged(LPCWSTR, const PROPERTYKEY) override; - HRESULT OnDeviceAdded(LPCWSTR) override; - HRESULT OnDeviceRemoved(LPCWSTR) override; - HRESULT OnDeviceStateChanged(LPCWSTR, DWORD) override; - HRESULT OnDefaultDeviceChanged(EDataFlow flow, ERole role, LPCWSTR) override; - - IMMDeviceEnumerator* _deviceEnumerator = nullptr; - - bool _deviceConfigurationChanged = false; -}; diff --git a/src/modules/videoconference/VideoConferenceModule/README.md b/src/modules/videoconference/VideoConferenceModule/README.md deleted file mode 100644 index d53920685ab0..000000000000 --- a/src/modules/videoconference/VideoConferenceModule/README.md +++ /dev/null @@ -1,14 +0,0 @@ -# Video Conference Mute - -# Introduction -The Video Conference Mute module allows muting microphone and/or web camera video stream during video calls or other activity. - -# Usage -If you'd like to mute your web camera, please select "PowerToys VideoConference Mute" device in your web camera-using app, then restart it. - -During a video call, you can use default shortcuts to mute microphone, web camera or both. You'll see a toolbar indicating corresponding mute statuses. - -# Options -You can tweak the toolbar position on the screen as well as set web camera overlay image during muting. - -# Backlog diff --git a/src/modules/videoconference/VideoConferenceModule/Toolbar.cpp b/src/modules/videoconference/VideoConferenceModule/Toolbar.cpp deleted file mode 100644 index 0dabd58d9c9c..000000000000 --- a/src/modules/videoconference/VideoConferenceModule/Toolbar.cpp +++ /dev/null @@ -1,390 +0,0 @@ -#include "pch.h" -#include "Toolbar.h" - -#include - -#include -#include - -#include "Logging.h" -#include "VideoConferenceModule.h" - -Toolbar* toolbar = nullptr; - -const int REFRESH_RATE = 100; -const int OVERLAY_SHOW_TIME = 500; -const int BORDER_OFFSET = 12; -const int TOP_RIGHT_BORDER_OFFSET = 40; -std::wstring cached_position = L""; - -Toolbar::Toolbar() -{ - toolbar = this; - darkImages.camOnMicOn = Gdiplus::Image::FromFile(L"Assets/VCM/On-On Dark.png"); - darkImages.camOffMicOn = Gdiplus::Image::FromFile(L"Assets/VCM/On-Off Dark.png"); - darkImages.camOnMicOff = Gdiplus::Image::FromFile(L"Assets/VCM/Off-On Dark.png"); - darkImages.camOffMicOff = Gdiplus::Image::FromFile(L"Assets/VCM/Off-Off Dark.png"); - darkImages.camUnusedMicOn = Gdiplus::Image::FromFile(L"Assets/VCM/On-NotInUse Dark.png"); - darkImages.camUnusedMicOff = Gdiplus::Image::FromFile(L"Assets/VCM/Off-NotInUse Dark.png"); - - lightImages.camOnMicOn = Gdiplus::Image::FromFile(L"Assets/VCM/On-On Light.png"); - lightImages.camOffMicOn = Gdiplus::Image::FromFile(L"Assets/VCM/On-Off Light.png"); - lightImages.camOnMicOff = Gdiplus::Image::FromFile(L"Assets/VCM/Off-On Light.png"); - lightImages.camOffMicOff = Gdiplus::Image::FromFile(L"Assets/VCM/Off-Off Light.png"); - lightImages.camUnusedMicOn = Gdiplus::Image::FromFile(L"Assets/VCM/On-NotInUse Light.png"); - lightImages.camUnusedMicOff = Gdiplus::Image::FromFile(L"Assets/VCM/Off-NotInUse Light.png"); -} - -void Toolbar::scheduleModuleSettingsUpdate() -{ - moduleSettingsUpdateScheduled = true; -} - -void Toolbar::scheduleGeneralSettingsUpdate() -{ - generalSettingsUpdateScheduled = true; -} - -inline POINT calculateToolbarPositioning(Box const& screenSize, std::wstring& position, const int desiredWidth, const int desiredHeight) -{ - POINT p; - p.x = p.y = 0; - - if (position == L"Top left corner") - { - p.x = screenSize.left() + BORDER_OFFSET; - p.y = screenSize.top() + BORDER_OFFSET; - } - else if (position == L"Top center") - { - p.x = screenSize.middle().x - desiredWidth / 2; - p.y = screenSize.top() + BORDER_OFFSET; - } - else if (position == L"Bottom left corner") - { - p.x = screenSize.left() + BORDER_OFFSET; - p.y = screenSize.bottom() - desiredHeight - BORDER_OFFSET; - } - else if (position == L"Bottom center") - { - p.x = screenSize.middle().x - desiredWidth / 2; - p.y = screenSize.bottom() - desiredHeight - BORDER_OFFSET; - } - else if (position == L"Bottom right corner") - { - p.x = screenSize.right() - desiredWidth - BORDER_OFFSET; - p.y = screenSize.bottom() - desiredHeight - BORDER_OFFSET; - } - else //"Top right corner" or non-present - { - p.x = screenSize.right() - desiredWidth - BORDER_OFFSET; - p.y = screenSize.top() + TOP_RIGHT_BORDER_OFFSET; - } - return p; -} - -LRESULT Toolbar::WindowProcessMessages(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) -{ - switch (msg) - { - case WM_DESTROY: - return 0; - case WM_LBUTTONDOWN: - { - int x = GET_X_LPARAM(lparam); - int y = GET_Y_LPARAM(lparam); - UINT dpi = DPIAware::DEFAULT_DPI; - DPIAware::GetScreenDPIForWindow(hwnd, dpi); - - if (x < 322 * static_cast(dpi) / static_cast(DPIAware::DEFAULT_DPI) / 2) - { - VideoConferenceModule::reverseMicrophoneMute(); - } - else - { - VideoConferenceModule::reverseVirtualCameraMuteState(); - } - - return DefWindowProcW(hwnd, msg, wparam, lparam); - } - case WM_DPICHANGED: - { - UINT dpi = LOWORD(wparam); - RECT* prcNewWindow = reinterpret_cast(lparam); - - POINT suggestedPosition; - suggestedPosition.x = prcNewWindow->left; - suggestedPosition.y = prcNewWindow->top; - - int desiredWidth = prcNewWindow->right - prcNewWindow->left; - int desiredHeight = prcNewWindow->bottom - prcNewWindow->top; - - HMONITOR hMonitor = MonitorFromPoint(suggestedPosition, MONITOR_DEFAULTTONEAREST); - - MonitorInfo info{ hMonitor }; - - suggestedPosition = calculateToolbarPositioning(info.GetScreenSize(false), cached_position, desiredWidth, desiredHeight); - - SetWindowPos(hwnd, - NULL, - suggestedPosition.x, - suggestedPosition.y, - desiredWidth, - desiredHeight, - SWP_NOZORDER | SWP_NOACTIVATE); - return DefWindowProcW(hwnd, msg, wparam, lparam); - } - case WM_CREATE: - case WM_PAINT: - { - PAINTSTRUCT ps; - HDC hdc; - UINT dpi = DPIAware::DEFAULT_DPI; - - DPIAware::GetScreenDPIForWindow(hwnd, dpi); - - hdc = BeginPaint(hwnd, &ps); - - Gdiplus::Graphics graphic(hdc); - - ToolbarImages* themeImages = &toolbar->darkImages; - - if (toolbar->theme == L"light" || (toolbar->theme == L"system" && !WindowsColors::is_dark_mode())) - { - themeImages = &toolbar->lightImages; - } - else - { - themeImages = &toolbar->darkImages; - } - Gdiplus::Image* toolbarImage = nullptr; - if (!toolbar->cameraInUse) - { - if (toolbar->microphoneMuted) - { - toolbarImage = themeImages->camUnusedMicOff; - } - else - { - toolbarImage = themeImages->camUnusedMicOn; - } - } - else if (toolbar->microphoneMuted) - { - if (toolbar->cameraMuted) - { - toolbarImage = themeImages->camOffMicOff; - } - else - { - toolbarImage = themeImages->camOnMicOff; - } - } - else - { - if (toolbar->cameraMuted) - { - toolbarImage = themeImages->camOffMicOn; - } - else - { - toolbarImage = themeImages->camOnMicOn; - } - } - // Images are scaled by 4 to support higher dpi values. - graphic.DrawImage(toolbarImage, 0, 0, toolbarImage->GetWidth() / 4 * dpi / DPIAware::DEFAULT_DPI, toolbarImage->GetHeight() / 4 * dpi / DPIAware::DEFAULT_DPI); - - EndPaint(hwnd, &ps); - break; - } - case WM_TIMER: - { - if (toolbar->audioConfChangesNotifier.PullPendingNotifications()) - { - instance->onMicrophoneConfigurationChanged(); - } - toolbar->microphoneMuted = instance->getMicrophoneMuteState(); - - if (toolbar->generalSettingsUpdateScheduled) - { - instance->onGeneralSettingsChanged(); - toolbar->generalSettingsUpdateScheduled = false; - } - if (toolbar->moduleSettingsUpdateScheduled) - { - instance->onModuleSettingsChanged(); - toolbar->moduleSettingsUpdateScheduled = false; - } - - toolbar->cameraInUse = VideoConferenceModule::getVirtualCameraInUse(); - - InvalidateRect(hwnd, NULL, NULL); - - using namespace std::chrono; - const auto nowMillis = duration_cast(system_clock::now().time_since_epoch()).count(); - const bool showOverlayTimeout = nowMillis - toolbar->lastTimeCamOrMicMuteStateChanged > OVERLAY_SHOW_TIME; - - static bool previousShow = false; - bool show = toolbar->ToolbarHide == L"Never"; - - const bool cameraJustStoppedInUse = toolbar->previouscameraInUse && !toolbar->cameraInUse; - bool shouldUnmuteAll = cameraJustStoppedInUse; - - if (toolbar->ToolbarHide == L"When both camera and microphone are muted") - { - // We shouldn't unmute devices, since we'd like to only show the toolbar only - // when something is unmuted -> the use case is to keep everything muted by default and track it - shouldUnmuteAll = false; - show = (!toolbar->cameraMuted && toolbar->cameraInUse) || !toolbar->microphoneMuted; - } - else if (toolbar->ToolbarHide == L"When both camera and microphone are unmuted") - show = (toolbar->cameraMuted && toolbar->cameraInUse) || toolbar->microphoneMuted; - - if (shouldUnmuteAll && !toolbar->moduleSettingsUpdateScheduled) - VideoConferenceModule::unmuteAll(); - - show = show || !showOverlayTimeout; - ShowWindow(hwnd, show ? SW_SHOW : SW_HIDE); - - if (previousShow != show) - { - previousShow = show; - LOG(show ? "Toolbar visibility changed to shown" : "Toolbar visibility changed to hidden"); - } - - KillTimer(hwnd, toolbar->nTimerId); - toolbar->previouscameraInUse = toolbar->cameraInUse; - break; - } - default: - return DefWindowProcW(hwnd, msg, wparam, lparam); - } - - toolbar->nTimerId = SetTimer(hwnd, 101, REFRESH_RATE, nullptr); - - return DefWindowProcW(hwnd, msg, wparam, lparam); -} - -void Toolbar::show(std::wstring position, std::wstring monitorString) -{ - cached_position = position; - for (auto& hwnd : hwnds) - { - PostMessageW(hwnd, WM_CLOSE, 0, 0); - } - hwnds.clear(); - - // Images are scaled by 4 to support higher dpi values. - int overlayWidth = darkImages.camOffMicOff->GetWidth() / 4; - int overlayHeight = darkImages.camOffMicOff->GetHeight() / 4; - - // Register the window class - LPCWSTR CLASS_NAME = L"MuteNotificationWindowClass"; - WNDCLASS wc{}; - wc.hInstance = GetModuleHandleW(nullptr); - wc.lpszClassName = CLASS_NAME; - wc.hCursor = LoadCursor(nullptr, IDC_ARROW); - wc.hbrBackground = reinterpret_cast(COLOR_WINDOW); - wc.lpfnWndProc = WindowProcessMessages; - RegisterClassW(&wc); - - // Create the window - DWORD dwExtStyle = 0; - DWORD dwStyle = WS_POPUPWINDOW; - - std::vector monitorInfos; - - if (monitorString == L"All monitors") - { - monitorInfos = MonitorInfo::GetMonitors(false); - } - else //"Main monitor" or non-present - { - monitorInfos.push_back(MonitorInfo::GetPrimaryMonitor()); - } - - for (auto& monitorInfo : monitorInfos) - { - const auto screenSize = monitorInfo.GetScreenSize(false); - UINT dpi = DPIAware::DEFAULT_DPI; - DPIAware::GetScreenDPIForMonitor(monitorInfo.GetHandle(), dpi); - - int scaledOverlayWidth = overlayWidth * dpi / DPIAware::DEFAULT_DPI; - int scaledOverlayHeight = overlayHeight * dpi / DPIAware::DEFAULT_DPI; - - POINT p = calculateToolbarPositioning(screenSize, position, scaledOverlayWidth, scaledOverlayHeight); - - HWND hwnd; - hwnd = CreateWindowExW( - WS_EX_TOOLWINDOW | WS_EX_LAYERED, - CLASS_NAME, - CLASS_NAME, - WS_POPUP, - static_cast(p.x), - static_cast(p.y), - scaledOverlayWidth, - scaledOverlayHeight, - nullptr, - nullptr, - GetModuleHandleW(nullptr), - nullptr); - - auto transparentColorKey = RGB(0, 0, 255); - HBRUSH brush = CreateSolidBrush(transparentColorKey); - SetClassLongPtr(hwnd, GCLP_HBRBACKGROUND, reinterpret_cast(brush)); - - SetLayeredWindowAttributes(hwnd, transparentColorKey, 0, LWA_COLORKEY); - - SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); - - hwnds.push_back(hwnd); - } -} - -void Toolbar::hide() -{ - for (auto& hwnd : hwnds) - { - PostMessage(hwnd, WM_CLOSE, 0, 0); - } - hwnds.clear(); -} - -bool Toolbar::getCameraMute() -{ - return cameraMuted; -} - -void Toolbar::setCameraMute(bool mute) -{ - if (mute != cameraMuted) - { - lastTimeCamOrMicMuteStateChanged = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); - } - cameraMuted = mute; -} - -bool Toolbar::getMicrophoneMute() -{ - return microphoneMuted; -} - -void Toolbar::setMicrophoneMute(bool mute) -{ - if (mute != microphoneMuted) - { - lastTimeCamOrMicMuteStateChanged = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); - } - - microphoneMuted = mute; -} - -void Toolbar::setToolbarHide(std::wstring hide) -{ - ToolbarHide = hide; -} - -void Toolbar::setTheme(std::wstring theme) -{ - Toolbar::theme = theme; -} diff --git a/src/modules/videoconference/VideoConferenceModule/Toolbar.h b/src/modules/videoconference/VideoConferenceModule/Toolbar.h deleted file mode 100644 index 04b1c28a233d..000000000000 --- a/src/modules/videoconference/VideoConferenceModule/Toolbar.h +++ /dev/null @@ -1,64 +0,0 @@ -#pragma once - -#include -#include -#include - -#include - -#include "AudioDeviceNotificationClient.h" - -struct ToolbarImages -{ - Gdiplus::Image* camOnMicOn = nullptr; - Gdiplus::Image* camOffMicOn = nullptr; - Gdiplus::Image* camOnMicOff = nullptr; - Gdiplus::Image* camOffMicOff = nullptr; - Gdiplus::Image* camUnusedMicOn = nullptr; - Gdiplus::Image* camUnusedMicOff = nullptr; -}; - -class Toolbar -{ -public: - Toolbar(); - - void scheduleModuleSettingsUpdate(); - void scheduleGeneralSettingsUpdate(); - - void show(std::wstring position, std::wstring monitorString); - void hide(); - - bool getCameraMute(); - void setCameraMute(bool mute); - bool getMicrophoneMute(); - void setMicrophoneMute(bool mute); - - void setTheme(std::wstring theme); - void setToolbarHide(std::wstring hide); - -private: - static LRESULT CALLBACK WindowProcessMessages(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); - - // Window callback can't be non-static so this members can't as well - std::vector hwnds; - - ToolbarImages darkImages; - ToolbarImages lightImages; - AudioDeviceNotificationClient audioConfChangesNotifier; - - bool cameraMuted = false; - bool cameraInUse = false; - bool previouscameraInUse = false; - bool microphoneMuted = false; - - std::wstring theme = L"system"; - - std::wstring ToolbarHide = L"When both camera and microphone are unmuted"; - - uint64_t lastTimeCamOrMicMuteStateChanged{}; - - std::atomic_bool moduleSettingsUpdateScheduled = false; - std::atomic_bool generalSettingsUpdateScheduled = false; - UINT_PTR nTimerId{}; -}; diff --git a/src/modules/videoconference/VideoConferenceModule/VideoConference.filters b/src/modules/videoconference/VideoConferenceModule/VideoConference.filters deleted file mode 100644 index e19316f1bdb9..000000000000 --- a/src/modules/videoconference/VideoConferenceModule/VideoConference.filters +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - - {2c7c97f7-0d87-4230-a4b2-baf2cfc35d58} - - - {aa4b6713-589d-42ef-804d-3a045833f83f} - - - - - - - - - \ No newline at end of file diff --git a/src/modules/videoconference/VideoConferenceModule/VideoConference.vcxproj b/src/modules/videoconference/VideoConferenceModule/VideoConference.vcxproj deleted file mode 100644 index e04332202145..000000000000 --- a/src/modules/videoconference/VideoConferenceModule/VideoConference.vcxproj +++ /dev/null @@ -1,189 +0,0 @@ - - - - - 15.0 - {5ABA70DE-3A3F-41F6-A1F5-D1F74F54F9BB} - Win32Proj - overlaywindow - VideoConferenceModule - ..\..\..\..\$(Platform)\$(Configuration)\ - PowerToys.VideoConferenceModule - - - - DynamicLibrary - true - v143 - Unicode - Spectre - - - DynamicLibrary - false - v143 - true - Unicode - Spectre - - - - - - - - - - - false - - - true - - - - Level3 - MaxSpeed - true - true - true - NDEBUG;OVERLAYWINDOW_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - MultiThreaded - ..\..\..\;..\..\;..\VideoConferenceShared\;%(AdditionalIncludeDirectories) - stdcpplatest - - - Windows - true - true - true - $(OutDir)$(TargetName)$(TargetExt) - shlwapi.lib;gdiplus.lib;dwmapi.lib;uxtheme.lib;shcore.lib;Wtsapi32.lib;%(AdditionalDependencies) - - - - - Level3 - Disabled - true - _DEBUG;OVERLAYWINDOW_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - MultiThreadedDebug - ..\..\..\common\inc;..\..\..\common\Telemetry;..\..\..\;..\..\;..\VideoConferenceShared\;%(AdditionalIncludeDirectories) - stdcpplatest - - - Windows - true - $(OutDir)$(TargetName)$(TargetExt) - shlwapi.lib;gdiplus.lib;dwmapi.lib;uxtheme.lib;shcore.lib;Wtsapi32.lib;dxguid.lib;%(AdditionalDependencies) - - - - - - - - - - - - - - - - - - Create - - - - - - {459e0768-7ebd-4c41-bba1-6db3b3815e0a} - - - - - true - PreserveNewest - - - true - PreserveNewest - - - true - PreserveNewest - - - true - PreserveNewest - - - true - PreserveNewest - - - true - PreserveNewest - - - true - PreserveNewest - - - true - PreserveNewest - - - true - PreserveNewest - - - true - PreserveNewest - - - true - PreserveNewest - - - true - PreserveNewest - - - true - PreserveNewest - - - - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - - - - {caba8dfb-823b-4bf2-93ac-3f31984150d9} - - - {6955446d-23f7-4023-9bb3-8657f904af99} - - - {98537082-0fdb-40de-abd8-0dc5a4269bab} - - - - - - - - - \ No newline at end of file diff --git a/src/modules/videoconference/VideoConferenceModule/VideoConference.vcxproj.filters b/src/modules/videoconference/VideoConferenceModule/VideoConference.vcxproj.filters deleted file mode 100644 index fea3b28290b5..000000000000 --- a/src/modules/videoconference/VideoConferenceModule/VideoConference.vcxproj.filters +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - {efd98846-4568-41d4-a425-451c246802cd} - - - {e79f8c1a-b78b-4ba5-b923-f7db79eba776} - - - - - - - - Assets\VCM - - - Assets\VCM - - - Assets\VCM - - - Assets\VCM - - - Assets\VCM - - - Assets\VCM - - - Assets\VCM - - - Assets\VCM - - - Assets\VCM - - - Assets\VCM - - - Assets\VCM - - - Assets\VCM - - - Assets\VCM - - - - - - - - - \ No newline at end of file diff --git a/src/modules/videoconference/VideoConferenceModule/VideoConferenceModule.cpp b/src/modules/videoconference/VideoConferenceModule/VideoConferenceModule.cpp deleted file mode 100644 index aab538e88389..000000000000 --- a/src/modules/videoconference/VideoConferenceModule/VideoConferenceModule.cpp +++ /dev/null @@ -1,733 +0,0 @@ -#include "pch.h" - -#include "VideoConferenceModule.h" - -#include - -#include -#include - -#include -#include - -#include -#include -#include -#include - -#include - -#include "logging.h" -#include "trace.h" - -extern "C" IMAGE_DOS_HEADER __ImageBase; - -VideoConferenceModule* instance = nullptr; - -VideoConferenceSettings VideoConferenceModule::settings; -Toolbar VideoConferenceModule::toolbar; -bool VideoConferenceModule::pushToTalkPressed = false; - -HHOOK VideoConferenceModule::hook_handle; - -IAudioEndpointVolume* endpointVolume = NULL; - -bool VideoConferenceModule::isKeyPressed(unsigned int keyCode) -{ - return (GetKeyState(keyCode) & 0x8000); -} - -namespace fs = std::filesystem; - -bool VideoConferenceModule::isHotkeyPressed(DWORD code, PowerToysSettings::HotkeyObject& hotkey) -{ - return code == hotkey.get_code() && - isKeyPressed(VK_SHIFT) == hotkey.shift_pressed() && - isKeyPressed(VK_CONTROL) == hotkey.ctrl_pressed() && - isKeyPressed(VK_LWIN) == hotkey.win_pressed() && - (isKeyPressed(VK_LMENU)) == hotkey.alt_pressed(); -} - -void VideoConferenceModule::reverseMicrophoneMute() -{ - // All controlled mic should same state with _microphoneTrackedInUI - // Avoid manually change in Control Panel make controlled mic has different state - bool muted = !getMicrophoneMuteState(); - for (auto& controlledMic : instance->_controlledMicrophones) - { - controlledMic->set_muted(muted); - } - if (muted) - { - Trace::MicrophoneMuted(); - } - instance->_mic_muted_state_during_disconnect = !instance->_mic_muted_state_during_disconnect; - - toolbar.setMicrophoneMute(muted); -} - -bool VideoConferenceModule::getMicrophoneMuteState() -{ - return instance->_microphoneTrackedInUI ? instance->_microphoneTrackedInUI->muted() : instance->_mic_muted_state_during_disconnect; -} - -void VideoConferenceModule::reverseVirtualCameraMuteState() -{ - bool muted = false; - if (!instance->_settingsUpdateChannel.has_value()) - { - return; - } - - instance->_settingsUpdateChannel->access([&muted](auto settingsMemory) { - auto settings = reinterpret_cast(settingsMemory._data); - settings->useOverlayImage = !settings->useOverlayImage; - muted = settings->useOverlayImage; - }); - - if (muted) - { - Trace::CameraMuted(); - } - toolbar.setCameraMute(muted); -} - -bool VideoConferenceModule::getVirtualCameraMuteState() -{ - bool disabled = false; - if (!instance->_settingsUpdateChannel.has_value()) - { - return disabled; - } - instance->_settingsUpdateChannel->access([&disabled](auto settingsMemory) { - auto settings = reinterpret_cast(settingsMemory._data); - disabled = settings->useOverlayImage; - }); - return disabled; -} - -bool VideoConferenceModule::getVirtualCameraInUse() -{ - if (!instance->_settingsUpdateChannel.has_value()) - { - return false; - } - bool inUse = false; - instance->_settingsUpdateChannel->access([&inUse](auto settingsMemory) { - auto settings = reinterpret_cast(settingsMemory._data); - inUse = settings->cameraInUse; - }); - return inUse; -} - -LRESULT CALLBACK VideoConferenceModule::LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) -{ - if (nCode == HC_ACTION) - { - KBDLLHOOKSTRUCT* kbd = reinterpret_cast(lParam); - switch (wParam) - { - case WM_KEYDOWN: - - if (isHotkeyPressed(kbd->vkCode, settings.cameraAndMicrophoneMuteHotkey)) - { - const bool cameraInUse = getVirtualCameraInUse(); - const bool microphoneIsMuted = getMicrophoneMuteState(); - const bool cameraIsMuted = cameraInUse && getVirtualCameraMuteState(); - if (cameraInUse) - { - // we're likely on a video call, so we must mute the unmuted cam/mic or reverse the mute state - // of everything, if cam and mic mute states are the same - if (microphoneIsMuted == cameraIsMuted) - { - reverseMicrophoneMute(); - reverseVirtualCameraMuteState(); - } - else if (cameraIsMuted) - { - reverseMicrophoneMute(); - } - else if (microphoneIsMuted) - { - reverseVirtualCameraMuteState(); - } - } - else - { - // if the camera is not in use, we just mute/unmute the mic - reverseMicrophoneMute(); - } - return 1; - } - else if (isHotkeyPressed(kbd->vkCode, settings.microphoneMuteHotkey)) - { - reverseMicrophoneMute(); - return 1; - } - else if (isHotkeyPressed(kbd->vkCode, settings.microphonePushToTalkHotkey)) - { - if (!pushToTalkPressed) - { - if (settings.pushToReverseEnabled || getMicrophoneMuteState()) - { - reverseMicrophoneMute(); - } - pushToTalkPressed = true; - } - return 1; - } - else if (isHotkeyPressed(kbd->vkCode, settings.cameraMuteHotkey)) - { - reverseVirtualCameraMuteState(); - return 1; - } - break; - case WM_KEYUP: - if (pushToTalkPressed && (kbd->vkCode == settings.microphonePushToTalkHotkey.get_code())) - { - reverseMicrophoneMute(); - pushToTalkPressed = false; - return 1; - } - } - } - - return CallNextHookEx(hook_handle, nCode, wParam, lParam); -} - -void VideoConferenceModule::onGeneralSettingsChanged() -{ - auto settings = PTSettingsHelper::load_general_settings(); - bool enabled = false; - try - { - if (json::has(settings, L"enabled")) - { - for (const auto& mod : settings.GetNamedObject(L"enabled")) - { - const auto value = mod.Value(); - if (value.ValueType() != json::JsonValueType::Boolean) - { - continue; - } - if (mod.Key() == get_key()) - { - enabled = value.GetBoolean(); - break; - } - } - } - } - catch (...) - { - LOG("Couldn't get enabled state"); - } - if (enabled) - { - enable(); - } - else - { - disable(); - } -} - -void VideoConferenceModule::onModuleSettingsChanged() -{ - try - { - PowerToysSettings::PowerToyValues values = PowerToysSettings::PowerToyValues::load_from_settings_file(get_key()); - //Trace::SettingsChanged(pressTime.value, overlayOpacity.value, theme.value); - - if (_enabled) - { - if (const auto val = values.get_json(L"mute_camera_and_microphone_hotkey")) - { - settings.cameraAndMicrophoneMuteHotkey = PowerToysSettings::HotkeyObject::from_json(*val); - } - if (const auto val = values.get_json(L"mute_microphone_hotkey")) - { - settings.microphoneMuteHotkey = PowerToysSettings::HotkeyObject::from_json(*val); - } - if (const auto val = values.get_json(L"push_to_talk_microphone_hotkey")) - { - settings.microphonePushToTalkHotkey = PowerToysSettings::HotkeyObject::from_json(*val); - } - if (const auto val = values.get_bool_value(L"push_to_reverse_enabled")) - { - settings.pushToReverseEnabled = *val; - } - if (const auto val = values.get_json(L"mute_camera_hotkey")) - { - settings.cameraMuteHotkey = PowerToysSettings::HotkeyObject::from_json(*val); - } - if (const auto val = values.get_string_value(L"toolbar_position")) - { - settings.toolbarPositionString = val.value(); - } - if (const auto val = values.get_string_value(L"toolbar_monitor")) - { - settings.toolbarMonitorString = val.value(); - } - if (const auto val = values.get_string_value(L"selected_camera"); val && val != settings.selectedCamera) - { - settings.selectedCamera = val.value(); - sendSourceCameraNameUpdate(); - } - if (const auto val = values.get_string_value(L"camera_overlay_image_path"); val && val != settings.imageOverlayPath) - { - settings.imageOverlayPath = val.value(); - sendOverlayImageUpdate(); - } - if (const auto val = values.get_string_value(L"toolbar_hide")) - { - toolbar.setToolbarHide(val.value()); - } - if (const auto val = values.get_string_value(L"startup_action")) - { - settings.startupAction = val.value(); - } - - const auto selectedMic = values.get_string_value(L"selected_mic"); - if (selectedMic && selectedMic != settings.selectedMicrophone) - { - settings.selectedMicrophone = *selectedMic; - updateControlledMicrophones(settings.selectedMicrophone); - } - - toolbar.show(settings.toolbarPositionString, settings.toolbarMonitorString); - } - } - catch (...) - { - LOG("onModuleSettingsChanged encountered an exception"); - } -} - -void VideoConferenceModule::onMicrophoneConfigurationChanged() -{ - if (!_controllingAllMics) - { - // Don't care if we don't control all the mics - return; - } - - const bool mutedStateForNewMics = getMicrophoneMuteState(); - std::unordered_set currentlyTrackedMicsIds; - for (const auto& controlledMic : _controlledMicrophones) - { - currentlyTrackedMicsIds.emplace(controlledMic->id()); - } - - auto allMics = MicrophoneDevice::getAllActive(); - for (auto& newMic : allMics) - { - if (currentlyTrackedMicsIds.contains(newMic->id())) - { - continue; - } - - if (mutedStateForNewMics) - { - newMic->set_muted(true); - } - - _controlledMicrophones.emplace_back(std::move(newMic)); - } - // Restore invalidated pointer - _microphoneTrackedInUI = controlledDefaultMic(); - if (_microphoneTrackedInUI) - { - _microphoneTrackedInUI->set_mute_changed_callback([](const bool muted) { - toolbar.setMicrophoneMute(muted); - }); - } -} - -VideoConferenceModule::VideoConferenceModule() -{ - init_settings(); - _settingsUpdateChannel = - SerializedSharedMemory::create(CameraSettingsUpdateChannel::endpoint(), sizeof(CameraSettingsUpdateChannel), false); - if (_settingsUpdateChannel) - { - _settingsUpdateChannel->access([](auto memory) { - -// Suppress warning 26403 - Reset or explicitly delete an owner pointer 'variable' (r.3) -// the video conference class should be only instantiated once and it is using placement new -// the access to the data can be done through memory._data -#pragma warning(push) -#pragma warning(disable : 26403) - auto updatesChannel = new (memory._data) CameraSettingsUpdateChannel{}; -#pragma warning(pop) - }); - } - sendSourceCameraNameUpdate(); - sendOverlayImageUpdate(); -} - -inline VideoConferenceModule::~VideoConferenceModule() -{ - toolbar.hide(); -} - -const wchar_t* VideoConferenceModule::get_name() -{ - return L"Video Conference"; -} - -const wchar_t* VideoConferenceModule::get_key() -{ - return L"Video Conference"; -} - -// Return the configured status for the gpo policy for the module -powertoys_gpo::gpo_rule_configured_t VideoConferenceModule::gpo_policy_enabled_configuration() -{ - return powertoys_gpo::getConfiguredVideoConferenceMuteEnabledValue(); -} - -bool VideoConferenceModule::get_config(wchar_t* buffer, int* buffer_size) -{ - return true; -} - -void VideoConferenceModule::set_config(const wchar_t* config) -{ - try - { - PowerToysSettings::PowerToyValues values = PowerToysSettings::PowerToyValues::from_json_string(config, get_key()); - values.save_to_settings_file(); - } - catch (...) - { - LOG("VideoConferenceModule::set_config: exception during saving new settings values"); - } -} - -void VideoConferenceModule::init_settings() -{ - try - { - PowerToysSettings::PowerToyValues powerToysSettings = PowerToysSettings::PowerToyValues::load_from_settings_file(L"Video Conference"); - - if (const auto val = powerToysSettings.get_json(L"mute_camera_and_microphone_hotkey")) - { - settings.cameraAndMicrophoneMuteHotkey = PowerToysSettings::HotkeyObject::from_json(*val); - } - if (const auto val = powerToysSettings.get_json(L"mute_microphone_hotkey")) - { - settings.microphoneMuteHotkey = PowerToysSettings::HotkeyObject::from_json(*val); - } - if (const auto val = powerToysSettings.get_json(L"push_to_talk_microphone_hotkey")) - { - settings.microphonePushToTalkHotkey = PowerToysSettings::HotkeyObject::from_json(*val); - } - if (const auto val = powerToysSettings.get_bool_value(L"push_to_reverse_enabled")) - { - settings.pushToReverseEnabled = *val; - } - if (const auto val = powerToysSettings.get_json(L"mute_camera_hotkey")) - { - settings.cameraMuteHotkey = PowerToysSettings::HotkeyObject::from_json(*val); - } - if (const auto val = powerToysSettings.get_string_value(L"toolbar_position")) - { - settings.toolbarPositionString = val.value(); - } - if (const auto val = powerToysSettings.get_string_value(L"toolbar_monitor")) - { - settings.toolbarMonitorString = val.value(); - } - if (const auto val = powerToysSettings.get_string_value(L"selected_camera")) - { - settings.selectedCamera = val.value(); - } - if (const auto val = powerToysSettings.get_string_value(L"camera_overlay_image_path")) - { - settings.imageOverlayPath = val.value(); - } - if (const auto val = powerToysSettings.get_string_value(L"toolbar_hide")) - { - toolbar.setToolbarHide(val.value()); - } - if (const auto val = powerToysSettings.get_string_value(L"startup_action")) - { - settings.startupAction = val.value(); - } - if (const auto val = powerToysSettings.get_string_value(L"selected_mic"); val && *val != settings.selectedMicrophone) - { - settings.selectedMicrophone = *val; - updateControlledMicrophones(settings.selectedMicrophone); - } - } - catch (std::exception&) - { - // Error while loading from the settings file. Just let default values stay as they are. - } - - try - { - auto loaded = PTSettingsHelper::load_general_settings(); - std::wstring settings_theme{ static_cast(loaded.GetNamedString(L"theme", L"system")) }; - if (settings_theme != L"dark" && settings_theme != L"light") - { - settings_theme = L"system"; - } - toolbar.setTheme(settings_theme); - } - catch (...) - { - } -} - -void VideoConferenceModule::updateControlledMicrophones(const std::wstring_view new_mic) -{ - for (auto& controlledMic : _controlledMicrophones) - { - controlledMic->set_muted(false); - } - _controlledMicrophones.clear(); - _microphoneTrackedInUI = nullptr; - auto allMics = MicrophoneDevice::getAllActive(); - if (new_mic == L"[All]") - { - _controllingAllMics = true; - _controlledMicrophones = std::move(allMics); - _microphoneTrackedInUI = controlledDefaultMic(); - } - else - { - _controllingAllMics = false; - for (auto& controlledMic : allMics) - { - if (controlledMic->name() == new_mic) - { - _controlledMicrophones.emplace_back(std::move(controlledMic)); - _microphoneTrackedInUI = _controlledMicrophones[0].get(); - break; - } - } - } - - if (_microphoneTrackedInUI) - { - _microphoneTrackedInUI->set_mute_changed_callback([](const bool muted) { - toolbar.setMicrophoneMute(muted); - }); - toolbar.setMicrophoneMute(_microphoneTrackedInUI->muted()); - } - - if (settings.startupAction == L"Unmute") - { - for (auto& controlledMic : _controlledMicrophones) - { - controlledMic->set_muted(false); - } - } - else if (settings.startupAction == L"Mute") - { - for (auto& controlledMic : _controlledMicrophones) - { - controlledMic->set_muted(true); - } - } -} - -MicrophoneDevice* VideoConferenceModule::controlledDefaultMic() -{ - if (auto defaultMic = MicrophoneDevice::getDefault()) - { - for (auto& controlledMic : _controlledMicrophones) - { - if (controlledMic->id() == defaultMic->id()) - { - return controlledMic.get(); - } - } - } - - return nullptr; -} - -void toggleProxyCamRegistration(const bool enable) -{ - if (!is_process_elevated()) - { - return; - } - - auto vcmRoot = fs::path{ get_module_folderpath() }; -#if defined(_M_ARM64) - std::array proxyFilters = { vcmRoot / "PowerToys.VideoConferenceProxyFilter_ARM64.dll", vcmRoot / "PowerToys.VideoConferenceProxyFilter_x86.dll" }; -#else - std::array proxyFilters = { vcmRoot / "PowerToys.VideoConferenceProxyFilter_x64.dll", vcmRoot / "PowerToys.VideoConferenceProxyFilter_x86.dll" }; -#endif - for (const auto filter : proxyFilters) - { - std::wstring params{ L"/s " }; - if (!enable) - { - params += L"/u "; - } - params += '"'; - params += filter; - params += '"'; - SHELLEXECUTEINFOW sei{ sizeof(sei) }; - sei.fMask = { SEE_MASK_FLAG_NO_UI | SEE_MASK_NOASYNC }; - sei.lpFile = L"regsvr32"; - sei.lpParameters = params.c_str(); - sei.nShow = SW_SHOWNORMAL; - ShellExecuteExW(&sei); - } -} - -void VideoConferenceModule::enable() -{ - if (!_enabled) - { - _generalSettingsWatcher = std::make_unique( - PTSettingsHelper::get_powertoys_general_save_file_location(), [this] { - toolbar.scheduleGeneralSettingsUpdate(); - }); - _moduleSettingsWatcher = std::make_unique( - PTSettingsHelper::get_module_save_file_location(get_key()), [this] { - toolbar.scheduleModuleSettingsUpdate(); - }); - - toggleProxyCamRegistration(true); - toolbar.setMicrophoneMute(getMicrophoneMuteState()); - toolbar.setCameraMute(getVirtualCameraMuteState()); - - toolbar.show(settings.toolbarPositionString, settings.toolbarMonitorString); - - _enabled = true; - -#if defined(DISABLE_LOWLEVEL_HOOKS_WHEN_DEBUGGED) - if (IsDebuggerPresent()) - { - return; - } -#endif - hook_handle = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, GetModuleHandle(NULL), NULL); - } - Trace::EnableVideoConference(true); -} - -void VideoConferenceModule::unmuteAll() -{ - if (getVirtualCameraMuteState()) - { - reverseVirtualCameraMuteState(); - } - - if (getMicrophoneMuteState()) - { - reverseMicrophoneMute(); - } -} - -void VideoConferenceModule::muteAll() -{ - if (!getVirtualCameraMuteState()) - { - reverseVirtualCameraMuteState(); - } - - if (!getMicrophoneMuteState()) - { - reverseMicrophoneMute(); - } -} - -void VideoConferenceModule::disable() -{ - if (_enabled) - { - _generalSettingsWatcher.reset(); - _moduleSettingsWatcher.reset(); - toggleProxyCamRegistration(false); - if (hook_handle) - { - bool success = UnhookWindowsHookEx(hook_handle); - if (success) - { - hook_handle = nullptr; - } - } - - if (getVirtualCameraMuteState()) - { - reverseVirtualCameraMuteState(); - } - - toolbar.hide(); - - _enabled = false; - } - Trace::EnableVideoConference(false); -} - -bool VideoConferenceModule::is_enabled() -{ - return _enabled; -} - -void VideoConferenceModule::destroy() -{ - delete this; - instance = nullptr; -} - -bool VideoConferenceModule::is_enabled_by_default() const -{ - return false; -} - -void VideoConferenceModule::sendSourceCameraNameUpdate() -{ - if (!_settingsUpdateChannel.has_value() || settings.selectedCamera.empty()) - { - return; - } - _settingsUpdateChannel->access([](auto memory) { - auto updatesChannel = reinterpret_cast(memory._data); - updatesChannel->sourceCameraName.emplace(); - std::copy(begin(settings.selectedCamera), end(settings.selectedCamera), begin(*updatesChannel->sourceCameraName)); - if (settings.startupAction == L"Unmute") - { - updatesChannel->useOverlayImage = false; - } - else if (settings.startupAction == L"Mute") - { - updatesChannel->useOverlayImage = true; - } - }); -} - -void VideoConferenceModule::sendOverlayImageUpdate() -{ - if (!_settingsUpdateChannel.has_value()) - { - return; - } - _imageOverlayChannel.reset(); - - wchar_t powertoysDirectory[MAX_PATH + 1]; - - DWORD length = GetModuleFileNameW(nullptr, powertoysDirectory, MAX_PATH); - PathRemoveFileSpecW(powertoysDirectory); - - std::wstring blankImagePath(powertoysDirectory); - blankImagePath += L"\\Assets\\VCM\\black.bmp"; - - _imageOverlayChannel = SerializedSharedMemory::create_readonly(CameraOverlayImageChannel::endpoint(), - settings.imageOverlayPath != L"" ? settings.imageOverlayPath : blankImagePath); - - const auto imageSize = static_cast(_imageOverlayChannel->size()); - _settingsUpdateChannel->access([imageSize](auto memory) { - auto updatesChannel = reinterpret_cast(memory._data); - updatesChannel->overlayImageSize.emplace(imageSize); - updatesChannel->newOverlayImagePosted = true; - }); -} diff --git a/src/modules/videoconference/VideoConferenceModule/VideoConferenceModule.h b/src/modules/videoconference/VideoConferenceModule/VideoConferenceModule.h deleted file mode 100644 index f3b835867a84..000000000000 --- a/src/modules/videoconference/VideoConferenceModule/VideoConferenceModule.h +++ /dev/null @@ -1,102 +0,0 @@ -#pragma once - -#include - -#include -#include - -#include - -#include -#include - -#include "Toolbar.h" - -#include - -extern class VideoConferenceModule* instance; - -struct VideoConferenceSettings -{ - PowerToysSettings::HotkeyObject cameraAndMicrophoneMuteHotkey = PowerToysSettings::HotkeyObject::from_settings(true, false, false, true, 81); - PowerToysSettings::HotkeyObject microphoneMuteHotkey = PowerToysSettings::HotkeyObject::from_settings(true, false, false, true, 65); - PowerToysSettings::HotkeyObject microphonePushToTalkHotkey = PowerToysSettings::HotkeyObject::from_settings(true, false, false, true, 73); - PowerToysSettings::HotkeyObject cameraMuteHotkey = PowerToysSettings::HotkeyObject::from_settings(true, false, false, true, 79); - - std::wstring toolbarPositionString; - std::wstring toolbarMonitorString; - - std::wstring selectedCamera; - std::wstring imageOverlayPath; - std::wstring selectedMicrophone; - - std::wstring startupAction; - - bool pushToReverseEnabled = false; -}; - -class VideoConferenceModule : public PowertoyModuleIface -{ -public: - VideoConferenceModule(); - ~VideoConferenceModule(); - virtual const wchar_t* get_name() override; - - virtual powertoys_gpo::gpo_rule_configured_t gpo_policy_enabled_configuration() override; - - virtual bool get_config(wchar_t* buffer, int* buffer_size) override; - - virtual void set_config(const wchar_t* config) override; - - virtual void enable() override; - virtual void disable() override; - virtual bool is_enabled() override; - virtual void destroy() override; - virtual bool is_enabled_by_default() const override; - - virtual const wchar_t * get_key() override; - - void sendSourceCameraNameUpdate(); - void sendOverlayImageUpdate(); - - static void unmuteAll(); - static void muteAll(); - static void reverseMicrophoneMute(); - static bool getMicrophoneMuteState(); - static void reverseVirtualCameraMuteState(); - static bool getVirtualCameraMuteState(); - static bool getVirtualCameraInUse(); - - void onGeneralSettingsChanged(); - void onModuleSettingsChanged(); - void onMicrophoneConfigurationChanged(); - -private: - - void init_settings(); - void updateControlledMicrophones(const std::wstring_view new_mic); - MicrophoneDevice* controlledDefaultMic(); - - // all callback methods and used by callback have to be static - static LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam); - static bool isKeyPressed(unsigned int keyCode); - static bool isHotkeyPressed(DWORD code, PowerToysSettings::HotkeyObject& hotkey); - - static HHOOK hook_handle; - bool _enabled = false; - - bool _mic_muted_state_during_disconnect = false; - bool _controllingAllMics = false; - std::vector> _controlledMicrophones; - MicrophoneDevice* _microphoneTrackedInUI = nullptr; - - std::optional _imageOverlayChannel; - std::optional _settingsUpdateChannel; - - std::unique_ptr _generalSettingsWatcher; - std::unique_ptr _moduleSettingsWatcher; - - static VideoConferenceSettings settings; - static Toolbar toolbar; - static bool pushToTalkPressed; -}; diff --git a/src/modules/videoconference/VideoConferenceModule/dllmain.cpp b/src/modules/videoconference/VideoConferenceModule/dllmain.cpp deleted file mode 100644 index c3d012cd6c5f..000000000000 --- a/src/modules/videoconference/VideoConferenceModule/dllmain.cpp +++ /dev/null @@ -1,35 +0,0 @@ -// dllmain.cpp : Defines the entry point for the DLL application. -#include "pch.h" -#include -#include "trace.h" -#include "VideoConferenceModule.h" - -BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) -{ - switch (ul_reason_for_call) - { - case DLL_PROCESS_ATTACH: - Trace::RegisterProvider(); - break; - case DLL_THREAD_ATTACH: - case DLL_THREAD_DETACH: - break; - case DLL_PROCESS_DETACH: - Trace::UnregisterProvider(); - break; - } - return TRUE; -} - -extern "C" __declspec(dllexport) PowertoyModuleIface* __cdecl powertoy_create() -{ - if (!instance) - { - instance = new VideoConferenceModule(); - return instance; - } - else - { - return nullptr; - } -} diff --git a/src/modules/videoconference/VideoConferenceModule/framework.h b/src/modules/videoconference/VideoConferenceModule/framework.h deleted file mode 100644 index 54b83e94fd33..000000000000 --- a/src/modules/videoconference/VideoConferenceModule/framework.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers -// Windows Header Files -#include diff --git a/src/modules/videoconference/VideoConferenceModule/pch.h b/src/modules/videoconference/VideoConferenceModule/pch.h deleted file mode 100644 index 7c614d9a5c65..000000000000 --- a/src/modules/videoconference/VideoConferenceModule/pch.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once -#define WIN32_LEAN_AND_MEAN -#include -#include - -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include diff --git a/src/modules/videoconference/VideoConferenceModule/resource.h b/src/modules/videoconference/VideoConferenceModule/resource.h deleted file mode 100644 index 6073efd0c352..000000000000 --- a/src/modules/videoconference/VideoConferenceModule/resource.h +++ /dev/null @@ -1,13 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by VideoConferenceModule.rc - -////////////////////////////// -// Non-localizable - -#define FILE_DESCRIPTION "PowerToys VideoConferenceMute Module" -#define INTERNAL_NAME "PowerToys.VideoConferenceModule" -#define ORIGINAL_FILENAME "PowerToys.VideoConferenceModule.dll" - -// Non-localizable -////////////////////////////// diff --git a/src/modules/videoconference/VideoConferenceModule/trace.cpp b/src/modules/videoconference/VideoConferenceModule/trace.cpp deleted file mode 100644 index 043c6b30e74b..000000000000 --- a/src/modules/videoconference/VideoConferenceModule/trace.cpp +++ /dev/null @@ -1,60 +0,0 @@ -#include "pch.h" - -#include "trace.h" - -#include - -TRACELOGGING_DEFINE_PROVIDER( - g_hProvider, - "Microsoft.PowerToys", - // {38e8889b-9731-53f5-e901-e8a7c1753074} - (0x38e8889b, 0x9731, 0x53f5, 0xe9, 0x01, 0xe8, 0xa7, 0xc1, 0x75, 0x30, 0x74), - TraceLoggingOptionProjectTelemetry()); - -// Log if the user has VCM enabled or disabled -void Trace::EnableVideoConference(const bool enabled) noexcept -{ - TraceLoggingWriteWrapper( - g_hProvider, - "VideoConference_EnableVideoConference", - ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance), - TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE), - TraceLoggingBoolean(enabled, "Enabled")); -} - -void Trace::SettingsChanged(const struct VideoConferenceSettings& settings) noexcept -{ - bool CustomOverlayImage = (settings.imageOverlayPath.length() > 0); - - TraceLoggingWriteWrapper( - g_hProvider, - "VideoConference_SettingsChanged", - TraceLoggingWideString(settings.toolbarPositionString.c_str(), "ToolbarPosition"), - TraceLoggingWideString(settings.toolbarMonitorString.c_str(), "ToolbarMonitorSelection"), - TraceLoggingBool(CustomOverlayImage, "CustomImageOverlayUsed"), - ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance), - TraceLoggingBoolean(TRUE, "UTCReplace_AppSessionGuid"), - TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE)); -} - -void Trace::MicrophoneMuted() noexcept -{ - TraceLoggingWriteWrapper( - g_hProvider, - "VideoConference_MicrophoneMuted", - TraceLoggingBoolean(true, "MicrophoneMuted"), - ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance), - TraceLoggingBoolean(TRUE, "UTCReplace_AppSessionGuid"), - TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE)); -} - -void Trace::CameraMuted() noexcept -{ - TraceLoggingWriteWrapper( - g_hProvider, - "VideoConference_CameraMuted", - TraceLoggingBoolean(true, "CameraMuted"), - ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance), - TraceLoggingBoolean(TRUE, "UTCReplace_AppSessionGuid"), - TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE)); -} diff --git a/src/modules/videoconference/VideoConferenceModule/trace.h b/src/modules/videoconference/VideoConferenceModule/trace.h deleted file mode 100644 index 0a9f193e6951..000000000000 --- a/src/modules/videoconference/VideoConferenceModule/trace.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once -#include "VideoConferenceModule.h" - -#include - -class Trace : public telemetry::TraceBase -{ -public: - static void EnableVideoConference(const bool enabled) noexcept; - static void SettingsChanged(const struct VideoConferenceSettings &settings) noexcept; - static void MicrophoneMuted() noexcept; - static void CameraMuted() noexcept; -}; diff --git a/src/modules/videoconference/VideoConferenceProxyFilter/DirectShowUtils.cpp b/src/modules/videoconference/VideoConferenceProxyFilter/DirectShowUtils.cpp deleted file mode 100644 index ef2d3f76ea5e..000000000000 --- a/src/modules/videoconference/VideoConferenceProxyFilter/DirectShowUtils.cpp +++ /dev/null @@ -1,113 +0,0 @@ -#include "DirectShowUtils.h" - -#include - -unique_media_type_ptr CopyMediaType(const AM_MEDIA_TYPE* source) -{ - unique_media_type_ptr target{ static_cast(CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE))) }; - *target = *source; - if (source->cbFormat) - { - target->pbFormat = static_cast(CoTaskMemAlloc(source->cbFormat)); - std::copy(source->pbFormat, source->pbFormat + source->cbFormat, target->pbFormat); - } - - if (target->pUnk) - { - target->pUnk->AddRef(); - } - - return target; -} - -wil::com_ptr_nothrow GetPinAllocator(wil::com_ptr_nothrow& inputPin) -{ - if (!inputPin) - { - return nullptr; - } - wil::com_ptr_nothrow allocator; - if (auto memInput = inputPin.try_query(); memInput) - { - memInput->GetAllocator(&allocator); - return allocator; - } - - return nullptr; -} - -void MyFreeMediaType(AM_MEDIA_TYPE& mt) -{ - if (mt.cbFormat != 0) - { - CoTaskMemFree(mt.pbFormat); - mt.cbFormat = 0; - mt.pbFormat = nullptr; - } - - if (mt.pUnk != nullptr) - { - mt.pUnk->Release(); - mt.pUnk = nullptr; - } -} - -void MyDeleteMediaType(AM_MEDIA_TYPE* pmt) -{ - if (!pmt) - { - return; - } - - MyFreeMediaType(*pmt); - CoTaskMemFree(const_cast(pmt)); -} - -HRESULT MediaTypeEnumerator::Next(ULONG cObjects, AM_MEDIA_TYPE** outObjects, ULONG* pcFetched) -{ - if (!outObjects) - { - return E_POINTER; - } - - ULONG fetched = 0; - ULONG toFetch = cObjects; - while (toFetch-- && _pos < _objects.size()) - { - auto copy = CopyMediaType(_objects[_pos++].get()); - outObjects[fetched++] = copy.release(); - } - - if (pcFetched) - { - *pcFetched = fetched; - } - - return fetched == cObjects ? S_OK : S_FALSE; -} - -HRESULT MediaTypeEnumerator::Skip(ULONG cObjects) -{ - _pos += cObjects; - return _pos < _objects.size() ? S_OK : S_FALSE; -} - -HRESULT MediaTypeEnumerator::Reset() -{ - _pos = 0; - return S_OK; -} - -HRESULT MediaTypeEnumerator::Clone(IEnumMediaTypes** ppEnum) -{ - auto cloned = winrt::make_self(); - cloned->_objects.resize(_objects.size()); - for (size_t i = 0; i < _objects.size(); ++i) - { - cloned->_objects[i] = CopyMediaType(_objects[i].get()); - } - - cloned->_pos = _pos; - cloned.as().copy_to(ppEnum); - return S_OK; -} \ No newline at end of file diff --git a/src/modules/videoconference/VideoConferenceProxyFilter/DirectShowUtils.h b/src/modules/videoconference/VideoConferenceProxyFilter/DirectShowUtils.h deleted file mode 100644 index d8c35a54b62b..000000000000 --- a/src/modules/videoconference/VideoConferenceProxyFilter/DirectShowUtils.h +++ /dev/null @@ -1,87 +0,0 @@ -#pragma once -#include - -#define WIN32_LEAN_AND_MEAN -#include -#include - -#include -#include - -#include - -#include "Logging.h" - -void MyDeleteMediaType(AM_MEDIA_TYPE* pmt); - -using unique_media_type_ptr = - wistd::unique_ptr>; - -unique_media_type_ptr CopyMediaType(const AM_MEDIA_TYPE* source); - -template -struct ObjectEnumerator : public winrt::implements, EnumeratorInterface> -{ - std::vector> _objects; - ULONG _pos = 0; - - HRESULT STDMETHODCALLTYPE Next(ULONG cObjects, ObjectInterface** outObjects, ULONG* pcFetched) override - { - if (!outObjects) - { - return E_POINTER; - } - - ULONG fetched = 0; - ULONG toFetch = cObjects; - while (toFetch-- && _pos < _objects.size()) - { - _objects[_pos++].copy_to(&outObjects[fetched++]); - } - - if (pcFetched) - { - *pcFetched = fetched; - } - - return fetched == cObjects ? S_OK : S_FALSE; - } - - HRESULT STDMETHODCALLTYPE Skip(ULONG cObjects) override - { - _pos += cObjects; - return _pos < _objects.size() ? S_OK : S_FALSE; - } - - HRESULT STDMETHODCALLTYPE Reset() override - { - _pos = 0; - return S_OK; - } - - HRESULT STDMETHODCALLTYPE Clone(EnumeratorInterface** ppEnum) override - { - auto cloned = winrt::make_self(); - cloned->_objects = _objects; - cloned->_pos = _pos; - cloned.as().copy_to(ppEnum); - return S_OK; - } - - virtual ~ObjectEnumerator() = default; -}; - -struct MediaTypeEnumerator : public winrt::implements -{ - std::vector _objects; - ULONG _pos = 0; - - HRESULT STDMETHODCALLTYPE Next(ULONG cObjects, AM_MEDIA_TYPE** outObjects, ULONG* pcFetched) override; - HRESULT STDMETHODCALLTYPE Skip(ULONG cObjects) override; - HRESULT STDMETHODCALLTYPE Reset() override; - HRESULT STDMETHODCALLTYPE Clone(IEnumMediaTypes** ppEnum) override; - - virtual ~MediaTypeEnumerator() = default; -}; - -wil::com_ptr_nothrow GetPinAllocator(wil::com_ptr_nothrow& inputPin); diff --git a/src/modules/videoconference/VideoConferenceProxyFilter/ImageLoading.cpp b/src/modules/videoconference/VideoConferenceProxyFilter/ImageLoading.cpp deleted file mode 100644 index 48878011540e..000000000000 --- a/src/modules/videoconference/VideoConferenceProxyFilter/ImageLoading.cpp +++ /dev/null @@ -1,424 +0,0 @@ -#include - -#include -#include -#include - -#pragma warning(push) -#pragma warning(disable : 4005) -#include -#pragma warning(pop) - -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include - -#include - -#include "Logging.h" - -IWICImagingFactory* _GetWIC() noexcept -{ - static IWICImagingFactory* s_Factory = nullptr; - - if (s_Factory) - { - return s_Factory; - } - - OK_OR_BAIL(CoCreateInstance( - CLSID_WICImagingFactory, nullptr, CLSCTX_INPROC_SERVER, __uuidof(IWICImagingFactory), (LPVOID*)&s_Factory)); - - return s_Factory; -} - -bool ReencodeJPGImage(BYTE* imageBuf, const DWORD imageSize, DWORD& reencodedSize) -{ - auto pWIC = _GetWIC(); - wil::com_ptr_nothrow imageStream = SHCreateMemStream(imageBuf, imageSize); - if (!imageStream) - { - return false; - } - - // Decode jpg into bitmap - wil::com_ptr_nothrow bitmapDecoder; - OK_OR_BAIL(pWIC->CreateDecoderFromStream(imageStream.get(), nullptr, WICDecodeMetadataCacheOnLoad, &bitmapDecoder)); - wil::com_ptr_nothrow decodedFrame; - OK_OR_BAIL(bitmapDecoder->GetFrame(0, &decodedFrame)); - wil::com_ptr_nothrow bitmap; - bitmap.attach(decodedFrame.detach()); - UINT width = 0, height = 0; - OK_OR_BAIL(bitmap->GetSize(&width, &height)); - - // Initialize jpg encoder - wil::com_ptr_nothrow encoder; - OK_OR_BAIL(pWIC->CreateEncoder(GUID_ContainerFormatJpeg, nullptr, &encoder)); - - wil::com_ptr_nothrow outputStream; - OK_OR_BAIL(CreateStreamOnHGlobal(nullptr, true, &outputStream)); - OK_OR_BAIL(encoder->Initialize(outputStream.get(), WICBitmapEncoderNoCache)); - wil::com_ptr_nothrow encodedFrame; - wil::com_ptr_nothrow encoderOptions; - OK_OR_BAIL(encoder->CreateNewFrame(&encodedFrame, &encoderOptions)); - - ULONG nProperties = 0; - OK_OR_BAIL(encoderOptions->CountProperties(&nProperties)); - for (ULONG propIdx = 0; propIdx < nProperties; ++propIdx) - { - PROPBAG2 propBag{}; - ULONG _; - OK_OR_BAIL(encoderOptions->GetPropertyInfo(propIdx, 1, &propBag, &_)); - if (propBag.pstrName == std::wstring_view{ L"ImageQuality" }) - { - wil::unique_variant variant; - variant.vt = VT_R4; - variant.fltVal = 0.1f; - OK_OR_BAIL(encoderOptions->Write(1, &propBag, &variant)); - LOG("Successfully set jpg compression quality"); - // skip the rest of the properties - propIdx = nProperties; - } - CoTaskMemFree(propBag.pstrName); - } - - OK_OR_BAIL(encodedFrame->Initialize(encoderOptions.get())); - WICPixelFormatGUID intermediateFormat = GUID_WICPixelFormat24bppRGB; - - OK_OR_BAIL(encodedFrame->SetPixelFormat(&intermediateFormat)); - OK_OR_BAIL(encodedFrame->SetSize(width, height)); - - // Commit the image encoding - OK_OR_BAIL(encodedFrame->WriteSource(bitmap.get(), nullptr)); - OK_OR_BAIL(encodedFrame->Commit()); - OK_OR_BAIL(encoder->Commit()); - - STATSTG intermediateStreamStat{}; - OK_OR_BAIL(outputStream->Stat(&intermediateStreamStat, STATFLAG_NONAME)); - const ULONGLONG jpgStreamSize = intermediateStreamStat.cbSize.QuadPart; - HGLOBAL streamMemoryHandle{}; - OK_OR_BAIL(GetHGlobalFromStream(outputStream.get(), &streamMemoryHandle)); - - auto jpgStreamMemory = static_cast(GlobalLock(streamMemoryHandle)); - std::copy(jpgStreamMemory, jpgStreamMemory + jpgStreamSize, imageBuf); - auto unlockJpgStreamMemory = wil::scope_exit([jpgStreamMemory] { GlobalUnlock(jpgStreamMemory); }); - reencodedSize = static_cast(jpgStreamSize); - return true; -} - -wil::com_ptr_nothrow LoadAsRGB24BitmapWithSize(IWICImagingFactory* pWIC, - wil::com_ptr_nothrow image, - const UINT targetWidth, - const UINT targetHeight) -{ - wil::com_ptr_nothrow bitmap; - // Initialize image bitmap decoder from filename and get the image frame - wil::com_ptr_nothrow bitmapDecoder; - OK_OR_BAIL(pWIC->CreateDecoderFromStream(image.get(), nullptr, WICDecodeMetadataCacheOnLoad, &bitmapDecoder)); - - wil::com_ptr_nothrow decodedFrame; - OK_OR_BAIL(bitmapDecoder->GetFrame(0, &decodedFrame)); - - UINT imageWidth = 0, imageHeight = 0; - OK_OR_BAIL(decodedFrame->GetSize(&imageWidth, &imageHeight)); - - // Scale the image if required - if (targetWidth != imageWidth || targetHeight != imageHeight) - { - wil::com_ptr_nothrow scaler; - OK_OR_BAIL(pWIC->CreateBitmapScaler(&scaler)); - OK_OR_BAIL( - scaler->Initialize(decodedFrame.get(), targetWidth, targetHeight, WICBitmapInterpolationModeHighQualityCubic)); - bitmap.attach(scaler.detach()); - } - else - { - bitmap.attach(decodedFrame.detach()); - } - WICPixelFormatGUID pixelFormat{}; - OK_OR_BAIL(bitmap->GetPixelFormat(&pixelFormat)); - - const auto targetPixelFormat = GUID_WICPixelFormat24bppBGR; - if (pixelFormat != targetPixelFormat) - { - wil::com_ptr_nothrow convertedBitmap; - if (SUCCEEDED(WICConvertBitmapSource(targetPixelFormat, bitmap.get(), &convertedBitmap))) - { - return convertedBitmap; - } - } - - return bitmap; -} - -wil::com_ptr_nothrow EncodeBitmapToContainer(IWICImagingFactory* pWIC, - wil::com_ptr_nothrow bitmap, - const GUID& containerGUID, - const UINT width, - const UINT height, - const float quality) -{ - wil::com_ptr_nothrow encoder; - pWIC->CreateEncoder(containerGUID, nullptr, &encoder); - - if (!encoder) - { - return nullptr; - } - - // Prepare the encoder output memory stream and encoding params - wil::com_ptr_nothrow encodedBitmap; - OK_OR_BAIL(CreateStreamOnHGlobal(nullptr, true, &encodedBitmap)); - OK_OR_BAIL(encoder->Initialize(encodedBitmap.get(), WICBitmapEncoderNoCache)); - wil::com_ptr_nothrow encodedFrame; - - wil::com_ptr_nothrow encoderOptions; - OK_OR_BAIL(encoder->CreateNewFrame(&encodedFrame, &encoderOptions)); - - ULONG nProperties = 0; - OK_OR_BAIL(encoderOptions->CountProperties(&nProperties)); - for (ULONG propIdx = 0; propIdx < nProperties; ++propIdx) - { - PROPBAG2 propBag{}; - ULONG _; - OK_OR_BAIL(encoderOptions->GetPropertyInfo(propIdx, 1, &propBag, &_)); - if (propBag.pstrName == std::wstring_view{ L"ImageQuality" }) - { - wil::unique_variant variant; - variant.vt = VT_R4; - variant.fltVal = quality; - OK_OR_BAIL(encoderOptions->Write(1, &propBag, &variant)); - LOG("Successfully set jpg compression quality"); - // skip the rest of the properties - propIdx = nProperties; - } - CoTaskMemFree(propBag.pstrName); - } - - OK_OR_BAIL(encodedFrame->Initialize(encoderOptions.get())); - - WICPixelFormatGUID intermediateFormat = GUID_WICPixelFormat24bppRGB; - OK_OR_BAIL(encodedFrame->SetPixelFormat(&intermediateFormat)); - OK_OR_BAIL(encodedFrame->SetSize(width, height)); - - // Commit the image encoding - OK_OR_BAIL(encodedFrame->WriteSource(bitmap.get(), nullptr)); - OK_OR_BAIL(encodedFrame->Commit()); - OK_OR_BAIL(encoder->Commit()); - return encodedBitmap; -} - -IMFSample* ConvertIMFVideoSample(const MFT_REGISTER_TYPE_INFO& inputType, - IMFMediaType* outputMediaType, - const wil::com_ptr_nothrow& inputSample, - const UINT width, - const UINT height) -{ - IMFActivate** ppVDActivate = nullptr; - UINT32 count = 0; - - MFT_REGISTER_TYPE_INFO outputType = { MFMediaType_Video, {} }; - outputMediaType->GetGUID(MF_MT_SUBTYPE, &outputType.guidSubtype); - - const std::array transformerCategories = { - MFT_CATEGORY_VIDEO_PROCESSOR, MFT_CATEGORY_VIDEO_DECODER, MFT_CATEGORY_VIDEO_ENCODER - }; - - for (const auto& transformerCategory : transformerCategories) - { - OK_OR_BAIL(MFTEnumEx(transformerCategory, MFT_ENUM_FLAG_SYNCMFT, &inputType, &outputType, &ppVDActivate, &count)); - if (count != 0) - { - break; - } - } - - wil::com_ptr_nothrow videoTransformer; - - bool videoDecoderActivated = false; - for (UINT32 i = 0; i < count; ++i) - { - if (!videoDecoderActivated && !FAILED(ppVDActivate[i]->ActivateObject(IID_PPV_ARGS(&videoTransformer)))) - { - videoDecoderActivated = true; - } - ppVDActivate[i]->Release(); - } - - if (count) - { - CoTaskMemFree(ppVDActivate); - } - - if (!videoDecoderActivated) - { - LOG("No converter available for the selected format"); - return nullptr; - } - - auto shutdownVideoDecoder = wil::scope_exit([&videoTransformer] { MFShutdownObject(videoTransformer.get()); }); - // Set input/output types for the decoder - wil::com_ptr_nothrow intermediateFrameMediaType; - OK_OR_BAIL(MFCreateMediaType(&intermediateFrameMediaType)); - intermediateFrameMediaType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video); - intermediateFrameMediaType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_RGB24); - intermediateFrameMediaType->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive); - intermediateFrameMediaType->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE); - OK_OR_BAIL(MFSetAttributeSize(intermediateFrameMediaType.get(), MF_MT_FRAME_SIZE, width, height)); - OK_OR_BAIL(MFSetAttributeRatio(intermediateFrameMediaType.get(), MF_MT_PIXEL_ASPECT_RATIO, width, height)); - OK_OR_BAIL(videoTransformer->SetInputType(0, intermediateFrameMediaType.get(), 0)); - OK_OR_BAIL(videoTransformer->SetOutputType(0, outputMediaType, 0)); - - // Process the input sample - OK_OR_BAIL(videoTransformer->ProcessInput(0, inputSample.get(), 0)); - - // Check whether we need to allocate output sample and buffer ourselves - MFT_OUTPUT_STREAM_INFO outputStreamInfo{}; - OK_OR_BAIL(videoTransformer->GetOutputStreamInfo(0, &outputStreamInfo)); - const bool onlyProvidesSamples = outputStreamInfo.dwFlags & MFT_OUTPUT_STREAM_PROVIDES_SAMPLES; - const bool canProvideSamples = outputStreamInfo.dwFlags & MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES; - const bool mustAllocateSample = - (!onlyProvidesSamples && !canProvideSamples) || - (!onlyProvidesSamples && (outputStreamInfo.dwFlags & MFT_PROCESS_OUTPUT_DISCARD_WHEN_NO_BUFFER)); - - MFT_OUTPUT_DATA_BUFFER outputSamples{}; - IMFSample* outputSample = nullptr; - - // If so, do the allocation - if (mustAllocateSample) - { - OK_OR_BAIL(MFCreateSample(&outputSample)); - OK_OR_BAIL(outputSample->SetSampleDuration(333333)); - OK_OR_BAIL(outputSample->SetSampleTime(1)); - OK_OR_BAIL(outputSample->SetUINT32(MF_MT_VIDEO_ROTATION, MFVideoRotationFormat::MFVideoRotationFormat_0)); - IMFMediaBuffer* outputMediaBuffer = nullptr; - OK_OR_BAIL( - MFCreateAlignedMemoryBuffer(outputStreamInfo.cbSize, outputStreamInfo.cbAlignment - 1, &outputMediaBuffer)); - OK_OR_BAIL(outputMediaBuffer->SetCurrentLength(outputStreamInfo.cbSize)); - OK_OR_BAIL(outputSample->AddBuffer(outputMediaBuffer)); - outputSamples.pSample = outputSample; - } - - // Finally, produce the output sample - DWORD processStatus = 0; - if (failed(videoTransformer->ProcessOutput(0, 1, &outputSamples, &processStatus))) - { - LOG("Failed to convert image frame"); - } - if (outputSamples.pEvents) - { - outputSamples.pEvents->Release(); - } - - return outputSamples.pSample; -} - -wil::com_ptr_nothrow LoadImageAsSample(wil::com_ptr_nothrow imageStream, - IMFMediaType* sampleMediaType, - const float quality) noexcept -{ - UINT targetWidth = 0; - UINT targetHeight = 0; - OK_OR_BAIL(MFGetAttributeSize(sampleMediaType, MF_MT_FRAME_SIZE, &targetWidth, &targetHeight)); - MFT_REGISTER_TYPE_INFO outputType = { MFMediaType_Video, {} }; - OK_OR_BAIL(sampleMediaType->GetGUID(MF_MT_SUBTYPE, &outputType.guidSubtype)); - - IWICImagingFactory* pWIC = _GetWIC(); - if (!pWIC) - { - LOG("Failed to create IWICImagingFactory"); - return nullptr; - } - - if (!imageStream) - { - return nullptr; - } - - const auto srcImageBitmap = LoadAsRGB24BitmapWithSize(pWIC, imageStream, targetWidth, targetHeight); - if (!srcImageBitmap) - { - return nullptr; - } - - // First, let's create a sample containing RGB24 bitmap - IMFSample* outputSample = nullptr; - OK_OR_BAIL(MFCreateSample(&outputSample)); - OK_OR_BAIL(outputSample->SetUINT32(MF_MT_VIDEO_ROTATION, MFVideoRotationFormat::MFVideoRotationFormat_0)); - OK_OR_BAIL(outputSample->SetSampleDuration(333333)); - OK_OR_BAIL(outputSample->SetSampleTime(1)); - IMFMediaBuffer* outputMediaBuffer = nullptr; - const DWORD nPixelBytes = targetWidth * targetHeight * 3; - OK_OR_BAIL(MFCreateAlignedMemoryBuffer(nPixelBytes, MF_64_BYTE_ALIGNMENT, &outputMediaBuffer)); - - const UINT stride = 3 * targetWidth; - - DWORD max_length = 0, current_length = 0; - BYTE* sampleBufferMemory = nullptr; - OK_OR_BAIL(outputMediaBuffer->Lock(&sampleBufferMemory, &max_length, ¤t_length)); - OK_OR_BAIL(srcImageBitmap->CopyPixels(nullptr, stride, nPixelBytes, sampleBufferMemory)); - OK_OR_BAIL(outputMediaBuffer->Unlock()); - - OK_OR_BAIL(outputMediaBuffer->SetCurrentLength(nPixelBytes)); - OK_OR_BAIL(outputSample->AddBuffer(outputMediaBuffer)); - - if (outputType.guidSubtype == MFVideoFormat_RGB24) - { - return outputSample; - } - - // Special case for mjpg, since we need to use jpg container for it instead of supplying raw pixels - if (outputType.guidSubtype == MFVideoFormat_MJPG) - { - // Use an intermediate jpg container sample which will be transcoded to the target format - wil::com_ptr_nothrow jpgStream = - EncodeBitmapToContainer(pWIC, srcImageBitmap, GUID_ContainerFormatJpeg, targetWidth, targetHeight, quality); - - // Obtain stream size and lock its memory pointer - STATSTG intermediateStreamStat{}; - OK_OR_BAIL(jpgStream->Stat(&intermediateStreamStat, STATFLAG_NONAME)); - const ULONGLONG jpgStreamSize = intermediateStreamStat.cbSize.QuadPart; - HGLOBAL streamMemoryHandle{}; - OK_OR_BAIL(GetHGlobalFromStream(jpgStream.get(), &streamMemoryHandle)); - - auto jpgStreamMemory = static_cast(GlobalLock(streamMemoryHandle)); - auto unlockJpgStreamMemory = wil::scope_exit([jpgStreamMemory] { GlobalUnlock(jpgStreamMemory); }); - - // Create a sample from the input image buffer - wil::com_ptr_nothrow jpgSample; - OK_OR_BAIL(MFCreateSample(&jpgSample)); - OK_OR_BAIL(jpgSample->SetUINT32(MF_MT_VIDEO_ROTATION, MFVideoRotationFormat::MFVideoRotationFormat_0)); - IMFMediaBuffer* inputMediaBuffer = nullptr; - OK_OR_BAIL(MFCreateAlignedMemoryBuffer(static_cast(jpgStreamSize), MF_64_BYTE_ALIGNMENT, &inputMediaBuffer)); - BYTE* inputBuf = nullptr; - OK_OR_BAIL(inputMediaBuffer->Lock(&inputBuf, &max_length, ¤t_length)); - if (max_length < jpgStreamSize) - { - return nullptr; - } - - std::copy(jpgStreamMemory, jpgStreamMemory + jpgStreamSize, inputBuf); - unlockJpgStreamMemory.reset(); - OK_OR_BAIL(inputMediaBuffer->Unlock()); - OK_OR_BAIL(inputMediaBuffer->SetCurrentLength(static_cast(jpgStreamSize))); - OK_OR_BAIL(jpgSample->AddBuffer(inputMediaBuffer)); - - return jpgSample; - } - - // Now we are ready to convert it to the requested media type - MFT_REGISTER_TYPE_INFO intermediateType = { MFMediaType_Video, MFVideoFormat_RGB24 }; - - // But if no conversion is needed, just return the input sample - - return ConvertIMFVideoSample(intermediateType, sampleMediaType, outputSample, targetWidth, targetHeight); -} \ No newline at end of file diff --git a/src/modules/videoconference/VideoConferenceProxyFilter/Resources.resx b/src/modules/videoconference/VideoConferenceProxyFilter/Resources.resx deleted file mode 100644 index 4770a524fe27..000000000000 --- a/src/modules/videoconference/VideoConferenceProxyFilter/Resources.resx +++ /dev/null @@ -1,124 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - VideoCaptureProxyFilter - do not loc, product name - - diff --git a/src/modules/videoconference/VideoConferenceProxyFilter/VideoCaptureDevice.cpp b/src/modules/videoconference/VideoConferenceProxyFilter/VideoCaptureDevice.cpp deleted file mode 100644 index 7b97891c5b39..000000000000 --- a/src/modules/videoconference/VideoConferenceProxyFilter/VideoCaptureDevice.cpp +++ /dev/null @@ -1,636 +0,0 @@ -#include "Logging.h" -#include "VideoCaptureDevice.h" - -#include -#include - -struct VideoCaptureReceiverFilter : winrt::implements -{ - FILTER_STATE _state = State_Stopped; - IFilterGraph* _graph = nullptr; - wil::com_ptr_nothrow _videoReceiverPin; - - ULONG STDMETHODCALLTYPE GetMiscFlags() override { return AM_FILTER_MISC_FLAGS_IS_RENDERER; } - - HRESULT STDMETHODCALLTYPE GetClassID(CLSID*) override { return E_NOTIMPL; } - - HRESULT STDMETHODCALLTYPE Stop() override - { - _state = State_Stopped; - return S_OK; - } - - HRESULT STDMETHODCALLTYPE Pause() override - { - _state = State_Paused; - return S_OK; - } - - HRESULT STDMETHODCALLTYPE Run(REFERENCE_TIME) override - { - _state = State_Running; - return S_OK; - } - - HRESULT STDMETHODCALLTYPE GetState(DWORD, FILTER_STATE* outState) override - { - *outState = _state; - return S_OK; - } - - HRESULT STDMETHODCALLTYPE GetSyncSource(IReferenceClock** outRefClock) override - { - *outRefClock = nullptr; - return NOERROR; - } - - HRESULT STDMETHODCALLTYPE SetSyncSource(IReferenceClock*) override { return S_OK; } - - HRESULT STDMETHODCALLTYPE EnumPins(IEnumPins** ppEnum) override - { - auto enumerator = winrt::make_self>(); - enumerator->_objects.emplace_back(_videoReceiverPin); - *ppEnum = enumerator.detach(); - - return S_OK; - } - - HRESULT STDMETHODCALLTYPE FindPin(LPCWSTR, IPin**) override { return E_NOTIMPL; } - - HRESULT STDMETHODCALLTYPE JoinFilterGraph(IFilterGraph* pGraph, LPCWSTR) override - { - _graph = pGraph; - return S_OK; - } - - HRESULT STDMETHODCALLTYPE QueryFilterInfo(FILTER_INFO* pInfo) override - { - std::copy(std::begin(NAME), std::end(NAME), pInfo->achName); - if (_graph) - { - pInfo->pGraph = _graph; - _graph->AddRef(); - } - return S_OK; - } - - HRESULT STDMETHODCALLTYPE QueryVendorInfo(LPWSTR* pVendorInfo) override - { - auto info = static_cast(CoTaskMemAlloc(sizeof(VENDOR))); - std::copy(std::begin(VENDOR), std::end(VENDOR), info); - *pVendorInfo = info; - return S_OK; - } - - virtual ~VideoCaptureReceiverFilter() = default; - - constexpr static inline wchar_t NAME[] = L"PowerToysVCMCaptureFilter"; - constexpr static inline wchar_t VENDOR[] = L"Microsoft Corporation"; -}; - -struct VideoCaptureReceiverPin : winrt::implements -{ - VideoCaptureReceiverFilter* _owningFilter = nullptr; - unique_media_type_ptr _expectedMediaType; - wil::com_ptr_nothrow _captureInputPin; - unique_media_type_ptr _inputCaptureMediaType; - std::atomic_bool _flushing = false; - VideoCaptureDevice::callback_t _frameCallback; - - wil::com_ptr_nothrow _allocator; - - VideoCaptureReceiverPin(unique_media_type_ptr mediaType, VideoCaptureReceiverFilter* filter) : - _expectedMediaType{ std::move(mediaType) }, _owningFilter{ filter } - { - } - - HRESULT STDMETHODCALLTYPE Connect(IPin*, const AM_MEDIA_TYPE* pmt) override - { - if (_owningFilter->_state == State_Running) - { - return VFW_E_NOT_STOPPED; - } - - if (_captureInputPin) - { - return VFW_E_ALREADY_CONNECTED; - } - - if (!pmt || pmt->majortype == GUID_NULL) - { - return S_OK; - } - - if (pmt->majortype != _expectedMediaType->majortype || pmt->subtype != _expectedMediaType->subtype) - { - return S_FALSE; - } - - return S_OK; - } - - HRESULT STDMETHODCALLTYPE ReceiveConnection(IPin* pConnector, const AM_MEDIA_TYPE* pmt) override - { - if (!pConnector || !pmt) - { - return E_POINTER; - } - - if (_captureInputPin) - { - return VFW_E_ALREADY_CONNECTED; - } - - if (_owningFilter->_state != State_Stopped) - { - return VFW_E_NOT_STOPPED; - } - - if (QueryAccept(pmt) != S_OK) - { - return VFW_E_TYPE_NOT_ACCEPTED; - } - - _captureInputPin = pConnector; - _inputCaptureMediaType = CopyMediaType(pmt); - - return S_OK; - } - - HRESULT STDMETHODCALLTYPE Disconnect() override - { - _allocator.reset(); - _captureInputPin.reset(); - _inputCaptureMediaType.reset(); - return S_OK; - } - - HRESULT STDMETHODCALLTYPE ConnectedTo(IPin** pPin) override - { - if (!_captureInputPin) - { - return VFW_E_NOT_CONNECTED; - } - - return _captureInputPin.try_copy_to(pPin) ? S_OK : E_FAIL; - } - - HRESULT STDMETHODCALLTYPE ConnectionMediaType(AM_MEDIA_TYPE* pmt) override - { - if (!pmt) - { - return E_POINTER; - } - - if (!_inputCaptureMediaType) - { - return VFW_E_NOT_CONNECTED; - } - - *pmt = *CopyMediaType(_inputCaptureMediaType.get()).release(); - return S_OK; - } - - HRESULT STDMETHODCALLTYPE QueryPinInfo(PIN_INFO* pInfo) override - { - if (!pInfo) - { - return E_POINTER; - } - - pInfo->pFilter = _owningFilter; - if (_owningFilter) - { - _owningFilter->AddRef(); - } - - pInfo->dir = PINDIR_INPUT; - std::copy(std::begin(NAME), std::end(NAME), pInfo->achName); - return S_OK; - } - - HRESULT STDMETHODCALLTYPE QueryDirection(PIN_DIRECTION* pPinDir) override - { - if (!pPinDir) - { - return E_POINTER; - } - - *pPinDir = PINDIR_INPUT; - return S_OK; - } - - HRESULT STDMETHODCALLTYPE QueryId(LPWSTR* lpId) override - { - if (!lpId) - { - return E_POINTER; - } - - *lpId = static_cast(CoTaskMemAlloc(sizeof(NAME))); - - std::copy(std::begin(NAME), std::end(NAME), *lpId); - return S_OK; - } - - HRESULT STDMETHODCALLTYPE QueryAccept(const AM_MEDIA_TYPE* pmt) override - { - if (!pmt) - { - return E_POINTER; - } - - if (pmt->majortype != _expectedMediaType->majortype || pmt->subtype != _expectedMediaType->subtype) - { - return S_FALSE; - } - - if (_captureInputPin) - { -// disable warning 26492 - Don't use const_cast to cast away const -// reset needs 'pmt' to be non-const, we can't easily change the query accept prototype -// because of the inheritance. -#pragma warning(suppress : 26492) - _inputCaptureMediaType.reset(const_cast(pmt)); - } - - return S_OK; - } - - HRESULT STDMETHODCALLTYPE EnumMediaTypes(IEnumMediaTypes** ppEnum) override - { - if (!ppEnum) - { - return E_POINTER; - } - - auto enumerator = winrt::make_self(); - enumerator->_objects.emplace_back(CopyMediaType(_expectedMediaType.get())); - *ppEnum = enumerator.detach(); - - return S_OK; - } - - HRESULT STDMETHODCALLTYPE QueryInternalConnections(IPin**, ULONG*) override { return E_NOTIMPL; } - - HRESULT STDMETHODCALLTYPE EndOfStream() override { return S_OK; } - - HRESULT STDMETHODCALLTYPE BeginFlush() override - { - _flushing = true; - return S_OK; - } - - HRESULT STDMETHODCALLTYPE EndFlush() override - { - _flushing = false; - return S_OK; - } - - HRESULT STDMETHODCALLTYPE NewSegment(REFERENCE_TIME, REFERENCE_TIME, double) override { return S_OK; } - - HRESULT STDMETHODCALLTYPE GetAllocator(IMemAllocator** allocator) override - { - VERBOSE_LOG; - if (!_allocator) - { - return VFW_E_NO_ALLOCATOR; - } - - return _allocator.try_copy_to(allocator) ? S_OK : E_FAIL; - } - - HRESULT STDMETHODCALLTYPE NotifyAllocator(IMemAllocator* allocator, BOOL readOnly) override - { - VERBOSE_LOG; - LOG(readOnly ? "Allocator READONLY: true" : "Allocator READONLY: false"); - _allocator = allocator; - return S_OK; - } - - HRESULT STDMETHODCALLTYPE GetAllocatorRequirements(ALLOCATOR_PROPERTIES*) override { return E_NOTIMPL; } - - HRESULT STDMETHODCALLTYPE Receive(IMediaSample* pSample) override - { - if (_flushing) - { - return S_FALSE; - } - - if (!pSample) - { - return E_POINTER; - } - - if (pSample && _frameCallback) - { - _frameCallback(pSample); - } - - return S_OK; - } - - HRESULT STDMETHODCALLTYPE ReceiveMultiple(IMediaSample** pSamples, long nSamples, long* nSamplesProcessed) override - { - if (!pSamples && nSamples) - { - return E_POINTER; - } - - if (_flushing) - { - return S_FALSE; - } - - for (long i = 0; i < nSamples; i++) - { - Receive(pSamples[i]); - } - - *nSamplesProcessed = nSamples; - return S_OK; - } - - HRESULT STDMETHODCALLTYPE ReceiveCanBlock() override { return S_FALSE; } - - virtual ~VideoCaptureReceiverPin() = default; - - constexpr static inline wchar_t NAME[] = L"PowerToysVCMCapturePin"; -}; - -constexpr long MINIMAL_FPS_ALLOWED = 29; - -const char* GetMediaSubTypeString(const GUID& guid) -{ - if (guid == MEDIASUBTYPE_RGB24) - { - return "MEDIASUBTYPE_RGB24"; - } - - if (guid == MEDIASUBTYPE_YUY2) - { - return "MEDIASUBTYPE_YUY2"; - } - - if (guid == MEDIASUBTYPE_MJPG) - { - return "MEDIASUBTYPE_MJPG"; - } - - if (guid == MEDIASUBTYPE_NV12) - { - return "MEDIASUBTYPE_NV12"; - } - - return "MEDIASUBTYPE_UNKNOWN"; -} - -std::optional SelectBestMediaType(wil::com_ptr_nothrow& pin) -{ - VERBOSE_LOG; - wil::com_ptr_nothrow mediaTypeEnum; - if (pin->EnumMediaTypes(&mediaTypeEnum); !mediaTypeEnum) - { - return std::nullopt; - } - - ULONG _ = 0; - VideoStreamFormat bestFormat; - unique_media_type_ptr mt; - while (mediaTypeEnum->Next(1, wil::out_param(mt), &_) == S_OK) - { - if (mt->majortype != MEDIATYPE_Video) - { - continue; - } - - auto format = reinterpret_cast(mt->pbFormat); - if (!format || !format->AvgTimePerFrame) - { - LOG("VideoInfoHeader not found"); - continue; - } - - const auto formatAvgFPS = 10000000LL / format->AvgTimePerFrame; - if (format->AvgTimePerFrame > bestFormat.avgFrameTime || formatAvgFPS < MINIMAL_FPS_ALLOWED) - { - continue; - } - - if (format->bmiHeader.biWidth < bestFormat.width || format->bmiHeader.biHeight < bestFormat.height) - { - continue; - } - - if (mt->subtype != MEDIASUBTYPE_YUY2 && mt->subtype != MEDIASUBTYPE_MJPG && mt->subtype != MEDIASUBTYPE_RGB24) - { - OLECHAR* guidString; - StringFromCLSID(mt->subtype, &guidString); - LOG("Skipping mediatype due to unsupported subtype: "); - LOG(guidString); - ::CoTaskMemFree(guidString); - continue; - } - - bestFormat.avgFrameTime = format->AvgTimePerFrame; - bestFormat.width = format->bmiHeader.biWidth; - bestFormat.height = format->bmiHeader.biHeight; - bestFormat.mediaType = std::move(mt); - } - - if (!bestFormat.mediaType) - { - LOG(L"Couldn't select a suitable media format"); - return std::nullopt; - } - - char selectedFormat[512]{}; - sprintf_s(selectedFormat, "Selected media format: %s %ldx%ld %lld fps", GetMediaSubTypeString(bestFormat.mediaType->subtype), bestFormat.width, bestFormat.height, 10000000LL / bestFormat.avgFrameTime); - LOG(selectedFormat); - - return std::move(bestFormat); -} - -std::vector VideoCaptureDevice::ListAll() -{ - std::vector devices; - auto enumeratorFactory = wil::CoCreateInstanceNoThrow(CLSID_SystemDeviceEnum); - if (!enumeratorFactory) - { - LOG("Couldn't create devenum factory"); - return devices; - } - - wil::com_ptr_nothrow enumMoniker; - enumeratorFactory->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &enumMoniker, CDEF_DEVMON_PNP_DEVICE); - if (!enumMoniker) - { - LOG("Couldn't create class enumerator"); - return devices; - } - - ULONG _ = 0; - wil::com_ptr_nothrow moniker; - while (enumMoniker->Next(1, &moniker, &_) == S_OK) - { - LOG("Inspecting moniker"); - VideoCaptureDeviceInfo deviceInfo; - - wil::com_ptr_nothrow propertyData; - moniker->BindToStorage(nullptr, nullptr, IID_IPropertyBag, reinterpret_cast(&propertyData)); - if (!propertyData) - { - LOG("BindToStorage failed"); - continue; - } - - wil::unique_variant propVal; - propVal.vt = VT_BSTR; - - if (FAILED(propertyData->Read(L"FriendlyName", &propVal, nullptr))) - { - LOG("Couldn't obtain FriendlyName property"); - continue; - } - - deviceInfo.friendlyName = { propVal.bstrVal, SysStringLen(propVal.bstrVal) }; - LOG(deviceInfo.friendlyName); - - propVal.reset(); - propVal.vt = VT_BSTR; - - if (FAILED(propertyData->Read(L"DevicePath", &propVal, nullptr))) - { - LOG("Couldn't obtain DevicePath property"); - continue; - } - deviceInfo.devicePath = { propVal.bstrVal, SysStringLen(propVal.bstrVal) }; - - wil::com_ptr_nothrow filter; - moniker->BindToObject(nullptr, nullptr, IID_IBaseFilter, reinterpret_cast(&filter)); - if (!filter) - { - LOG("Couldn't BindToObject"); - continue; - } - - wil::com_ptr_nothrow pinsEnum; - if (FAILED(filter->EnumPins(&pinsEnum))) - { - LOG("BindToObject EnumPins"); - continue; - } - - wil::com_ptr_nothrow pin; - while (pinsEnum->Next(1, &pin, &_) == S_OK) - { - LOG("Inspecting pin"); - // Skip pins which do not belong to capture category - GUID category{}; - DWORD __; - if (auto props = pin.try_copy(); - !props || - FAILED(props->Get(AMPROPSETID_Pin, AMPROPERTY_PIN_CATEGORY, nullptr, 0, &category, sizeof(GUID), &__)) || - category != PIN_CATEGORY_CAPTURE) - { - continue; - } - - // Skip non-output pins - if (PIN_DIRECTION direction = {}; FAILED(pin->QueryDirection(&direction)) || direction != PINDIR_OUTPUT) - { - continue; - } - - LOG("Found a pin of suitable category and direction, selecting format"); - auto bestFormat = SelectBestMediaType(pin); - if (!bestFormat) - { - continue; - } - - deviceInfo.captureOutputPin = std::move(pin); - deviceInfo.bestFormat = std::move(bestFormat.value()); - deviceInfo.captureOutputFilter = std::move(filter); - devices.emplace_back(std::move(deviceInfo)); - } - } - - return devices; -} - -std::optional VideoCaptureDevice::Create(VideoCaptureDeviceInfo&& vdi, callback_t callback) -{ - VERBOSE_LOG; - VideoCaptureDevice result; - - result._graph = wil::CoCreateInstanceNoThrow(CLSID_FilterGraph); - result._builder = wil::CoCreateInstanceNoThrow(CLSID_CaptureGraphBuilder2); - if (!result._graph || !result._builder) - { - return std::nullopt; - } - - if (FAILED(result._builder->SetFiltergraph(result._graph.get()))) - { - return std::nullopt; - } - - result._control = result._graph.try_query(); - if (!result._control) - { - return std::nullopt; - } - - auto pinConfig = vdi.captureOutputPin.try_query(); - if (!pinConfig) - { - return std::nullopt; - } - - if (FAILED(pinConfig->SetFormat(vdi.bestFormat.mediaType.get()))) - { - return std::nullopt; - } - - auto captureInputFilter = winrt::make_self(); - auto receiverPin = winrt::make_self(std::move(vdi.bestFormat.mediaType), captureInputFilter.get()); - receiverPin->_frameCallback = std::move(callback); - captureInputFilter->_videoReceiverPin.attach(receiverPin.get()); - auto detachReceiverPin = wil::scope_exit([&receiverPin]() { receiverPin.detach(); }); - - if (FAILED(result._graph->AddFilter(captureInputFilter.get(), nullptr))) - { - return std::nullopt; - } - - if (FAILED(result._graph->AddFilter(vdi.captureOutputFilter.get(), nullptr))) - { - return std::nullopt; - } - - if (FAILED(result._graph->ConnectDirect(vdi.captureOutputPin.get(), captureInputFilter->_videoReceiverPin.get(), nullptr))) - { - return std::nullopt; - } - - result._allocator = receiverPin->_allocator; - return std::make_optional(std::move(result)); -} - -bool VideoCaptureDevice::StartCapture() -{ - VERBOSE_LOG; - return SUCCEEDED(_control->Run()); -} - -bool VideoCaptureDevice::StopCapture() -{ - VERBOSE_LOG; - return SUCCEEDED(_control->Stop()); -} - -VideoCaptureDevice::~VideoCaptureDevice() -{ - StopCapture(); -} diff --git a/src/modules/videoconference/VideoConferenceProxyFilter/VideoCaptureDevice.h b/src/modules/videoconference/VideoConferenceProxyFilter/VideoCaptureDevice.h deleted file mode 100644 index 3af63691a6a0..000000000000 --- a/src/modules/videoconference/VideoConferenceProxyFilter/VideoCaptureDevice.h +++ /dev/null @@ -1,62 +0,0 @@ -#pragma once -#include -#define WIN32_LEAN_AND_MEAN - -#include -#include - -#include - -#include -#include -#include -#include - -#include "DirectShowUtils.h" - -struct VideoStreamFormat -{ - long width = 0; - long height = 0; - REFERENCE_TIME avgFrameTime = std::numeric_limits::max(); - unique_media_type_ptr mediaType; - - VideoStreamFormat() = default; - - VideoStreamFormat(const VideoStreamFormat&) = delete; - VideoStreamFormat& operator=(const VideoStreamFormat&) = delete; - - VideoStreamFormat(VideoStreamFormat&&) = default; - VideoStreamFormat& operator=(VideoStreamFormat&&) = default; -}; - -struct VideoCaptureDeviceInfo -{ - std::wstring friendlyName; - std::wstring devicePath; - wil::com_ptr_nothrow captureOutputPin; - wil::com_ptr_nothrow captureOutputFilter; - VideoStreamFormat bestFormat; -}; - -class VideoCaptureDevice final -{ -public: - wil::com_ptr_nothrow _allocator; - - using callback_t = std::function; - - static std::vector ListAll(); - static std::optional Create(VideoCaptureDeviceInfo&& vdi, callback_t callback); - - bool StartCapture(); - bool StopCapture(); - - ~VideoCaptureDevice(); - -private: - wil::com_ptr_nothrow _graph; - wil::com_ptr_nothrow _builder; - wil::com_ptr_nothrow _control; - callback_t _callback; -}; diff --git a/src/modules/videoconference/VideoConferenceProxyFilter/VideoCaptureProxyFilter.cpp b/src/modules/videoconference/VideoConferenceProxyFilter/VideoCaptureProxyFilter.cpp deleted file mode 100644 index 2a860a72fadd..000000000000 --- a/src/modules/videoconference/VideoConferenceProxyFilter/VideoCaptureProxyFilter.cpp +++ /dev/null @@ -1,937 +0,0 @@ -#include "VideoCaptureProxyFilter.h" - -#include "VideoCaptureDevice.h" -#include -#include -#include -#include - -constexpr static inline wchar_t FILTER_NAME[] = L"PowerToysVCMProxyFilter"; -constexpr static inline wchar_t PIN_NAME[] = L"PowerToysVCMProxyPIN"; -constexpr static inline wchar_t VENDOR[] = L"Microsoft Corporation"; - -namespace -{ - constexpr float initialJpgQuality = 0.5f; - constexpr std::array overlayColor = { 0, 0, 0 }; - // clang-format off - unsigned char bmpPixelData[58] = { - 0x42, 0x4D, 0x3A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, - 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x00, 0xC4, 0x0E, 0x00, 0x00, 0xC4, 0x0E, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, overlayColor[0], overlayColor[1], overlayColor[2], 0x00 - }; - // clang-format on -} - -wil::com_ptr_nothrow VideoCaptureProxyPin::FindAllocator() -{ - auto allocator = GetPinAllocator(_connectedInputPin); - if (!allocator && _owningFilter->_captureDevice) - { - allocator = _owningFilter->_captureDevice->_allocator; - } - - return allocator; -} - -wil::com_ptr_nothrow LoadImageAsSample(wil::com_ptr_nothrow imageStream, - IMFMediaType* sampleMediaType, - const float quality) noexcept; -bool ReencodeJPGImage(BYTE* imageBuf, const DWORD imageSize, DWORD& reencodedSize); - -HRESULT VideoCaptureProxyPin::Connect(IPin* pReceivePin, const AM_MEDIA_TYPE*) -{ - if (!pReceivePin) - { - LOG("VideoCaptureProxyPin::Connect FAILED pReceivePin"); - return E_POINTER; - } - - if (_owningFilter->_state == State_Running) - { - LOG("VideoCaptureProxyPin::Connect FAILED _owningFilter->_state"); - return VFW_E_NOT_STOPPED; - } - - if (_connectedInputPin) - { - LOG("VideoCaptureProxyPin::Connect FAILED _connectedInputPin"); - return VFW_E_ALREADY_CONNECTED; - } - - if (FAILED(pReceivePin->ReceiveConnection(this, _mediaFormat.get()))) - { - LOG("VideoCaptureProxyPin::Connect FAILED pReceivePin->ReceiveConnection"); - return E_POINTER; - } - - _connectedInputPin = pReceivePin; - - auto memInput = _connectedInputPin.try_query(); - if (!memInput) - { - LOG("VideoCaptureProxyPin::Connect FAILED _connectedInputPin.try_query"); - return VFW_E_NO_TRANSPORT; - } - - auto allocator = FindAllocator(); - if (allocator == nullptr) - { - LOG("VideoCaptureProxyPin::Connect FAILED FindAllocator"); - return VFW_E_NO_TRANSPORT; - } - - if (FAILED(memInput->NotifyAllocator(allocator.get(), false))) - { - LOG("VideoCaptureProxyPin::Connect FAILED memInput->NotifyAllocator"); - return VFW_E_NO_TRANSPORT; - } - - return S_OK; -} - -HRESULT VideoCaptureProxyPin::ReceiveConnection(IPin*, const AM_MEDIA_TYPE*) -{ - return S_OK; -} - -HRESULT VideoCaptureProxyPin::Disconnect(void) -{ - if (!_connectedInputPin) - { - LOG("VideoCaptureProxyPin::Disconnect FAILED _connectedInputPin"); - return S_FALSE; - } - - _connectedInputPin.reset(); - return S_OK; -} - -HRESULT VideoCaptureProxyPin::ConnectedTo(IPin** pPin) -{ - if (!_connectedInputPin) - { - *pPin = nullptr; - return VFW_E_NOT_CONNECTED; - } - - return _connectedInputPin.try_copy_to(pPin) ? S_OK : E_FAIL; -} - -HRESULT VideoCaptureProxyPin::ConnectionMediaType(AM_MEDIA_TYPE* pmt) -{ - if (!_connectedInputPin) - { - LOG("VideoCaptureProxyPin::ConnectionMediaType FAILED _connectedInputPin"); - return VFW_E_NOT_CONNECTED; - } - - *pmt = *CopyMediaType(_mediaFormat.get()).release(); - return S_OK; -} - -HRESULT VideoCaptureProxyPin::QueryPinInfo(PIN_INFO* pInfo) -{ - if (!pInfo) - { - LOG("VideoCaptureProxyPin::QueryPinInfo FAILED pInfo"); - return E_POINTER; - } - - pInfo->pFilter = _owningFilter; - if (_owningFilter) - { - _owningFilter->AddRef(); - } - - if (_mediaFormat->majortype == MEDIATYPE_Video) - { - std::copy(std::begin(PIN_NAME), std::end(PIN_NAME), pInfo->achName); - } - - pInfo->dir = PINDIR_OUTPUT; - return S_OK; -} - -HRESULT VideoCaptureProxyPin::QueryDirection(PIN_DIRECTION* pPinDir) -{ - if (!pPinDir) - { - LOG("VideoCaptureProxyPin::QueryDirection FAILED pPinDir"); - return E_POINTER; - } - - *pPinDir = PINDIR_OUTPUT; - return S_OK; -} - -HRESULT VideoCaptureProxyPin::QueryId(LPWSTR* Id) -{ - if (!Id) - { - LOG("VideoCaptureProxyPin::QueryId FAILED Id"); - return E_POINTER; - } - - *Id = static_cast(CoTaskMemAlloc(sizeof(PIN_NAME))); - std::copy(std::begin(PIN_NAME), std::end(PIN_NAME), *Id); - return S_OK; -} - -HRESULT VideoCaptureProxyPin::QueryAccept(const AM_MEDIA_TYPE*) -{ - return S_OK; -} - -HRESULT VideoCaptureProxyPin::EnumMediaTypes(IEnumMediaTypes** ppEnum) -{ - if (!ppEnum) - { - LOG("VideoCaptureProxyPin::EnumMediaTypes FAILED ppEnum"); - return E_POINTER; - } - - *ppEnum = nullptr; - - auto enumerator = winrt::make_self(); - enumerator->_objects.emplace_back(CopyMediaType(_mediaFormat.get())); - *ppEnum = enumerator.detach(); - - return S_OK; -} - -HRESULT VideoCaptureProxyPin::QueryInternalConnections(IPin** pins, ULONG*) -{ - if (pins) - { - *pins = nullptr; - } - return E_NOTIMPL; -} - -HRESULT VideoCaptureProxyPin::EndOfStream(void) -{ - return S_OK; -} - -HRESULT VideoCaptureProxyPin::BeginFlush(void) -{ - _flushing = true; - return S_OK; -} - -HRESULT VideoCaptureProxyPin::EndFlush(void) -{ - _flushing = false; - return S_OK; -} - -HRESULT VideoCaptureProxyPin::NewSegment(REFERENCE_TIME, REFERENCE_TIME, double) -{ - return S_OK; -} - -HRESULT VideoCaptureProxyPin::SetFormat(AM_MEDIA_TYPE* pmt) -{ - if (pmt == nullptr) - { - return S_OK; - } - - _mediaFormat = CopyMediaType(pmt); - return S_OK; -} - -HRESULT VideoCaptureProxyPin::GetFormat(AM_MEDIA_TYPE** ppmt) -{ - if (!ppmt) - { - LOG("VideoCaptureProxyPin::GetFormat FAILED ppmt"); - return E_POINTER; - } - *ppmt = CopyMediaType(_mediaFormat.get()).release(); - return S_OK; -} - -HRESULT VideoCaptureProxyPin::GetNumberOfCapabilities(int* piCount, int* piSize) -{ - if (!piCount || !piSize) - { - LOG("VideoCaptureProxyPin::GetNumberOfCapabilities FAILED piCount || piSize"); - return E_POINTER; - } - - *piCount = 1; - *piSize = sizeof(VIDEO_STREAM_CONFIG_CAPS); - return S_OK; -} - -HRESULT VideoCaptureProxyPin::GetStreamCaps(int iIndex, AM_MEDIA_TYPE** ppmt, BYTE* pSCC) -{ - if (!ppmt || !pSCC) - { - LOG("VideoCaptureProxyPin::GetStreamCaps FAILED ppmt || pSCC"); - return E_POINTER; - } - - if (iIndex != 0) - { - LOG("VideoCaptureProxyPin::GetStreamCaps FAILED iIndex"); - return S_FALSE; - } - - VIDEOINFOHEADER* vih = reinterpret_cast(_mediaFormat->pbFormat); - - VIDEO_STREAM_CONFIG_CAPS caps{}; - caps.guid = FORMAT_VideoInfo; - caps.MinFrameInterval = vih->AvgTimePerFrame; - caps.MaxFrameInterval = vih->AvgTimePerFrame; - caps.MinOutputSize.cx = vih->bmiHeader.biWidth; - caps.MinOutputSize.cy = vih->bmiHeader.biHeight; - caps.MaxOutputSize = caps.MinOutputSize; - caps.InputSize = caps.MinOutputSize; - caps.MinCroppingSize = caps.MinOutputSize; - caps.MaxCroppingSize = caps.MinOutputSize; - caps.CropGranularityX = vih->bmiHeader.biWidth; - caps.CropGranularityY = vih->bmiHeader.biHeight; - caps.MinBitsPerSecond = vih->dwBitRate; - caps.MaxBitsPerSecond = caps.MinBitsPerSecond; - - *ppmt = CopyMediaType(_mediaFormat.get()).release(); - - const auto caps_begin = reinterpret_cast(&caps); - std::copy(caps_begin, caps_begin + sizeof(caps), pSCC); - return S_OK; -} - -HRESULT VideoCaptureProxyPin::Set(REFGUID, DWORD, LPVOID, DWORD, LPVOID, DWORD) -{ - return E_NOTIMPL; -} - -HRESULT VideoCaptureProxyPin::Get( - REFGUID guidPropSet, - DWORD dwPropID, - LPVOID, - DWORD, - LPVOID pPropData, - DWORD cbPropData, - DWORD* pcbReturned) -{ - if (guidPropSet != AMPROPSETID_Pin) - { - LOG("VideoCaptureProxyPin::Get FAILED guidPropSet"); - return E_PROP_SET_UNSUPPORTED; - } - - if (dwPropID != AMPROPERTY_PIN_CATEGORY) - { - LOG("VideoCaptureProxyPin::Get FAILED dwPropID"); - return E_PROP_ID_UNSUPPORTED; - } - - if (!pPropData) - { - LOG("VideoCaptureProxyPin::Get FAILED pPropData || pcbReturned"); - return E_POINTER; - } - - if (pcbReturned) - { - *pcbReturned = sizeof(GUID); - } - - if (cbPropData < sizeof(GUID)) - { - LOG("VideoCaptureProxyPin::Get FAILED cbPropData"); - return E_UNEXPECTED; - } - - *static_cast(pPropData) = PIN_CATEGORY_CAPTURE; - - LOG("VideoCaptureProxyPin::Get SUCCESS"); - return S_OK; -} - -HRESULT VideoCaptureProxyPin::QuerySupported(REFGUID guidPropSet, DWORD dwPropID, DWORD* pTypeSupport) -{ - if (guidPropSet != AMPROPSETID_Pin) - { - LOG("VideoCaptureProxyPin::QuerySupported FAILED guidPropSet"); - return E_PROP_SET_UNSUPPORTED; - } - - if (dwPropID != AMPROPERTY_PIN_CATEGORY) - { - LOG("VideoCaptureProxyPin::QuerySupported FAILED dwPropID"); - return E_PROP_ID_UNSUPPORTED; - } - - if (pTypeSupport) - { - *pTypeSupport = KSPROPERTY_SUPPORT_GET; - } - - return S_OK; -} - -long GetImageSize(wil::com_ptr_nothrow& image) -{ - if (!image) - { - return 0; - } - - DWORD imageSize = 0; - wil::com_ptr_nothrow imageBuf; - - OK_OR_BAIL(image->GetBufferByIndex(0, &imageBuf)); - OK_OR_BAIL(imageBuf->GetCurrentLength(&imageSize)); - return imageSize; -} - -void ReencodeFrame(IMediaSample* frame) -{ - BYTE* frameData = nullptr; - frame->GetPointer(&frameData); - if (!frameData) - { - LOG("VideoCaptureProxyPin::ReencodeFrame FAILED frameData"); - return; - } - const DWORD frameSize = frame->GetSize(); - DWORD reencodedSize = 0; - if (!ReencodeJPGImage(frameData, frameSize, reencodedSize)) - { - LOG("VideoCaptureProxyPin::ReencodeJPGImage FAILED"); - return; - } - frame->SetActualDataLength(reencodedSize); -} - -bool OverwriteFrame(IMediaSample* frame, wil::com_ptr_nothrow& image) -{ - if (!image) - { - return false; - } - - BYTE* frameData = nullptr; - frame->GetPointer(&frameData); - if (!frameData) - { - LOG("VideoCaptureProxyPin::OverwriteFrame FAILED frameData"); - return false; - } - - wil::com_ptr_nothrow imageBuf; - const DWORD frameSize = frame->GetSize(); - - image->GetBufferByIndex(0, &imageBuf); - if (!imageBuf) - { - LOG("VideoCaptureProxyPin::OverwriteFrame FAILED imageBuf"); - return false; - } - - BYTE* imageData = nullptr; - DWORD _ = 0, imageSize = 0; - imageBuf->Lock(&imageData, &_, &imageSize); - if (!imageData) - { - LOG("VideoCaptureProxyPin::OverwriteFrame FAILED imageData"); - return false; - } - - if (imageSize > frameSize && failed(frame->SetActualDataLength(imageSize))) - { - char buf[512]{}; - sprintf_s(buf, "VideoCaptureProxyPin::OverwriteFrame FAILED overlay image size %lu is larger than frame size %lu", imageSize, frameSize); - LOG(buf); - imageBuf->Unlock(); - return false; - } - - std::copy(imageData, imageData + imageSize, frameData); - imageBuf->Unlock(); - frame->SetActualDataLength(imageSize); - - return true; -} - -//#define DEBUG_FRAME_DATA -//#define DEBUG_OVERWRITE_FRAME -//#define DEBUG_REENCODE_JPG_DATA - -#if defined(DEBUG_OVERWRITE_FRAME) -void DebugOverwriteFrame(IMediaSample* frame, std::string_view filepath) -{ - std::ifstream file{ filepath.data(), std::ios::binary }; - std::streampos fileSize = 0; - fileSize = file.tellg(); - file.seekg(0, std::ios::end); - fileSize = file.tellg() - fileSize; - - BYTE* frameData = nullptr; - if (!frame) - { - LOG("null frame provided"); - return; - } - frame->GetPointer(&frameData); - const DWORD frameSize = frame->GetSize(); - - if (fileSize > frameSize || !frameData) - { - LOG("frame can't be filled with data"); - return; - } - file.read((char*)frameData, fileSize); - frame->SetActualDataLength((long)fileSize); - LOG("DebugOverwriteFrame success"); -} - -#endif - -#if defined(DEBUG_FRAME_DATA) -#include - -namespace fs = std::filesystem; - -void DumpSample(IMediaSample* frame, const std::string_view filename) -{ - BYTE* data = nullptr; - frame->GetPointer(&data); - if (!data) - { - LOG("Couldn't get sample pointer"); - return; - } - const long nBytes = frame->GetActualDataLength(); - std::ofstream file{ fs::temp_directory_path() / filename, std::ios::binary }; - file.write((const char*)data, nBytes); -} -#endif - -VideoCaptureProxyFilter::VideoCaptureProxyFilter() : - _worker_thread{ - std::thread{ - [this]() { - using namespace std::chrono_literals; - const auto uninitializedSleepInterval = 15ms; - std::vector lowerJpgQualityModes = { 0.1f, 0.25f }; - while (!_shutdown_request) - { - std::unique_lock lock{ _worker_mutex }; - _worker_cv.wait(lock, [this] { return _pending_frame != nullptr || _shutdown_request; }); - - if (!_outPin || !_outPin->_connectedInputPin) - { - lock.unlock(); - std::this_thread::sleep_for(uninitializedSleepInterval); - continue; - } - - auto input = _outPin->_connectedInputPin.try_query(); - if (!input) - { - continue; - } - - IMediaSample* sample = _pending_frame; - if (!sample) - { - continue; - } -#if defined(DEBUG_FRAME_DATA) - static bool realFrameSaved = false; - if (!realFrameSaved) - { - DumpSample(sample, "PowerToysVCMRealFrame.binary"); - realFrameSaved = true; - } -#endif - auto newSettings = SyncCurrentSettings(); - if (newSettings.webcamDisabled) - { -#if !defined(DEBUG_OVERWRITE_FRAME) - bool overwritten = OverwriteFrame(_pending_frame, _overlayImage ? _overlayImage : _blankImage); - while (!overwritten && _overlayImage) - { - _overlayImage.reset(); - newSettings = SyncCurrentSettings(); - if (!lowerJpgQualityModes.empty() && newSettings.overlayImage) - { - const float quality = lowerJpgQualityModes.back(); - lowerJpgQualityModes.pop_back(); - char buf[512]{}; - sprintf_s(buf, "Reload overlay image with quality %f", quality); - LOG(buf); - _overlayImage = LoadImageAsSample(newSettings.overlayImage, _targetMediaType.get(), quality); - overwritten = OverwriteFrame(_pending_frame, _overlayImage); - } - else - { - LOG("Couldn't overwrite frame with image with all available quality modes."); - } - } -#if defined(DEBUG_FRAME_DATA) - static bool overlayFrameSaved = false; - if (!overlayFrameSaved && _overlayImage && overwritten) - { - DumpSample(sample, "PowerToysVCMOverlayImageFrame.binary"); - overlayFrameSaved = true; - } -#endif - if (!overwritten && !_overlayImage) - { - OverwriteFrame(_pending_frame, _blankImage); - } -#else - DebugOverwriteFrame(_pending_frame, "R:\\frame.data"); -#endif - } -#if defined(DEBUG_REENCODE_JPG_DATA) - else - { - GUID subtype{}; - _targetMediaType->GetGUID(MF_MT_SUBTYPE, &subtype); - if (subtype == MFVideoFormat_MJPG) - { - ReencodeFrame(_pending_frame); - } - } -#endif - - _pending_frame = nullptr; - input->Receive(sample); - sample->Release(); - } - } } - } -{ -} - -HRESULT VideoCaptureProxyFilter::Stop(void) -{ - if (_state != State_Stopped && _captureDevice) - { - _captureDevice->StopCapture(); - } - - _state = State_Stopped; - return S_OK; -} - -HRESULT VideoCaptureProxyFilter::Pause(void) -{ - if (_state == State_Stopped) - { - std::unique_lock lock{ _worker_mutex }; - - if (!_outPin) - { - LOG("VideoCaptureProxyPin::Pause FAILED _outPin"); - return VFW_E_NO_TRANSPORT; - } - - auto allocator = _outPin->FindAllocator(); - if (!allocator) - { - LOG("VideoCaptureProxyPin::Pause FAILED allocator"); - return VFW_E_NO_TRANSPORT; - } - - allocator->Commit(); - } - - _state = State_Paused; - return S_OK; -} - -HRESULT VideoCaptureProxyFilter::Run(REFERENCE_TIME) -{ - _state = State_Running; - if (_captureDevice) - { - _captureDevice->StartCapture(); - } - - return S_OK; -} - -HRESULT VideoCaptureProxyFilter::GetState(DWORD, FILTER_STATE* State) -{ - *State = _state; - return S_OK; -} - -HRESULT VideoCaptureProxyFilter::SetSyncSource(IReferenceClock* pClock) -{ - _clock = pClock; - return S_OK; -} - -HRESULT VideoCaptureProxyFilter::GetSyncSource(IReferenceClock** pClock) -{ - if (!pClock) - { - return E_POINTER; - } - *pClock = nullptr; - return _clock.try_copy_to(pClock) ? S_OK : E_FAIL; -} - -GUID MapDShowSubtypeToMFT(const GUID& dshowSubtype) -{ - if (dshowSubtype == MEDIASUBTYPE_YUY2) - { - return MFVideoFormat_YUY2; - } - else if (dshowSubtype == MEDIASUBTYPE_MJPG) - { - return MFVideoFormat_MJPG; - } - else if (dshowSubtype == MEDIASUBTYPE_RGB24) - { - return MFVideoFormat_RGB24; - } - else - { - LOG("MapDShowSubtypeToMFT: Unsupported media type format provided!"); - return MFVideoFormat_MJPG; - } -} - -HRESULT VideoCaptureProxyFilter::EnumPins(IEnumPins** ppEnum) -{ - if (!ppEnum) - { - LOG("VideoCaptureProxyFilter::EnumPins null arg provided"); - return E_POINTER; - } - *ppEnum = nullptr; - auto enumerator = winrt::make_self>(); - auto detached_enumerator = enumerator.detach(); - *ppEnum = detached_enumerator; - - std::unique_lock lock{ _worker_mutex }; - - // We cannot initialize capture device and outpin during VideoCaptureProxyFilter ctor - // since that results in a deadlock -> initializing now. - if (!_outPin) - { - LOG("VideoCaptureProxyFilter::EnumPins started pin initialization"); - const auto newSettings = SyncCurrentSettings(); - std::vector webcams; - webcams = VideoCaptureDevice::ListAll(); - if (webcams.empty()) - { - LOG("VideoCaptureProxyFilter::EnumPins no physical webcams found"); - return E_FAIL; - } - - std::optional selectedCamIdx; - for (size_t i = 0; i < size(webcams); ++i) - { - if (newSettings.newCameraName == webcams[i].friendlyName) - { - selectedCamIdx = i; - LOG("VideoCaptureProxyFilter::EnumPins webcam selected using settings"); - break; - } - } - - if (!selectedCamIdx) - { - for (size_t i = 0; i < size(webcams); ++i) - { - if (newSettings.newCameraName != CAMERA_NAME) - { - LOG("VideoCaptureProxyFilter::EnumPins webcam selected using first fit"); - selectedCamIdx = i; - break; - } - } - } - - if (!selectedCamIdx) - { - LOG("VideoCaptureProxyFilter::EnumPins FAILED webcam couldn't be selected"); - return E_FAIL; - } - - auto& webcam = webcams[*selectedCamIdx]; - auto pin = winrt::make_self(); - pin->_mediaFormat = CopyMediaType(webcam.bestFormat.mediaType.get()); - pin->_owningFilter = this; - _outPin.attach(pin.detach()); - - auto frameCallback = [this](IMediaSample* sample) { - std::unique_lock lock{ _worker_mutex }; - sample->AddRef(); - _pending_frame = sample; - _worker_cv.notify_one(); - }; - - _targetMediaType.reset(); - MFCreateMediaType(&_targetMediaType); - _targetMediaType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video); - _targetMediaType->SetGUID(MF_MT_SUBTYPE, MapDShowSubtypeToMFT(webcam.bestFormat.mediaType->subtype)); - _targetMediaType->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive); - _targetMediaType->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE); - MFSetAttributeSize( - _targetMediaType.get(), MF_MT_FRAME_SIZE, webcam.bestFormat.width, webcam.bestFormat.height); - MFSetAttributeRatio(_targetMediaType.get(), MF_MT_PIXEL_ASPECT_RATIO, 1, 1); - - _captureDevice = VideoCaptureDevice::Create(std::move(webcam), std::move(frameCallback)); - if (_captureDevice) - { - if (!_blankImage) - { - wil::com_ptr_nothrow blackBMPImage = SHCreateMemStream(bmpPixelData, sizeof(bmpPixelData)); - _blankImage = LoadImageAsSample(blackBMPImage, _targetMediaType.get(), initialJpgQuality); - } - - _overlayImage = LoadImageAsSample(newSettings.overlayImage, _targetMediaType.get(), initialJpgQuality); - LOG("VideoCaptureProxyFilter::EnumPins capture device created successfully"); - } - else - { - LOG("VideoCaptureProxyFilter::EnumPins FAILED couldn't create capture device"); - } - } - - detached_enumerator->_objects.emplace_back(_outPin); - - return S_OK; -} - -HRESULT VideoCaptureProxyFilter::FindPin(LPCWSTR, IPin** pin) -{ - if (pin) - { - *pin = nullptr; - } - return E_NOTIMPL; -} - -HRESULT VideoCaptureProxyFilter::QueryFilterInfo(FILTER_INFO* pInfo) -{ - if (!pInfo) - { - LOG("VideoCaptureProxyPin::QueryFilterInfo FAILED pInfo"); - return E_POINTER; - } - - VERBOSE_LOG; - std::copy(std::begin(FILTER_NAME), std::end(FILTER_NAME), pInfo->achName); - - pInfo->pGraph = _graph; - if (_graph) - { - _graph->AddRef(); - } - - return S_OK; -} - -HRESULT VideoCaptureProxyFilter::JoinFilterGraph(IFilterGraph* pGraph, LPCWSTR) -{ - _graph = pGraph; - return S_OK; -} - -HRESULT VideoCaptureProxyFilter::QueryVendorInfo(LPWSTR* pVendorInfo) -{ - auto info = static_cast(CoTaskMemAlloc(sizeof(VENDOR))); - std::copy(std::begin(VENDOR), std::end(VENDOR), info); - *pVendorInfo = info; - return S_OK; -} - -HRESULT VideoCaptureProxyFilter::GetClassID(CLSID*) -{ - return E_NOTIMPL; -} - -ULONG VideoCaptureProxyFilter::GetMiscFlags(void) -{ - return AM_FILTER_MISC_FLAGS_IS_SOURCE; -} - -VideoCaptureProxyFilter::~VideoCaptureProxyFilter() -{ - VERBOSE_LOG; - _shutdown_request = true; - - _worker_cv.notify_one(); - _worker_thread.join(); - if (_settingsUpdateChannel) - { - _settingsUpdateChannel->access([](auto settingsMemory) { - auto settings = reinterpret_cast(settingsMemory._data); - settings->cameraInUse = false; - }); - } -} - -VideoCaptureProxyFilter::SyncedSettings VideoCaptureProxyFilter::SyncCurrentSettings() -{ - SyncedSettings result; - if (!_settingsUpdateChannel.has_value()) - { - _settingsUpdateChannel = SerializedSharedMemory::open(CameraSettingsUpdateChannel::endpoint(), sizeof(CameraSettingsUpdateChannel), false); - } - - if (!_settingsUpdateChannel) - { - return result; - } - - _settingsUpdateChannel->access([this, &result](auto settingsMemory) { - auto settings = reinterpret_cast(settingsMemory._data); - bool cameraNameUpdated = false; - result.webcamDisabled = settings->useOverlayImage; - - settings->cameraInUse = true; - - if (settings->sourceCameraName.has_value()) - { - std::wstring_view newCameraNameView{ settings->sourceCameraName->data() }; - if (!_currentSourceCameraName.has_value() || *_currentSourceCameraName != newCameraNameView) - { - cameraNameUpdated = true; - result.newCameraName = newCameraNameView; - } - } - - if (!settings->overlayImageSize.has_value()) - { - return; - } - - if (settings->newOverlayImagePosted || !_overlayImage) - { - auto imageChannel = - SerializedSharedMemory::open(CameraOverlayImageChannel::endpoint(), *settings->overlayImageSize, true); - if (!imageChannel) - { - return; - } - - imageChannel->access([this, settings, &result](auto imageMemory) { - result.overlayImage = SHCreateMemStream(imageMemory._data, static_cast(imageMemory._size)); - if (!result.overlayImage) - { - return; - } - - settings->newOverlayImagePosted = false; - }); - } - }); - return result; -} diff --git a/src/modules/videoconference/VideoConferenceProxyFilter/VideoCaptureProxyFilter.h b/src/modules/videoconference/VideoConferenceProxyFilter/VideoCaptureProxyFilter.h deleted file mode 100644 index 58f49f032af0..000000000000 --- a/src/modules/videoconference/VideoConferenceProxyFilter/VideoCaptureProxyFilter.h +++ /dev/null @@ -1,120 +0,0 @@ -#pragma once - -#include - -#define WIN32_LEAN_AND_MEAN -#include -#include - -#include -#include -#include - -#include -#include - -#include "VideoCaptureDevice.h" - -#include -#include - -struct VideoCaptureProxyPin; -struct IMFSample; -struct IMFMediaType; - -inline const wchar_t CAMERA_NAME[] = L"PowerToys VideoConference Mute"; - -struct VideoCaptureProxyFilter : winrt::implements -{ - // BLOCK START: member accessed concurrently - wil::com_ptr_nothrow _outPin; - IMediaSample* _pending_frame = nullptr; - std::atomic_bool _shutdown_request = false; - std::optional _settingsUpdateChannel; - std::optional _currentSourceCameraName; - wil::com_ptr_nothrow _blankImage; - wil::com_ptr_nothrow _overlayImage; - wil::com_ptr_nothrow _targetMediaType; - // BLOCK END: member accessed concurrently - - std::mutex _worker_mutex; - std::condition_variable _worker_cv; - - FILTER_STATE _state = State_Stopped; - wil::com_ptr_nothrow _clock; - IFilterGraph* _graph = nullptr; - std::optional _captureDevice; - - std::thread _worker_thread; - - VideoCaptureProxyFilter(); - ~VideoCaptureProxyFilter(); - - struct SyncedSettings - { - bool webcamDisabled = false; - std::wstring newCameraName; - wil::com_ptr_nothrow overlayImage; - }; - - SyncedSettings SyncCurrentSettings(); - - HRESULT STDMETHODCALLTYPE Stop(void) override; - HRESULT STDMETHODCALLTYPE Pause(void) override; - HRESULT STDMETHODCALLTYPE Run(REFERENCE_TIME tStart) override; - HRESULT STDMETHODCALLTYPE GetState(DWORD dwMilliSecsTimeout, FILTER_STATE* State) override; - HRESULT STDMETHODCALLTYPE SetSyncSource(IReferenceClock* pClock) override; - HRESULT STDMETHODCALLTYPE GetSyncSource(IReferenceClock** pClock) override; - HRESULT STDMETHODCALLTYPE EnumPins(IEnumPins** ppEnum) override; - HRESULT STDMETHODCALLTYPE FindPin(LPCWSTR Id, IPin** ppPin) override; - HRESULT STDMETHODCALLTYPE QueryFilterInfo(FILTER_INFO* pInfo) override; - HRESULT STDMETHODCALLTYPE JoinFilterGraph(IFilterGraph* pGraph, LPCWSTR pName) override; - HRESULT STDMETHODCALLTYPE QueryVendorInfo(LPWSTR* pVendorInfo) override; - - HRESULT STDMETHODCALLTYPE GetClassID(CLSID* pClassID) override; - ULONG STDMETHODCALLTYPE GetMiscFlags(void) override; -}; -struct VideoCaptureProxyPin : winrt::implements -{ - VideoCaptureProxyFilter* _owningFilter = nullptr; - wil::com_ptr_nothrow _connectedInputPin; - unique_media_type_ptr _mediaFormat; - std::atomic_bool _flushing = false; - - HRESULT STDMETHODCALLTYPE Connect(IPin* pReceivePin, const AM_MEDIA_TYPE* pmt) override; - HRESULT STDMETHODCALLTYPE ReceiveConnection(IPin* pConnector, const AM_MEDIA_TYPE* pmt) override; - HRESULT STDMETHODCALLTYPE Disconnect(void) override; - HRESULT STDMETHODCALLTYPE ConnectedTo(IPin** pPin) override; - HRESULT STDMETHODCALLTYPE ConnectionMediaType(AM_MEDIA_TYPE* pmt) override; - HRESULT STDMETHODCALLTYPE QueryPinInfo(PIN_INFO* pInfo) override; - HRESULT STDMETHODCALLTYPE QueryDirection(PIN_DIRECTION* pPinDir) override; - HRESULT STDMETHODCALLTYPE QueryId(LPWSTR* Id) override; - HRESULT STDMETHODCALLTYPE QueryAccept(const AM_MEDIA_TYPE* pmt) override; - HRESULT STDMETHODCALLTYPE EnumMediaTypes(IEnumMediaTypes** ppEnum) override; - HRESULT STDMETHODCALLTYPE QueryInternalConnections(IPin** apPin, ULONG* nPin) override; - HRESULT STDMETHODCALLTYPE EndOfStream(void) override; - HRESULT STDMETHODCALLTYPE BeginFlush(void) override; - HRESULT STDMETHODCALLTYPE EndFlush(void) override; - HRESULT STDMETHODCALLTYPE NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate) override; - - HRESULT STDMETHODCALLTYPE SetFormat(AM_MEDIA_TYPE* pmt) override; - HRESULT STDMETHODCALLTYPE GetFormat(AM_MEDIA_TYPE** ppmt) override; - HRESULT STDMETHODCALLTYPE GetNumberOfCapabilities(int* piCount, int* piSize) override; - HRESULT STDMETHODCALLTYPE GetStreamCaps(int iIndex, AM_MEDIA_TYPE** ppmt, BYTE* pSCC) override; - HRESULT STDMETHODCALLTYPE Set(REFGUID guidPropSet, - DWORD dwPropID, - LPVOID pInstanceData, - DWORD cbInstanceData, - LPVOID pPropData, - DWORD cbPropData) override; - HRESULT STDMETHODCALLTYPE Get(REFGUID guidPropSet, - DWORD dwPropID, - LPVOID pInstanceData, - DWORD cbInstanceData, - LPVOID pPropData, - DWORD cbPropData, - DWORD* pcbReturned) override; - HRESULT STDMETHODCALLTYPE QuerySupported(REFGUID guidPropSet, DWORD dwPropID, DWORD* pTypeSupport) override; - - wil::com_ptr_nothrow FindAllocator(); -}; diff --git a/src/modules/videoconference/VideoConferenceProxyFilter/VideoConferenceProxyFilter.vcxproj b/src/modules/videoconference/VideoConferenceProxyFilter/VideoConferenceProxyFilter.vcxproj deleted file mode 100644 index fd8525072f32..000000000000 --- a/src/modules/videoconference/VideoConferenceProxyFilter/VideoConferenceProxyFilter.vcxproj +++ /dev/null @@ -1,157 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Debug - ARM64 - - - Release - Win32 - - - Release - x64 - - - Release - ARM64 - - - - 16.0 - {AC2857B4-103D-4D6D-9740-926EBF785042} - Win32Proj - VideoConferenceProxyFilter - VideoConferenceProxyFilter - - - - DynamicLibrary - - - v143 - - - v143 - - - v143 - - - v143 - - - - $(SolutionDir)\src\;$(ProjectDir)..\..\..\ - Level4 - - - - - _DEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - true - - - true - - - - - NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(SolutionDir)\src\; - - - Console - - - true - - - call "$(ProjectDir)build_vcm_x86.cmd" - - - - ..\..\..\..\$(Platform)\$(Configuration)\ - PowerToys.VideoConferenceProxyFilter_$(Platform) - - - ..\..\..\..\x86\$(Configuration)\ - PowerToys.VideoConferenceProxyFilter_x86 - - - - - - - - - - ..\VideoConferenceShared\;%(AdditionalIncludeDirectories) - _LIB;NOMINMAX;%(PreprocessorDefinitions) - NotUsing - MultiThreaded - MultiThreadedDebug - - - $(OutDir)VideoConferenceShared.lib;Windowscodecs.lib;Wtsapi32.lib;mfplat.lib;WindowsApp.lib;Mfsensorgroup.lib;Mf.lib;Shlwapi.lib;Strmiids.lib;%(AdditionalDependencies); - module.def - - - _WIN64;_UNICODE;UNICODE;%(PreprocessorDefinitions) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {459e0768-7ebd-4c41-bba1-6db3b3815e0a} - - - {cc6e41ac-8174-4e8a-8d22-85dd7f4851df} - - - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - \ No newline at end of file diff --git a/src/modules/videoconference/VideoConferenceProxyFilter/VideoConferenceProxyFilterx86.sln b/src/modules/videoconference/VideoConferenceProxyFilter/VideoConferenceProxyFilterx86.sln deleted file mode 100644 index e4f5a921765f..000000000000 --- a/src/modules/videoconference/VideoConferenceProxyFilter/VideoConferenceProxyFilterx86.sln +++ /dev/null @@ -1,51 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.30907.101 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VideoConferenceProxyFilter", "VideoConferenceProxyFilter.vcxproj", "{AC2857B4-103D-4D6D-9740-926EBF785042}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VideoConferenceShared", "..\VideoConferenceShared\VideoConferenceShared.vcxproj", "{459E0768-7EBD-4C41-BBA1-6DB3B3815E0A}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Version", "..\..\..\common\version\version.vcxproj", "{CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {AC2857B4-103D-4D6D-9740-926EBF785042}.Debug|Win32.ActiveCfg = Debug|Win32 - {AC2857B4-103D-4D6D-9740-926EBF785042}.Debug|Win32.Build.0 = Debug|Win32 - {AC2857B4-103D-4D6D-9740-926EBF785042}.Debug|x64.ActiveCfg = Debug|x64 - {AC2857B4-103D-4D6D-9740-926EBF785042}.Debug|x64.Build.0 = Debug|x64 - {AC2857B4-103D-4D6D-9740-926EBF785042}.Release|Win32.ActiveCfg = Release|Win32 - {AC2857B4-103D-4D6D-9740-926EBF785042}.Release|Win32.Build.0 = Release|Win32 - {AC2857B4-103D-4D6D-9740-926EBF785042}.Release|x64.ActiveCfg = Release|x64 - {AC2857B4-103D-4D6D-9740-926EBF785042}.Release|x64.Build.0 = Release|x64 - {459E0768-7EBD-4C41-BBA1-6DB3B3815E0A}.Debug|Win32.ActiveCfg = Debug|Win32 - {459E0768-7EBD-4C41-BBA1-6DB3B3815E0A}.Debug|Win32.Build.0 = Debug|Win32 - {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|Win32.ActiveCfg = Release|Win32 - {459E0768-7EBD-4C41-BBA1-6DB3B3815E0A}.Release|Win32.Build.0 = Release|Win32 - {459E0768-7EBD-4C41-BBA1-6DB3B3815E0A}.Release|x64.ActiveCfg = Release|x64 - {459E0768-7EBD-4C41-BBA1-6DB3B3815E0A}.Release|x64.Build.0 = Release|x64 - {CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Debug|Win32.ActiveCfg = Debug|Win32 - {CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Debug|Win32.Build.0 = Debug|Win32 - {CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Debug|x64.ActiveCfg = Debug|x64 - {CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Debug|x64.Build.0 = Debug|x64 - {CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Release|Win32.ActiveCfg = Release|Win32 - {CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Release|Win32.Build.0 = Release|Win32 - {CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Release|x64.ActiveCfg = Release|x64 - {CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {0E41348C-22CB-45A4-8A16-8D7BEA070BB2} - EndGlobalSection -EndGlobal diff --git a/src/modules/videoconference/VideoConferenceProxyFilter/build_vcm_x86.cmd b/src/modules/videoconference/VideoConferenceProxyFilter/build_vcm_x86.cmd deleted file mode 100644 index 9b8507862344..000000000000 --- a/src/modules/videoconference/VideoConferenceProxyFilter/build_vcm_x86.cmd +++ /dev/null @@ -1,3 +0,0 @@ -msbuild VideoConferenceProxyFilterx86.sln -p:Configuration="Release" -p:Platform="Win32" - -exit 0 \ No newline at end of file diff --git a/src/modules/videoconference/VideoConferenceProxyFilter/dllmain.cpp b/src/modules/videoconference/VideoConferenceProxyFilter/dllmain.cpp deleted file mode 100644 index 61133572c82b..000000000000 --- a/src/modules/videoconference/VideoConferenceProxyFilter/dllmain.cpp +++ /dev/null @@ -1,242 +0,0 @@ -#include "VideoCaptureProxyFilter.h" - -#include - -#include -#include - -namespace -{ -#if defined(_WIN64) - class __declspec(uuid("{31AD75E9-8C3A-49C8-B9ED-5880D6B4A764}")) GUID_DECL_POWERTOYS_VCM; -#elif defined(_WIN32) - class __declspec(uuid("{31AD75E9-8C3A-49C8-B9ED-5880D6B4A732}")) GUID_DECL_POWERTOYS_VCM; -#endif - const GUID CLSID_POWERTOYS_VCM = __uuidof(GUID_DECL_POWERTOYS_VCM); - - const REGPINTYPES MEDIA_TYPES = { &MEDIATYPE_Video, &MEDIASUBTYPE_MJPG }; - - const wchar_t FILTER_NAME[] = L"Output"; - const REGFILTERPINS PINS_REGISTRATION = { - (wchar_t*)FILTER_NAME, - false, - true, - false, - false, - &CLSID_NULL, - nullptr, - 1, - &MEDIA_TYPES - }; - - HINSTANCE DLLInstance{}; -} - -struct __declspec(uuid("9DCAF869-9C13-4BDF-BD0D-3592C5579DD6")) VideoCaptureProxyFilterFactory : winrt::implements -{ - HRESULT STDMETHODCALLTYPE CreateInstance(IUnknown*, REFIID riid, void** ppvObject) noexcept override - { - try - { - return winrt::make()->QueryInterface(riid, ppvObject); - } - catch (...) - { - return winrt::to_hresult(); - } - } - - HRESULT STDMETHODCALLTYPE LockServer(BOOL fLock) noexcept override - { - if (fLock) - { - ++winrt::get_module_lock(); - } - else - { - --winrt::get_module_lock(); - } - - return S_OK; - } -}; - -HRESULT STDMETHODCALLTYPE DllCanUnloadNow() -{ - if (winrt::get_module_lock()) - { - return S_FALSE; - } - - winrt::clear_factory_cache(); - return S_OK; -} - -HRESULT STDMETHODCALLTYPE DllGetClassObject(GUID const& clsid, GUID const& iid, void** result) -{ - if (!result) - { - return E_POINTER; - } - - if (iid != IID_IClassFactory && iid != IID_IUnknown) - { - return E_NOINTERFACE; - } - - if (clsid != CLSID_POWERTOYS_VCM) - { - return E_INVALIDARG; - } - - try - { - *result = nullptr; - - auto factory = winrt::make(); - factory->AddRef(); - *result = static_cast(factory.get()); - return S_OK; - } - catch (...) - { - return winrt::to_hresult(); - } -} - -std::wstring RegistryPath() -{ - std::wstring registryPath; - registryPath.resize(CHARS_IN_GUID, L'\0'); - - StringFromGUID2(CLSID_POWERTOYS_VCM, registryPath.data(), CHARS_IN_GUID); - registryPath.resize(registryPath.size() - 1); - registryPath = L"CLSID\\" + registryPath; - return registryPath; -} - -bool RegisterServer() -{ - std::wstring dllPath; - dllPath.resize(MAX_PATH, L'\0'); - if (auto length = GetModuleFileNameW(DLLInstance, dllPath.data(), MAX_PATH); length != 0) - { - dllPath.resize(length); - } - else - { - return false; - } - - wil::unique_hkey key; - wil::unique_hkey subkey; - const auto registryPath = RegistryPath(); - if (RegCreateKeyW(HKEY_CLASSES_ROOT, registryPath.c_str(), &key)) - { - return false; - } - - if (RegSetValueW(key.get(), nullptr, REG_SZ, CAMERA_NAME, sizeof(CAMERA_NAME))) - { - return false; - } - - if (RegCreateKeyW(key.get(), L"InprocServer32", &subkey)) - { - return false; - } - - if (RegSetValueW(subkey.get(), nullptr, REG_SZ, dllPath.c_str(), static_cast((dllPath.length() + 1) * sizeof(wchar_t)))) - { - return false; - } - const wchar_t THREADING_MODEL[] = L"Both"; - RegSetValueExW(subkey.get(), L"ThreadingModel", 0, REG_SZ, (const BYTE*)THREADING_MODEL, sizeof(THREADING_MODEL)); - - return true; -} - -bool UnregisterServer() -{ - const auto registryPath = RegistryPath(); - return !RegDeleteTreeW(HKEY_CLASSES_ROOT, registryPath.c_str()); -} - -bool RegisterFilter() -{ - auto filterMapper = wil::CoCreateInstanceNoThrow(CLSID_FilterMapper2); - if (!filterMapper) - { - return false; - } - - REGFILTER2 regFilter{ .dwVersion = 1, .dwMerit = MERIT_DO_NOT_USE, .cPins = 1, .rgPins = &PINS_REGISTRATION }; - - wil::com_ptr_nothrow moniker; - - return SUCCEEDED(filterMapper->RegisterFilter( - CLSID_POWERTOYS_VCM, CAMERA_NAME, &moniker, &CLSID_VideoInputDeviceCategory, nullptr, ®Filter)); -} - -bool UnregisterFilter() -{ - auto filterMapper = wil::CoCreateInstanceNoThrow(CLSID_FilterMapper2); - if (!filterMapper) - { - return false; - } - - return SUCCEEDED(filterMapper->UnregisterFilter(&CLSID_VideoInputDeviceCategory, nullptr, CLSID_POWERTOYS_VCM)); -} - -HRESULT STDMETHODCALLTYPE DllRegisterServer() -{ - if (!RegisterServer()) - { - UnregisterServer(); - return E_FAIL; - } - - auto COMContext = wil::CoInitializeEx(COINIT_APARTMENTTHREADED); - - if (!RegisterFilter()) - { - UnregisterFilter(); - UnregisterServer(); - return E_FAIL; - } - - return S_OK; -} - -HRESULT STDMETHODCALLTYPE DllUnregisterServer() -{ - auto COMContext = wil::CoInitializeEx(COINIT_APARTMENTTHREADED); - - UnregisterFilter(); - UnregisterServer(); - - return S_OK; -} - -HRESULT STDMETHODCALLTYPE DllInstall(BOOL install, LPCWSTR) -{ - if (install) - { - return DllRegisterServer(); - } - else - { - return DllUnregisterServer(); - } -} - -BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID) -{ - if (fdwReason == DLL_PROCESS_ATTACH) - { - DLLInstance = hinstDLL; - } - - return true; -} diff --git a/src/modules/videoconference/VideoConferenceProxyFilter/module.def b/src/modules/videoconference/VideoConferenceProxyFilter/module.def deleted file mode 100644 index c4fcbcc6619b..000000000000 --- a/src/modules/videoconference/VideoConferenceProxyFilter/module.def +++ /dev/null @@ -1,7 +0,0 @@ -EXPORTS - DllMain PRIVATE - DllGetClassObject PRIVATE - DllCanUnloadNow PRIVATE - DllRegisterServer PRIVATE - DllUnregisterServer PRIVATE - DllInstall PRIVATE diff --git a/src/modules/videoconference/VideoConferenceProxyFilter/packages.config b/src/modules/videoconference/VideoConferenceProxyFilter/packages.config deleted file mode 100644 index 6199e2345ccd..000000000000 --- a/src/modules/videoconference/VideoConferenceProxyFilter/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/src/modules/videoconference/VideoConferenceProxyFilter/resource.h b/src/modules/videoconference/VideoConferenceProxyFilter/resource.h deleted file mode 100644 index fbba96964503..000000000000 --- a/src/modules/videoconference/VideoConferenceProxyFilter/resource.h +++ /dev/null @@ -1,11 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by VideoConferenceProxyFilter.rc - -////////////////////////////// -// Non-localizable - -#define FILE_DESCRIPTION "PowerToys VideoConferenceProxyFilter" -#define INTERNAL_NAME "PowerToys.VideoConferenceProxyFilter" -#define ORIGINAL_FILENAME "PowerToys.VideoConferenceProxyFilter_x64.dll" - diff --git a/src/modules/videoconference/VideoConferenceProxyFilter/resource.x86.h b/src/modules/videoconference/VideoConferenceProxyFilter/resource.x86.h deleted file mode 100644 index fe511d09292e..000000000000 --- a/src/modules/videoconference/VideoConferenceProxyFilter/resource.x86.h +++ /dev/null @@ -1,11 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by VideoConferenceProxyFilter.rc - -////////////////////////////// -// Non-localizable - -#define FILE_DESCRIPTION "PowerToys VideoConferenceProxyFilter" -#define INTERNAL_NAME "PowerToys.VideoConferenceProxyFilter" -#define ORIGINAL_FILENAME "PowerToys.VideoConferenceProxyFilter_x86.dll" - diff --git a/src/modules/videoconference/VideoConferenceShared/CameraStateUpdateChannels.cpp b/src/modules/videoconference/VideoConferenceShared/CameraStateUpdateChannels.cpp deleted file mode 100644 index 534428531bd3..000000000000 --- a/src/modules/videoconference/VideoConferenceShared/CameraStateUpdateChannels.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include "CameraStateUpdateChannels.h" - -#include "naming.h" - -std::wstring_view CameraOverlayImageChannel::endpoint() -{ - static const std::wstring endpoint = ObtainStableGlobalNameForKernelObject(L"PowerToysVideoConferenceCameraOverlayImageChannelSharedMemory", true); - return endpoint; -} - -std::wstring_view CameraSettingsUpdateChannel::endpoint() -{ - static const std::wstring endpoint = ObtainStableGlobalNameForKernelObject(L"PowerToysVideoConferenceSettingsChannelSharedMemory", true); - return endpoint; -} diff --git a/src/modules/videoconference/VideoConferenceShared/CameraStateUpdateChannels.h b/src/modules/videoconference/VideoConferenceShared/CameraStateUpdateChannels.h deleted file mode 100644 index 02ec542f7ae6..000000000000 --- a/src/modules/videoconference/VideoConferenceShared/CameraStateUpdateChannels.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include -#include -#include - -struct alignas(16) CameraSettingsUpdateChannel -{ - bool useOverlayImage = false; - bool cameraInUse = false; - - std::optional overlayImageSize; - std::optional> sourceCameraName; - - bool newOverlayImagePosted = false; - - static std::wstring_view endpoint(); -}; - -namespace CameraOverlayImageChannel -{ - std::wstring_view endpoint(); -} diff --git a/src/modules/videoconference/VideoConferenceShared/DLLProviderHelpers.h b/src/modules/videoconference/VideoConferenceShared/DLLProviderHelpers.h deleted file mode 100644 index 73c29cf08bc7..000000000000 --- a/src/modules/videoconference/VideoConferenceShared/DLLProviderHelpers.h +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once - -#define WIN32_LEAN_AND_MEAN -#include - -#include -#include -#include - -#define DECLARE_DLL_FUNCTION(NAME) \ - std::function NAME = (std::add_pointer_t)GetProcAddress(_library_handle, #NAME); - -#define DECLARE_DLL_PROVIDER_BEGIN(DLL_NAME) \ - class DLL_NAME##APIProvider final \ - { \ - HMODULE _library_handle; \ - DLL_NAME##APIProvider(HMODULE h) : _library_handle{ h } {} \ - \ - public: \ - ~DLL_NAME##APIProvider() { FreeLibrary(_library_handle); } \ - static std::optional create() \ - { \ - HMODULE h = LoadLibraryA(#DLL_NAME ".dll"); \ - std::optional result; \ - if (!h) \ - return result; \ - result.emplace(DLL_NAME##APIProvider{ h }); \ - return result; \ - } - -#define DECLARE_DLL_PROVIDER_END \ - } \ - ; diff --git a/src/modules/videoconference/VideoConferenceShared/Logging.cpp b/src/modules/videoconference/VideoConferenceShared/Logging.cpp deleted file mode 100644 index faeab04bb52b..000000000000 --- a/src/modules/videoconference/VideoConferenceShared/Logging.cpp +++ /dev/null @@ -1,202 +0,0 @@ -#include "Logging.h" - -#include -#include -#include -#include -#include -#include - -#include -#include - -#pragma warning(disable : 4127) - -static std::mutex logMutex; -constexpr inline size_t maxLogSizeMegabytes = 10; -constexpr inline bool alwaysLogVerbose = true; - -void LogToFile(std::wstring what, const bool verbose) -{ - std::error_code _; - const auto tempPath = std::filesystem::temp_directory_path(_); - if (verbose) - { - const bool verboseIndicatorFilePresent = std::filesystem::exists(tempPath / L"PowerToysVideoConferenceVerbose.flag", _); - if (!alwaysLogVerbose && !verboseIndicatorFilePresent) - { - return; - } - } - time_t now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); - std::tm tm; - localtime_s(&tm, &now); - char prefix[64]; - const auto pid = GetCurrentProcessId(); - const auto iter = prefix + sprintf_s(prefix, "[%ld]", pid); - std::strftime(iter, sizeof(prefix) - (prefix - iter), "[%d.%m %H:%M:%S] ", &tm); - - std::lock_guard lock{ logMutex }; - std::wstring logFilePath = tempPath; -#if defined(_WIN64) - logFilePath += L"\\PowerToysVideoConference_x64.log"; -#elif defined(_WIN32) - logFilePath += L"\\PowerToysVideoConference_x86.log"; -#endif - size_t logSizeMBs = 0; - try - { - logSizeMBs = static_cast(std::filesystem::file_size(logFilePath) >> 20); - } - catch (...) - { - } - if (logSizeMBs > maxLogSizeMegabytes) - { - std::error_code __; - // Truncate the log file to zero - std::filesystem::resize_file(logFilePath, 0, __); - } - std::wofstream myfile; - myfile.open(logFilePath, std::fstream::app); - - static const auto newLaunch = [&] { - myfile << prefix << "\n\n<<>"; - return 0; - }(); - - myfile << prefix << what << "\n"; - myfile.close(); -} - -void LogToFile(std::string what, const bool verbose) -{ - std::wstring native{ begin(what), end(what) }; - LogToFile(std::move(native), verbose); -} - -std::string toMediaTypeString(GUID subtype) -{ - if (subtype == MFVideoFormat_YUY2) - return "MFVideoFormat_YUY2"; - else if (subtype == MFVideoFormat_RGB32) - return "MFVideoFormat_RGB32"; - else if (subtype == MFVideoFormat_RGB24) - return "MFVideoFormat_RGB24"; - else if (subtype == MFVideoFormat_ARGB32) - return "MFVideoFormat_ARGB32"; - else if (subtype == MFVideoFormat_RGB555) - return "MFVideoFormat_RGB555"; - else if (subtype == MFVideoFormat_RGB565) - return "MFVideoFormat_RGB565"; - else if (subtype == MFVideoFormat_RGB8) - return "MFVideoFormat_RGB8"; - else if (subtype == MFVideoFormat_L8) - return "MFVideoFormat_L8"; - else if (subtype == MFVideoFormat_L16) - return "MFVideoFormat_L16"; - else if (subtype == MFVideoFormat_D16) - return "MFVideoFormat_D16"; - else if (subtype == MFVideoFormat_AYUV) - return "MFVideoFormat_AYUV"; - else if (subtype == MFVideoFormat_YVYU) - return "MFVideoFormat_YVYU"; - else if (subtype == MFVideoFormat_YVU9) - return "MFVideoFormat_YVU9"; - else if (subtype == MFVideoFormat_UYVY) - return "MFVideoFormat_UYVY"; - else if (subtype == MFVideoFormat_NV11) - return "MFVideoFormat_NV11"; - else if (subtype == MFVideoFormat_NV12) - return "MFVideoFormat_NV12"; - else if (subtype == MFVideoFormat_YV12) - return "MFVideoFormat_YV12"; - else if (subtype == MFVideoFormat_I420) - return "MFVideoFormat_I420"; - else if (subtype == MFVideoFormat_IYUV) - return "MFVideoFormat_IYUV"; - else if (subtype == MFVideoFormat_Y210) - return "MFVideoFormat_Y210"; - else if (subtype == MFVideoFormat_Y216) - return "MFVideoFormat_Y216"; - else if (subtype == MFVideoFormat_Y410) - return "MFVideoFormat_Y410"; - else if (subtype == MFVideoFormat_Y416) - return "MFVideoFormat_Y416"; - else if (subtype == MFVideoFormat_Y41P) - return "MFVideoFormat_Y41P"; - else if (subtype == MFVideoFormat_Y41T) - return "MFVideoFormat_Y41T"; - else if (subtype == MFVideoFormat_Y42T) - return "MFVideoFormat_Y42T"; - else if (subtype == MFVideoFormat_P210) - return "MFVideoFormat_P210"; - else if (subtype == MFVideoFormat_P216) - return "MFVideoFormat_P216"; - else if (subtype == MFVideoFormat_P010) - return "MFVideoFormat_P010"; - else if (subtype == MFVideoFormat_P016) - return "MFVideoFormat_P016"; - else if (subtype == MFVideoFormat_v210) - return "MFVideoFormat_v210"; - else if (subtype == MFVideoFormat_v216) - return "MFVideoFormat_v216"; - else if (subtype == MFVideoFormat_v410) - return "MFVideoFormat_v410"; - else if (subtype == MFVideoFormat_MP43) - return "MFVideoFormat_MP43"; - else if (subtype == MFVideoFormat_MP4S) - return "MFVideoFormat_MP4S"; - else if (subtype == MFVideoFormat_M4S2) - return "MFVideoFormat_M4S2"; - else if (subtype == MFVideoFormat_MP4V) - return "MFVideoFormat_MP4V"; - else if (subtype == MFVideoFormat_WMV1) - return "MFVideoFormat_WMV1"; - else if (subtype == MFVideoFormat_WMV2) - return "MFVideoFormat_WMV2"; - else if (subtype == MFVideoFormat_WMV3) - return "MFVideoFormat_WMV3"; - else if (subtype == MFVideoFormat_WVC1) - return "MFVideoFormat_WVC1"; - else if (subtype == MFVideoFormat_MSS1) - return "MFVideoFormat_MSS1"; - else if (subtype == MFVideoFormat_MSS2) - return "MFVideoFormat_MSS2"; - else if (subtype == MFVideoFormat_MPG1) - return "MFVideoFormat_MPG1"; - else if (subtype == MFVideoFormat_DVSL) - return "MFVideoFormat_DVSL"; - else if (subtype == MFVideoFormat_DVSD) - return "MFVideoFormat_DVSD"; - else if (subtype == MFVideoFormat_DVHD) - return "MFVideoFormat_DVHD"; - else if (subtype == MFVideoFormat_DV25) - return "MFVideoFormat_DV25"; - else if (subtype == MFVideoFormat_DV50) - return "MFVideoFormat_DV50"; - else if (subtype == MFVideoFormat_DVH1) - return "MFVideoFormat_DVH1"; - else if (subtype == MFVideoFormat_DVC) - return "MFVideoFormat_DVC"; - else if (subtype == MFVideoFormat_H264) - return "MFVideoFormat_H264"; - else if (subtype == MFVideoFormat_H265) - return "MFVideoFormat_H265"; - else if (subtype == MFVideoFormat_MJPG) - return "MFVideoFormat_MJPG"; - else if (subtype == MFVideoFormat_420O) - return "MFVideoFormat_420O"; - else if (subtype == MFVideoFormat_HEVC) - return "MFVideoFormat_HEVC"; - else if (subtype == MFVideoFormat_HEVC_ES) - return "MFVideoFormat_HEVC_ES"; - else if (subtype == MFVideoFormat_VP80) - return "MFVideoFormat_VP80"; - else if (subtype == MFVideoFormat_VP90) - return "MFVideoFormat_VP90"; - else if (subtype == MFVideoFormat_ORAW) - return "MFVideoFormat_ORAW"; - else - return "Other VideoFormat"; -} \ No newline at end of file diff --git a/src/modules/videoconference/VideoConferenceShared/Logging.h b/src/modules/videoconference/VideoConferenceShared/Logging.h deleted file mode 100644 index e58575922923..000000000000 --- a/src/modules/videoconference/VideoConferenceShared/Logging.h +++ /dev/null @@ -1,62 +0,0 @@ -#pragma once - -#include -#include -#include - -#include -#include - -void LogToFile(std::string what, const bool verbose = false); -void LogToFile(std::wstring what, const bool verbose = false); -std::string toMediaTypeString(GUID subtype); - -#define RETURN_IF_FAILED_WITH_LOGGING(val) \ - hr = (val); \ - if (FAILED(hr)) \ - { \ - LogToFile(std::string(__FUNCTION__ "() ") + #val + ": " + std::system_category().message(hr)); \ - return hr; \ - } - -#define RETURN_NULLPTR_IF_FAILED_WITH_LOGGING(val) \ - hr = val; \ - if (FAILED(hr)) \ - { \ - LogToFile(std::string(__FUNCTION__ "() ") + #val + ": " + std::system_category().message(hr)); \ - return nullptr; \ - } - -#define VERBOSE_LOG \ - std::string functionNameTMPVAR = __FUNCTION__; \ - LogToFile(std::string(functionNameTMPVAR + " enter"), true); \ - auto verboseLogOnScopeEnd = wil::scope_exit([&] { \ - LogToFile(std::string(functionNameTMPVAR + " exit"), true); \ - }); - -#if defined(PowerToysInterop) -#undef LOG -#define LOG(...) -#else -#define LOG(str) LogToFile(str, false); -#endif - -constexpr inline bool failed(HRESULT hr) -{ - return hr != S_OK; -} - -constexpr inline bool failed(bool val) -{ - return val == false; -} - -template -inline bool failed(wil::com_ptr_nothrow& ptr) -{ - return ptr == nullptr; -} - -#define OK_OR_BAIL(expr) \ - if (failed(expr)) \ - return {}; diff --git a/src/modules/videoconference/VideoConferenceShared/MediaFoundationAPIProvider.h b/src/modules/videoconference/VideoConferenceShared/MediaFoundationAPIProvider.h deleted file mode 100644 index e3d6fcec09ea..000000000000 --- a/src/modules/videoconference/VideoConferenceShared/MediaFoundationAPIProvider.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include -#include - -#include "DLLProviderHelpers.h" - -DECLARE_DLL_PROVIDER_BEGIN(mfplat) -DECLARE_DLL_FUNCTION(MFCreateAttributes) -DECLARE_DLL_PROVIDER_END - -DECLARE_DLL_PROVIDER_BEGIN(mf) -DECLARE_DLL_FUNCTION(MFEnumDeviceSources) -DECLARE_DLL_PROVIDER_END diff --git a/src/modules/videoconference/VideoConferenceShared/MicrophoneDevice.cpp b/src/modules/videoconference/VideoConferenceShared/MicrophoneDevice.cpp deleted file mode 100644 index f8e6f00a80e3..000000000000 --- a/src/modules/videoconference/VideoConferenceShared/MicrophoneDevice.cpp +++ /dev/null @@ -1,154 +0,0 @@ -#include "pch.h" -#include "MicrophoneDevice.h" - -#include "Logging.h" - -#include - -MicrophoneDevice::MicrophoneDevice(wil::com_ptr_nothrow device, wil::com_ptr_nothrow endpoint) : - _device{ std::move(device) }, - _endpoint{ std::move(endpoint) } -{ - if (!_device || !_endpoint) - { - throw std::logic_error("MicrophoneDevice was initialized with null objects"); - } - _device->GetId(&_id); - wil::com_ptr_nothrow props; - _device->OpenPropertyStore( - STGM_READ, &props); - if (props) - { - props->GetValue(PKEY_Device_FriendlyName, &_friendly_name); - } - else - { - LOG("MicrophoneDevice::MicrophoneDevice couldn't open property store"); - } -} - -MicrophoneDevice::~MicrophoneDevice() -{ - if (_notifier) - { - _endpoint->UnregisterControlChangeNotify(_notifier.get()); - } -} - -bool MicrophoneDevice::active() const noexcept -{ - DWORD state = 0; - _device->GetState(&state); - return state == DEVICE_STATE_ACTIVE; -} - -void MicrophoneDevice::set_muted(const bool muted) noexcept -{ - _endpoint->SetMute(muted, nullptr); -} - -bool MicrophoneDevice::muted() const noexcept -{ - BOOL muted = FALSE; - _endpoint->GetMute(&muted); - return muted; -} - -std::wstring_view MicrophoneDevice::id() const noexcept -{ - return _id ? _id.get() : FALLBACK_ID; -} - -std::wstring_view MicrophoneDevice::name() const noexcept -{ - return _friendly_name.pwszVal ? _friendly_name.pwszVal : FALLBACK_NAME; -} - -void MicrophoneDevice::set_mute_changed_callback(mute_changed_cb_t callback) noexcept -{ - if (_notifier) - { - _endpoint->UnregisterControlChangeNotify(_notifier.get()); - } - _mute_changed_callback = std::move(callback); - _notifier = winrt::make(this); - - _endpoint->RegisterControlChangeNotify(_notifier.get()); -} - -std::unique_ptr MicrophoneDevice::getDefault() -{ - auto deviceEnumerator = wil::CoCreateInstanceNoThrow(); - if (!deviceEnumerator) - { - LOG("MicrophoneDevice::getDefault MMDeviceEnumerator returned null"); - return nullptr; - } - wil::com_ptr_nothrow captureDevice; - deviceEnumerator->GetDefaultAudioEndpoint(eCapture, eCommunications, &captureDevice); - if (!captureDevice) - { - LOG("MicrophoneDevice::getDefault captureDevice is null"); - return nullptr; - } - wil::com_ptr_nothrow microphoneEndpoint; - captureDevice->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_INPROC_SERVER, nullptr, reinterpret_cast(µphoneEndpoint)); - if (!microphoneEndpoint) - { - LOG("MicrophoneDevice::getDefault captureDevice is null"); - return nullptr; - } - return std::make_unique(std::move(captureDevice), std::move(microphoneEndpoint)); -} - -std::vector> MicrophoneDevice::getAllActive() -{ - std::vector> microphoneDevices; - auto deviceEnumerator = wil::CoCreateInstanceNoThrow(); - if (!deviceEnumerator) - { - LOG("MicrophoneDevice::getAllActive MMDeviceEnumerator returned null"); - return microphoneDevices; - } - - wil::com_ptr_nothrow captureDevices; - deviceEnumerator->EnumAudioEndpoints(eCapture, DEVICE_STATE_ACTIVE, &captureDevices); - if (!captureDevices) - { - LOG("MicrophoneDevice::getAllActive EnumAudioEndpoints returned null"); - return microphoneDevices; - } - UINT nDevices = 0; - captureDevices->GetCount(&nDevices); - microphoneDevices.reserve(nDevices); - for (UINT i = 0; i < nDevices; ++i) - { - wil::com_ptr_nothrow device; - captureDevices->Item(i, &device); - if (!device) - { - continue; - } - wil::com_ptr_nothrow microphoneEndpoint; - device->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_INPROC_SERVER, nullptr, reinterpret_cast(µphoneEndpoint)); - if (!microphoneEndpoint) - { - continue; - } - microphoneDevices.push_back(std::make_unique(std::move(device), std::move(microphoneEndpoint))); - } - return microphoneDevices; -} - -MicrophoneDevice::VolumeNotifier::VolumeNotifier(MicrophoneDevice* subscribedDevice) : - _subscribedDevice{ subscribedDevice } -{ -} - -HRESULT __stdcall MicrophoneDevice::VolumeNotifier::OnNotify(PAUDIO_VOLUME_NOTIFICATION_DATA data) -{ - if (_subscribedDevice && _subscribedDevice->_mute_changed_callback) - _subscribedDevice->_mute_changed_callback(data->bMuted); - - return S_OK; -} diff --git a/src/modules/videoconference/VideoConferenceShared/MicrophoneDevice.h b/src/modules/videoconference/VideoConferenceShared/MicrophoneDevice.h deleted file mode 100644 index 6a40fb5d54d2..000000000000 --- a/src/modules/videoconference/VideoConferenceShared/MicrophoneDevice.h +++ /dev/null @@ -1,64 +0,0 @@ -#pragma once -#define NOMINMAX - -#include -#include - -#include -#include - -#include -#include - -#include - -#include -#include -#include - -#include -#include - -class MicrophoneDevice -{ -public: - using mute_changed_cb_t = std::function; - -private: - friend struct VolumeNotifier; - - struct VolumeNotifier : winrt::implements - { - MicrophoneDevice* _subscribedDevice = nullptr; - VolumeNotifier(MicrophoneDevice* subscribedDevice); - - virtual HRESULT __stdcall OnNotify(PAUDIO_VOLUME_NOTIFICATION_DATA data) override; - }; - - wil::unique_cotaskmem_string _id; - wil::unique_prop_variant _friendly_name; - mute_changed_cb_t _mute_changed_callback; - winrt::com_ptr _notifier; - wil::com_ptr_nothrow _endpoint; - wil::com_ptr_nothrow _device; - - constexpr static inline std::wstring_view FALLBACK_NAME = L"Unknown device"; - constexpr static inline std::wstring_view FALLBACK_ID = L"UNKNOWN_ID"; - -public: - MicrophoneDevice(MicrophoneDevice&&) noexcept = delete; - MicrophoneDevice(const MicrophoneDevice&) noexcept = delete; - MicrophoneDevice(wil::com_ptr_nothrow device, wil::com_ptr_nothrow endpoint); - ~MicrophoneDevice(); - - bool active() const noexcept; - void set_muted(const bool muted) noexcept; - bool muted() const noexcept; - - std::wstring_view id() const noexcept; - std::wstring_view name() const noexcept; - void set_mute_changed_callback(mute_changed_cb_t callback) noexcept; - - static std::unique_ptr getDefault(); - static std::vector> getAllActive(); -}; diff --git a/src/modules/videoconference/VideoConferenceShared/SerializedSharedMemory.cpp b/src/modules/videoconference/VideoConferenceShared/SerializedSharedMemory.cpp deleted file mode 100644 index a7620e77419f..000000000000 --- a/src/modules/videoconference/VideoConferenceShared/SerializedSharedMemory.cpp +++ /dev/null @@ -1,190 +0,0 @@ -#include "SerializedSharedMemory.h" -#ifdef _M_ARM64 -#define _mm_pause() __yield(); -#endif -inline char* SerializedSharedMemory::lock_flag_addr() noexcept -{ - return reinterpret_cast(_memory._data + _memory._size); -} - -inline void SerializedSharedMemory::lock() noexcept -{ - if (_read_only) - { - return; - } - while (LOCKED == _InterlockedCompareExchange8(lock_flag_addr(), LOCKED, !LOCKED)) - { - while (*lock_flag_addr() == LOCKED) - { - _mm_pause(); - } - } -} - -inline void SerializedSharedMemory::unlock() noexcept -{ - if (_read_only) - { - return; - } - _InterlockedExchange8(lock_flag_addr(), !LOCKED); -} - -SerializedSharedMemory::SerializedSharedMemory(std::array handles, - memory_t memory, - const bool readonly) noexcept - : - _handles{ std::move(handles) }, _memory{ std::move(memory) }, _read_only(readonly) -{ -} - -SerializedSharedMemory::~SerializedSharedMemory() noexcept -{ - if (_memory._data) - { - UnmapViewOfFile(_memory._data); - } -} - -SerializedSharedMemory::SerializedSharedMemory(SerializedSharedMemory&& rhs) noexcept -{ - *this = std::move(rhs); -} - -SerializedSharedMemory& SerializedSharedMemory::operator=(SerializedSharedMemory&& rhs) noexcept -{ - _handles = {}; - _handles.swap(rhs._handles); - _memory = std::move(rhs._memory); - rhs._memory = {}; - _read_only = rhs._read_only; - rhs._read_only = true; - - return *this; -} - -std::optional SerializedSharedMemory::create(const std::wstring_view object_name, - const size_t size, - const bool read_only, - SECURITY_ATTRIBUTES* maybe_attributes) noexcept -{ - SECURITY_DESCRIPTOR sd; - SECURITY_ATTRIBUTES sa = { sizeof SECURITY_ATTRIBUTES }; - if (!maybe_attributes) - { - sa.lpSecurityDescriptor = &sd; - sa.bInheritHandle = false; - if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION) || - !SetSecurityDescriptorDacl(&sd, true, nullptr, false)) - { - return std::nullopt; - } - } - - // We need an extra byte for locking if it's not readonly - const ULARGE_INTEGER UISize{ .QuadPart = static_cast(size) + !read_only }; - - wil::unique_handle hMapFile{ CreateFileMappingW(INVALID_HANDLE_VALUE, - maybe_attributes ? maybe_attributes : &sa, - read_only ? PAGE_READONLY : PAGE_READWRITE, - UISize.HighPart, - UISize.LowPart, - object_name.data()) }; - if (!hMapFile) - { - return std::nullopt; - } - auto shmem = static_cast( - MapViewOfFile(hMapFile.get(), read_only ? FILE_MAP_READ : FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, static_cast(UISize.QuadPart))); - if (!shmem) - { - return std::nullopt; - } - std::array handles = { std::move(hMapFile), {} }; - return SerializedSharedMemory{ std::move(handles), memory_t{ shmem, size }, read_only }; -} - -std::optional SerializedSharedMemory::open(const std::wstring_view object_name, - const size_t size, - const bool read_only) noexcept -{ - wil::unique_handle hMapFile{ OpenFileMappingW(FILE_MAP_READ | FILE_MAP_WRITE, FALSE, object_name.data()) }; - if (!hMapFile) - { - return std::nullopt; - } - - auto shmem = static_cast( - MapViewOfFile(hMapFile.get(), read_only ? FILE_MAP_READ : FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, size + !read_only)); - - if (!shmem) - { - return std::nullopt; - } - std::array handles = { std::move(hMapFile), {} }; - return SerializedSharedMemory{ std::move(handles), memory_t{ shmem, size }, read_only }; -} - -std::optional SerializedSharedMemory::create_readonly( - const std::wstring_view object_name, - const std::wstring_view file_path, - SECURITY_ATTRIBUTES* maybe_attributes) noexcept -{ - SECURITY_DESCRIPTOR sd; - SECURITY_ATTRIBUTES sa = { sizeof SECURITY_ATTRIBUTES }; - if (!maybe_attributes) - { - sa.lpSecurityDescriptor = &sd; - sa.bInheritHandle = false; - if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION) || - !SetSecurityDescriptorDacl(&sd, true, nullptr, false)) - { - return std::nullopt; - } - } - wil::unique_handle hFile{ CreateFileW(file_path.data(), - GENERIC_READ, - FILE_SHARE_READ | FILE_SHARE_WRITE, - maybe_attributes ? maybe_attributes : &sa, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - nullptr) }; - - if (!hFile) - { - return std::nullopt; - } - - LARGE_INTEGER fileSize; - if (!GetFileSizeEx(hFile.get(), &fileSize)) - { - return std::nullopt; - } - wil::unique_handle hMapFile{ CreateFileMappingW(hFile.get(), - maybe_attributes ? maybe_attributes : &sa, - PAGE_READONLY, - fileSize.HighPart, - fileSize.LowPart, - object_name.data()) }; - if (!hMapFile) - { - return std::nullopt; - } - - auto shmem = static_cast(MapViewOfFile(nullptr, FILE_MAP_READ, 0, 0, static_cast(fileSize.QuadPart))); - if (shmem) - { - return std::nullopt; - } - std::array handles = { std::move(hMapFile), std::move(hFile) }; - - return SerializedSharedMemory{ std::move(handles), memory_t{ shmem, static_cast(fileSize.QuadPart) }, true }; -} - -void SerializedSharedMemory::access(std::function access_routine) noexcept -{ - lock(); - access_routine(_memory); - unlock(); -} \ No newline at end of file diff --git a/src/modules/videoconference/VideoConferenceShared/SerializedSharedMemory.h b/src/modules/videoconference/VideoConferenceShared/SerializedSharedMemory.h deleted file mode 100644 index 15f10527467b..000000000000 --- a/src/modules/videoconference/VideoConferenceShared/SerializedSharedMemory.h +++ /dev/null @@ -1,54 +0,0 @@ -#pragma once -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif - -#include -#include -#include -#include -#include -#include - -// Wrapper class allowing sharing readonly/writable memory with a serialized access via atomic locking. -// Note that it doesn't protect against a 3rd party concurrently modifying physical file contents. -class SerializedSharedMemory -{ -public: - struct memory_t - { - uint8_t * _data = nullptr; - size_t _size = 0; - }; - - static std::optional create(const std::wstring_view object_name, - const size_t size, - const bool read_only, - SECURITY_ATTRIBUTES* maybe_attributes = nullptr) noexcept; - static std::optional create_readonly( - const std::wstring_view object_name, - const std::wstring_view file_path, - SECURITY_ATTRIBUTES* maybe_attributes = nullptr) noexcept; - static std::optional open(const std::wstring_view object_name, - const size_t size, - const bool read_only) noexcept; - - void access(std::function access_routine) noexcept; - inline size_t size() const noexcept { return _memory._size; } - - ~SerializedSharedMemory() noexcept; - SerializedSharedMemory(SerializedSharedMemory&&) noexcept; - SerializedSharedMemory& operator=(SerializedSharedMemory&&) noexcept; - -private: - std::array _handles; - memory_t _memory; - bool _read_only = true; - constexpr static inline int64_t LOCKED = 1; - - char* lock_flag_addr() noexcept; - void lock() noexcept; - void unlock() noexcept; - - SerializedSharedMemory(std::array handles, memory_t memory, const bool readonly) noexcept; -}; \ No newline at end of file diff --git a/src/modules/videoconference/VideoConferenceShared/VideoCaptureDeviceList.cpp b/src/modules/videoconference/VideoConferenceShared/VideoCaptureDeviceList.cpp deleted file mode 100644 index ba710a0453dc..000000000000 --- a/src/modules/videoconference/VideoConferenceShared/VideoCaptureDeviceList.cpp +++ /dev/null @@ -1,107 +0,0 @@ -#include "pch.h" -#include "VideoCaptureDeviceList.h" -#include "Logging.h" -#include "MediaFoundationAPIProvider.h" -#include -#include - -#include -#include - -void VideoCaptureDeviceList::Clear() -{ - for (UINT32 i = 0; i < m_numberDevices; i++) - { - CoTaskMemFree(m_deviceFriendlyNames[i]); - if (m_ppDevices[i]) - { - m_ppDevices[i]->Release(); - } - } - CoTaskMemFree(m_ppDevices); - m_ppDevices = nullptr; - if (m_deviceFriendlyNames) - { - delete[] m_deviceFriendlyNames; - } - - m_deviceFriendlyNames = nullptr; - m_numberDevices = 0; -} - -HRESULT VideoCaptureDeviceList::EnumerateDevices() -{ - HRESULT hr = S_OK; - wil::com_ptr pAttributes; - Clear(); - auto mfplatAPI = mfplatAPIProvider::create(); - auto mfAPI = mfAPIProvider::create(); - if (!mfplatAPI || !mfAPI) - { - return ERROR_FILE_NOT_FOUND; - } - - // Initialize an attribute store. We will use this to - // specify the enumeration parameters. - - hr = mfplatAPI->MFCreateAttributes(&pAttributes, 1); - - // Ask for source type = video capture devices - if (SUCCEEDED(hr)) - { - hr = pAttributes->SetGUID( - MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE, - MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID); - } - else - { - LOG("VideoCaptureDeviceList::EnumerateDevices(): Couldn't MFCreateAttributes"); - } - // Enumerate devices. - if (SUCCEEDED(hr)) - { - hr = mfAPI->MFEnumDeviceSources(pAttributes.get(), &m_ppDevices, &m_numberDevices); - } - else - { - LOG("VideoCaptureDeviceList::EnumerateDevices(): Couldn't SetGUID"); - } - - if (FAILED(hr)) - { - LOG("VideoCaptureDeviceList::EnumerateDevices(): MFEnumDeviceSources failed"); - return hr; - } - - m_deviceFriendlyNames = new (std::nothrow) wchar_t*[m_numberDevices]; - for (UINT32 i = 0; i < m_numberDevices; i++) - { - UINT32 nameLength = 0; - m_ppDevices[i]->GetAllocatedString(MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME, &m_deviceFriendlyNames[i], &nameLength); - } - - return hr; -} - -HRESULT VideoCaptureDeviceList::GetDevice(UINT32 index, IMFActivate** ppActivate) -{ - if (index >= Count()) - { - return E_INVALIDARG; - } - - *ppActivate = m_ppDevices[index]; - (*ppActivate)->AddRef(); - - return S_OK; -} - -std::wstring_view VideoCaptureDeviceList::GetDeviceName(UINT32 index) -{ - if (index >= Count()) - { - return {}; - } - - return m_deviceFriendlyNames[index]; -} diff --git a/src/modules/videoconference/VideoConferenceShared/VideoCaptureDeviceList.h b/src/modules/videoconference/VideoConferenceShared/VideoCaptureDeviceList.h deleted file mode 100644 index eb0bf4afd4b3..000000000000 --- a/src/modules/videoconference/VideoConferenceShared/VideoCaptureDeviceList.h +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once - -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif -#include -#include -#include - -class VideoCaptureDeviceList -{ - UINT32 m_numberDevices; - // TODO: use wil - IMFActivate** m_ppDevices = nullptr; - wchar_t** m_deviceFriendlyNames = nullptr; - -public: - VideoCaptureDeviceList() : - m_ppDevices(NULL), m_numberDevices(0) - { - } - ~VideoCaptureDeviceList() - { - Clear(); - } - - UINT32 Count() const { return m_numberDevices; } - - void Clear(); - HRESULT EnumerateDevices(); - HRESULT GetDevice(UINT32 index, IMFActivate** ppActivate); - std::wstring_view GetDeviceName(UINT32 index); -}; diff --git a/src/modules/videoconference/VideoConferenceShared/naming.cpp b/src/modules/videoconference/VideoConferenceShared/naming.cpp deleted file mode 100644 index b93088cd003f..000000000000 --- a/src/modules/videoconference/VideoConferenceShared/naming.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include "naming.h" - -#include "username.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/modules/videoconference/VideoConferenceShared/naming.h b/src/modules/videoconference/VideoConferenceShared/naming.h deleted file mode 100644 index 8d127b06231a..000000000000 --- a/src/modules/videoconference/VideoConferenceShared/naming.h +++ /dev/null @@ -1,5 +0,0 @@ -#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/modules/videoconference/VideoConferenceShared/pch.h b/src/modules/videoconference/VideoConferenceShared/pch.h deleted file mode 100644 index 128bb3589fa9..000000000000 --- a/src/modules/videoconference/VideoConferenceShared/pch.h +++ /dev/null @@ -1,2 +0,0 @@ -#pragma once -// Dummy file to allow compiling VideoCaptureDeviceList.h and MicrophoneDevice.h in this project, since it's also used in PowerToys.Interop.vcxproj, which has a pch. diff --git a/src/modules/videoconference/VideoConferenceShared/username.cpp b/src/modules/videoconference/VideoConferenceShared/username.cpp deleted file mode 100644 index d8b99e8dd57b..000000000000 --- a/src/modules/videoconference/VideoConferenceShared/username.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "username.h" - -#include -#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/modules/videoconference/VideoConferenceShared/username.h b/src/modules/videoconference/VideoConferenceShared/username.h deleted file mode 100644 index dcbefec38bbe..000000000000 --- a/src/modules/videoconference/VideoConferenceShared/username.h +++ /dev/null @@ -1,9 +0,0 @@ -#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/modules/videoconference/make_cab.ddf b/src/modules/videoconference/make_cab.ddf deleted file mode 100644 index 0c75024114b2..000000000000 --- a/src/modules/videoconference/make_cab.ddf +++ /dev/null @@ -1,20 +0,0 @@ -; Disable default limits -.option EXPLICIT -.set CabinetFileCountThreshold=0 -.set FolderFileCountThreshold=0 -.set FolderSizeThreshold=0 -.set MaxCabinetSize=0 -.set MaxDiskFileCount=0 -.set MaxDiskSize=0 - -.set GenerateInf=ON -.set Compress=OFF -.set Cabinet=ON -.set CabinetNameTemplate=driver.cab -.set DestinationDir=cab_output -.set DiskDirectoryTemplate=driver - -VideoConferenceCustomMediaSource.dll -videoconferencevirtualdriver.cat -VideoConferenceVirtualDriver.dll -VideoConferenceVirtualDriver.inf \ No newline at end of file diff --git a/src/runner/main.cpp b/src/runner/main.cpp index f3f64d868e04..4e86320ba458 100644 --- a/src/runner/main.cpp +++ b/src/runner/main.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include "UpdateUtils.h" #include "ActionRunnerUtils.h" @@ -132,6 +133,15 @@ int runner(bool isProcessElevated, bool openSettings, std::string settingsWindow } }.detach(); chdir_current_executable(); + + // We deprecated a utility called Video Conference Mute, which registered itself as a video input device. + // When running elevated, we try to clean up the device registration from previous installations. + // This is done here too because a user-scope installer won't be able to remove the driver registration due to lack of permissions. + if (isProcessElevated) + { + clean_video_conference(); + } + // Load PowerToys DLLs std::vector knownModules = { @@ -164,13 +174,8 @@ int runner(bool isProcessElevated, bool openSettings, std::string settingsWindow L"WinUI3Apps/PowerToys.FileActionsMenu.dll", L"PowerToys.CmdNotFoundModuleInterface.dll", L"PowerToys.WorkspacesModuleInterface.dll", + L"PowerToys.ZoomItModuleInterface.dll", }; - const auto VCM_PATH = L"PowerToys.VideoConferenceModule.dll"; - if (const auto mf = LoadLibraryA("mf.dll")) - { - FreeLibrary(mf); - knownModules.emplace_back(VCM_PATH); - } for (auto moduleSubdir : knownModules) { diff --git a/src/runner/settings_window.cpp b/src/runner/settings_window.cpp index 4c2787194eda..671fec0018da 100644 --- a/src/runner/settings_window.cpp +++ b/src/runner/settings_window.cpp @@ -674,8 +674,6 @@ std::string ESettingsWindowNames_to_string(ESettingsWindowNames value) return "FileExplorer"; case ESettingsWindowNames::ShortcutGuide: return "ShortcutGuide"; - case ESettingsWindowNames::VideoConference: - return "VideoConference"; case ESettingsWindowNames::Hosts: return "Hosts"; case ESettingsWindowNames::MeasureTool: @@ -696,6 +694,8 @@ std::string ESettingsWindowNames_to_string(ESettingsWindowNames value) return "AdvancedPaste"; case ESettingsWindowNames::NewPlus: return "NewPlus"; + case ESettingsWindowNames::ZoomIt: + return "ZoomIt"; default: { Logger::error(L"Can't convert ESettingsWindowNames value={} to string", static_cast(value)); @@ -751,10 +751,6 @@ ESettingsWindowNames ESettingsWindowNames_from_string(std::string value) { return ESettingsWindowNames::ShortcutGuide; } - else if (value == "VideoConference") - { - return ESettingsWindowNames::VideoConference; - } else if (value == "Hosts") { return ESettingsWindowNames::Hosts; @@ -795,6 +791,10 @@ ESettingsWindowNames ESettingsWindowNames_from_string(std::string value) { return ESettingsWindowNames::NewPlus; } + else if (value == "ZoomIt") + { + return ESettingsWindowNames::ZoomIt; + } else { Logger::error(L"Can't convert string value={} to ESettingsWindowNames", winrt::to_hstring(value)); diff --git a/src/runner/settings_window.h b/src/runner/settings_window.h index 6fd5afca0ff3..251fff28c7ce 100644 --- a/src/runner/settings_window.h +++ b/src/runner/settings_window.h @@ -16,7 +16,6 @@ enum class ESettingsWindowNames PowerRename, FileExplorer, ShortcutGuide, - VideoConference, Hosts, MeasureTool, PowerOCR, @@ -26,6 +25,7 @@ enum class ESettingsWindowNames EnvironmentVariables, AdvancedPaste, NewPlus, + ZoomIt, }; std::string ESettingsWindowNames_to_string(ESettingsWindowNames value); diff --git a/src/settings-ui/Settings.UI.Library/EnabledModules.cs b/src/settings-ui/Settings.UI.Library/EnabledModules.cs index 65bae34dea95..c571c29303bc 100644 --- a/src/settings-ui/Settings.UI.Library/EnabledModules.cs +++ b/src/settings-ui/Settings.UI.Library/EnabledModules.cs @@ -41,7 +41,7 @@ public bool FancyZones private bool fileActionsMenu = true; - [JsonPropertyName("File Actions Menu")] + [JsonPropertyName("FileActionsMenu")] public bool FileActionsMenu { get => fileActionsMenu; @@ -105,22 +105,6 @@ public bool ShortcutGuide } } - private bool videoConference; // defaulting to off https://github.com/microsoft/PowerToys/issues/14507 - - [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 @@ -513,6 +497,23 @@ public bool Workspaces } } + private bool zoomIt; + + [JsonPropertyName("ZoomIt")] + public bool ZoomIt + { + get => zoomIt; + set + { + if (zoomIt != value) + { + LogTelemetryEvent(value); + zoomIt = value; + NotifyChange(); + } + } + } + private void NotifyChange() { notifyEnabledChangedAction?.Invoke(); diff --git a/src/settings-ui/Settings.UI.Library/FileActionsMenuSettings.cs b/src/settings-ui/Settings.UI.Library/FileActionsMenuSettings.cs index 8b5a4056be63..b0985e754ce2 100644 --- a/src/settings-ui/Settings.UI.Library/FileActionsMenuSettings.cs +++ b/src/settings-ui/Settings.UI.Library/FileActionsMenuSettings.cs @@ -10,7 +10,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library { public class FileActionsMenuSettings : BasePTModuleSettings, ISettingsConfig { - public const string ModuleName = "File Actions Menu"; + public const string ModuleName = "FileActionsMenu"; public const string ModuleVersion = "1"; [JsonPropertyName("properties")] diff --git a/src/settings-ui/Settings.UI.Library/PeekPreviewSettings.cs b/src/settings-ui/Settings.UI.Library/PeekPreviewSettings.cs index f098b180520f..fa2fb3bf6c79 100644 --- a/src/settings-ui/Settings.UI.Library/PeekPreviewSettings.cs +++ b/src/settings-ui/Settings.UI.Library/PeekPreviewSettings.cs @@ -21,12 +21,15 @@ public class PeekPreviewSettings : ISettingsConfig public BoolProperty SourceCodeStickyScroll { get; set; } + public BoolProperty SourceCodeMinimap { get; set; } + public PeekPreviewSettings() { SourceCodeWrapText = new BoolProperty(false); SourceCodeTryFormat = new BoolProperty(false); SourceCodeFontSize = new IntProperty(14); SourceCodeStickyScroll = new BoolProperty(true); + SourceCodeMinimap = new BoolProperty(false); } public string ToJsonString() diff --git a/src/settings-ui/Settings.UI.Library/PowerLauncherPluginSettings.cs b/src/settings-ui/Settings.UI.Library/PowerLauncherPluginSettings.cs index 2b84fe16f230..0eac24b1269e 100644 --- a/src/settings-ui/Settings.UI.Library/PowerLauncherPluginSettings.cs +++ b/src/settings-ui/Settings.UI.Library/PowerLauncherPluginSettings.cs @@ -14,8 +14,12 @@ public class PowerLauncherPluginSettings public string Description { get; set; } + public string Version { get; set; } + public string Author { get; set; } + public string Website { get; set; } + public bool Disabled { get; set; } // Use to communicate the state to settings UI (Using int type because we can't reference GPOWrapper.) diff --git a/src/settings-ui/Settings.UI.Library/PowerPreviewProperties.cs b/src/settings-ui/Settings.UI.Library/PowerPreviewProperties.cs index 28d76dd067be..f6dd52701531 100644 --- a/src/settings-ui/Settings.UI.Library/PowerPreviewProperties.cs +++ b/src/settings-ui/Settings.UI.Library/PowerPreviewProperties.cs @@ -155,6 +155,23 @@ public bool MonacoPreviewStickyScroll } } + private bool monacoPreviewMinimap; + + [JsonPropertyName("monaco-previewer-minimap")] + [JsonConverter(typeof(BoolPropertyJsonConverter))] + public bool MonacoPreviewMinimap + { + get => monacoPreviewMinimap; + set + { + if (value != monacoPreviewMinimap) + { + LogTelemetryEvent(value); + monacoPreviewMinimap = value; + } + } + } + private bool enablePdfPreview; [JsonPropertyName("pdf-previewer-toggle-setting")] diff --git a/src/settings-ui/Settings.UI.Library/Settings.UI.Library.csproj b/src/settings-ui/Settings.UI.Library/Settings.UI.Library.csproj index a967dd28a770..c3832b11c508 100644 --- a/src/settings-ui/Settings.UI.Library/Settings.UI.Library.csproj +++ b/src/settings-ui/Settings.UI.Library/Settings.UI.Library.csproj @@ -19,6 +19,7 @@ + diff --git a/src/settings-ui/Settings.UI.Library/SndVideoConferenceSettings.cs b/src/settings-ui/Settings.UI.Library/SndVideoConferenceSettings.cs deleted file mode 100644 index b16c79de7910..000000000000 --- a/src/settings-ui/Settings.UI.Library/SndVideoConferenceSettings.cs +++ /dev/null @@ -1,25 +0,0 @@ -// 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.Library -{ - public class SndVideoConferenceSettings - { - [JsonPropertyName("Video Conference")] - public VideoConferenceSettings VideoConference { get; set; } - - public SndVideoConferenceSettings(VideoConferenceSettings settings) - { - VideoConference = settings; - } - - public string ToJsonString() - { - return JsonSerializer.Serialize(this); - } - } -} diff --git a/src/settings-ui/Settings.UI.Library/VideoConferenceConfigProperties.cs b/src/settings-ui/Settings.UI.Library/VideoConferenceConfigProperties.cs deleted file mode 100644 index 9c7b33f80411..000000000000 --- a/src/settings-ui/Settings.UI.Library/VideoConferenceConfigProperties.cs +++ /dev/null @@ -1,113 +0,0 @@ -// 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; - -using Settings.UI.Library.Attributes; - -namespace Microsoft.PowerToys.Settings.UI.Library -{ - public class VideoConferenceConfigProperties - { - [CmdConfigureIgnoreAttribute] - public HotkeySettings DefaultMuteCameraAndMicrophoneHotkey => new HotkeySettings() - { - Win = true, - Ctrl = false, - Alt = false, - Shift = true, - Key = "Q", - Code = 81, - }; - - [CmdConfigureIgnoreAttribute] - public HotkeySettings DefaultMuteMicrophoneHotkey => new HotkeySettings() - { - Win = true, - Ctrl = false, - Alt = false, - Shift = true, - Key = "A", - Code = 65, - }; - - [CmdConfigureIgnoreAttribute] - public HotkeySettings DefaultPushToTalkMicrophoneHotkey => new HotkeySettings() - { - Win = true, - Ctrl = false, - Alt = false, - Shift = true, - Key = "I", - Code = 73, - }; - - [CmdConfigureIgnoreAttribute] - public HotkeySettings DefaultMuteCameraHotkey => new HotkeySettings() - { - Win = true, - Ctrl = false, - Alt = false, - Shift = true, - Key = "O", - Code = 79, - }; - - public VideoConferenceConfigProperties() - { - MuteCameraAndMicrophoneHotkey = new KeyboardKeysProperty(DefaultMuteCameraAndMicrophoneHotkey); - MuteMicrophoneHotkey = new KeyboardKeysProperty(DefaultMuteMicrophoneHotkey); - PushToTalkMicrophoneHotkey = new KeyboardKeysProperty(DefaultPushToTalkMicrophoneHotkey); - MuteCameraHotkey = new KeyboardKeysProperty(DefaultMuteCameraHotkey); - - PushToReverseEnabled = new BoolProperty(false); - } - - [JsonPropertyName("mute_camera_and_microphone_hotkey")] - public KeyboardKeysProperty MuteCameraAndMicrophoneHotkey { get; set; } - - [JsonPropertyName("mute_microphone_hotkey")] - public KeyboardKeysProperty MuteMicrophoneHotkey { get; set; } - - [JsonPropertyName("push_to_talk_microphone_hotkey")] - public KeyboardKeysProperty PushToTalkMicrophoneHotkey { get; set; } - - [JsonPropertyName("push_to_reverse_enabled")] - public BoolProperty PushToReverseEnabled { get; set; } - - [JsonPropertyName("mute_camera_hotkey")] - public KeyboardKeysProperty MuteCameraHotkey { get; set; } - - [JsonPropertyName("selected_camera")] - public StringProperty SelectedCamera { get; set; } = string.Empty; - - [JsonPropertyName("selected_mic")] - public StringProperty SelectedMicrophone { get; set; } = string.Empty; - - [JsonPropertyName("toolbar_position")] - public StringProperty ToolbarPosition { get; set; } = "Top right corner"; - - [JsonPropertyName("toolbar_monitor")] - public StringProperty ToolbarMonitor { get; set; } = "Main monitor"; - - [JsonPropertyName("camera_overlay_image_path")] - public StringProperty CameraOverlayImagePath { get; set; } = string.Empty; - - [JsonPropertyName("theme")] - public StringProperty Theme { get; set; } - - [JsonPropertyName("toolbar_hide")] - public StringProperty ToolbarHide { get; set; } = "When both camera and microphone are unmuted"; - - [JsonPropertyName("startup_action")] - public StringProperty StartupAction { get; set; } = "Nothing"; - - // converts the current to a json string. - public string ToJsonString() - { - return JsonSerializer.Serialize(this); - } - } -} diff --git a/src/settings-ui/Settings.UI.Library/VideoConferenceSettingsIPCMessage.cs b/src/settings-ui/Settings.UI.Library/VideoConferenceSettingsIPCMessage.cs deleted file mode 100644 index 1fdc7f489e33..000000000000 --- a/src/settings-ui/Settings.UI.Library/VideoConferenceSettingsIPCMessage.cs +++ /dev/null @@ -1,29 +0,0 @@ -// 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.Library -{ - 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/settings-ui/Settings.UI.Library/ZoomItProperties.cs b/src/settings-ui/Settings.UI.Library/ZoomItProperties.cs new file mode 100644 index 000000000000..3cd756267368 --- /dev/null +++ b/src/settings-ui/Settings.UI.Library/ZoomItProperties.cs @@ -0,0 +1,107 @@ +// 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.Serialization; +using Settings.UI.Library.Attributes; + +namespace Microsoft.PowerToys.Settings.UI.Library +{ + public class ZoomItProperties + { + public ZoomItProperties() + { + } + + [CmdConfigureIgnore] + public static HotkeySettings DefaultToggleKey => new HotkeySettings(false, true, false, false, '1'); // Ctrl+1 + + [CmdConfigureIgnore] + public static HotkeySettings DefaultLiveZoomToggleKey => new HotkeySettings(false, true, false, false, '4'); // Ctrl+4 + + [CmdConfigureIgnore] + public static HotkeySettings DefaultDrawToggleKey => new HotkeySettings(false, true, false, false, '2'); // Ctrl+2 + + [CmdConfigureIgnore] + public static HotkeySettings DefaultRecordToggleKey => new HotkeySettings(false, true, false, false, '5'); // Ctrl+5 + + [CmdConfigureIgnore] + public static HotkeySettings DefaultSnipToggleKey => new HotkeySettings(false, true, false, false, '6'); // Ctrl+6 + + [CmdConfigureIgnore] + public static HotkeySettings DefaultBreakTimerKey => new HotkeySettings(false, true, false, false, '3'); // Ctrl+3 + + [CmdConfigureIgnore] + public static HotkeySettings DefaultDemoTypeToggleKey => new HotkeySettings(false, true, false, false, '7'); // Ctrl+7 + + public KeyboardKeysProperty ToggleKey { get; set; } + + public KeyboardKeysProperty LiveZoomToggleKey { get; set; } + + public KeyboardKeysProperty DrawToggleKey { get; set; } + + public KeyboardKeysProperty RecordToggleKey { get; set; } + + public KeyboardKeysProperty SnipToggleKey { get; set; } + + public StringProperty PenColor { get; set; } + + public IntProperty PenWidth { get; set; } + + public StringProperty BreakPenColor { get; set; } + + public KeyboardKeysProperty BreakTimerKey { get; set; } + + public StringProperty Font { get; set; } + + public KeyboardKeysProperty DemoTypeToggleKey { get; set; } + + public StringProperty DemoTypeFile { get; set; } + + public IntProperty DemoTypeSpeedSlider { get; set; } + + public BoolProperty DemoTypeUserDrivenMode { get; set; } + + public IntProperty BreakTimeout { get; set; } + + public IntProperty BreakOpacity { get; set; } + + public BoolProperty BreakPlaySoundFile { get; set; } + + public StringProperty BreakSoundFile { get; set; } + + public BoolProperty BreakShowBackgroundFile { get; set; } + + public BoolProperty BreakBackgroundStretch { get; set; } + + public StringProperty BreakBackgroundFile { get; set; } + + public IntProperty BreakTimerPosition { get; set; } + + public BoolProperty BreakShowDesktop { get; set; } + + public BoolProperty BreakOnSecondary { get; set; } + + public IntProperty FontScale { get; set; } + + public BoolProperty ShowExpiredTime { get; set; } + + public BoolProperty ShowTrayIcon { get; set; } + + public BoolProperty AnimnateZoom { get; set; } + + public BoolProperty TelescopeZoomOut { get; set; } + + public BoolProperty SnapToGrid { get; set; } + + public IntProperty ZoominSliderLevel { get; set; } + + public IntProperty RecordFrameRate { get; set; } + + public IntProperty RecordScaling { get; set; } + + public BoolProperty CaptureAudio { get; set; } + + public StringProperty MicrophoneDeviceId { get; set; } + } +} diff --git a/src/settings-ui/Settings.UI.Library/VideoConferenceSettings.cs b/src/settings-ui/Settings.UI.Library/ZoomItSettings.cs similarity index 57% rename from src/settings-ui/Settings.UI.Library/VideoConferenceSettings.cs rename to src/settings-ui/Settings.UI.Library/ZoomItSettings.cs index c33bcdaaa6d4..db3b07f36365 100644 --- a/src/settings-ui/Settings.UI.Library/VideoConferenceSettings.cs +++ b/src/settings-ui/Settings.UI.Library/ZoomItSettings.cs @@ -1,32 +1,32 @@ -// Copyright (c) Microsoft Corporation +// 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.Serialization; - using Microsoft.PowerToys.Settings.UI.Library.Interfaces; namespace Microsoft.PowerToys.Settings.UI.Library { - public class VideoConferenceSettings : BasePTModuleSettings, ISettingsConfig + public class ZoomItSettings : BasePTModuleSettings, ISettingsConfig { - public const string ModuleName = "Video Conference"; + public const string ModuleName = "ZoomIt"; + + [JsonPropertyName("properties")] + public ZoomItProperties Properties { get; set; } - public VideoConferenceSettings() + public ZoomItSettings() { - Version = "1"; Name = ModuleName; - Properties = new VideoConferenceConfigProperties(); + Properties = new ZoomItProperties(); + Version = "1.0"; } - [JsonPropertyName("properties")] - public VideoConferenceConfigProperties Properties { get; set; } - public string GetModuleName() { return Name; } + // This can be utilized in the future if the settings.json file is to be modified/deleted. public bool UpgradeSettingsConfiguration() { return false; diff --git a/src/settings-ui/Settings.UI.Library/backup_restore_settings.json b/src/settings-ui/Settings.UI.Library/backup_restore_settings.json index 84a03db71379..390df0bfb92c 100644 --- a/src/settings-ui/Settings.UI.Library/backup_restore_settings.json +++ b/src/settings-ui/Settings.UI.Library/backup_restore_settings.json @@ -5,7 +5,8 @@ "*settings.json", "*FancyZones\\custom-layouts.json", "*FancyZones\\layout-hotkeys.json", - "*FancyZones\\layout-templates.json" + "*FancyZones\\layout-templates.json", + "*Workspaces\\workspaces.json" ], "IgnoreFiles": [ "*PowerToys\\log_settings.json", diff --git a/src/settings-ui/Settings.UI/Assets/Settings/Icons/VideoConferenceMute.png b/src/settings-ui/Settings.UI/Assets/Settings/Icons/VideoConferenceMute.png deleted file mode 100644 index 22a39baf64ce..000000000000 Binary files a/src/settings-ui/Settings.UI/Assets/Settings/Icons/VideoConferenceMute.png and /dev/null differ diff --git a/src/settings-ui/Settings.UI/Assets/Settings/Icons/ZoomIt.png b/src/settings-ui/Settings.UI/Assets/Settings/Icons/ZoomIt.png new file mode 100644 index 000000000000..f3c8aff3dedd Binary files /dev/null and b/src/settings-ui/Settings.UI/Assets/Settings/Icons/ZoomIt.png differ diff --git a/src/settings-ui/Settings.UI/Assets/Settings/Modules/OOBE/VideoConferenceMute.png b/src/settings-ui/Settings.UI/Assets/Settings/Modules/OOBE/VideoConferenceMute.png deleted file mode 100644 index 722ee5ca1d3a..000000000000 Binary files a/src/settings-ui/Settings.UI/Assets/Settings/Modules/OOBE/VideoConferenceMute.png and /dev/null differ diff --git a/src/settings-ui/Settings.UI/Assets/Settings/Modules/OOBE/ZoomIt.gif b/src/settings-ui/Settings.UI/Assets/Settings/Modules/OOBE/ZoomIt.gif new file mode 100644 index 000000000000..74c024ae8177 Binary files /dev/null and b/src/settings-ui/Settings.UI/Assets/Settings/Modules/OOBE/ZoomIt.gif differ diff --git a/src/settings-ui/Settings.UI/Assets/Settings/Modules/VideoConference.png b/src/settings-ui/Settings.UI/Assets/Settings/Modules/VideoConference.png deleted file mode 100644 index 028d98889c62..000000000000 Binary files a/src/settings-ui/Settings.UI/Assets/Settings/Modules/VideoConference.png and /dev/null differ diff --git a/src/settings-ui/Settings.UI/Assets/Settings/Modules/ZoomIt.png b/src/settings-ui/Settings.UI/Assets/Settings/Modules/ZoomIt.png new file mode 100644 index 000000000000..c4fb8b00f6ee Binary files /dev/null and b/src/settings-ui/Settings.UI/Assets/Settings/Modules/ZoomIt.png differ diff --git a/src/settings-ui/Settings.UI/Converters/ZoomItInitialZoomConverter.cs b/src/settings-ui/Settings.UI/Converters/ZoomItInitialZoomConverter.cs new file mode 100644 index 000000000000..2107caa39147 --- /dev/null +++ b/src/settings-ui/Settings.UI/Converters/ZoomItInitialZoomConverter.cs @@ -0,0 +1,34 @@ +// 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 Microsoft.PowerToys.Settings.UI.Library; +using Microsoft.UI.Xaml.Data; + +namespace Microsoft.PowerToys.Settings.UI.Converters +{ + public sealed partial class ZoomItInitialZoomConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, string language) + { + string targetValue = string.Empty; + int zoomLevel = System.Convert.ToInt32((double)value); + + // Should match the zoom values expected by ZoomIt internal logic. + switch (zoomLevel) + { + case 0: targetValue = "1.25"; break; + case 1: targetValue = "1.5"; break; + case 2: targetValue = "1.75"; break; + case 3: targetValue = "2.0"; break; + case 4: targetValue = "3.0"; break; + case 5: targetValue = "4.0"; break; + } + + return targetValue; + } + + public object ConvertBack(object value, Type targetType, object parameter, string language) => throw new NotImplementedException(); + } +} diff --git a/src/settings-ui/Settings.UI/Converters/ZoomItTypeSpeedSliderConverter.cs b/src/settings-ui/Settings.UI/Converters/ZoomItTypeSpeedSliderConverter.cs new file mode 100644 index 000000000000..61208b00b353 --- /dev/null +++ b/src/settings-ui/Settings.UI/Converters/ZoomItTypeSpeedSliderConverter.cs @@ -0,0 +1,27 @@ +// 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 Microsoft.PowerToys.Settings.UI.Helpers; +using Microsoft.PowerToys.Settings.UI.Library; +using Microsoft.UI.Xaml.Data; + +namespace Microsoft.PowerToys.Settings.UI.Converters +{ + public sealed partial class ZoomItTypeSpeedSliderConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, string language) + { + string targetValue = string.Empty; + int zoomLevel = System.Convert.ToInt32((double)value); + string explanation = ResourceLoaderInstance.ResourceLoader.GetString("ZoomIt_DemoType_SpeedSlider_Thumbnail_Explanation"); + + targetValue = $"{zoomLevel} ({explanation})"; + + return targetValue; + } + + public object ConvertBack(object value, Type targetType, object parameter, string language) => throw new NotImplementedException(); + } +} diff --git a/src/settings-ui/Settings.UI/Helpers/CHOOSEFONT.cs b/src/settings-ui/Settings.UI/Helpers/CHOOSEFONT.cs new file mode 100644 index 000000000000..026a9f01a192 --- /dev/null +++ b/src/settings-ui/Settings.UI/Helpers/CHOOSEFONT.cs @@ -0,0 +1,70 @@ +// 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.Runtime.InteropServices; + +namespace Microsoft.PowerToys.Settings.UI.Helpers +{ + [System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1307:Accessible fields should begin with upper-case letter", Justification = "Keep original names from original structure")] + [System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1306:Field names should begin with lower-case letter", Justification = "Keep original names from original structure")] + [System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401:Fields should be private", Justification = "Structure used for win32 interop. We need to access the fields")] + [System.Diagnostics.CodeAnalysis.SuppressMessage("Performance", "CA1805:Do not initialize unnecessarily", Justification = "Let's have initializations be explicit for these win32 interop types")] + + // Class to select the Dialog options to call ChooseFont. + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] + public class CHOOSEFONT + { + public int lStructSize = Marshal.SizeOf(typeof(CHOOSEFONT)); + public IntPtr hwndOwner = IntPtr.Zero; + public IntPtr hDC = IntPtr.Zero; + public IntPtr lpLogFont = IntPtr.Zero; + public int iPointSize = 0; + public int Flags = 0; + public int rgbColors = 0; + public IntPtr lCustData = IntPtr.Zero; + public IntPtr lpfnHook = IntPtr.Zero; + public string lpTemplateName = null; + public IntPtr hInstance = IntPtr.Zero; + public string lpszStyle = null; + public short nFontType; + private short __MISSING_ALIGNMENT__; + public int nSizeMin; + public int nSizeMax; + } + + [Flags] + public enum CHOOSE_FONT_FLAGS + { + CF_SCREENFONTS = 0x00000001, + CF_PRINTER_FONTS = 0x00000002, + CF_BOTH = CF_SCREENFONTS | CF_PRINTER_FONTS, + CF_SHOW_HELP = 0x00000004, + CF_ENABLE_HOOK = 0x00000008, + CF_ENABLETEMPLATE = 0x00000010, + CF_ENABLETEMPLATE_HANDLE = 0x00000020, + CF_INITTOLOGFONTSTRUCT = 0x00000040, + CF_USE_STYLE = 0x00000080, + CF_EFFECTS = 0x00000100, + CF_APPLY = 0x00000200, + CF_ANSI_ONLY = 0x00000400, + CF_SCRIPTS_ONLY = CF_ANSI_ONLY, + CF_NO_VECTOR_FONTS = 0x00000800, + CF_NO_OEM_FONTS = CF_NO_VECTOR_FONTS, + CF_NO_SIMULATIONS = 0x00001000, + CF_LIMITSIZE = 0x00002000, + CF_FIXED_PITCH_ONLY = 0x00004000, + CF_WYSIWYG = 0x00008000, + CF_FORCE_FONT_EXIST = 0x00010000, + CF_SCALABLE_ONLY = 0x00020000, + CF_TT_ONLY = 0x00040000, + CF_NO_FACE_SEL = 0x00080000, + CF_NO_STYLE_SEL = 0x00100000, + CF_NO_SIZE_SEL = 0x00200000, + CF_SELECT_SCRIPT = 0x00400000, + CF_NO_SCRIPT_SEL = 0x00800000, + CF_NO_VERT_FONTS = 0x01000000, + CF_INACTIVE_FONTS = 0x02000000, + } +} diff --git a/src/settings-ui/Settings.UI/Helpers/LOGFONT.cs b/src/settings-ui/Settings.UI/Helpers/LOGFONT.cs new file mode 100644 index 000000000000..575f91d117d3 --- /dev/null +++ b/src/settings-ui/Settings.UI/Helpers/LOGFONT.cs @@ -0,0 +1,125 @@ +// 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.Runtime.InteropServices; + +namespace Microsoft.PowerToys.Settings.UI.Helpers +{ + [System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1307:Accessible fields should begin with upper-case letter", Justification = "Keep original names from original structure")] + [System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401:Fields should be private", Justification = "Structure used for win32 interop. We need to access the fields")] + [System.Diagnostics.CodeAnalysis.SuppressMessage("Performance", "CA1805:Do not initialize unnecessarily", Justification = "Let's have initializations be explicit for these win32 interop types")] + + // Result from calling ChooseFont. + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] + public class LOGFONT + { + public int lfHeight = 0; + public int lfWidth = 0; + public int lfEscapement = 0; + public int lfOrientation = 0; + public int lfWeight = 0; + public byte lfItalic = 0; + public byte lfUnderline = 0; + public byte lfStrikeOut = 0; + public byte lfCharSet = 0; + public byte lfOutPrecision = 0; + public byte lfClipPrecision = 0; + public byte lfQuality = 0; + public byte lfPitchAndFamily = 0; + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] + public string lfFaceName = string.Empty; + } + + public enum FontWeight : int + { + FW_DONT_CARE = 0, + FW_THIN = 100, + FW_EXTRALIGHT = 200, + FW_LIGHT = 300, + FW_NORMAL = 400, + FW_MEDIUM = 500, + FW_SEMIBOLD = 600, + FW_BOLD = 700, + FW_EXTRABOLD = 800, + FW_HEAVY = 900, + } + + public enum FontCharSet : byte + { + ANSI_CHARSET = 0, + DEFAULT_CHARSET = 1, + SYMBOL_CHARSET = 2, + SHIFT_JIS_CHARSET = 128, + HANGEUL_CHARSET = 129, + HANGUL_CHARSET = HANGEUL_CHARSET, + GB2312_CHARSET = 134, + CHINESE_BIG5_CHARSET = 136, + OEM_CHARSET = 255, + JOHAB_CHARSET = 130, + HEBREW_CHARSET = 177, + ARABIC_CHARSET = 178, + GREEK_CHARSET = 161, + TURKISH_CHARSET = 162, + VIETNAMESE_CHARSET = 163, + THAI_CHARSET = 222, + EAST_EUROPE_CHARSET = 238, + RUSSIAN_CHARSET = 204, + MAC_CHARSET = 77, + BALTIC_CHARSET = 186, + } + + public enum FontPrecision : byte + { + OUT_DEFAULT_PRECIS = 0, + OUT_STRING_PRECIS = 1, + OUT_CHARACTER_PRECIS = 2, + OUT_STROKE_PRECIS = 3, + OUT_TT_PRECIS = 4, + OUT_DEVICE_PRECIS = 5, + OUT_RASTER_PRECIS = 6, + OUT_TT_ONLY_PRECIS = 7, + OUT_OUTLINE_PRECIS = 8, + OUT_SCREEN_OUTLINE_PRECIS = 9, + OUT_PS_ONLY_PRECIS = 10, + } + + public enum FontClipPrecision : byte + { + CLIP_DEFAULT_PRECIS = 0, + CLIP_CHARACTER_PRECIS = 1, + CLIP_STROKE_PRECIS = 2, + CLIP_MASK = 0xf, + CLIP_LH_ANGLES = 1 << 4, + CLIP_TT_ALWAYS = 2 << 4, + CLIP_DFA_DISABLE = 4 << 4, + CLIP_EMBEDDED = 8 << 4, + } + + public enum FontQuality : byte + { + DEFAULT_QUALITY = 0, + DRAFT_QUALITY = 1, + PROOF_QUALITY = 2, + NONANTIALIASED_QUALITY = 3, + ANTIALIASED_QUALITY = 4, + CLEAR_TYPE_QUALITY = 5, + CLEAR_TYPE_NATURAL_QUALITY = 6, + } + + [Flags] + public enum FontPitchAndFamily : byte + { + DEFAULT_PITCH = 0, + FIXED_PITCH = 1, + VARIABLE_PITCH = 2, + FF_DONT_CARE = DEFAULT_PITCH, + FF_ROMAN = 1 << 4, + FF_SWISS = 2 << 4, + FF_MODERN = 3 << 4, + FF_SCRIPT = 4 << 4, + FF_DECORATIVE = 5 << 4, + } +} diff --git a/src/settings-ui/Settings.UI/Helpers/ModuleHelper.cs b/src/settings-ui/Settings.UI/Helpers/ModuleHelper.cs index 4d466cd461ec..8e0f8f0f0c62 100644 --- a/src/settings-ui/Settings.UI/Helpers/ModuleHelper.cs +++ b/src/settings-ui/Settings.UI/Helpers/ModuleHelper.cs @@ -73,6 +73,7 @@ public static bool GetIsModuleEnabled(Library.GeneralSettings generalSettingsCon case ModuleType.MeasureTool: return generalSettingsConfig.Enabled.MeasureTool; case ModuleType.ShortcutGuide: return generalSettingsConfig.Enabled.ShortcutGuide; case ModuleType.PowerOCR: return generalSettingsConfig.Enabled.PowerOcr; + case ModuleType.ZoomIt: return generalSettingsConfig.Enabled.ZoomIt; default: return false; } } @@ -111,6 +112,7 @@ internal static void SetIsModuleEnabled(GeneralSettings generalSettingsConfig, M case ModuleType.MeasureTool: generalSettingsConfig.Enabled.MeasureTool = isEnabled; break; case ModuleType.ShortcutGuide: generalSettingsConfig.Enabled.ShortcutGuide = isEnabled; break; case ModuleType.PowerOCR: generalSettingsConfig.Enabled.PowerOcr = isEnabled; break; + case ModuleType.ZoomIt: generalSettingsConfig.Enabled.ZoomIt = isEnabled; break; } } @@ -144,6 +146,7 @@ public static GpoRuleConfigured GetModuleGpoConfiguration(ModuleType moduleType) case ModuleType.MeasureTool: return GPOWrapper.GetConfiguredScreenRulerEnabledValue(); case ModuleType.ShortcutGuide: return GPOWrapper.GetConfiguredShortcutGuideEnabledValue(); case ModuleType.PowerOCR: return GPOWrapper.GetConfiguredTextExtractorEnabledValue(); + case ModuleType.ZoomIt: return GPOWrapper.GetConfiguredZoomItEnabledValue(); default: return GpoRuleConfigured.Unavailable; } } @@ -179,6 +182,7 @@ public static System.Type GetModulePageType(ModuleType moduleType) ModuleType.MeasureTool => typeof(MeasureToolPage), ModuleType.ShortcutGuide => typeof(ShortcutGuidePage), ModuleType.PowerOCR => typeof(PowerOcrPage), + ModuleType.ZoomIt => typeof(ZoomItPage), _ => typeof(DashboardPage), // never called, all values listed above }; } diff --git a/src/settings-ui/Settings.UI/Helpers/NativeMethods.cs b/src/settings-ui/Settings.UI/Helpers/NativeMethods.cs index c895866c1ebc..072f12b00cd3 100644 --- a/src/settings-ui/Settings.UI/Helpers/NativeMethods.cs +++ b/src/settings-ui/Settings.UI/Helpers/NativeMethods.cs @@ -48,6 +48,12 @@ public static class NativeMethods [DllImport("Comdlg32.dll", CharSet = CharSet.Unicode)] internal static extern bool GetOpenFileName([In, Out] OpenFileName openFileName); + [DllImport("comdlg32.dll", CharSet = CharSet.Auto, EntryPoint = "ChooseFont", SetLastError = true)] + internal static extern bool ChooseFont(IntPtr lpChooseFont); + + [DllImport("comdlg32.dll", SetLastError = true)] + internal static extern int CommDlgExtendedError(); + #pragma warning disable CA1401 // P/Invokes should not be visible [DllImport("user32.dll")] public static extern bool ShowWindow(System.IntPtr hWnd, int nCmdShow); diff --git a/src/settings-ui/Settings.UI/Helpers/StartProcessHelper.cs b/src/settings-ui/Settings.UI/Helpers/StartProcessHelper.cs index 70157075acf3..ce172b2aa2f4 100644 --- a/src/settings-ui/Settings.UI/Helpers/StartProcessHelper.cs +++ b/src/settings-ui/Settings.UI/Helpers/StartProcessHelper.cs @@ -3,8 +3,7 @@ // See the LICENSE file in the project root for more information. using System.Diagnostics; - -using Common.UI; +using ManagedCommon; namespace Microsoft.PowerToys.Settings.UI.Helpers { diff --git a/src/settings-ui/Settings.UI/OOBE/Enums/PowerToysModules.cs b/src/settings-ui/Settings.UI/OOBE/Enums/PowerToysModules.cs index 0520629dd938..310a4f24940d 100644 --- a/src/settings-ui/Settings.UI/OOBE/Enums/PowerToysModules.cs +++ b/src/settings-ui/Settings.UI/OOBE/Enums/PowerToysModules.cs @@ -28,12 +28,12 @@ public enum PowerToysModules QuickAccent, ShortcutGuide, TextExtractor, - VideoConference, MeasureTool, Hosts, Workspaces, WhatsNew, RegistryPreview, NewPlus, + ZoomIt, } } diff --git a/src/settings-ui/Settings.UI/PowerToys.Settings.csproj b/src/settings-ui/Settings.UI/PowerToys.Settings.csproj index 7a465fbd01f6..1e460af13d7f 100644 --- a/src/settings-ui/Settings.UI/PowerToys.Settings.csproj +++ b/src/settings-ui/Settings.UI/PowerToys.Settings.csproj @@ -33,7 +33,7 @@ - PowerToys.GPOWrapper + PowerToys.GPOWrapper;PowerToys.ZoomItSettingsInterop $(OutDir) false @@ -87,6 +87,7 @@ + diff --git a/src/settings-ui/Settings.UI/SettingsXAML/App.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/App.xaml.cs index 85f64f62cc79..1fb40ce907d9 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/App.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/App.xaml.cs @@ -241,6 +241,10 @@ private void OnLaunchedFromRunner(string[] cmdArgs) // https://github.com/microsoft/microsoft-ui-xaml/issues/7595 - Activate doesn't bring window to the foreground // Need to call SetForegroundWindow to actually gain focus. WindowHelpers.BringToForeground(settingsWindow.GetWindowHandle()); + + // https://github.com/microsoft/microsoft-ui-xaml/issues/8948 - A window's top border incorrectly + // renders as black on Windows 10. + WindowHelpers.ForceTopBorder1PixelInsetOnWindows10(WindowNative.GetWindowHandle(settingsWindow)); } else { @@ -255,6 +259,7 @@ private void OnLaunchedFromRunner(string[] cmdArgs) OobeWindow oobeWindow = new OobeWindow(OOBE.Enums.PowerToysModules.Overview); oobeWindow.Activate(); oobeWindow.ExtendsContentIntoTitleBar = true; + WindowHelpers.ForceTopBorder1PixelInsetOnWindows10(WindowNative.GetWindowHandle(settingsWindow)); SetOobeWindow(oobeWindow); } else if (ShowScoobe) @@ -263,6 +268,7 @@ private void OnLaunchedFromRunner(string[] cmdArgs) OobeWindow scoobeWindow = new OobeWindow(OOBE.Enums.PowerToysModules.WhatsNew); scoobeWindow.Activate(); scoobeWindow.ExtendsContentIntoTitleBar = true; + WindowHelpers.ForceTopBorder1PixelInsetOnWindows10(WindowNative.GetWindowHandle(settingsWindow)); SetOobeWindow(scoobeWindow); } else if (ShowFlyout) @@ -310,6 +316,7 @@ protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs ar // Window is also needed to show MessageDialog settingsWindow = new MainWindow(); settingsWindow.ExtendsContentIntoTitleBar = true; + WindowHelpers.ForceTopBorder1PixelInsetOnWindows10(WindowNative.GetWindowHandle(settingsWindow)); settingsWindow.Activate(); settingsWindow.NavigateToSection(StartupPage); ShowMessageDialog("The application is running in Debug mode.", "DEBUG"); @@ -433,7 +440,6 @@ public static Type GetPage(string settingWindow) case "FileExplorer": return typeof(PowerPreviewPage); case "ShortcutGuide": return typeof(ShortcutGuidePage); case "PowerOcr": return typeof(PowerOcrPage); - case "VideoConference": return typeof(VideoConferencePage); case "MeasureTool": return typeof(MeasureToolPage); case "Hosts": return typeof(HostsPage); case "RegistryPreview": return typeof(RegistryPreviewPage); @@ -442,6 +448,7 @@ public static Type GetPage(string settingWindow) case "EnvironmentVariables": return typeof(EnvironmentVariablesPage); case "NewPlus": return typeof(NewPlusPage); case "Workspaces": return typeof(WorkspacesPage); + case "ZoomIt": return typeof(ZoomItPage); default: // Fallback to Dashboard Debug.Assert(false, "Unexpected SettingsWindow argument value"); diff --git a/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeShellPage.xaml b/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeShellPage.xaml index 0bf3abeb2f11..fef6a5105e18 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeShellPage.xaml +++ b/src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/OobeShellPage.xaml @@ -162,14 +162,14 @@ x:Uid="Shell_TextExtractor" Icon="{ui:BitmapIcon Source=/Assets/Settings/Icons/TextExtractor.png}" Tag="TextExtractor" /> - + - - - - - - - - - - - - - - - - -