diff --git a/.gitignore b/.gitignore
index dfcfd56..b107b64 100644
--- a/.gitignore
+++ b/.gitignore
@@ -348,3 +348,9 @@ MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
+
+# C++
+**/vcpkg_installed/**
+
+# Other
+Gyroshell/Resources/rmclient.dll
\ No newline at end of file
diff --git a/GyroShell.ImmersiveShellHook/GyroShell.ImmersiveShellHook.vcxproj b/GyroShell.ImmersiveShellHook/GyroShell.ImmersiveShellHook.vcxproj
new file mode 100644
index 0000000..ffc9113
--- /dev/null
+++ b/GyroShell.ImmersiveShellHook/GyroShell.ImmersiveShellHook.vcxproj
@@ -0,0 +1,172 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ 17.0
+ Win32Proj
+ {617aea24-0755-490c-bc05-6dbb5e2059e0}
+ GyroShellImmersiveShellHook
+ 10.0
+
+
+
+ DynamicLibrary
+ true
+ v143
+ Unicode
+
+
+ DynamicLibrary
+ false
+ v143
+ true
+ Unicode
+
+
+ DynamicLibrary
+ true
+ v143
+ Unicode
+
+
+ DynamicLibrary
+ false
+ v143
+ true
+ Unicode
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ rmclient
+
+
+
+ Level3
+ true
+ WIN32;_DEBUG;GYROSHELLIMMERSIVESHELLHOOK_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
+ true
+ Use
+ pch.h
+
+
+ Windows
+ true
+ false
+ Source.def
+
+
+
+
+ Level3
+ true
+ true
+ true
+ WIN32;NDEBUG;GYROSHELLIMMERSIVESHELLHOOK_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
+ true
+ Use
+ pch.h
+
+
+ Windows
+ true
+ true
+ true
+ false
+ Source.def
+
+
+
+
+ Level3
+ true
+ _DEBUG;GYROSHELLIMMERSIVESHELLHOOK_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
+ true
+ Use
+ pch.h
+
+
+ Windows
+ true
+ false
+ shlwapi.lib;rpcrt4.lib;Wtsapi32.lib;%(AdditionalDependencies)
+ Source.def
+
+
+
+
+ Level3
+ true
+ true
+ true
+ NDEBUG;GYROSHELLIMMERSIVESHELLHOOK_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
+ true
+ Use
+ pch.h
+
+
+ Windows
+ true
+ true
+ true
+ false
+ shlwapi.lib;rpcrt4.lib;Wtsapi32.lib;%(AdditionalDependencies)
+ Source.def
+
+
+
+
+
+
+
+
+
+
+ Create
+ Create
+ Create
+ Create
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/GyroShell.ImmersiveShellHook/GyroShell.ImmersiveShellHook.vcxproj.filters b/GyroShell.ImmersiveShellHook/GyroShell.ImmersiveShellHook.vcxproj.filters
new file mode 100644
index 0000000..c5cea67
--- /dev/null
+++ b/GyroShell.ImmersiveShellHook/GyroShell.ImmersiveShellHook.vcxproj.filters
@@ -0,0 +1,41 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+
+
+ Source Files
+
+
+
\ No newline at end of file
diff --git a/GyroShell.ImmersiveShellHook/Source.def b/GyroShell.ImmersiveShellHook/Source.def
new file mode 100644
index 0000000..789090c
--- /dev/null
+++ b/GyroShell.ImmersiveShellHook/Source.def
@@ -0,0 +1,5 @@
+EXPORTS
+HamCloseActivity
+HamPopulateActivityProperties
+SECTIONS
+.imrsiv READ
\ No newline at end of file
diff --git a/GyroShell.ImmersiveShellHook/dllmain.cpp b/GyroShell.ImmersiveShellHook/dllmain.cpp
new file mode 100644
index 0000000..eaad3f1
--- /dev/null
+++ b/GyroShell.ImmersiveShellHook/dllmain.cpp
@@ -0,0 +1,277 @@
+#include "pch.h"
+#include
+#include
+#include
+#include
+#include
+
+//INSTALL DETOURS FROM NUGET! (or build from source yourself)
+#include
+#include
+
+#include "undoc.h"
+
+typedef HRESULT(CALLBACK* SetShellWindow)(HWND hwnd);
+
+long PcRef = 0;
+IUnknown* ThreadObject = NULL;
+
+LRESULT ProgmanWndProc(HWND hwnd, UINT msg, WPARAM w, LPARAM l)
+{
+ if (msg == WM_CREATE)
+ {
+ auto user32 = LoadLibrary(TEXT("user32.dll"));
+ SetShellWindow SetShellWindowFunc = (SetShellWindow)GetProcAddress(user32, "SetShellWindow");
+ if (SetShellWindowFunc == NULL)
+ {
+ printf("immersive shell starter: failed to get pointer to SetShellWindow()\n");
+ system("pause");
+ return GetLastError();
+ }
+
+ if (FAILED(SetShellWindowFunc(hwnd)))
+ {
+ printf("SetShellWindow failed\n");
+ return 0;
+ }
+ SendMessageW(hwnd, WM_CHANGEUISTATE, 3u, 0);
+ SendMessageW(hwnd, WM_UPDATEUISTATE, 0x10001u, 0);
+
+ SetProp(hwnd, TEXT("NonRudeHWND"), (HANDLE)HANDLE_FLAG_INHERIT);
+ SetProp(hwnd, TEXT("AllowConsentToStealFocus"), (HANDLE)HANDLE_FLAG_INHERIT);
+
+
+ if (SUCCEEDED(SHCreateThreadRef(&PcRef, &ThreadObject)))
+ {
+ SHSetThreadRef(ThreadObject);
+ }
+ else
+ {
+ printf("Failed to create thread reference");
+ }
+ }
+ else if (msg == WM_DESTROY)
+ {
+ if (GetShellWindow() == hwnd)
+ {
+ RemovePropW(hwnd, L"AllowConsentToStealFocus");
+ RemovePropW(hwnd, L"NonRudeHWND");
+
+ auto user32 = LoadLibrary(TEXT("user32.dll"));
+ SetShellWindow SetShellWindowFunc = (SetShellWindow)GetProcAddress(user32, "SetShellWindow");
+ if (SetShellWindowFunc == NULL)
+ {
+ printf("immersive shell starter: failed to get pointer to SetShellWindow()\n");
+ system("pause");
+ return GetLastError();
+ }
+ SetShellWindowFunc(NULL);
+ }
+ }
+ else if (msg == WM_SIZE)
+ {
+ ShowWindow(hwnd, 5);
+ }
+ else if (msg == WM_CLOSE)
+ {
+ return -1;
+ }
+ else if (msg == WM_PAINT)
+ {
+ PAINTSTRUCT Paint;
+ RECT Rect;
+ HDC dc = BeginPaint(hwnd, &Paint);
+ GetClientRect(hwnd, &Rect);
+ FillRect(dc, &Rect, CreateSolidBrush(RGB(0, 36, 0)));
+ EndPaint(hwnd, &Paint);
+ return 0;
+ }
+ else if (msg == WM_TIMER)
+ {
+ printf("timer!\n");
+ }
+ return DefWindowProc(hwnd, msg, w, l);
+}
+
+
+
+HINSTANCE g_hInstance = NULL;
+
+HWND CreateProgman()
+{
+ printf("Create program manager\n");
+
+ WNDCLASSEX progmanclass = {};
+ progmanclass.cbClsExtra = 0;
+ progmanclass.hIcon = 0;
+ progmanclass.lpszMenuName = 0;
+ progmanclass.hIconSm = 0;
+ progmanclass.cbSize = 80;
+ progmanclass.style = 8;
+ progmanclass.lpfnWndProc = (WNDPROC)ProgmanWndProc;
+ progmanclass.cbWndExtra = 8;
+ progmanclass.hInstance = g_hInstance;
+ progmanclass.hCursor = LoadCursor(NULL, IDC_ARROW);
+ progmanclass.hbrBackground = (HBRUSH)2;
+ progmanclass.lpszClassName = TEXT("Progman");
+
+ if (!RegisterClassExW(&progmanclass))
+ {
+ printf("failed to register progman class %d", GetLastError());
+ return NULL;
+ }
+
+ return CreateWindowExW(128, L"Progman", TEXT("Program Manager"), 0x82000000, 0, 0, 0, 0, 0, 0, progmanclass.hInstance, 0);
+}
+
+int MainHook(
+ HINSTANCE hInstance,
+ HINSTANCE hPrevInstance,
+ LPSTR lpCmdLine,
+ int nShowCmd
+)
+{
+ printf("Winmain hooked!\n");
+ g_hInstance = hInstance;
+
+ if (FAILED(CoInitializeEx(NULL, 2)))
+ {
+ printf("Failed to initialize COM\n");
+ return -1;
+ }
+ printf("Starting the immersive shell provider/controller\n");
+
+
+
+
+ // find progman window and set it as the shell window
+ HWND progman = CreateProgman();
+ if (!progman)
+ {
+ printf("failed to create progman window\n");
+ system("pause");
+ return GetLastError();
+ }
+
+ IImmersiveShellBuilder* ImmersiveShellBuilder = NULL;
+
+ GUID guid;
+ if (FAILED(CLSIDFromString(L"{c71c41f1-ddad-42dc-a8fc-f5bfc61df957}", &guid)))
+ {
+ printf("failed to read guid1\n");
+ return -1;
+ }
+ GUID guid2;
+ if (FAILED(CLSIDFromString(L"{1c56b3e4-e6ea-4ced-8a74-73b72c6bd435}", &guid2)))
+ {
+ printf("failed to read guid2\n");
+ return -1;
+ }
+ HRESULT hr = CoCreateInstance(
+ guid,
+ 0,
+ 1u,
+ guid2,
+ (LPVOID*)&ImmersiveShellBuilder);
+
+ if (FAILED(hr))
+ {
+ printf("Failed to create the immersive shell builder: 0x%x\n", hr);
+ system("pause");
+ return hr;
+ }
+ IImmersiveShellController* controller = NULL;
+ hr = ImmersiveShellBuilder->CreateImmersiveShellController(&controller); //CImmersiveShellController
+ if (FAILED(hr))
+ {
+ printf("Failed to create the immersive shell controller: 0x%x\n", hr);
+ system("pause");
+ return hr;
+ }
+
+
+
+ hr = controller->Start();
+
+
+ if (FAILED(hr))
+ {
+ printf("immersive shell start failed with 0x%x\n", hr);
+ }
+ else
+ {
+ printf("Immersive shell created. Starting message loop\n");
+
+ if (!CreateEventW(0, TRUE, 0, L"Local\\ShellStartupEvent"))
+ {
+ printf("Failed to create start event: %d\n", GetLastError());
+
+ }
+
+ HANDLE StartEvent = OpenEvent(2, FALSE, TEXT("Local\\ShellStartupEvent"));
+ if (!StartEvent)
+ {
+ printf("Failed to open start event: %d\n", GetLastError());
+ }
+ else
+ {
+ if (!SetEvent(StartEvent))
+ {
+ printf("Failed to set start event: %d\n", GetLastError());
+ }
+ }
+ }
+
+ return -1;
+}
+
+BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
+{
+ switch (ul_reason_for_call)
+ {
+ case DLL_PROCESS_ATTACH:
+ {
+ DisableThreadLibraryCalls(hModule);
+ AllocConsole();
+
+ freopen("CONIN$", "r", stdin);
+ freopen("CONOUT$", "w", stdout);
+ freopen("CONOUT$", "w", stderr);
+
+ printf("Hooked into runtimebroker");
+
+ //LaunchCustomShellHost
+ MODULEINFO info = {};
+ if (!GetModuleInformation(GetCurrentProcess(), NULL, &info, sizeof(MODULEINFO)))
+ {
+ printf("GetModuleInformation() failure: %d", GetLastError());
+ }
+ else
+ {
+ printf("entry point of runtimebroker is at %x, hooking it now\n", info.EntryPoint);
+
+ DetourTransactionBegin();
+ DetourUpdateThread(GetCurrentThread());
+ DetourAttach(&info.EntryPoint, (PVOID)MainHook);
+ DetourTransactionCommit();
+ }
+ }
+ break;
+ case DLL_PROCESS_DETACH:
+ {
+ //TODO
+ }
+ break;
+ }
+ return TRUE;
+}
+
+void HamCloseActivity()
+{
+ printf("STUB FUNCTION: HamCloseActivity\n");
+}
+
+void HamPopulateActivityProperties()
+{
+ printf("STUB FUNCTION: HamPopulateActivityProperties\n");
+}
\ No newline at end of file
diff --git a/GyroShell.ImmersiveShellHook/framework.h b/GyroShell.ImmersiveShellHook/framework.h
new file mode 100644
index 0000000..0965e73
--- /dev/null
+++ b/GyroShell.ImmersiveShellHook/framework.h
@@ -0,0 +1,6 @@
+#pragma once
+
+#define _CRT_SECURE_NO_WARNINGS 1
+#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+// Windows Header Files
+#include
diff --git a/GyroShell.ImmersiveShellHook/pch.cpp b/GyroShell.ImmersiveShellHook/pch.cpp
new file mode 100644
index 0000000..91c22df
--- /dev/null
+++ b/GyroShell.ImmersiveShellHook/pch.cpp
@@ -0,0 +1,5 @@
+// pch.cpp: source file corresponding to the pre-compiled header
+
+#include "pch.h"
+
+// When you are using pre-compiled headers, this source file is necessary for compilation to succeed.
diff --git a/GyroShell.ImmersiveShellHook/pch.h b/GyroShell.ImmersiveShellHook/pch.h
new file mode 100644
index 0000000..04ff4c2
--- /dev/null
+++ b/GyroShell.ImmersiveShellHook/pch.h
@@ -0,0 +1,13 @@
+// pch.h: This is a precompiled header file.
+// Files listed below are compiled only once, improving build performance for future builds.
+// This also affects IntelliSense performance, including code completion and many code browsing features.
+// However, files listed here are ALL re-compiled if any one of them is updated between builds.
+// Do not add files here that you will be updating frequently as this negates the performance advantage.
+
+#ifndef PCH_H
+#define PCH_H
+
+// add headers that you want to pre-compile here
+#include "framework.h"
+
+#endif //PCH_H
diff --git a/GyroShell.ImmersiveShellHook/undoc.h b/GyroShell.ImmersiveShellHook/undoc.h
new file mode 100644
index 0000000..f485c98
--- /dev/null
+++ b/GyroShell.ImmersiveShellHook/undoc.h
@@ -0,0 +1,12 @@
+#pragma once
+interface IImmersiveShellController : IUnknown
+{
+ virtual HRESULT Start();
+ virtual HRESULT Stop(void* unknown);
+ virtual HRESULT SetCreationBehavior(void* structure);
+
+};
+interface IImmersiveShellBuilder : IUnknown
+{
+ virtual HRESULT CreateImmersiveShellController(IImmersiveShellController** other);
+};
diff --git a/GyroShell.ImmersiveShellHook/vcpkg-configuration.json b/GyroShell.ImmersiveShellHook/vcpkg-configuration.json
new file mode 100644
index 0000000..b9734a0
--- /dev/null
+++ b/GyroShell.ImmersiveShellHook/vcpkg-configuration.json
@@ -0,0 +1,14 @@
+{
+ "default-registry": {
+ "kind": "git",
+ "baseline": "7f9f0e44db287e8e67c0e888141bfa200ab45121",
+ "repository": "https://github.com/microsoft/vcpkg"
+ },
+ "registries": [
+ {
+ "kind": "artifact",
+ "location": "https://github.com/microsoft/vcpkg-ce-catalog/archive/refs/heads/main.zip",
+ "name": "microsoft"
+ }
+ ]
+}
diff --git a/GyroShell.ImmersiveShellHook/vcpkg.json b/GyroShell.ImmersiveShellHook/vcpkg.json
new file mode 100644
index 0000000..d184b6f
--- /dev/null
+++ b/GyroShell.ImmersiveShellHook/vcpkg.json
@@ -0,0 +1,5 @@
+{
+ "dependencies": [
+ "detours"
+ ]
+}
diff --git a/GyroShell.Library/Helpers/Win32/Win32Interop.cs b/GyroShell.Library/Helpers/Win32/Win32Interop.cs
index b7c883a..6e1f6c5 100644
--- a/GyroShell.Library/Helpers/Win32/Win32Interop.cs
+++ b/GyroShell.Library/Helpers/Win32/Win32Interop.cs
@@ -1,493 +1,579 @@
-#region Copyright (BSD 3-Clause License)
-/*
- * GyroShell - A modern, extensible, fast, and customizable shell platform.
- * Copyright 2022-2024 Pdawg
- *
- * Licensed under the BSD 3-Clause License.
- * SPDX-License-Identifier: BSD-3-Clause
- */
-#endregion
-
-using System;
-using System.Runtime.InteropServices;
-using System.Text;
-using static GyroShell.Library.Interfaces.IPropertyStoreAUMID;
-
-namespace GyroShell.Library.Helpers.Win32
-{
- public static class Win32Interop
- {
- [StructLayout(LayoutKind.Sequential)]
- public struct NativeRect
- {
- public int Left;
- public int Top;
- public int Right;
- public int Bottom;
- }
-
- [StructLayout(LayoutKind.Sequential)]
- public struct RECT
- {
- public int left;
- public int top;
- public int right;
- public int bottom;
- }
-
- public const int WM_COMMAND = 0x0111;
- public const int WM_SYSCOMMAND = 0x0112;
-
- public const int SC_MINIMIZE = 0xF020;
- public const int SC_MOVE = 0xF010;
- public const int SC_RESTORE = 0xF120;
- public const int SC_SIZE = 0xF000;
- public const int SC_CLOSE = 0xF060;
-
- public const int SW_RESTORE = 9;
- public const int SW_MINIMIZE = 6;
- public const int SW_SHOW = 5;
- public const int SW_HIDE = 0;
- public const int SW_MAXIMIZE = 3;
-
- public const int SPI_SETWORKAREA = 0x002F;
- public const int SPI_GETWORKAREA = 0x0030;
-
- public const int SPIF_UPDATEINIFILE = 1;
-
- public const int GWL_EXSTYLE = -20;
- public const int GWL_STYLE = -16;
-
- public const int DWMWA_CLOAKED = 14;
-
- public const int GCL_HICONSM = -34;
- public const int GCL_HICON = -14;
-
- public const int ICON_SMALL = 0;
- public const int ICON_BIG = 1;
- public const int ICON_SMALL2 = 2;
- public const int WM_GETICON = 0x7F;
-
- public const uint GA_PARENT = 1;
- public const uint GA_ROOT = 2;
- public const uint GA_ROOTOWNER = 3;
-
- public const int WS_EX_APPWINDOW = 0x00040000;
- public const int WS_EX_TOOLWINDOW = 0x00000080;
- public const int WS_EX_NOACTIVATE = 0x08000000;
- public const int WS_EX_WINDOWEDGE = 0x100;
- public const int WS_EX_TOPMOST = 0x00000008;
- public const int WS_VISIBLE = 0x10000000;
- public const int WS_CHILD = 0x40000000;
-
- public const int HSHELL_WINDOWCREATED = 1;
- public const int HSHELL_WINDOWDESTROYED = 2;
- public const int HSHELL_ACTIVATESHELLWINDOW = 3;
- public const int HSHELL_WINDOWACTIVATED = 4;
- public const int HSHELL_RUDEAPPACTIVATED = 32772;
- public const int HSHELL_GETMINRECT = 5;
- public const int HSHELL_REDRAW = 6;
- public const int HSHELL_TASKMAN = 7;
- public const int HSHELL_LANGUAGE = 8;
- public const int HSHELL_SYSMENU = 9;
- public const int HSHELL_ENDTASK = 10;
- public const int HSHELL_ACCESSIBILITYSTATE = 11;
- public const int HSHELL_APPCOMMAND = 12;
- public const int HSHELL_WINDOWREPLACED = 13;
- public const int HSHELL_WINDOWREPLACING = 14;
- public const int HSHELL_MONITORCHANGED = 16; //A window is moved to a different monitor.
- public const int HSHELL_HIGHBIT = 0x8000;
- public const int HSHELL_FLASH = 0x8006;
-
- public const int FAPPCOMMAND_MASK = 0xF000;
-
- public const int GWLP_WNDPROC = -4;
- public const int SM_CXSCREEN = 0;
- public const int SM_CYSCREEN = 1;
-
- public const int WINEVENT_OUTOFCONTEXT = 0x0000;
- public const int WINEVENT_SKIPOWNTHREAD = 0x0001;
- public const int EVENT_SYSTEM_DESKTOPSWITCH = 0x0020;
- public const int EVENT_OBJECT_CLOAKED = 0x8017;
- public const int EVENT_OBJECT_UNCLOAKED = 0x8018;
- public const int EVENT_OBJECT_NAMECHANGED = 0x800C;
- public const int EVENT_OBJECT_DESTROY = 0x8001;
- public const int EVENT_OBJECT_CREATE = 0x8000;
- public const int WINEVENT_INCONTEXT = 4;
- public const int WINEVENT_SKIPOWNPROCESS = 2;
- public const int EVENT_SYSTEM_FOREGROUND = 3;
- public const int WH_SHELL = 10;
- public const int GW_OWNER = 4;
- public const long OBJID_WINDOW = 0x00000000L;
-
- public const uint PROCESS_QUERY_INFORMATION = 0x0400;
-
- public const uint EWX_LOGOFF = 0x00000000;
-
- public delegate bool EnumThreadProc(IntPtr hwnd, IntPtr lParam);
-
- [DllImport("dwmapi.dll")]
- public static extern int DwmGetWindowAttribute(IntPtr hwnd, int dwAttribute, out int pvAttribute, int cbAttribute);
-
- [DllImport("user32.dll", ExactSpelling = true)]
- public static extern IntPtr GetAncestor(IntPtr hwnd, GetAncestorFlags flags);
- public enum GetAncestorFlags
- {
- GetParent = 1,
- GetRoot = 2,
- GetRootOwner = 3
- }
-
- [DllImport("user32.dll", SetLastError = true)]
- public static extern IntPtr GetWindow(IntPtr hWnd, GetWindowType uCmd);
- public enum GetWindowType : uint
- {
- GW_HWNDFIRST = 0,
- GW_HWNDLAST = 1,
- GW_HWNDNEXT = 2,
- GW_HWNDPREV = 3,
- GW_OWNER = 4,
- GW_CHILD = 5,
- GW_ENABLEDPOPUP = 6
- }
-
- [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
- public static extern int MessageBox(IntPtr hWnd, string text, string caption, uint type);
-
- [DllImport("PowrProf.dll")]
- public static extern bool SetSuspendState(bool hibernate, bool forceCritical, bool disableWakeEvent);
-
- [DllImport("user32.dll")]
- public static extern bool ExitWindowsEx(uint uFlags, uint dwReason);
-
- [DllImport("user32.dll")]
- public static extern IntPtr GetForegroundWindow();
-
- [DllImport("user32.dll")]
- public static extern bool EnumWindows(EnumWindowsCallback lpEnumFunc, IntPtr lParam);
- public delegate bool EnumWindowsCallback(IntPtr hwnd, IntPtr lParam);
-
- [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
- public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
-
- [DllImport("user32.dll")]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool IsWindowVisible(IntPtr hWnd);
-
- [DllImport("user32.dll", SetLastError = true)]
- public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
-
- [DllImport("user32.dll")]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool IsWindow(IntPtr hWnd);
-
- [DllImport("user32.dll", SetLastError = true)]
- public static extern int GetWindowLong(IntPtr hWnd, int nIndex);
-
- [DllImport("user32.dll")]
- public static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
-
- [DllImport("user32.dll", EntryPoint = "GetWindowLongPtr")]
- public static extern IntPtr GetWindowLongPtr(IntPtr hWnd, int nIndex);
-
- public delegate void WinEventDelegate(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime);
- [DllImport("user32.dll")]
- public static extern IntPtr SetWinEventHook(uint eventMin, uint eventMax, IntPtr hmodWinEventProc, WinEventDelegate lpfnWinEventProc, uint idProcess, uint idThread, uint dwFlags);
-
- [DllImport("user32.dll")]
- public static extern bool UnhookWinEvent(IntPtr hWinEventHook);
-
- [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
- public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
-
- [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
- public static extern int GetWindowTextLength(IntPtr hWnd);
-
- [DllImport("user32.dll", SetLastError = true)]
- public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, string windowTitle);
-
- [DllImport("user32.dll")]
- public static extern int ShowWindow(IntPtr hwnd, int nCmdShow);
-
- [DllImport("Kernel32.dll", SetLastError = true)]
- public static extern IntPtr OpenEvent(uint dwDesiredAccess, bool bInheritHandle, string lpName);
-
- [DllImport("kernel32.dll")]
- public static extern bool SetEvent(IntPtr hEvent);
-
- [DllImport("kernel32", SetLastError = true)]
- public static extern bool CloseHandle(IntPtr hObject);
-
- [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool SystemParametersInfoA(uint uiAction, uint uiParam, ref NativeRect pvParam, uint fWinIni);
-
- public delegate bool MonitorEnumProc(IntPtr hMonitor, IntPtr hdcMonitor, ref NativeRect lprcMonitor, IntPtr dwData);
-
- [DllImport("User32.dll")]
- public static extern bool EnumDisplayMonitors(IntPtr hdc, IntPtr lprcClip, MonitorEnumProc lpfnEnum, IntPtr dwData);
-
- [DllImport("User32.dll")]
- public static extern int GetSystemMetrics(int nIndex);
-
- [DllImport("user32.dll", EntryPoint = "SetWindowLong")] // 32-bit Eq. of SetWindowLongPtr
- public static extern IntPtr SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
-
- [DllImport("user32.dll", EntryPoint = "SetWindowLongPtr")]
- public static extern IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
-
- [DllImport("user32.dll", CharSet = CharSet.Auto)]
- public static extern IntPtr CallWindowProc(IntPtr lpPrevWndFunc, IntPtr hwnd, uint msg, IntPtr wParam, IntPtr lParam);
-
- [DllImport("user32.dll")]
- public static extern IntPtr SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam);
-
- [DllImport("user32.dll")]
- public static extern uint SendMessageTimeout(IntPtr hWnd, uint messageId, uint wparam, uint lparam, uint timeoutFlags, uint timeout, ref IntPtr retval);
-
- [DllImport("Shell32.dll", CharSet = CharSet.Auto, SetLastError = true)]
- public static extern IntPtr ShellExecute(IntPtr hwnd, string lpOperation, string lpFile, string lpParameters, string lpDirectory, int nShowCmd);
-
- [DllImport("user32.dll", SetLastError = true)]
- public static extern bool RegisterShellHookWindow(IntPtr hWnd);
-
- [DllImport("user32.dll")]
- public static extern bool DeregisterShellHookWindow(IntPtr hWnd);
-
- [DllImport("user32.dll", SetLastError = true)]
- public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint processId);
-
- [DllImport("kernel32.dll", SetLastError = true)]
- public static extern IntPtr OpenProcess(uint processAccess, bool bInheritHandle, uint processId);
-
- public const uint ProcessQueryLimitedInformation = 0x1000;
-
- // DWM API attrib
- public enum DWMWINDOWATTRIBUTE
- {
- DWMWA_WINDOW_CORNER_PREFERENCE = 33
- }
- // Copied from dwmapi.h
- public enum DWM_WINDOW_CORNER_PREFERENCE
- {
- DWMWCP_DEFAULT = 0,
- DWMWCP_DONOTROUND = 1,
- DWMWCP_ROUND = 2,
- DWMWCP_ROUNDSMALL = 3
- }
- // DwmSetWindowAttribute
- [DllImport("dwmapi.dll", CharSet = CharSet.Unicode, PreserveSig = false)]
- public static extern void DwmSetWindowAttribute(IntPtr hwnd, DWMWINDOWATTRIBUTE attribute, ref DWM_WINDOW_CORNER_PREFERENCE pvAttribute, uint cbAttribute);
-
- // Proc info API for unpackaged
- [DllImport("kernel32.dll")]
- public static extern void GetNativeSystemInfo(out SYSTEM_INFO lpSystemInfo);
-
- [DllImport("shell32.dll", SetLastError = true, EntryPoint = "#188")]
- public static extern bool ShellDDEInit(bool init);
-
- [DllImport("shell32.dll", SetLastError = true, EntryPoint = "#181")]
- public static extern bool RegisterShellHook(IntPtr hwnd, int fInstall);
-
- [StructLayout(LayoutKind.Sequential)]
- public struct SYSTEM_INFO
- {
- public ushort wProcessorArchitecture;
- public ushort wReserved;
- public uint dwPageSize;
- public IntPtr lpMinimumApplicationAddress;
- public IntPtr lpMaximumApplicationAddress;
- public IntPtr dwActiveProcessorMask;
- public uint dwNumberOfProcessors;
- public uint dwProcessorType;
- public uint dwAllocationGranularity;
- public ushort wProcessorLevel;
- public ushort wProcessorRevision;
- }
-
- // APPBAR code
- [StructLayout(LayoutKind.Sequential)]
- public struct APPBARDATA
- {
- public int cbSize;
- public IntPtr hWnd;
- public int uCallbackMessage;
- public int uEdge;
- public RECT rc;
- public IntPtr lParam;
- }
-
- public enum ABMsg : int
- {
- ABM_NEW = 0,
- ABM_REMOVE,
- ABM_QUERYPOS,
- ABM_SETPOS,
- ABM_GETSTATE,
- ABM_GETTASKBARPOS,
- ABM_ACTIVATE,
- ABM_GETAUTOHIDEBAR,
- ABM_SETAUTOHIDEBAR,
- ABM_WINDOWPOSCHANGED,
- ABM_SETSTATE
- }
-
- public enum ABNotify : int
- {
- ABN_STATECHANGE = 0,
- ABN_POSCHANGED,
- ABN_FULLSCREENAPP,
- ABN_WINDOWARRANGE
- }
-
- public enum ABEdge : int
- {
- ABE_LEFT = 0,
- ABE_TOP,
- ABE_RIGHT,
- ABE_BOTTOM
- }
-
- public enum ABState
- {
- ABS_TOP = 0x00,
- ABS_AUTOHIDE = 0x01
- }
-
- public delegate IntPtr WndProcDelegate(IntPtr hwnd, uint message, IntPtr wParam, IntPtr lParam);
-
- [DllImport("SHELL32", CallingConvention = CallingConvention.StdCall)]
- public static extern uint SHAppBarMessage(int dwMessage, ref APPBARDATA pData);
-
- [DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
- public static extern bool MoveWindow(IntPtr hWnd, int x, int y, int cx, int cy, bool repaint);
-
- [DllImport("user32.dll", CharSet = CharSet.Auto)]
- public static extern int RegisterWindowMessage(string msg);
-
- [DllImport("user32.dll", SetLastError = true)]
- public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
-
- public enum SWPFlags
- {
- SWP_NOSIZE = 0x0001,
- SWP_NOMOVE = 0x0002,
- SWP_NOZORDER = 0x0004,
- SWP_NOREDRAW = 0x0008,
- SWP_NOACTIVATE = 0x0010,
- SWP_DRAWFRAME = 0x0020,
- SWP_FRAMECHANGED = 0x0020,
- SWP_SHOWWINDOW = 0x0040,
- SWP_HIDEWINDOW = 0x0080,
- SWP_NOCOPYBITS = 0x0100,
- SWP_NOOWNERZORDER = 0x0200,
- SWP_NOREPOSITION = 0x0200,
- SWP_NOSENDCHANGING = 0x0400,
- SWP_DEFERERASE = 0x2000,
- SWP_ASYNCWINDOWPOS = 0x4000
- }
-
- public enum WindowZOrder
- {
- HWND_TOP = 0,
- HWND_BOTTOM = 1,
- HWND_TOPMOST = -1,
- HWND_NOTOPMOST = -2,
- }
-
- [DllImport("UXTheme.dll", SetLastError = true, EntryPoint = "#138")]
- public static extern bool ShouldSystemUseDarkMode();
-
-
- [DllImport("user32.dll", EntryPoint = "GetClassLongPtr")]
- public static extern IntPtr GetClassLongPtr64(IntPtr hWnd, int nIndex);
-
- [StructLayout(LayoutKind.Sequential, Pack = 4)]
- public struct PACKAGE_ID
- {
- public int reserved;
- public AppxPackageArchitecture processorArchitecture;
- public IntPtr version;
- public IntPtr name;
- public IntPtr publisher;
- public IntPtr resourceId;
- public IntPtr publisherId;
- }
- public enum AppxPackageArchitecture
- {
- x86 = 0,
- Arm = 5,
- x64 = 9,
- Neutral = 11,
- Arm64 = 12
- }
-
- [DllImport("psapi.dll")]
- public static extern uint GetProcessImageFileName(
- IntPtr hProcess,
- [Out] StringBuilder lpImageFileName,
- [In][MarshalAs(UnmanagedType.U4)] int nSize);
-
- [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
- public static extern int GetPackagePathByFullName(
- string packageFullName,
- ref uint pathLength,
- IntPtr path);
-
- [DllImport("ext-ms-win-ntuser-window-l1-1-4.dll")]
- public static extern void SwitchToThisWindow(IntPtr hWnd, bool fUnknown);
-
- [DllImport("ole32.dll")]
- public static extern int PropVariantClear(ref PropVariant pvar);
-
- [DllImport("shell32.dll")]
- public static extern int SHGetPropertyStoreForWindow(IntPtr hwnd, ref Guid iid, [Out, MarshalAs(UnmanagedType.Interface)] out IPropertyStore propertyStore);
-
- [DllImport("user32.dll", EntryPoint = "#2573")]
- public static extern bool IsShellFrameWindow(IntPtr hWnd);
-
- [DllImport("user32.dll")]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool GetWindowBand([In] IntPtr hWnd, [Out] out UIntPtr pdwBand);
- public enum ZBID : uint
- {
- ZBID_DEFAULT = 0,
- ZBID_DESKTOP = 1,
- ZBID_UIACCESS = 2,
- ZBID_IMMERSIVE_IHM = 3,
- ZBID_IMMERSIVE_NOTIFICATION = 4,
- ZBID_IMMERSIVE_APPCHROME = 5,
- ZBID_IMMERSIVE_MOGO = 6,
- ZBID_IMMERSIVE_EDGY = 7,
- ZBID_IMMERSIVE_INACTIVEMOBODY = 8,
- ZBID_IMMERSIVE_INACTIVEDOCK = 9,
- ZBID_IMMERSIVE_ACTIVEMOBODY = 10,
- ZBID_IMMERSIVE_ACTIVEDOCK = 11,
- ZBID_IMMERSIVE_BACKGROUND = 12,
- ZBID_IMMERSIVE_SEARCH = 13,
- ZBID_GENUINE_WINDOWS = 14,
- ZBID_IMMERSIVE_RESTRICTED = 15,
- ZBID_SYSTEM_TOOLS = 16,
- ZBID_LOCK = 17,
- ZBID_ABOVELOCK_UX = 18,
- };
-
- [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
- public static extern int GetPackagesByPackageFamily(
- string packageFamilyName,
- ref uint count,
- [Out, Optional] IntPtr packageFullNames,
- ref uint bufferLength,
- [Out, Optional] IntPtr buffer);
-
- [DllImport("user32.dll")]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool SetForegroundWindow(IntPtr hWnd);
-
- [DllImport("user32.dll")]
- public static extern IntPtr GetLastActivePopup(IntPtr hWnd);
-
- [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
- public static extern bool QueryFullProcessImageName(IntPtr hProcess, uint dwFlags, [Out, MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpExeName, ref uint lpdwSize);
- }
+#region Copyright (BSD 3-Clause License)
+/*
+ * GyroShell - A modern, extensible, fast, and customizable shell platform.
+ * Copyright 2022-2024 Pdawg
+ *
+ * Licensed under the BSD 3-Clause License.
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#endregion
+
+using System;
+using System.Runtime.InteropServices;
+using System.Text;
+using static GyroShell.Library.Interfaces.IPropertyStoreAUMID;
+
+namespace GyroShell.Library.Helpers.Win32
+{
+ public static class Win32Interop
+ {
+ [StructLayout(LayoutKind.Sequential)]
+ public struct NativeRect
+ {
+ public int Left;
+ public int Top;
+ public int Right;
+ public int Bottom;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct RECT
+ {
+ public int left;
+ public int top;
+ public int right;
+ public int bottom;
+ }
+
+ public const int WM_COMMAND = 0x0111;
+ public const int WM_SYSCOMMAND = 0x0112;
+
+ public const int SC_MINIMIZE = 0xF020;
+ public const int SC_MOVE = 0xF010;
+ public const int SC_RESTORE = 0xF120;
+ public const int SC_SIZE = 0xF000;
+ public const int SC_CLOSE = 0xF060;
+
+ public const int SW_RESTORE = 9;
+ public const int SW_MINIMIZE = 6;
+ public const int SW_SHOW = 5;
+ public const int SW_HIDE = 0;
+ public const int SW_MAXIMIZE = 3;
+
+ public const int SPI_SETWORKAREA = 0x002F;
+ public const int SPI_GETWORKAREA = 0x0030;
+
+ public const int SPIF_UPDATEINIFILE = 1;
+
+ public const int GWL_EXSTYLE = -20;
+ public const int GWL_STYLE = -16;
+
+ public const int DWMWA_CLOAKED = 14;
+
+ public const int GCL_HICONSM = -34;
+ public const int GCL_HICON = -14;
+
+ public const int ICON_SMALL = 0;
+ public const int ICON_BIG = 1;
+ public const int ICON_SMALL2 = 2;
+ public const int WM_GETICON = 0x7F;
+
+ public const uint GA_PARENT = 1;
+ public const uint GA_ROOT = 2;
+ public const uint GA_ROOTOWNER = 3;
+
+ public const int WS_EX_APPWINDOW = 0x00040000;
+ public const int WS_EX_TOOLWINDOW = 0x00000080;
+ public const int WS_EX_NOACTIVATE = 0x08000000;
+ public const int WS_EX_WINDOWEDGE = 0x100;
+ public const int WS_EX_TOPMOST = 0x00000008;
+ public const int WS_VISIBLE = 0x10000000;
+ public const int WS_CHILD = 0x40000000;
+
+ public const int HSHELL_WINDOWCREATED = 1;
+ public const int HSHELL_WINDOWDESTROYED = 2;
+ public const int HSHELL_ACTIVATESHELLWINDOW = 3;
+ public const int HSHELL_WINDOWACTIVATED = 4;
+ public const int HSHELL_RUDEAPPACTIVATED = 32772;
+ public const int HSHELL_GETMINRECT = 5;
+ public const int HSHELL_REDRAW = 6;
+ public const int HSHELL_TASKMAN = 7;
+ public const int HSHELL_LANGUAGE = 8;
+ public const int HSHELL_SYSMENU = 9;
+ public const int HSHELL_ENDTASK = 10;
+ public const int HSHELL_ACCESSIBILITYSTATE = 11;
+ public const int HSHELL_APPCOMMAND = 12;
+ public const int HSHELL_WINDOWREPLACED = 13;
+ public const int HSHELL_WINDOWREPLACING = 14;
+ public const int HSHELL_MONITORCHANGED = 16; //A window is moved to a different monitor.
+ public const int HSHELL_HIGHBIT = 0x8000;
+ public const int HSHELL_FLASH = 0x8006;
+
+ public const int FAPPCOMMAND_MASK = 0xF000;
+
+ public const int GWLP_WNDPROC = -4;
+ public const int SM_CXSCREEN = 0;
+ public const int SM_CYSCREEN = 1;
+
+ public const int WINEVENT_OUTOFCONTEXT = 0x0000;
+ public const int WINEVENT_SKIPOWNTHREAD = 0x0001;
+ public const int EVENT_SYSTEM_DESKTOPSWITCH = 0x0020;
+ public const int EVENT_OBJECT_CLOAKED = 0x8017;
+ public const int EVENT_OBJECT_UNCLOAKED = 0x8018;
+ public const int EVENT_OBJECT_NAMECHANGED = 0x800C;
+ public const int EVENT_OBJECT_DESTROY = 0x8001;
+ public const int EVENT_OBJECT_CREATE = 0x8000;
+ public const int WINEVENT_INCONTEXT = 4;
+ public const int WINEVENT_SKIPOWNPROCESS = 2;
+ public const int EVENT_SYSTEM_FOREGROUND = 3;
+ public const int WH_SHELL = 10;
+ public const int GW_OWNER = 4;
+ public const long OBJID_WINDOW = 0x00000000L;
+
+ public const uint PROCESS_QUERY_INFORMATION = 0x0400;
+
+ public const uint EWX_LOGOFF = 0x00000000;
+
+ public delegate bool EnumThreadProc(IntPtr hwnd, IntPtr lParam);
+
+ [DllImport("dwmapi.dll")]
+ public static extern int DwmGetWindowAttribute(IntPtr hwnd, int dwAttribute, out int pvAttribute, int cbAttribute);
+
+ [DllImport("user32.dll", ExactSpelling = true)]
+ public static extern IntPtr GetAncestor(IntPtr hwnd, GetAncestorFlags flags);
+ public enum GetAncestorFlags
+ {
+ GetParent = 1,
+ GetRoot = 2,
+ GetRootOwner = 3
+ }
+
+ [DllImport("user32.dll", SetLastError = true)]
+ public static extern IntPtr GetWindow(IntPtr hWnd, GetWindowType uCmd);
+ public enum GetWindowType : uint
+ {
+ GW_HWNDFIRST = 0,
+ GW_HWNDLAST = 1,
+ GW_HWNDNEXT = 2,
+ GW_HWNDPREV = 3,
+ GW_OWNER = 4,
+ GW_CHILD = 5,
+ GW_ENABLEDPOPUP = 6
+ }
+
+ [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
+ public static extern int MessageBoxW(IntPtr hWnd, string text, string caption, uint type);
+
+ [DllImport("PowrProf.dll")]
+ public static extern bool SetSuspendState(bool hibernate, bool forceCritical, bool disableWakeEvent);
+
+ [DllImport("user32.dll")]
+ public static extern bool ExitWindowsEx(uint uFlags, uint dwReason);
+
+ [DllImport("user32.dll")]
+ public static extern IntPtr GetForegroundWindow();
+
+ [DllImport("user32.dll")]
+ public static extern bool EnumWindows(EnumWindowsCallback lpEnumFunc, IntPtr lParam);
+ public delegate bool EnumWindowsCallback(IntPtr hwnd, IntPtr lParam);
+
+ [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
+ public static extern int GetClassNameW(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
+
+ [DllImport("user32.dll")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool IsWindowVisible(IntPtr hWnd);
+
+ [DllImport("user32.dll", SetLastError = true)]
+ public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
+
+ [DllImport("user32.dll")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool IsWindow(IntPtr hWnd);
+
+ [DllImport("user32.dll", SetLastError = true)]
+ public static extern int GetWindowLong(IntPtr hWnd, int nIndex);
+
+ [DllImport("user32.dll")]
+ public static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
+
+ [DllImport("user32.dll", EntryPoint = "GetWindowLongPtr")]
+ public static extern IntPtr GetWindowLongPtr(IntPtr hWnd, int nIndex);
+
+ public delegate void WinEventDelegate(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime);
+ [DllImport("user32.dll")]
+ public static extern IntPtr SetWinEventHook(uint eventMin, uint eventMax, IntPtr hmodWinEventProc, WinEventDelegate lpfnWinEventProc, uint idProcess, uint idThread, uint dwFlags);
+
+ [DllImport("user32.dll")]
+ public static extern bool UnhookWinEvent(IntPtr hWinEventHook);
+
+ [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+ public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
+
+ [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
+ public static extern int GetWindowTextLength(IntPtr hWnd);
+
+ [DllImport("user32.dll", SetLastError = true)]
+ public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, string windowTitle);
+
+ [DllImport("user32.dll")]
+ public static extern int ShowWindow(IntPtr hwnd, int nCmdShow);
+
+ [DllImport("Kernel32.dll", SetLastError = true)]
+ public static extern IntPtr OpenEvent(uint dwDesiredAccess, bool bInheritHandle, string lpName);
+
+ [DllImport("kernel32.dll")]
+ public static extern bool SetEvent(IntPtr hEvent);
+
+ [DllImport("kernel32", SetLastError = true)]
+ public static extern bool CloseHandle(IntPtr hObject);
+
+ [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool SystemParametersInfoA(uint uiAction, uint uiParam, ref NativeRect pvParam, uint fWinIni);
+
+ public delegate bool MonitorEnumProc(IntPtr hMonitor, IntPtr hdcMonitor, ref NativeRect lprcMonitor, IntPtr dwData);
+
+ [DllImport("User32.dll")]
+ public static extern bool EnumDisplayMonitors(IntPtr hdc, IntPtr lprcClip, MonitorEnumProc lpfnEnum, IntPtr dwData);
+
+ [DllImport("User32.dll")]
+ public static extern int GetSystemMetrics(int nIndex);
+
+ [DllImport("user32.dll", EntryPoint = "SetWindowLong")] // 32-bit Eq. of SetWindowLongPtr
+ public static extern IntPtr SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
+
+ [DllImport("user32.dll", EntryPoint = "SetWindowLongPtr")]
+ public static extern IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
+
+ [DllImport("user32.dll", CharSet = CharSet.Auto)]
+ public static extern IntPtr CallWindowProc(IntPtr lpPrevWndFunc, IntPtr hwnd, uint msg, IntPtr wParam, IntPtr lParam);
+
+ [DllImport("user32.dll")]
+ public static extern IntPtr SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam);
+
+ [DllImport("user32.dll")]
+ public static extern uint SendMessageTimeout(IntPtr hWnd, uint messageId, uint wparam, uint lparam, uint timeoutFlags, uint timeout, ref IntPtr retval);
+
+ [DllImport("Shell32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+ public static extern IntPtr ShellExecute(IntPtr hwnd, string lpOperation, string lpFile, string lpParameters, string lpDirectory, int nShowCmd);
+
+ [DllImport("user32.dll", SetLastError = true)]
+ public static extern bool RegisterShellHookWindow(IntPtr hWnd);
+
+ [DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
+ public static extern uint RegisterWindowMessageW(string lpString);
+
+ [DllImport("user32.dll")]
+ public static extern bool DeregisterShellHookWindow(IntPtr hWnd);
+
+ [DllImport("user32.dll", SetLastError = true)]
+ public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint processId);
+
+ [DllImport("kernel32.dll", SetLastError = true)]
+ public static extern IntPtr OpenProcess(uint processAccess, bool bInheritHandle, uint processId);
+
+ public const uint ProcessQueryLimitedInformation = 0x1000;
+
+ // DWM API attrib
+ public enum DWMWINDOWATTRIBUTE
+ {
+ DWMWA_WINDOW_CORNER_PREFERENCE = 33
+ }
+ // Copied from dwmapi.h
+ public enum DWM_WINDOW_CORNER_PREFERENCE
+ {
+ DWMWCP_DEFAULT = 0,
+ DWMWCP_DONOTROUND = 1,
+ DWMWCP_ROUND = 2,
+ DWMWCP_ROUNDSMALL = 3
+ }
+ // DwmSetWindowAttribute
+ [DllImport("dwmapi.dll", CharSet = CharSet.Unicode, PreserveSig = false)]
+ public static extern void DwmSetWindowAttribute(IntPtr hwnd, DWMWINDOWATTRIBUTE attribute, ref DWM_WINDOW_CORNER_PREFERENCE pvAttribute, uint cbAttribute);
+
+ // Proc info API for unpackaged
+ [DllImport("kernel32.dll")]
+ public static extern void GetNativeSystemInfo(out SYSTEM_INFO lpSystemInfo);
+
+ [DllImport("shell32.dll", SetLastError = true, EntryPoint = "#188")]
+ public static extern bool ShellDDEInit(bool init);
+
+ [DllImport("shell32.dll", SetLastError = true, EntryPoint = "#181")]
+ public static extern bool RegisterShellHook(IntPtr hwnd, int fInstall);
+ [DllImport("user32.dll", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.U2)]
+ public static extern ushort RegisterClassExW([In] ref WNDCLASSEX lpwcx);
+ [DllImport("user32.dll", SetLastError = true, CharSet =CharSet.Unicode)]
+ public static extern IntPtr CreateWindowExW(
+ uint dwExStyle,
+ string lpClassName,
+ string lpWindowName,
+ uint dwStyle,
+ int x,
+ int y,
+ int nWidth,
+ int nHeight,
+ IntPtr hWndParent,
+ IntPtr hMenu,
+ IntPtr hInstance,
+ IntPtr lpParam);
+ [DllImport("user32.dll")]
+ public static extern IntPtr DefWindowProcW(nint hWnd, uint uMsg, nint wParam, nint lParam);
+ [DllImport("user32.dll", SetLastError = true)]
+ public static extern bool SetTaskmanWindow(nint hWnd);
+ [DllImport("user32.dll")]
+ public static extern nint GetTaskmanWindow();
+
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
+ public struct WNDCLASSEX
+ {
+ [MarshalAs(UnmanagedType.U4)]
+ public int cbSize;
+ [MarshalAs(UnmanagedType.U4)]
+ public int style;
+ public IntPtr lpfnWndProc; // not WndProc
+ public int cbClsExtra;
+ public int cbWndExtra;
+ public IntPtr hInstance;
+ public IntPtr hIcon;
+ public IntPtr hCursor;
+ public IntPtr hbrBackground;
+ public string lpszMenuName;
+ public string lpszClassName;
+ public IntPtr hIconSm;
+
+ //Use this function to make a new one with cbSize already filled in.
+ //For example:
+ //var WndClss = WNDCLASSEX.Build()
+ public static WNDCLASSEX Build()
+ {
+ var nw = new WNDCLASSEX();
+ nw.cbSize = Marshal.SizeOf(typeof(WNDCLASSEX));
+ return nw;
+ }
+ }
+
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct SYSTEM_INFO
+ {
+ public ushort wProcessorArchitecture;
+ public ushort wReserved;
+ public uint dwPageSize;
+ public IntPtr lpMinimumApplicationAddress;
+ public IntPtr lpMaximumApplicationAddress;
+ public IntPtr dwActiveProcessorMask;
+ public uint dwNumberOfProcessors;
+ public uint dwProcessorType;
+ public uint dwAllocationGranularity;
+ public ushort wProcessorLevel;
+ public ushort wProcessorRevision;
+ }
+
+ // APPBAR code
+ [StructLayout(LayoutKind.Sequential)]
+ public struct APPBARDATA
+ {
+ public int cbSize;
+ public IntPtr hWnd;
+ public int uCallbackMessage;
+ public int uEdge;
+ public RECT rc;
+ public IntPtr lParam;
+ }
+
+ public enum ABMsg : int
+ {
+ ABM_NEW = 0,
+ ABM_REMOVE,
+ ABM_QUERYPOS,
+ ABM_SETPOS,
+ ABM_GETSTATE,
+ ABM_GETTASKBARPOS,
+ ABM_ACTIVATE,
+ ABM_GETAUTOHIDEBAR,
+ ABM_SETAUTOHIDEBAR,
+ ABM_WINDOWPOSCHANGED,
+ ABM_SETSTATE
+ }
+
+ public enum ABNotify : int
+ {
+ ABN_STATECHANGE = 0,
+ ABN_POSCHANGED,
+ ABN_FULLSCREENAPP,
+ ABN_WINDOWARRANGE
+ }
+
+ public enum ABEdge : int
+ {
+ ABE_LEFT = 0,
+ ABE_TOP,
+ ABE_RIGHT,
+ ABE_BOTTOM
+ }
+
+ public enum ABState
+ {
+ ABS_TOP = 0x00,
+ ABS_AUTOHIDE = 0x01
+ }
+
+ public delegate IntPtr WndProcDelegate(IntPtr hwnd, uint message, IntPtr wParam, IntPtr lParam);
+
+ [DllImport("SHELL32", CallingConvention = CallingConvention.StdCall)]
+ public static extern uint SHAppBarMessage(int dwMessage, ref APPBARDATA pData);
+
+ [DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
+ public static extern bool MoveWindow(IntPtr hWnd, int x, int y, int cx, int cy, bool repaint);
+
+ [DllImport("user32.dll", CharSet = CharSet.Auto)]
+ public static extern int RegisterWindowMessage(string msg);
+
+ [DllImport("user32.dll", SetLastError = true)]
+ public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
+
+ public enum SWPFlags
+ {
+ SWP_NOSIZE = 0x0001,
+ SWP_NOMOVE = 0x0002,
+ SWP_NOZORDER = 0x0004,
+ SWP_NOREDRAW = 0x0008,
+ SWP_NOACTIVATE = 0x0010,
+ SWP_DRAWFRAME = 0x0020,
+ SWP_FRAMECHANGED = 0x0020,
+ SWP_SHOWWINDOW = 0x0040,
+ SWP_HIDEWINDOW = 0x0080,
+ SWP_NOCOPYBITS = 0x0100,
+ SWP_NOOWNERZORDER = 0x0200,
+ SWP_NOREPOSITION = 0x0200,
+ SWP_NOSENDCHANGING = 0x0400,
+ SWP_DEFERERASE = 0x2000,
+ SWP_ASYNCWINDOWPOS = 0x4000
+ }
+
+ public enum WindowZOrder
+ {
+ HWND_TOP = 0,
+ HWND_BOTTOM = 1,
+ HWND_TOPMOST = -1,
+ HWND_NOTOPMOST = -2,
+ }
+
+ [DllImport("UXTheme.dll", SetLastError = true, EntryPoint = "#138")]
+ public static extern bool ShouldSystemUseDarkMode();
+
+ [ComImport]
+ [Guid("914d9b3a-5e53-4e14-bbba-46062acb35a4")]
+ [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ public interface IImmersiveShellHookService
+ {
+ int Register(); //TODO args
+ int Unregister(uint cookie);
+ int PostShellHookMessage(nint wparam, nint lparam);
+ int SetTargetWindowForSerialization(nint hwnd);
+ int PostShellHookMessageWithSerialization();//todo: args
+ int UpdateWindowApplicationId(nint hwnd, string pszAppid);
+ int HandleWindowReplacement(nint hwndOld, nint hwndNew);
+ bool IsExecutionOnSerializedThread();
+ }
+ [ComImport]
+ [Guid("6d5140c1-7436-11ce-8034-00aa006009fa")]
+ [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ public interface IServiceProvider
+ {
+ int QueryService(ref Guid guidService, ref Guid riid,
+ [MarshalAs(UnmanagedType.Interface)] out object ppvObject);
+ }
+ [ComImport]
+ [Guid("c2f03a33-21f5-47fa-b4bb-156362a2f239")]
+ [ClassInterface(ClassInterfaceType.None)]
+ public class CImmersiveShell
+ {
+
+ }
+
+
+ [DllImport("user32.dll", EntryPoint = "GetClassLongPtr")]
+ public static extern IntPtr GetClassLongPtr64(IntPtr hWnd, int nIndex);
+
+ [StructLayout(LayoutKind.Sequential, Pack = 4)]
+ public struct PACKAGE_ID
+ {
+ public int reserved;
+ public AppxPackageArchitecture processorArchitecture;
+ public IntPtr version;
+ public IntPtr name;
+ public IntPtr publisher;
+ public IntPtr resourceId;
+ public IntPtr publisherId;
+ }
+ public enum AppxPackageArchitecture
+ {
+ x86 = 0,
+ Arm = 5,
+ x64 = 9,
+ Neutral = 11,
+ Arm64 = 12
+ }
+
+ [DllImport("psapi.dll")]
+ public static extern uint GetProcessImageFileName(
+ IntPtr hProcess,
+ [Out] StringBuilder lpImageFileName,
+ [In][MarshalAs(UnmanagedType.U4)] int nSize);
+
+ [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
+ public static extern int GetPackagePathByFullName(
+ string packageFullName,
+ ref uint pathLength,
+ IntPtr path);
+
+ [DllImport("ext-ms-win-ntuser-window-l1-1-4.dll")]
+ public static extern void SwitchToThisWindow(IntPtr hWnd, bool fUnknown);
+
+ [DllImport("ole32.dll")]
+ public static extern int PropVariantClear(ref PropVariant pvar);
+
+ [DllImport("shell32.dll")]
+ public static extern int SHGetPropertyStoreForWindow(IntPtr hwnd, ref Guid iid, [Out, MarshalAs(UnmanagedType.Interface)] out IPropertyStore propertyStore);
+
+ [DllImport("user32.dll", EntryPoint = "#2573")]
+ public static extern bool IsShellFrameWindow(IntPtr hWnd);
+
+ [DllImport("user32.dll")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool GetWindowBand([In] IntPtr hWnd, [Out] out UIntPtr pdwBand);
+ public enum ZBID : uint
+ {
+ ZBID_DEFAULT = 0,
+ ZBID_DESKTOP = 1,
+ ZBID_UIACCESS = 2,
+ ZBID_IMMERSIVE_IHM = 3,
+ ZBID_IMMERSIVE_NOTIFICATION = 4,
+ ZBID_IMMERSIVE_APPCHROME = 5,
+ ZBID_IMMERSIVE_MOGO = 6,
+ ZBID_IMMERSIVE_EDGY = 7,
+ ZBID_IMMERSIVE_INACTIVEMOBODY = 8,
+ ZBID_IMMERSIVE_INACTIVEDOCK = 9,
+ ZBID_IMMERSIVE_ACTIVEMOBODY = 10,
+ ZBID_IMMERSIVE_ACTIVEDOCK = 11,
+ ZBID_IMMERSIVE_BACKGROUND = 12,
+ ZBID_IMMERSIVE_SEARCH = 13,
+ ZBID_GENUINE_WINDOWS = 14,
+ ZBID_IMMERSIVE_RESTRICTED = 15,
+ ZBID_SYSTEM_TOOLS = 16,
+ ZBID_LOCK = 17,
+ ZBID_ABOVELOCK_UX = 18,
+ };
+
+ [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
+ public static extern int GetPackagesByPackageFamily(
+ string packageFamilyName,
+ ref uint count,
+ [Out, Optional] IntPtr packageFullNames,
+ ref uint bufferLength,
+ [Out, Optional] IntPtr buffer);
+
+ [DllImport("user32.dll")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool SetForegroundWindow(IntPtr hWnd);
+
+ [DllImport("user32.dll")]
+ public static extern IntPtr GetLastActivePopup(IntPtr hWnd);
+
+ [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
+ public static extern bool QueryFullProcessImageName(IntPtr hProcess, uint dwFlags, [Out, MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpExeName, ref uint lpdwSize);
+ }
}
\ No newline at end of file
diff --git a/GyroShell.Library/Helpers/Win32/WindowChecks.cs b/GyroShell.Library/Helpers/Win32/WindowChecks.cs
index eb45b73..07523e7 100644
--- a/GyroShell.Library/Helpers/Win32/WindowChecks.cs
+++ b/GyroShell.Library/Helpers/Win32/WindowChecks.cs
@@ -62,7 +62,7 @@ private static bool IsCloaked(IntPtr hWnd)
private static bool ClassNameCheck(IntPtr hWnd)
{
- GetClassName(hWnd, className, className.Capacity);
+ GetClassNameW(hWnd, className, className.Capacity);
if (className.ToString() == "ApplicationFrameWindow" || className.ToString() == "Windows.UI.Core.CoreWindow")
{
diff --git a/GyroShell.sln b/GyroShell.sln
index ed6d5f8..7e540d8 100644
--- a/GyroShell.sln
+++ b/GyroShell.sln
@@ -4,6 +4,9 @@ Microsoft Visual Studio Solution File, Format Version 12.00
VisualStudioVersion = 17.3.32922.545
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GyroShell", "GyroShell\GyroShell.csproj", "{9489365D-B182-45AD-A7BF-F6D942949A5A}"
+ ProjectSection(ProjectDependencies) = postProject
+ {617AEA24-0755-490C-BC05-6DBB5E2059E0} = {617AEA24-0755-490C-BC05-6DBB5E2059E0}
+ EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{9C6095DC-1FBF-4CF2-9225-F8E391132412}"
ProjectSection(SolutionItems) = preProject
@@ -12,6 +15,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GyroShell.Library", "GyroShell.Library\GyroShell.Library.csproj", "{1623C0B8-50B8-4904-92F8-BDB6999BCEE1}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GyroShell.ImmersiveShellHook", "GyroShell.ImmersiveShellHook\GyroShell.ImmersiveShellHook.vcxproj", "{617AEA24-0755-490C-BC05-6DBB5E2059E0}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -64,6 +69,22 @@ Global
{1623C0B8-50B8-4904-92F8-BDB6999BCEE1}.Release|x64.Build.0 = Release|Any CPU
{1623C0B8-50B8-4904-92F8-BDB6999BCEE1}.Release|x86.ActiveCfg = Release|Any CPU
{1623C0B8-50B8-4904-92F8-BDB6999BCEE1}.Release|x86.Build.0 = Release|Any CPU
+ {617AEA24-0755-490C-BC05-6DBB5E2059E0}.Debug|Any CPU.ActiveCfg = Debug|x64
+ {617AEA24-0755-490C-BC05-6DBB5E2059E0}.Debug|Any CPU.Build.0 = Debug|x64
+ {617AEA24-0755-490C-BC05-6DBB5E2059E0}.Debug|arm64.ActiveCfg = Debug|x64
+ {617AEA24-0755-490C-BC05-6DBB5E2059E0}.Debug|arm64.Build.0 = Debug|x64
+ {617AEA24-0755-490C-BC05-6DBB5E2059E0}.Debug|x64.ActiveCfg = Debug|x64
+ {617AEA24-0755-490C-BC05-6DBB5E2059E0}.Debug|x64.Build.0 = Debug|x64
+ {617AEA24-0755-490C-BC05-6DBB5E2059E0}.Debug|x86.ActiveCfg = Debug|Win32
+ {617AEA24-0755-490C-BC05-6DBB5E2059E0}.Debug|x86.Build.0 = Debug|Win32
+ {617AEA24-0755-490C-BC05-6DBB5E2059E0}.Release|Any CPU.ActiveCfg = Release|x64
+ {617AEA24-0755-490C-BC05-6DBB5E2059E0}.Release|Any CPU.Build.0 = Release|x64
+ {617AEA24-0755-490C-BC05-6DBB5E2059E0}.Release|arm64.ActiveCfg = Release|x64
+ {617AEA24-0755-490C-BC05-6DBB5E2059E0}.Release|arm64.Build.0 = Release|x64
+ {617AEA24-0755-490C-BC05-6DBB5E2059E0}.Release|x64.ActiveCfg = Release|x64
+ {617AEA24-0755-490C-BC05-6DBB5E2059E0}.Release|x64.Build.0 = Release|x64
+ {617AEA24-0755-490C-BC05-6DBB5E2059E0}.Release|x86.ActiveCfg = Release|Win32
+ {617AEA24-0755-490C-BC05-6DBB5E2059E0}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/GyroShell/Controls/StartupWindow.xaml.cs b/GyroShell/Controls/StartupWindow.xaml.cs
index 5befc5e..bb0a2f2 100644
--- a/GyroShell/Controls/StartupWindow.xaml.cs
+++ b/GyroShell/Controls/StartupWindow.xaml.cs
@@ -59,7 +59,7 @@ internal StartupWindow()
OverlappedPresenter presenter = GetAppWindowAndPresenter();
presenter.IsMaximizable = false;
presenter.IsMinimizable = false;
- presenter.IsAlwaysOnTop = true;
+ presenter.IsAlwaysOnTop = false;
presenter.IsResizable = false;
presenter.SetBorderAndTitleBar(false, false);
m_AppWindow = GetAppWindowForCurrentWindow();
@@ -101,7 +101,7 @@ private void CloseTimer_Elapsed(object sender, ElapsedEventArgs e)
private new void Close()
{
- MessageBox(hWnd, "If you keep seeing this message, please contact the developers.", "GyroShell was unable to start.", 0x00000000 | 0x00000030);
+ MessageBoxW(hWnd, "If you keep seeing this message, please contact the developers.", "GyroShell was unable to start.", 0x00000000 | 0x00000030);
m_explorerManager.ShowTaskbar();
appProcess.Kill();
}
diff --git a/GyroShell/GyroShell.csproj b/GyroShell/GyroShell.csproj
index 7d3d769..acbf83c 100644
--- a/GyroShell/GyroShell.csproj
+++ b/GyroShell/GyroShell.csproj
@@ -14,6 +14,8 @@
-include WindowsUdk
true
False
+ true
+ copy /Y $(SolutionDir)$(Platform)\$(Configuration)\rmclient.dll $(SolutionDir)\GyroShell\Resources\rmclient.dll
@@ -80,6 +82,19 @@
+
+
+ True
+ True
+ Resources.resx
+
+
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+
+
MSBuild:Compile
diff --git a/GyroShell/Properties/Resources.Designer.cs b/GyroShell/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..c27c999
--- /dev/null
+++ b/GyroShell/Properties/Resources.Designer.cs
@@ -0,0 +1,73 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace GyroShell.Properties {
+ using System;
+
+
+ ///
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ ///
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ ///
+ /// Returns the cached ResourceManager instance used by this class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("GyroShell.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ ///
+ /// Looks up a localized resource of type System.Byte[].
+ ///
+ internal static byte[] ImmersiveShellHook {
+ get {
+ object obj = ResourceManager.GetObject("ImmersiveShellHook", resourceCulture);
+ return ((byte[])(obj));
+ }
+ }
+ }
+}
diff --git a/GyroShell/Properties/Resources.resx b/GyroShell/Properties/Resources.resx
new file mode 100644
index 0000000..25352f0
--- /dev/null
+++ b/GyroShell/Properties/Resources.resx
@@ -0,0 +1,124 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 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
+
+
+
+ ..\Resources\rmclient.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/GyroShell/Services/Helpers/IconHelperService.cs b/GyroShell/Services/Helpers/IconHelperService.cs
index b9047aa..a4527dc 100644
--- a/GyroShell/Services/Helpers/IconHelperService.cs
+++ b/GyroShell/Services/Helpers/IconHelperService.cs
@@ -1,163 +1,163 @@
-#region Copyright (BSD 3-Clause License)
-/*
- * GyroShell - A modern, extensible, fast, and customizable shell platform.
- * Copyright 2022-2024 Pdawg
- *
- * Licensed under the BSD 3-Clause License.
- * SPDX-License-Identifier: BSD-3-Clause
- */
-#endregion
-
-using GyroShell.Library.Services.Helpers;
-using Microsoft.UI.Xaml.Media.Imaging;
-using System;
-using System.Diagnostics;
-using System.Drawing;
-using System.Drawing.Imaging;
-using System.Runtime.InteropServices.WindowsRuntime;
-using System.Runtime.InteropServices;
-using Windows.Graphics.Imaging;
-using static GyroShell.Library.Helpers.Win32.Win32Interop;
-using System.Threading.Tasks;
-using WinRT;
-using Microsoft.UI.Xaml.Media;
-using Windows.Storage;
-using Windows.Storage.Streams;
-using System.IO;
-
-namespace GyroShell.Services.Helpers
-{
- public class IconHelperService : IIconHelperService
- {
- private readonly IBitmapHelperService m_bmpHelper;
- private readonly IAppHelperService m_appHelper;
-
- public IconHelperService(IBitmapHelperService bmpHelper, IAppHelperService appHelper)
- {
- m_bmpHelper = bmpHelper;
- m_appHelper = appHelper;
- }
-
- public bool IsUwpWindow(IntPtr hWnd) => IsShellFrameWindow(hWnd);
-
- public async Task GetUwpOrWin32Icon(IntPtr hWnd, int targetSize)
- {
- if (IsUwpWindow(hWnd))
- {
- return m_bmpHelper.RemoveTransparentPadding(await GetUWPBitmap(hWnd));
- }
- else
- {
- return ConvertIconBitmapToSoftwareBitmapSource(GetWin32Bitmap(hWnd, 32));
- }
- }
-
-
- #region Win32
- private Bitmap GetWin32Bitmap(IntPtr hWnd, int targetSize)
- {
- try
- {
- // get the icon from the HWND
- IntPtr hIcon = SendMessage(hWnd, WM_GETICON, (IntPtr)ICON_BIG, IntPtr.Zero);
- if (hIcon == IntPtr.Zero)
- hIcon = SendMessage(hWnd, WM_GETICON, (IntPtr)ICON_SMALL, IntPtr.Zero);
- if (hIcon == IntPtr.Zero)
- hIcon = SendMessage(hWnd, WM_GETICON, (IntPtr)ICON_SMALL2, IntPtr.Zero);
- if (hIcon == IntPtr.Zero)
- hIcon = GetClassLongPtr64(hWnd, -14);
- if (hIcon == IntPtr.Zero)
- hIcon = GetClassLongPtr64(hWnd, -34);
-
- if (hIcon != IntPtr.Zero)
- {
- Icon icon = Icon.FromHandle(hIcon);
- Bitmap resizedBitmap = new Bitmap(icon.ToBitmap(), new Size(targetSize, targetSize));
- Icon resizedIcon = Icon.FromHandle(resizedBitmap.GetHicon());
- return resizedIcon.ToBitmap();
- }
- return null;
- }
- catch (Exception ex)
- {
- Debug.WriteLine("GetHandleIcon => GetIcon: " + ex.Message);
- return null;
- }
- }
- #endregion
-
- #region UWP
- private async Task GetUWPBitmap(IntPtr hWnd)
- {
- try
- {
- string iconPath = m_appHelper.GetUwpAppIconPath(hWnd);
- WriteableBitmap writeableBitmap;
-
- // Open the file as a stream
- StorageFile file = await StorageFile.GetFileFromPathAsync(iconPath);
- using IRandomAccessStream fileStream = await file.OpenAsync(FileAccessMode.Read);
-
- BitmapImage bi = new(new Uri(iconPath));
- BitmapDecoder decoder = await BitmapDecoder.CreateAsync(fileStream);
-
- var transform = new BitmapTransform()
- {
- InterpolationMode = BitmapInterpolationMode.Fant
- };
-
- // Get the pixel data with the applied transform
- var pixelData = await decoder.GetPixelDataAsync(
- decoder.BitmapPixelFormat,
- BitmapAlphaMode.Premultiplied,
- transform,
- ExifOrientationMode.IgnoreExifOrientation,
- ColorManagementMode.DoNotColorManage
- );
-
- writeableBitmap = new WriteableBitmap((int)decoder.PixelWidth, (int)decoder.PixelHeight);
- using (Stream pixelStream = writeableBitmap.PixelBuffer.AsStream())
- {
- byte[] pixels = pixelData.DetachPixelData();
- await pixelStream.WriteAsync(pixels, 0, pixels.Length);
- }
- return writeableBitmap;
- }
- catch (Exception e)
- {
- Debug.WriteLine(e.Message);
- return null;
- }
- }
- #endregion
-
- #region Common
- private SoftwareBitmapSource ConvertIconBitmapToSoftwareBitmapSource(Bitmap bmp)
- {
- if (bmp == null) return null;
- Bitmap resampledBmp = m_bmpHelper.FilterAndScaleBitmap(bmp, bmp.Width, bmp.Height);
-
- BitmapData data = resampledBmp.LockBits(
- new Rectangle(0, 0, resampledBmp.Width, resampledBmp.Height),
- ImageLockMode.ReadOnly,
- resampledBmp.PixelFormat);
-
- byte[] bytes = new byte[data.Stride * data.Height];
- Marshal.Copy(data.Scan0, bytes, 0, bytes.Length);
- resampledBmp.UnlockBits(data);
-
- SoftwareBitmap softwareBitmap = new SoftwareBitmap(
- BitmapPixelFormat.Bgra8,
- resampledBmp.Width,
- resampledBmp.Height,
- BitmapAlphaMode.Premultiplied);
- softwareBitmap.CopyFromBuffer(bytes.AsBuffer());
-
- SoftwareBitmapSource source = new SoftwareBitmapSource();
- source.SetBitmapAsync(softwareBitmap);
-
- return source;
- }
- #endregion
- }
+#region Copyright (BSD 3-Clause License)
+/*
+ * GyroShell - A modern, extensible, fast, and customizable shell platform.
+ * Copyright 2022-2024 Pdawg
+ *
+ * Licensed under the BSD 3-Clause License.
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#endregion
+
+using GyroShell.Library.Services.Helpers;
+using Microsoft.UI.Xaml.Media.Imaging;
+using System;
+using System.Diagnostics;
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.Runtime.InteropServices.WindowsRuntime;
+using System.Runtime.InteropServices;
+using Windows.Graphics.Imaging;
+using static GyroShell.Library.Helpers.Win32.Win32Interop;
+using System.Threading.Tasks;
+using WinRT;
+using Microsoft.UI.Xaml.Media;
+using Windows.Storage;
+using Windows.Storage.Streams;
+using System.IO;
+
+namespace GyroShell.Services.Helpers
+{
+ public class IconHelperService : IIconHelperService
+ {
+ private readonly IBitmapHelperService m_bmpHelper;
+ private readonly IAppHelperService m_appHelper;
+
+ public IconHelperService(IBitmapHelperService bmpHelper, IAppHelperService appHelper)
+ {
+ m_bmpHelper = bmpHelper;
+ m_appHelper = appHelper;
+ }
+
+ public bool IsUwpWindow(IntPtr hWnd) => IsShellFrameWindow(hWnd);
+
+ public async Task GetUwpOrWin32Icon(IntPtr hWnd, int targetSize)
+ {
+ if (IsUwpWindow(hWnd))
+ {
+ return m_bmpHelper.RemoveTransparentPadding(await GetUWPBitmap(hWnd));
+ }
+ else
+ {
+ return ConvertIconBitmapToSoftwareBitmapSource(GetWin32Bitmap(hWnd, 32));
+ }
+ }
+
+
+ #region Win32
+ private Bitmap GetWin32Bitmap(IntPtr hWnd, int targetSize)
+ {
+ try
+ {
+ // get the icon from the HWND
+ IntPtr hIcon = SendMessage(hWnd, WM_GETICON, (IntPtr)ICON_BIG, IntPtr.Zero);
+ if (hIcon == IntPtr.Zero)
+ hIcon = SendMessage(hWnd, WM_GETICON, (IntPtr)ICON_SMALL, IntPtr.Zero);
+ if (hIcon == IntPtr.Zero)
+ hIcon = SendMessage(hWnd, WM_GETICON, (IntPtr)ICON_SMALL2, IntPtr.Zero);
+ if (hIcon == IntPtr.Zero)
+ hIcon = GetClassLongPtr64(hWnd, -14);
+ if (hIcon == IntPtr.Zero)
+ hIcon = GetClassLongPtr64(hWnd, -34);
+
+ if (hIcon != IntPtr.Zero)
+ {
+ Icon icon = Icon.FromHandle(hIcon);
+ Bitmap resizedBitmap = new Bitmap(icon.ToBitmap(), new Size(targetSize, targetSize));
+ Icon resizedIcon = Icon.FromHandle(resizedBitmap.GetHicon());
+ return resizedIcon.ToBitmap();
+ }
+ return null;
+ }
+ catch (Exception ex)
+ {
+ Debug.WriteLine("GetHandleIcon => GetIcon: " + ex.Message);
+ return null;
+ }
+ }
+ #endregion
+
+ #region UWP
+ private async Task GetUWPBitmap(IntPtr hWnd)
+ {
+ try
+ {
+ string iconPath = m_appHelper.GetUwpAppIconPath(hWnd);
+ WriteableBitmap writeableBitmap;
+
+ // Open the file as a stream
+ StorageFile file = await StorageFile.GetFileFromPathAsync(iconPath);
+ using IRandomAccessStream fileStream = await file.OpenAsync(FileAccessMode.Read);
+
+ BitmapImage bi = new(new Uri(iconPath));
+ BitmapDecoder decoder = await BitmapDecoder.CreateAsync(fileStream);
+
+ var transform = new BitmapTransform()
+ {
+ InterpolationMode = BitmapInterpolationMode.Fant
+ };
+
+ // Get the pixel data with the applied transform
+ var pixelData = await decoder.GetPixelDataAsync(
+ decoder.BitmapPixelFormat,
+ BitmapAlphaMode.Premultiplied,
+ transform,
+ ExifOrientationMode.IgnoreExifOrientation,
+ ColorManagementMode.DoNotColorManage
+ );
+
+ writeableBitmap = new WriteableBitmap((int)decoder.PixelWidth, (int)decoder.PixelHeight);
+ using (Stream pixelStream = writeableBitmap.PixelBuffer.AsStream())
+ {
+ byte[] pixels = pixelData.DetachPixelData();
+ await pixelStream.WriteAsync(pixels, 0, pixels.Length);
+ }
+ return writeableBitmap;
+ }
+ catch (Exception e)
+ {
+ Debug.WriteLine(e.Message);
+ return null;
+ }
+ }
+ #endregion
+
+ #region Common
+ private SoftwareBitmapSource ConvertIconBitmapToSoftwareBitmapSource(Bitmap bmp)
+ {
+ if (bmp == null) return null;
+ Bitmap resampledBmp = m_bmpHelper.FilterAndScaleBitmap(bmp, bmp.Width, bmp.Height);
+
+ BitmapData data = resampledBmp.LockBits(
+ new Rectangle(0, 0, resampledBmp.Width, resampledBmp.Height),
+ ImageLockMode.ReadOnly,
+ resampledBmp.PixelFormat);
+
+ byte[] bytes = new byte[data.Stride * data.Height];
+ Marshal.Copy(data.Scan0, bytes, 0, bytes.Length);
+ resampledBmp.UnlockBits(data);
+
+ SoftwareBitmap softwareBitmap = new SoftwareBitmap(
+ BitmapPixelFormat.Bgra8,
+ resampledBmp.Width,
+ resampledBmp.Height,
+ BitmapAlphaMode.Premultiplied);
+ softwareBitmap.CopyFromBuffer(bytes.AsBuffer());
+
+ SoftwareBitmapSource source = new SoftwareBitmapSource();
+ source.SetBitmapAsync(softwareBitmap);
+
+ return source;
+ }
+ #endregion
+ }
}
\ No newline at end of file
diff --git a/GyroShell/Services/Managers/ExplorerManagerService.cs b/GyroShell/Services/Managers/ExplorerManagerService.cs
index 41bd61e..b57df11 100644
--- a/GyroShell/Services/Managers/ExplorerManagerService.cs
+++ b/GyroShell/Services/Managers/ExplorerManagerService.cs
@@ -11,6 +11,9 @@
using GyroShell.Library.Events;
using GyroShell.Library.Services.Managers;
using System;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.IO;
using System.Runtime.InteropServices;
using static GyroShell.Library.Helpers.Win32.Win32Interop;
@@ -22,20 +25,150 @@ internal class ExplorerManagerService : IExplorerManagerService
public IntPtr m_hTaskBar { get; set; }
public IntPtr m_hMultiTaskBar { get; set; }
- public IntPtr m_hStartMenu { get; set; }
+ public IntPtr m_hStartMenu { get; set; }
+
+ private static Guid SID_ImmersiveShellHookService = new Guid("4624bd39-5fc3-44a8-a809-163a836e9031");
+ private static Guid ImmersiveShellHookServiceInterface = new Guid("914d9b3a-5e53-4e14-bbba-46062acb35a4");
+ private static IImmersiveShellHookService? HookService;
public void Initialize()
{
m_hTaskBar = FindWindow("Shell_TrayWnd", null);
m_hMultiTaskBar = FindWindow("Shell_SecondaryTrayWnd", null);
- m_hStartMenu = FindWindowEx(m_hStartMenu, IntPtr.Zero, "Button", "Start");
-
+ m_hStartMenu = FindWindowEx(m_hStartMenu, IntPtr.Zero, "Button", "Start");
+
if (m_hStartMenu == IntPtr.Zero)
{
m_hStartMenu = FindWindow("Button", null);
- }
- }
-
+ }
+
+ if (m_hTaskBar != IntPtr.Zero)
+ {
+ // Explorer is probably already running.
+ return;
+ }
+
+ RegisterTaskmanWindow();
+
+ /* In order to allow Immersive processes (packaged apps, uwp apps, etc) to run, we need to use the CImmersiveShellController interface.
+ However, that API requires IAM access, which means that the app must be signed by Microsoft and must have the .imsrv PE header section.
+ In order to circumvent this, we need to copy runtimebroker.exe to a temp folder which meets those requirements, inject a DLL into it
+ to replace WinMain with our own, and then run it. This will allow us to start the Immersive Shell Controller and allow Immersive processes to run.
+
+ Copy runtimebroker.exe to a temp folder, write injected dll, and start it.
+ */
+
+ string tempPath = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.LocalApplicationData), "Temp", "GyroshellImmersiveUtility");
+ string process = Path.Combine(tempPath, "GryoShellImmersiveShell.exe");
+ Directory.CreateDirectory(tempPath);
+
+ // todo: remove this hack
+ Process.Start("taskkill", "/f /im GryoShellImmersiveShell.exe").WaitForExit();
+ Process.Start("taskkill", "/f /im explorer.exe").WaitForExit();
+
+ try
+ {
+ File.Delete(process);
+ File.Delete(Path.Combine(tempPath, "rmclient.dll"));
+ }
+ catch
+ {
+ Debugger.Break();
+ }
+
+ File.Copy(Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.System), "RuntimeBroker.exe"), process, true);
+ File.WriteAllBytes(Path.Combine(tempPath, "rmclient.dll"), Properties.Resources.ImmersiveShellHook);
+
+ // start the process
+ Process.Start(process);
+ }
+ private static uint windowMessage;
+ delegate nint WndProcDelegate(nint hwnd, uint message, nint wParam, nint lParam);
+ private static nint TaskmanWindowProc(nint hwnd, uint message, nint wParam, nint lParam)
+ {
+ if (message == 1)
+ {
+ // WM_CREATE
+ if (!SetTaskmanWindow(hwnd))
+ {
+ throw new Win32Exception();
+ }
+ windowMessage = RegisterWindowMessageW("SHELLHOOK");
+ if (!RegisterShellHookWindow(hwnd))
+ {
+ throw new Win32Exception();
+ }
+ }
+ else if (message == 2)
+ {
+ // WM_DESTROY
+ if (GetTaskmanWindow() == hwnd)
+ {
+ SetTaskmanWindow(0);
+ }
+ DeregisterShellHookWindow(hwnd);
+ }
+ else if (message == windowMessage || message == 0x312) //WM_HOTKEY
+ {
+ if (HookService == null)
+ {
+ var x = (Library.Helpers.Win32.Win32Interop.IServiceProvider)new CImmersiveShell();
+ if (x.QueryService(ref SID_ImmersiveShellHookService, ref ImmersiveShellHookServiceInterface, out object shellhooksrv) < 0)
+ {
+ Console.WriteLine("failed to get the immersive shell hook service");
+ return 0;
+ }
+ else
+ {
+ HookService = (IImmersiveShellHookService)shellhooksrv;
+ }
+
+ return 0;
+ }
+
+ // Pass the message to TwinUI to allow UWP apps to work correctly.
+
+ bool handle = true;
+ if (wParam == 12)
+ {
+ Console.WriteLine("set window");
+ HookService.SetTargetWindowForSerialization(lParam);
+ }
+ else if (wParam == 0x32)
+ {
+ handle = false;
+ }
+ if (handle)
+ {
+ HookService.PostShellHookMessage(wParam, lParam);
+ }
+ return 0;
+ }
+
+ return DefWindowProcW(hwnd, message, wParam, lParam);
+ }
+ private void RegisterTaskmanWindow()
+ {
+ WNDCLASSEX progman = WNDCLASSEX.Build();
+ progman.style = 8;
+ progman.hInstance = Marshal.GetHINSTANCE(typeof(ExplorerManagerService).Module);
+ progman.lpszClassName = "TaskmanWndClass";
+ progman.lpfnWndProc = Marshal.GetFunctionPointerForDelegate((WndProcDelegate)TaskmanWindowProc);
+
+ ushort atom = RegisterClassExW(ref progman);
+ if (atom == 0)
+ {
+ throw new Win32Exception();
+ }
+
+ var hwnd = CreateWindowExW(0, progman.lpszClassName, null, 0x82000000, 0, 0, 0, 0, IntPtr.Zero, IntPtr.Zero, Marshal.GetHINSTANCE(typeof(ExplorerManagerService).Module), IntPtr.Zero);
+
+ if (hwnd == IntPtr.Zero)
+ {
+ throw new Win32Exception();
+ }
+ }
+
public event EventHandler SystemControlStateChanged;
private bool _isStartMenuOpen;