├── .gitignore
├── .gitmodules
├── Images
└── Screenshot.png
├── LICENSE
├── README.md
├── Rectify11CPL
├── CControlPanelNavLink.cpp
├── CControlPanelNavLink.h
├── CControlPanelNavLinkCommand.h
├── CControlPanelNavLinks.cpp
├── CControlPanelNavLinks.h
├── CRectifyUtil.cpp
├── CRectifyUtil.h
├── ClassFactory.cpp
├── ClassFactory.h
├── ElementProvider.cpp
├── ElementProvider.h
├── ElevationManager.cpp
├── ElevationManager.h
├── FolderViewImpl.vcxproj.filters
├── Guid.h
├── IRectifyUtil.idl
├── IRectifyUtil_c.c
├── IRectifyUtil_h.h
├── IRectifyUtil_i.c
├── IRectifyUtil_p.c
├── IRectifyUtil_s.c
├── Rectify11CPL.def
├── Rectify11CPL.h
├── Rectify11CPL.rc
├── Rectify11CPL.vcxproj
├── Rectify11CPL.vcxproj.filters
├── RectifyMainPage.cpp
├── RectifyMainPage.h
├── RectifyMainPage.xml
├── RectifyThemeCfgPage.cpp
├── RectifyThemeCfgPage.h
├── RectifyThemeCfgPage.xml
├── Templetes.h
├── dlldata.c
├── dllmain.cpp
├── dllmain.h
├── icon.ico
├── pages.xml
├── preview_dark.bmp
├── preview_light.bmp
├── proxy.c
├── resource.h
├── taskslist.xml
├── theme.cpp
├── theme.h
└── undoc.h
├── logo.png
└── rectify11cpl.sln
/.gitignore:
--------------------------------------------------------------------------------
1 | .vs/
2 | *.user
3 | DirectUIx64/x64/
4 | DirectUIx64/debug/
5 |
6 | FolderViewImpl_Sample_folderview/x64/
7 | FolderViewImpl_Sample_folderview/debug/
8 | x64/
9 | Rectify11Installer/
10 | *.aps
11 | *.user
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "dui70"]
2 | path = dui70
3 | url = https://github.com/MishaProductions/dui70
4 |
--------------------------------------------------------------------------------
/Images/Screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Rectify11/RectifyControlPanel2/0007d9b37f0c529fb86428de30c5d528d8ff9b29/Images/Screenshot.png
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | ---
6 |
7 |
8 |
9 | [](https://github.com/Rectify11/RectifyControlPanel2/tree/master/Rectify11CPL)
10 | [](https://discord.gg/gsgu9GCtsk)
11 |
12 |
13 |
14 |
15 | The first control panel applet not made by Microsoft to use Microsoft's DirectUI library
16 |
17 |
18 |
19 |
20 | ## Usage
21 | Build the Rectify11CPL project, and then register it using regsrv32 inside of admin command prompt. Make sure to restart explorer.
22 |
23 | ## Libaries used
24 | - https://github.com/seven-mile/dui70 - DirectUI library
25 | - https://github.com/namazso/SecureUxTheme - UxTheme patcher & theme changer
26 |
27 |
--------------------------------------------------------------------------------
/Rectify11CPL/CControlPanelNavLink.cpp:
--------------------------------------------------------------------------------
1 | #include "Rectify11CPL.h"
2 | #include "CControlPanelNavLinkCommand.h"
3 | #include "CControlPanelNavLink.h"
4 |
5 | HRESULT __cdecl CControlPanelNavLink::Create(CPNAV_LIST list, CControlPanelNavLink** result)
6 | {
7 | CControlPanelNavLink* navLink = new CControlPanelNavLink();
8 | if (navLink != NULL)
9 | {
10 | navLink->m_Icon = NULL;
11 | navLink->m_Name = NULL;
12 | navLink->m_ExecType.m_ExecType = CPNAVTYPE_None;
13 | navLink->m_Type = list;
14 | *result = navLink;
15 | return S_OK;
16 | }
17 | else
18 | {
19 | return E_OUTOFMEMORY;
20 | }
21 | }
22 |
23 | void CControlPanelNavLink::SetName(LPCWSTR name)
24 | {
25 | SHStrDupW(name, &this->m_Name);
26 | }
--------------------------------------------------------------------------------
/Rectify11CPL/CControlPanelNavLink.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | class CControlPanelNavLink
3 | {
4 | public:
5 | static HRESULT Create(CPNAV_LIST list, CControlPanelNavLink** result);
6 | void SetName(LPCWSTR name);
7 | CPNAV_LIST m_Type; //0x00
8 | DWORD m_Unknown; //0x04
9 | WCHAR* m_Name; //0x08
10 | WCHAR* m_args; //0x18
11 | HICON m_Icon; //0x20
12 | CControlPanelNavLinkCommand m_ExecType;
13 | char unknown_bytes[0x33];
14 | };
15 |
16 |
--------------------------------------------------------------------------------
/Rectify11CPL/CControlPanelNavLinkCommand.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | class CControlPanelNavLinkCommand
3 | {
4 | public:
5 | CPNAVTYPE m_ExecType;
6 | DWORD m_space;
7 | LPWSTR m_AppletOrCommand;
8 | LPWSTR m_Arguments;
9 | };
10 |
11 |
--------------------------------------------------------------------------------
/Rectify11CPL/CControlPanelNavLinks.cpp:
--------------------------------------------------------------------------------
1 | #include "Rectify11CPL.h"
2 | #include "CControlPanelNavLinks.h"
3 | #include "CControlPanelNavLink.h"
4 | #include "CControlPanelNavLinkCommand.h"
5 |
6 | CControlPanelNavLinks::CControlPanelNavLinks()
7 | {
8 | m_dpaList = NULL;
9 | m_refCount = 1;
10 | }
11 |
12 | void NavLinksDPA_DeleteCB(CControlPanelNavLink* p, void* pData)
13 | {
14 | delete p;
15 | }
16 |
17 | CControlPanelNavLinks::~CControlPanelNavLinks()
18 | {
19 | if (this->m_dpaList != NULL) {
20 | DPA_DestroyCallback(this->m_dpaList, (PFNDAENUMCALLBACKCONST)NavLinksDPA_DeleteCB, NULL);
21 | this->m_dpaList = NULL;
22 | }
23 | }
24 |
25 | IFACEMETHODIMP CControlPanelNavLinks::QueryInterface(REFIID riid, __out void** ppv)
26 | {
27 | *ppv = NULL;
28 | if (riid == IID_IUnknown)
29 | {
30 | *ppv = (IUnknown*)this;
31 | return S_OK;
32 | }
33 | return E_NOINTERFACE;
34 | }
35 | IFACEMETHODIMP_(ULONG) CControlPanelNavLinks::AddRef()
36 | {
37 | return InterlockedIncrement(&m_refCount);
38 | }
39 | IFACEMETHODIMP_(ULONG) CControlPanelNavLinks::Release()
40 | {
41 | ULONG ref = InterlockedDecrement(&m_refCount);
42 | if (ref == 0)
43 | {
44 | delete this;
45 | }
46 | return ref;
47 | }
48 | HRESULT CControlPanelNavLinks::AddLinkShellEx(LPCWSTR name, LPCWSTR file, LPCWSTR arguments, CPNAV_LIST DisplayType, HICON icon)
49 | {
50 | CControlPanelNavLink* link = NULL;
51 | HRESULT hr = CControlPanelNavLink::Create(DisplayType, &link);
52 | if (SUCCEEDED(hr))
53 | {
54 | link->SetName(name);
55 |
56 | if (icon != NULL)
57 | {
58 | link->m_Icon = icon;
59 | }
60 |
61 | link->m_ExecType.m_ExecType = CPNAVTYPE_ShellExec;
62 | SHStrDupW(file, &link->m_ExecType.m_AppletOrCommand);
63 | SHStrDupW(arguments, &link->m_ExecType.m_Arguments);
64 | return Add(link);
65 | }
66 | else
67 | {
68 | return hr;
69 | }
70 | }
71 | HRESULT CControlPanelNavLinks::AddLinkControlPanel(LPCWSTR name, LPCWSTR path, LPCWSTR arguments, CPNAV_LIST DisplayType, HICON icon)
72 | {
73 | CControlPanelNavLink* link = NULL;
74 | HRESULT hr = CControlPanelNavLink::Create(DisplayType, &link);
75 | if (SUCCEEDED(hr))
76 | {
77 | link->SetName(name);
78 |
79 | if (icon != NULL)
80 | {
81 | link->m_Icon = icon;
82 | }
83 |
84 | link->m_ExecType.m_ExecType = CPNAVTYPE_Navigate;
85 | SHStrDupW(path, &link->m_ExecType.m_AppletOrCommand);
86 | SHStrDupW(arguments, &link->m_ExecType.m_Arguments);
87 | return Add(link);
88 | }
89 | else
90 | {
91 | return hr;
92 | }
93 | }
94 |
95 | HRESULT CControlPanelNavLinks::Add(CControlPanelNavLink* link)
96 | {
97 | if (m_dpaList == NULL)
98 | {
99 | m_dpaList = DPA_Create(10);
100 | if (m_dpaList == NULL)
101 | {
102 | return E_OUTOFMEMORY;
103 | }
104 | }
105 | if (DPA_InsertPtr(m_dpaList, 0x7fffffff, link) != -1)
106 | {
107 | return S_OK;
108 | }
109 | else
110 | {
111 | return E_OUTOFMEMORY;
112 | }
113 | }
--------------------------------------------------------------------------------
/Rectify11CPL/CControlPanelNavLinks.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | class CControlPanelNavLinks : public IUnknown
3 | {
4 | public:
5 | CControlPanelNavLinks();
6 |
7 | IFACEMETHODIMP QueryInterface(REFIID riid, __out void** ppv);
8 | IFACEMETHODIMP_(ULONG) AddRef();
9 | IFACEMETHODIMP_(ULONG) Release();
10 |
11 | HRESULT AddLinkControlPanel(LPCWSTR name, LPCWSTR path, LPCWSTR arguments, CPNAV_LIST DisplayType, HICON icon);
12 | HRESULT AddLinkShellEx(LPCWSTR name, LPCWSTR file, LPCWSTR arguments, CPNAV_LIST DisplayType, HICON icon);
13 | HRESULT Add(CControlPanelNavLink* link);
14 | virtual ~CControlPanelNavLinks();
15 | private:
16 | HDPA m_dpaList;
17 | long m_refCount;
18 | };
19 |
20 |
--------------------------------------------------------------------------------
/Rectify11CPL/CRectifyUtil.cpp:
--------------------------------------------------------------------------------
1 | // This class implements the IRectifyUtil interface. This class is registered as a COM object to allow the code
2 | // to be ran as administrator, without elevating explorer.exe or starting another process
3 |
4 | #include "Rectify11CPL.h"
5 | #include "CRectifyUtil.h"
6 | #include "psapi.h"
7 | #include
8 | #include
9 | #include
10 | #include "Guid.h"
11 | #include
12 | #include
13 | #include
14 | #include
15 |
16 | #pragma comment(lib, "taskschd.lib")
17 | #pragma comment(lib, "comsupp.lib")
18 | #pragma comment(lib, "comsuppw.lib")
19 |
20 | WCHAR Rectify11PrefsKey[] = L"SOFTWARE\\Rectify11Prefs";
21 |
22 | CRectifyUtil::CRectifyUtil() : m_ref(1)
23 | {
24 | DllAddRef();
25 | }
26 |
27 | CRectifyUtil::~CRectifyUtil()
28 | {
29 | DllRelease();
30 | }
31 |
32 | DWORD FindProcessId(const WCHAR* procname)
33 | {
34 | HANDLE hSnapshot;
35 | PROCESSENTRY32 pe;
36 | int pid = 0;
37 | BOOL hResult;
38 |
39 | memset(&pe, 0, sizeof(pe));
40 |
41 | // snapshot of all processes in the system
42 | hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
43 | if (INVALID_HANDLE_VALUE == hSnapshot) return 0;
44 |
45 | // initializing size: needed for using Process32First
46 | pe.dwSize = sizeof(PROCESSENTRY32);
47 |
48 | // info about first process encountered in a system snapshot
49 | hResult = Process32First(hSnapshot, &pe);
50 |
51 | // retrieve information about the processes
52 | // and exit if unsuccessful
53 | while (hResult) {
54 | // if we find the process: return process ID
55 | if (wcscmp(procname, pe.szExeFile) == 0) {
56 | pid = pe.th32ProcessID;
57 | break;
58 | }
59 | hResult = Process32Next(hSnapshot, &pe);
60 | }
61 |
62 | // closes an open handle (CreateToolhelp32Snapshot)
63 | CloseHandle(hSnapshot);
64 | return pid;
65 | }
66 |
67 | HRESULT deleteTask(std::wstring taskName)
68 | {
69 | HRESULT hr = S_OK;
70 |
71 | ITaskService* pITS = NULL;
72 | hr = CoCreateInstance(CLSID_TaskScheduler, nullptr, CLSCTX_INPROC_SERVER, IID_ITaskService, (void**)&pITS);
73 | if (FAILED(hr)) {
74 | return hr;
75 | }
76 |
77 | hr = pITS->Connect(_variant_t(), _variant_t(), _variant_t(), _variant_t());
78 | if (FAILED(hr)) {
79 | pITS->Release();
80 | return hr;
81 | }
82 |
83 | ITaskFolder* pITF;
84 | hr = pITS->GetFolder(_bstr_t(L"\\"), &pITF);
85 | if (FAILED(hr)) {
86 | pITS->Release();
87 | return hr;
88 | }
89 |
90 | pITS->Release();
91 |
92 | hr = pITF->DeleteTask(_bstr_t(taskName.c_str()), 0);
93 | if (FAILED(hr)) {
94 | pITF->Release();
95 | return hr;
96 | }
97 |
98 | pITF->Release();
99 |
100 | return hr;
101 | }
102 |
103 | HRESULT taskExists(wstring taskName, BOOL* taskExists)
104 | {
105 | HRESULT hr = S_OK;
106 | *taskExists = FALSE;
107 | ITaskService* pITS = NULL;
108 | hr = CoCreateInstance(CLSID_TaskScheduler, nullptr, CLSCTX_INPROC_SERVER, IID_ITaskService, (void**)&pITS);
109 | if (FAILED(hr)) {
110 | return hr;
111 | }
112 |
113 | hr = pITS->Connect(_variant_t(), _variant_t(), _variant_t(), _variant_t());
114 | if (FAILED(hr)) {
115 | pITS->Release();
116 | return hr;
117 | }
118 |
119 | ITaskFolder* pITF;
120 | hr = pITS->GetFolder(_bstr_t(L"\\"), &pITF);
121 | if (FAILED(hr)) {
122 | pITS->Release();
123 | return hr;
124 | }
125 |
126 | pITS->Release();
127 |
128 | IRegisteredTask* task = NULL;
129 | hr = pITF->GetTask(_bstr_t(taskName.c_str()), &task);
130 | if (FAILED(hr)) {
131 | pITF->Release();
132 | return hr;
133 | }
134 | else
135 | {
136 | *taskExists = TRUE;
137 | }
138 |
139 | pITF->Release();
140 |
141 | return hr;
142 | }
143 |
144 | HRESULT createTask(std::wstring taskName, std::wstring taskExe)
145 | {
146 | HRESULT hr = S_OK;
147 |
148 | ITaskService* pITS = NULL;
149 | hr = CoCreateInstance(CLSID_TaskScheduler, nullptr, CLSCTX_INPROC_SERVER, IID_ITaskService, (void**)&pITS);
150 | if (FAILED(hr)) {
151 | return hr;
152 | }
153 |
154 | hr = pITS->Connect(_variant_t(), _variant_t(), _variant_t(), _variant_t());
155 | if (FAILED(hr)) {
156 | pITS->Release();
157 | return hr;
158 | }
159 |
160 | ITaskFolder* pITF;
161 | hr = pITS->GetFolder(_bstr_t(L"\\"), &pITF);
162 | if (FAILED(hr)) {
163 | pITS->Release();
164 | return hr;
165 | }
166 |
167 | wstring taskxml = wstring(L"");
168 | taskxml += L"\\";
169 | taskxml += taskName;
170 | taskxml += L"trueS-1-5-32-545HighestAvailableIgnoreNewfalsefalsetruefalsefalsetruefalsetruetruefalsefalsefalsePT0S5";
171 | taskxml += taskExe;
172 | taskxml += L"";
173 |
174 | pITS->Release();
175 | IRegisteredTask* task;
176 | hr = pITF->RegisterTask(_bstr_t(taskName.c_str()), _bstr_t(taskxml.c_str()), TASK_CREATE_OR_UPDATE, variant_t(), variant_t(), TASK_LOGON_INTERACTIVE_TOKEN, variant_t(), &task);
177 | if (FAILED(hr)) {
178 | pITF->Release();
179 | return hr;
180 | }
181 |
182 | pITF->Release();
183 |
184 | return hr;
185 | }
186 |
187 | int DeleteDirectory(const std::string& refcstrRootDirectory,
188 | bool bDeleteSubdirectories = true)
189 | {
190 | bool bSubdirectory = false; // Flag, indicating whether
191 | // subdirectories have been found
192 | HANDLE hFile; // Handle to directory
193 | std::string strFilePath; // Filepath
194 | std::string strPattern; // Pattern
195 | WIN32_FIND_DATAA FileInformation; // File information
196 |
197 |
198 | strPattern = refcstrRootDirectory + "\\*.*";
199 | hFile = ::FindFirstFileA(strPattern.c_str(), &FileInformation);
200 | if (hFile != INVALID_HANDLE_VALUE)
201 | {
202 | do
203 | {
204 | if (FileInformation.cFileName[0] != '.')
205 | {
206 | strFilePath.erase();
207 | strFilePath = refcstrRootDirectory + "\\" + FileInformation.cFileName;
208 |
209 | if (FileInformation.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
210 | {
211 | if (bDeleteSubdirectories)
212 | {
213 | // Delete subdirectory
214 | int iRC = DeleteDirectory(strFilePath, bDeleteSubdirectories);
215 | if (iRC)
216 | return iRC;
217 | }
218 | else
219 | bSubdirectory = true;
220 | }
221 | else
222 | {
223 | // Set file attributes
224 | if (::SetFileAttributesA(strFilePath.c_str(),
225 | FILE_ATTRIBUTE_NORMAL) == FALSE)
226 | return ::GetLastError();
227 |
228 | // Delete file
229 | if (::DeleteFileA(strFilePath.c_str()) == FALSE)
230 | return ::GetLastError();
231 | }
232 | }
233 | } while (::FindNextFileA(hFile, &FileInformation) == TRUE);
234 |
235 | // Close handle
236 | ::FindClose(hFile);
237 |
238 | DWORD dwError = ::GetLastError();
239 | if (dwError != ERROR_NO_MORE_FILES)
240 | return dwError;
241 | else
242 | {
243 | if (!bSubdirectory)
244 | {
245 | // Set directory attributes
246 | if (::SetFileAttributesA(refcstrRootDirectory.c_str(),
247 | FILE_ATTRIBUTE_NORMAL) == FALSE)
248 | return ::GetLastError();
249 |
250 | // Delete directory
251 | if (::RemoveDirectoryA(refcstrRootDirectory.c_str()) == FALSE)
252 | return ::GetLastError();
253 | }
254 | }
255 | }
256 |
257 | return 0;
258 | }
259 |
260 | BOOL CRectifyUtil::KillTask(wstring proc)
261 | {
262 | while (1)
263 | {
264 | DWORD pid = FindProcessId(proc.c_str());
265 | if (pid == 0)
266 | {
267 | return FALSE;
268 | }
269 |
270 | const auto proc = OpenProcess(PROCESS_TERMINATE, false, pid);
271 | BOOL result = TerminateProcess(proc, 1);
272 | CloseHandle(proc);
273 | }
274 | return TRUE;
275 | }
276 |
277 |
278 | HRESULT startProc(LPCWSTR proc, wstring args = L"", bool waitForExit = false)
279 | {
280 | STARTUPINFOW si;
281 | PROCESS_INFORMATION pi;
282 | ZeroMemory(&si, sizeof(si));
283 | si.cb = sizeof(si);
284 | ZeroMemory(&pi, sizeof(pi));
285 |
286 | WCHAR proc_buffer[1000];
287 | if (proc)
288 | {
289 | ExpandEnvironmentStringsW(proc, proc_buffer, 999);
290 | }
291 |
292 | WCHAR args_buffer[1000] = { 0 };
293 | if (!args.empty())
294 | {
295 | wcsncpy_s(args_buffer, 999, args.c_str(), args.size());
296 | }
297 | BOOL hr = CreateProcessW(proc ? proc_buffer : NULL,
298 | args_buffer, // Command line
299 | NULL, // Process handle not inheritable
300 | NULL, // Thread handle not inheritable
301 | FALSE, // Set handle inheritance to FALSE
302 | CREATE_NO_WINDOW, // No creation flags
303 | NULL, // Use parent's environment block
304 | NULL, // Use parent's starting directory
305 | &si, // Pointer to STARTUPINFO structure
306 | &pi // Pointer to PROCESS_INFORMATION structure
307 | );
308 |
309 | if (!hr)
310 | {
311 | WCHAR error_buffer[1000];
312 |
313 | DWORD err = GetLastError();
314 | std::string message = std::system_category().message(err);
315 |
316 | std::wstring_convert> converter;
317 |
318 | std::wstring messageUnicode = converter.from_bytes(message);
319 |
320 | swprintf_s(error_buffer, L"Error while starting process %s with arguments %s: %s (%ld)", proc, args.c_str(), messageUnicode.c_str(), err);
321 | MessageBox(NULL, error_buffer, TEXT("Starting process failed"), MB_ICONERROR);
322 | }
323 | else
324 | {
325 | if (waitForExit)
326 | {
327 | // Successfully created the process. Wait for it to finish.
328 | WaitForSingleObject(pi.hProcess, INFINITE);
329 | DWORD exitCode;
330 | // Get the exit code.
331 | hr = GetExitCodeProcess(pi.hProcess, &exitCode);
332 | }
333 | }
334 |
335 | CloseHandle(pi.hProcess);
336 | CloseHandle(pi.hThread);
337 | return hr ? S_OK : S_FALSE;
338 | }
339 |
340 | bool check_if_file_exists(std::wstring path)
341 | {
342 | std::ifstream ff(path.c_str());
343 | return ff.is_open();
344 | }
345 | size_t GetSizeOfFile(const std::wstring& path)
346 | {
347 | struct _stat fileinfo;
348 | _wstat(path.c_str(), &fileinfo);
349 | return fileinfo.st_size;
350 | }
351 |
352 | std::wstring LoadUtf8FileToString(const std::wstring& filename)
353 | {
354 | std::wstring buffer; // stores file contents
355 | FILE* f = NULL;
356 | _wfopen_s(&f, filename.c_str(), L"rtS, ccs=UTF-8");
357 |
358 | // Failed to open file
359 | if (f == NULL)
360 | {
361 | // ...handle some error...
362 | return buffer;
363 | }
364 |
365 | size_t filesize = GetSizeOfFile(filename);
366 |
367 | // Read entire file contents in to memory
368 | if (filesize > 0)
369 | {
370 | buffer.resize(filesize);
371 | size_t wchars_read = fread(&(buffer.front()), sizeof(wchar_t), filesize, f);
372 | buffer.resize(wchars_read);
373 | buffer.shrink_to_fit();
374 | }
375 |
376 | fclose(f);
377 |
378 | return buffer;
379 | }
380 |
381 | void CRectifyUtil::RestartExplorer()
382 | {
383 | HWND hwnd = FindWindow(L"Shell_TrayWnd", NULL);
384 | DWORD pid = {};
385 | GetWindowThreadProcessId(hwnd, &pid);
386 |
387 | HANDLE h_explorer;
388 | h_explorer = OpenProcess(PROCESS_TERMINATE, false, pid);
389 | TerminateProcess(h_explorer, 2);
390 | CloseHandle(h_explorer);
391 |
392 | startProc(L"C:\\windows\\explorer.exe");
393 | }
394 |
395 | HRESULT CreateLink(LPCWSTR lpszTarget, LPCWSTR lpszDesc, LPCWSTR lpszWorkingDir, LPCSTR lpszShortcutPath)
396 | {
397 | HRESULT hres;
398 | IShellLink* psl = NULL;
399 |
400 | // Get a pointer to the IShellLink interface. It is assumed that CoInitialize
401 | // has already been called.
402 | hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl);
403 | if (SUCCEEDED(hres))
404 | {
405 | IPersistFile* ppf = NULL;
406 |
407 | // Set the path to the shortcut target and add the description.
408 | psl->SetPath(lpszTarget);
409 | psl->SetDescription(lpszDesc);
410 | psl->SetWorkingDirectory(lpszWorkingDir);
411 |
412 | // Query IShellLink for the IPersistFile interface, used for saving the
413 | // shortcut in persistent storage.
414 | hres = psl->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf);
415 |
416 | if (SUCCEEDED(hres))
417 | {
418 | WCHAR wsz[MAX_PATH];
419 |
420 | // Ensure that the string is Unicode.
421 | MultiByteToWideChar(CP_ACP, 0, lpszShortcutPath, -1, wsz, MAX_PATH);
422 |
423 | // Save the link by calling IPersistFile::Save.
424 | hres = ppf->Save(wsz, TRUE);
425 | ppf->Release();
426 | }
427 | psl->Release();
428 | }
429 | return hres;
430 | }
431 | ///
432 | /// Check if mica for everyone is enabled
433 | ///
434 | /// Returns if Mica for everyone is enabled
435 | HRESULT CRectifyUtil::GetMicaSettings(BOOL* pEnabled, BOOL* pTabbed)
436 | {
437 | *pEnabled = FALSE;
438 | *pTabbed = FALSE;
439 |
440 | taskExists(L"mfe", pEnabled);
441 |
442 | // read mfe config file
443 | struct stat sb;
444 | wstring config_file = wstring(L"c:\\windows\\micaforeveryone\\MicaForEveryone.conf");
445 | if (stat("c:\\windows\\micaforeveryone\\MicaForEveryone.conf", &sb) == 0)
446 | {
447 | wstring config = LoadUtf8FileToString(config_file);
448 | if (config.compare(L"Tabbed"))
449 | {
450 | *pTabbed = TRUE;
451 | }
452 | }
453 |
454 |
455 | return S_OK;
456 | }
457 |
458 | HRESULT CRectifyUtil::_EnableClassicTransparent()
459 | {
460 | CHAR path[MAX_PATH];
461 | HRESULT hr = SHGetFolderPathA(NULL, CSIDL_COMMON_STARTMENU, NULL, 0, path);
462 | if (SUCCEEDED(hr))
463 | {
464 | WCHAR workingdir_buffer[MAX_PATH];
465 | ExpandEnvironmentStringsW(L"%windir%\\nilesoft\\AcrylicMenus", workingdir_buffer, MAX_PATH);
466 |
467 | WCHAR target_buffer[MAX_PATH] = { 0 };
468 | ExpandEnvironmentStringsW(L"%windir%\\nilesoft\\AcrylicMenus\\AcrylicMenusLoader.exe", target_buffer, MAX_PATH);
469 |
470 | string shortcut_path = string(path);
471 | shortcut_path += +"\\programs\\startup\\acrylmenu.lnk";
472 | startProc(target_buffer);
473 | return CreateLink(target_buffer, L"Launch classic transparent menu hook", workingdir_buffer, shortcut_path.c_str());
474 | }
475 | else
476 | {
477 | return hr;
478 | }
479 | }
480 |
481 | HRESULT CRectifyUtil::_DeleteClassicTransparent()
482 | {
483 | CHAR path[MAX_PATH];
484 | HRESULT hr = SHGetFolderPathA(NULL, CSIDL_COMMON_STARTMENU, NULL, 0, path);
485 | KillTask(L"AcrylicMenusLoader.exe");
486 | if (SUCCEEDED(hr))
487 | {
488 | string file = string(path);
489 | file += +"\\programs\\startup\\acrylmenu.lnk";
490 | return DeleteFileA(file.c_str()) ? S_OK : E_ACTIVATIONDENIED_SHELLNOTREADY;
491 | }
492 | else
493 | {
494 | return hr;
495 | }
496 | }
497 | HRESULT CRectifyUtil::_EnableClassicMenu()
498 | {
499 | HKEY result;
500 | HRESULT status = RegCreateKey(HKEY_CURRENT_USER, TEXT("Software\\Classes\\CLSID\\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}"), &result);
501 | if (SUCCEEDED(status))
502 | {
503 | HKEY inprocServer;
504 | HRESULT status = RegCreateKey(result, TEXT("InprocServer32"), &inprocServer);
505 | if (SUCCEEDED(status))
506 | {
507 | RegSetValueExW(inprocServer, NULL, 0, REG_SZ, (const BYTE*)L"", 2);
508 | RegCloseKey(inprocServer);
509 | return S_OK;
510 | }
511 | RegCloseKey(result);
512 | return status;
513 | }
514 | return status;
515 | }
516 |
517 | HRESULT CRectifyUtil::_DeleteNilesoftIfExists()
518 | {
519 | struct stat sb;
520 | if (stat("c:\\windows\\nilesoft\\shell.nss", &sb) == 0)
521 | {
522 | // delete configuration file
523 | BOOL h = DeleteFile(TEXT("c:\\windows\\nilesoft\\shell.nss"));
524 | if (!h)
525 | {
526 | WCHAR buffer[200];
527 |
528 | swprintf(buffer, 199, L"Failed to uninstall nilesoft. failed to delete config file. hresult is %d\n", GetLastError());
529 | MessageBox(NULL, buffer, TEXT("_DeleteNilesoftIfExists"), MB_ICONERROR);
530 | }
531 |
532 | startProc(NULL, L"c:\\windows\\nilesoft\\shell.exe -unregister", true);
533 | return S_OK;
534 | }
535 | return S_OK;
536 | }
537 |
538 | ///
539 | /// Enable/disable micaforeveryone tool
540 | ///
541 | ///
542 | HRESULT CRectifyUtil::SetMicaForEveryoneEnabled(BOOL micaEnabled, BOOL tabbed)
543 | {
544 | HRESULT hr = S_OK;
545 | WCHAR value[255] = { 0 };
546 | PVOID pvData = value;
547 | DWORD size = sizeof(value);
548 | RegGetValue(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\ThemeManager", L"DllName", RRF_RT_REG_SZ, 0, pvData, &size);
549 | std::wstring msstylePath = std::wstring((LPCWSTR)pvData);
550 |
551 | std::wstring currentThemeName = msstylePath;
552 |
553 | const size_t last_slash_idx = currentThemeName.find_last_of(L"\\/");
554 | if (std::string::npos != last_slash_idx)
555 | {
556 | currentThemeName.erase(0, last_slash_idx + 1);
557 | }
558 |
559 | // Remove extension if present.
560 | const size_t period_idx = currentThemeName.rfind('.');
561 | if (std::string::npos != period_idx)
562 | {
563 | currentThemeName.erase(period_idx);
564 | }
565 |
566 | WCHAR buffer[1024];
567 | if (micaEnabled)
568 | {
569 | struct stat sb;
570 | if (stat("c:/windows/MicaForEveryone", &sb) == 0)
571 | {
572 | // kill micaforeveryone and explorerframe if already running
573 | KillTask(L"MicaForEveryone.exe");
574 | KillTask(L"ExplorerFrame.exe");
575 |
576 | char* localappdata = nullptr;
577 | size_t sz = 0;
578 | if (_dupenv_s(&localappdata, &sz, "localappdata") == 0 && localappdata != nullptr)
579 | {
580 | string appdata = string(localappdata);
581 | string micaFolder = appdata + "/Mica For Everyone/";
582 | if (stat(micaFolder.c_str(), &sb) != 0)
583 | {
584 | if (DeleteDirectory(micaFolder.c_str()))
585 | {
586 | MessageBox(NULL, L"Failed to delete local micaforeveryone folder.", L"Failed to create MFE task", MB_ICONERROR);
587 | }
588 | }
589 | HRESULT hr = createTask(TEXT("mfe"), TEXT("%systemroot%\\MicaForEveryone\\MicaForEveryone.exe"));
590 | if (FAILED(hr))
591 | {
592 | swprintf(buffer, 1024, L"Failed create MFE task: %x", hr);
593 | MessageBox(NULL, buffer, L"Failed to create MFE task", MB_ICONERROR);
594 | }
595 |
596 | wstring config_file_src = wstring(L"c:\\windows\\micaforeveryone\\CONF\\");
597 | if (tabbed)
598 | config_file_src += L"T";
599 | config_file_src += currentThemeName;
600 | config_file_src += L".conf";
601 |
602 | if (!check_if_file_exists(config_file_src))
603 | {
604 | swprintf(buffer, 1024, L"Warning: Micaforeveryone configuration file is missing! File name is %ws. Try reinstalling themes option in Rectify11 Installer", config_file_src.c_str());
605 | MessageBox(NULL, buffer, L"Rectify11 control panel applet", MB_ICONWARNING);
606 | }
607 | else
608 | {
609 | if (!CopyFileExW(config_file_src.c_str(), L"c:\\windows\\micaforeveryone\\MicaForEveryone.conf", NULL, NULL, NULL, 0))
610 | {
611 | swprintf(buffer, 1024, L"Warning: Failed to copy micaforeveryone configuration file with result %x", GetLastError());
612 | MessageBox(NULL, buffer, L"Warning", MB_ICONWARNING);
613 | }
614 | }
615 |
616 | // Enable micafix if black theme
617 | if (currentThemeName.compare(L"black"))
618 | {
619 | createTask(L"mfefix", L"%systemroot%\\MicaForEveryone\\EFamd64\\ExplorerFrame.exe");
620 | startProc(L"%systemroot%\\MicaForEveryone\\EFamd64\\ExplorerFrame.exe");
621 | }
622 | else
623 | {
624 | deleteTask(L"mfefix");
625 | KillTask(L"ExplorerFrame.exe");
626 | }
627 |
628 | // Start mica for everyone
629 | startProc(L"%systemroot%\\MicaForEveryone\\MicaForEveryone.exe");
630 | }
631 | else
632 | {
633 | MessageBox(NULL, L"Appdata env variable not found", L"Failed to create MFE task", MB_ICONERROR);
634 | }
635 | }
636 | else
637 | {
638 | MessageBox(NULL, L"Micaforeveryone is not correctly installed. Please rerun the rectify11 installed.", L"Failed to create MFE task", MB_ICONERROR);
639 | }
640 | }
641 | else
642 | {
643 | BOOL mfeExists;
644 | taskExists(L"mfe", &mfeExists);
645 | if (FAILED(deleteTask(L"mfe")) && mfeExists)
646 | {
647 | MessageBox(NULL, L"Failed to delete MFE task", L"Failed to delete MFE task", MB_ICONERROR);
648 | }
649 | deleteTask(L"mfefix");
650 | KillTask(L"MicaForEveryone.exe");
651 | KillTask(L"ExplorerFrame.exe");
652 | }
653 | return hr;
654 | }
655 |
656 | HRESULT CRectifyUtil::GetCurrentMenuIndex(DWORD* menuIndex)
657 | {
658 | *menuIndex = Normal;
659 | struct stat sb;
660 | if (stat("c:\\windows\\nilesoft\\shell.nss", &sb) != 0)
661 | {
662 | HKEY key = HKEY_CURRENT_USER;
663 | HKEY result;
664 | LONG hr = RegOpenKeyEx(key, L"Software\\Classes\\CLSID\\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}", 0, KEY_READ, &result);
665 |
666 |
667 | if (hr == 0)
668 | {
669 | *menuIndex = Classic;
670 | RegCloseKey(result);
671 | }
672 |
673 | CHAR path[MAX_PATH];
674 |
675 | hr = SHGetFolderPathA(NULL, CSIDL_COMMON_STARTMENU, NULL, 0, path);
676 |
677 | string file = string(path);
678 | file += +"\\programs\\startup\\acrylmenu.lnk";
679 | if (stat(file.c_str(), &sb) == 0)
680 | {
681 | *menuIndex = ClassicTransparent;
682 | }
683 | }
684 | else
685 | {
686 | wstring config = LoadUtf8FileToString(L"c:\\windows\\nilesoft\\shell.nss");
687 | if (config.compare(L"modify(where=this.title.length > 15 menu=title.more_options)"))
688 | {
689 | *menuIndex = NilesoftSmall;
690 | }
691 | else
692 | {
693 | *menuIndex = NilesoftFull;
694 | }
695 | }
696 | return S_OK;
697 | }
698 |
699 | HRESULT CRectifyUtil::SetCurrentMenuByIndex(DWORD menuIndex)
700 | {
701 | HRESULT hr = S_OK;
702 | if (menuIndex == Normal)
703 | {
704 | // Restore default Windows 11 menus
705 | hr = RegDeleteTree(HKEY_CURRENT_USER, TEXT("Software\\Classes\\CLSID\\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}"));
706 | _DeleteClassicTransparent();
707 | _DeleteNilesoftIfExists();
708 | }
709 | else if (menuIndex == NilesoftSmall)
710 | {
711 | std::wofstream f(L"c:\\windows\\nilesoft\\shell.nss");
712 | f.clear();
713 | f << "settings\r\n{\r\n priority=1\r\n exclude.where = !process.is_explorer\r\n showdelay = 100\r\n // Options to allow modification of system items\r\n modify.remove.duplicate=1\r\n tip\r\n {\r\n enabled=1\r\n opacity=100\r\n width=400\r\n radius=1\r\n time=1.25\r\n padding=[10,10]\r\n }\r\n}\r\ntheme\r\n{\r\n name=\"modern\"\r\n}\r\nimport 'imports/theme.nss'\r\nimport 'imports/images.nss'\r\n\r\nimport 'imports/modify.nss'\r\nmodify(where=this.title.length > 15 menu=title.more_options)\r\n\r\nmenu(mode=\"multiple\" title=\"Pin/Unpin\" image=icon.pin) {}\r\nmenu(mode=\"multiple\" title=title.more_options image=icon.more_options) {}\r\nimport 'imports/taskbar.nss'";
714 | f.close();
715 |
716 | startProc(NULL, L"c:\\windows\\nilesoft\\shell.exe -register", true);
717 |
718 |
719 | }
720 | else if (menuIndex == NilesoftFull)
721 | {
722 | std::wofstream f(L"c:\\windows\\nilesoft\\shell.nss");
723 | f.clear();
724 | f << "settings\r\n{\r\n priority=1\r\n exclude.where = !process.is_explorer\r\n showdelay = 100\r\n // Options to allow modification of system items\r\n modify.remove.duplicate=1\r\n tip\r\n {\r\n enabled=1\r\n opacity=100\r\n width=400\r\n radius=1\r\n time=1.25\r\n padding=[10,10]\r\n }\r\n}\r\ntheme\r\n{\r\n name=\"modern\"\r\n}\r\nimport 'imports/theme.nss'\r\nimport 'imports/images.nss'\r\n\r\nimport 'imports/modify.nss'\r\nmenu(mode=\"multiple\" title=\"Pin/Unpin\" image=icon.pin) {}\r\nmenu(mode=\"multiple\" title=title.more_options image=icon.more_options) {}\r\nimport 'imports/taskbar.nss'";
725 | f.close();
726 |
727 | startProc(NULL, L"c:\\windows\\nilesoft\\shell.exe -register", true);
728 | }
729 | else if (menuIndex == Classic)
730 | {
731 | _DeleteClassicTransparent();
732 | _DeleteNilesoftIfExists();
733 | hr = _EnableClassicMenu();
734 | }
735 | else if (menuIndex == ClassicTransparent)
736 | {
737 | _DeleteNilesoftIfExists();
738 | hr = _EnableClassicMenu();
739 | if (SUCCEEDED(hr))
740 | {
741 | hr = _EnableClassicTransparent();
742 | }
743 | }
744 | else
745 | {
746 | WCHAR buffer[200];
747 |
748 | swprintf(buffer, 199, L"Failed to update menu settings. Unknown enum index %d", menuIndex);
749 | MessageBox(NULL, buffer, TEXT("SetCurrentMenuByIndex"), MB_ICONERROR);
750 | hr = E_NOTIMPL;
751 | }
752 |
753 | return hr;
754 | }
755 |
756 | static bool themetool_loaded = false;
757 | HRESULT CRectifyUtil::ApplyTheme(LPCWSTR pThemeName)
758 | {
759 | HRESULT hr = S_OK;
760 | if (!themetool_loaded)
761 | {
762 | hr = themetool_init();
763 | }
764 |
765 | if (FAILED(hr))
766 | {
767 | return hr;
768 | }
769 | else {
770 | themetool_loaded = true;
771 | }
772 | ULONG apply_flags = 0;
773 |
774 | // load appy flags
775 | HKEY Rectify11;
776 | if (RegCreateKey(HKEY_CURRENT_USER, Rectify11PrefsKey, &Rectify11))
777 | {
778 | SHOW_ERROR("Failed to create Rectify11Prefs key");
779 | }
780 |
781 | DWORD size = 4;
782 |
783 | DWORD IgnoreBgVal = 0;
784 | DWORD IgnoreCursorsVal = 0;
785 | DWORD IgnoreIconsVal = 0;
786 | DWORD IgnoreColorsVal = 0;
787 | DWORD IgnoreSoundsVal = 0;
788 | DWORD IgnoreScreensaversVal = 0;
789 |
790 | RegQueryValueExW(Rectify11, L"IgnoreBg", 0, NULL, (LPBYTE)&IgnoreBgVal, &size);
791 | RegQueryValueExW(Rectify11, L"IgnoreCursors", 0, NULL, (LPBYTE)&IgnoreCursorsVal, &size);
792 | RegQueryValueExW(Rectify11, L"IgnoreIcons", 0, NULL, (LPBYTE)&IgnoreIconsVal, &size);
793 | RegQueryValueExW(Rectify11, L"IgnoreColors", 0, NULL, (LPBYTE)&IgnoreColorsVal, &size);
794 | RegQueryValueExW(Rectify11, L"IgnoreSounds", 0, NULL, (LPBYTE)&IgnoreSoundsVal, &size);
795 | RegQueryValueExW(Rectify11, L"IgnoreScreensavers", 0, NULL, (LPBYTE)&IgnoreScreensaversVal, &size);
796 | RegCloseKey(Rectify11);
797 |
798 | if (IgnoreBgVal)
799 | {
800 | apply_flags |= THEMETOOL_APPLY_FLAG_IGNORE_BACKGROUND;
801 | }
802 | if (IgnoreCursorsVal)
803 | {
804 | apply_flags |= THEMETOOL_APPLY_FLAG_IGNORE_CURSOR;
805 | }
806 | if (IgnoreIconsVal)
807 | {
808 | apply_flags |= THEMETOOL_APPLY_FLAG_IGNORE_DESKTOP_ICONS;
809 | }
810 | if (IgnoreColorsVal)
811 | {
812 | apply_flags |= THEMETOOL_APPLY_FLAG_IGNORE_COLOR;
813 | }
814 | if (IgnoreSoundsVal)
815 | {
816 | apply_flags |= THEMETOOL_APPLY_FLAG_IGNORE_SOUND;
817 | }
818 | if (IgnoreSoundsVal)
819 | {
820 | apply_flags |= THEMETOOL_APPLY_FLAG_IGNORE_SCREENSAVER;
821 | }
822 |
823 |
824 | ULONG themeCount = 0;
825 | themetool_get_theme_count(&themeCount);
826 | if (FAILED(hr))
827 | {
828 | return hr;
829 | }
830 | std::wstring targetTheme(pThemeName);
831 | std::transform(targetTheme.begin(), targetTheme.end(), targetTheme.begin(), ::tolower);
832 |
833 | for (ULONG i = 0; i < themeCount; i++)
834 | {
835 | ITheme* theme = NULL;
836 | themetool_get_theme(i, &theme);
837 |
838 | WCHAR buffer[512];
839 | themetool_theme_get_display_name(theme, buffer, 256);
840 |
841 | std::wstring displayName(buffer);
842 | std::transform(displayName.begin(), displayName.end(), displayName.begin(), ::tolower);
843 |
844 | if (displayName == targetTheme)
845 | {
846 | hr = themetool_set_active(NULL, i, TRUE, 0, 0);
847 |
848 | themetool_theme_release(theme);
849 | break;
850 | }
851 |
852 | themetool_theme_release(theme);
853 | }
854 | return hr;
855 | }
856 | HRESULT CRectifyUtil::InstallThemeTool()
857 | {
858 | HRESULT hr = S_OK;
859 | if (!themetool_loaded)
860 | {
861 | hr = themetool_init();
862 | }
863 |
864 | if (hr != S_OK)
865 | {
866 | return hr;
867 | }
868 | else {
869 | themetool_loaded = true;
870 | }
871 |
872 | hr = secureuxtheme_install(SECUREUXTHEME_INSTALL_HOOK_LOGONUI | SECUREUXTHEME_INSTALL_RENAME_DEFAULTCOLORS);
873 | return hr;
874 | }
875 | HRESULT CRectifyUtil::UninstallThemeTool()
876 | {
877 | HRESULT hr = S_OK;
878 | if (!themetool_loaded)
879 | {
880 | hr = themetool_init();
881 | }
882 |
883 | if (FAILED(hr))
884 | {
885 | return hr;
886 | }
887 | else {
888 | themetool_loaded = true;
889 | }
890 |
891 | hr = secureuxtheme_uninstall();
892 | return hr;
893 | }
894 |
895 | BOOL IsDarkTheme()
896 | {
897 | WCHAR value[255] = { 0 };
898 | PVOID pvData = value;
899 | DWORD size = sizeof(value);
900 | RegGetValueW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\ThemeManager", L"DllName", RRF_RT_REG_SZ, 0, pvData, &size);
901 | std::wstring msstylePath = std::wstring((LPCWSTR)pvData);
902 |
903 | size_t result = msstylePath.find(L"Dark");
904 | return result > 0 ? TRUE : FALSE;
905 | }
906 |
907 | HRESULT CRectifyUtil::QueryInterface(
908 | REFIID riid,
909 | _COM_Outptr_ void __RPC_FAR* __RPC_FAR* ppv)
910 | {
911 | static const QITAB qit[] = {
912 | QITABENT(CRectifyUtil, IRectifyUtil),
913 | QITABENT(CRectifyUtil, IUnknown),
914 | { 0 },
915 | };
916 | HRESULT x = QISearch(this, qit, riid, ppv);
917 | return x;
918 | }
919 |
920 | ULONG CRectifyUtil::AddRef(void)
921 | {
922 | return m_ref++;
923 | }
924 |
925 | ULONG CRectifyUtil::Release(void)
926 | {
927 | ULONG cRef = InterlockedDecrement(&m_ref);
928 | if (0 == cRef)
929 | {
930 | delete this;
931 | }
932 | return cRef;
933 | }
--------------------------------------------------------------------------------
/Rectify11CPL/CRectifyUtil.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 | #include "IRectifyUtil_h.h"
4 | using namespace std;
5 |
6 | extern WCHAR Rectify11PrefsKey[];
7 |
8 | class CRectifyUtil : IRectifyUtil
9 | {
10 | public:
11 | CRectifyUtil();
12 | ~CRectifyUtil();
13 | virtual HRESULT QueryInterface(
14 | REFIID riid,
15 | _COM_Outptr_ void __RPC_FAR* __RPC_FAR* ppvObject);
16 | virtual ULONG AddRef(void);
17 | virtual ULONG Release(void);
18 |
19 | virtual HRESULT GetMicaSettings(BOOL* pEnabled, BOOL* pTabbed);
20 | virtual HRESULT SetMicaForEveryoneEnabled(BOOL micaEnabled, BOOL tabbed);
21 |
22 | virtual HRESULT GetCurrentMenuIndex(DWORD* menuIndex);
23 | virtual HRESULT SetCurrentMenuByIndex(DWORD pIndex);
24 |
25 | virtual HRESULT ApplyTheme(LPCWSTR pThemeName);
26 | virtual HRESULT InstallThemeTool();
27 | virtual HRESULT UninstallThemeTool();
28 |
29 | static BOOL KillTask(wstring proc);
30 | static void RestartExplorer();
31 |
32 | private:
33 | LONG m_ref;
34 | HRESULT _EnableClassicTransparent();
35 | HRESULT _DeleteClassicTransparent();
36 | HRESULT _EnableClassicMenu();
37 | HRESULT _DeleteNilesoftIfExists();
38 | };
39 |
40 | BOOL IsDarkTheme();
--------------------------------------------------------------------------------
/Rectify11CPL/ClassFactory.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include "Rectify11CPL.h"
4 | #include "ElementProvider.h"
5 | #include "ClassFactory.h"
6 | #include "Guid.h"
7 | #include "Templetes.h"
8 | #include "RectifyMainPage.h"
9 | #include "RectifyThemeCfgPage.h"
10 |
11 | CFolderViewImplClassFactory::CFolderViewImplClassFactory(REFCLSID rclsid) : m_cRef(1), m_rclsid(rclsid)
12 | {
13 | DllAddRef();
14 | }
15 |
16 | CFolderViewImplClassFactory::~CFolderViewImplClassFactory()
17 | {
18 | DllRelease();
19 | }
20 |
21 | HRESULT CFolderViewImplClassFactory::QueryInterface(__in REFIID riid, __deref_out void **ppv)
22 | {
23 | static const QITAB qit[] = {
24 | QITABENT (CFolderViewImplClassFactory, IClassFactory),
25 | { 0 },
26 | };
27 | return QISearch(this, qit, riid, ppv);
28 | }
29 |
30 | DWORD CFolderViewImplClassFactory::AddRef()
31 | {
32 | return InterlockedIncrement(&m_cRef);
33 | }
34 |
35 | DWORD CFolderViewImplClassFactory::Release()
36 | {
37 | ULONG cRef = InterlockedDecrement(&m_cRef);
38 | if (0 == cRef)
39 | {
40 | delete this;
41 | }
42 | return cRef;
43 | }
44 |
45 | HRESULT CElementProvider_CreateInstance(__in REFIID riid, __deref_out void** ppv)
46 | {
47 | HRESULT hr = S_ALLTHRESHOLD;
48 | CElementProvider* pElementProvider = new CElementProvider();
49 | hr = pElementProvider ? S_OK : E_OUTOFMEMORY;
50 | if (SUCCEEDED(hr))
51 | {
52 | hr = pElementProvider->QueryInterface(riid, ppv);
53 |
54 | DirectUI::ClassInfo>::Register();
55 | DirectUI::ClassInfo>::Register();
56 | pElementProvider->Release();
57 | }
58 | return hr;
59 | }
60 |
61 | HRESULT CRectifyUtil_CreateInstance(__in REFIID riid, __deref_out void** ppv)
62 | {
63 | HRESULT hr = S_ALLTHRESHOLD;
64 | CRectifyUtil* pUtility = new CRectifyUtil();
65 | hr = pUtility ? S_OK : E_OUTOFMEMORY;
66 | if (SUCCEEDED(hr))
67 | {
68 | hr = pUtility->QueryInterface(riid, ppv);
69 | pUtility->Release();
70 | }
71 | return hr;
72 | }
73 |
74 | HRESULT CFolderViewImplClassFactory::CreateInstance(__in_opt IUnknown* punkOuter,
75 | __in REFIID riid,
76 | __deref_out void **ppv)
77 | {
78 | *ppv = NULL;
79 |
80 | HRESULT hr = !punkOuter ? S_OK : CLASS_E_NOAGGREGATION;
81 | if (SUCCEEDED(hr))
82 | {
83 | if (m_rclsid == CLSID_FolderViewImplElement)
84 | {
85 | hr = CElementProvider_CreateInstance(riid, ppv);
86 | }
87 | else if (m_rclsid == CLSID_CRectifyUtil)
88 | {
89 | hr = CRectifyUtil_CreateInstance(riid, ppv);
90 | }
91 | else if (riid == IID_IUnknown)
92 | {
93 | // TODO: is this correct? Not sure why this is being called with IUnknown instead of CRectifyUtil
94 | // in Windows 11 23H2
95 | // for some reason m_rclsid is DCC67965-7FFB-0000-1400 ....
96 | hr = CRectifyUtil_CreateInstance(riid, ppv);
97 | }
98 | else
99 | {
100 | hr = E_NOINTERFACE;
101 |
102 | WCHAR szGuid[400] = { 0 };
103 |
104 | swprintf(szGuid, 400, L"RIID: {%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}\nRCLSID: {%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
105 | riid.Data1, riid.Data2, riid.Data3, riid.Data4[0], riid.Data4[1], riid.Data4[2], riid.Data4[3], riid.Data4[4], riid.Data4[5], riid.Data4[6], riid.Data4[7],
106 | m_rclsid.Data1, m_rclsid.Data2, m_rclsid.Data3, m_rclsid.Data4[0], m_rclsid.Data4[1], m_rclsid.Data4[2], m_rclsid.Data4[3], m_rclsid.Data4[4], m_rclsid.Data4[5], m_rclsid.Data4[6], m_rclsid.Data4[7]);
107 |
108 | MessageBox(NULL, szGuid, TEXT("Unknown interface in CFolderViewImplClassFactory::CreateInstance()"), MB_ICONERROR);
109 | }
110 | }
111 | return hr;
112 | }
113 |
114 | HRESULT CFolderViewImplClassFactory::LockServer(BOOL fLock)
115 | {
116 | if (fLock)
117 | {
118 | DllAddRef();
119 | }
120 | else
121 | {
122 | DllRelease();
123 | }
124 | return S_OK;
125 | }
126 |
--------------------------------------------------------------------------------
/Rectify11CPL/ClassFactory.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | class CFolderViewImplClassFactory : public IClassFactory
4 | {
5 | public:
6 | CFolderViewImplClassFactory(REFCLSID rclsid);
7 |
8 | // IUnknown methods
9 | IFACEMETHODIMP QueryInterface(__in REFIID riid, __deref_out void **ppv);
10 | IFACEMETHODIMP_(ULONG) AddRef();
11 | IFACEMETHODIMP_(ULONG) Release();
12 |
13 | // IClassFactory methods
14 | IFACEMETHODIMP CreateInstance(__in_opt IUnknown *pUnknown, __in REFIID riid, __deref_out void **ppv);
15 | IFACEMETHODIMP LockServer(BOOL fLock);
16 |
17 | private:
18 | ~CFolderViewImplClassFactory();
19 | REFCLSID m_rclsid;
20 | LONG m_cRef;
21 | };
22 |
--------------------------------------------------------------------------------
/Rectify11CPL/ElementProvider.cpp:
--------------------------------------------------------------------------------
1 | // This class is created by Shell32 CLayoutFolder class. This class "provides" the Element for DirectUI to render in explorer.
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 |
10 | #include "Rectify11CPL.h"
11 | #include "ElevationManager.h"
12 | #include "ElementProvider.h"
13 | #include "resource.h"
14 | #include "RectifyMainPage.h"
15 | #include "RectifyThemeCfgPage.h"
16 | #include