From 937954cf6c1d410ab520427083a97c67da033c5e Mon Sep 17 00:00:00 2001 From: Whindmar Saksit Date: Tue, 20 May 2025 16:59:02 +0200 Subject: [PATCH] [BROWSEUI][SHELL32][SHLWAPI][BOOTDATA] Implement and use IRegTreeOptions (#7255) --- boot/bootdata/hivesft.inf | 9 + dll/win32/browseui/regtreeoptions.cpp | 576 ++++++++++++- dll/win32/browseui/regtreeoptions.h | 42 +- dll/win32/shell32/CDefViewUtil.cpp | 22 - dll/win32/shell32/dialogs/folder_options.cpp | 106 +-- dll/win32/shell32/dialogs/folder_options.h | 4 - dll/win32/shell32/dialogs/view.cpp | 852 ++----------------- dll/win32/shlwapi/ordinal.c | 44 + dll/win32/shlwapi/shlwapi.spec | 2 +- sdk/include/reactos/shellutils.h | 33 + sdk/include/reactos/shlobj_undoc.h | 18 +- sdk/include/reactos/shlwapi_undoc.h | 1 + 12 files changed, 709 insertions(+), 1000 deletions(-) diff --git a/boot/bootdata/hivesft.inf b/boot/bootdata/hivesft.inf index 77e0b708d5b..db87b39fd31 100644 --- a/boot/bootdata/hivesft.inf +++ b/boot/bootdata/hivesft.inf @@ -269,6 +269,7 @@ HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\Desktop HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\DesktopProcess","UncheckedValue",0x00010001,0x00000000 HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\DesktopProcess","DefaultValue",0x00010001,0x00000000 HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\DesktopProcess","HelpID",0x00000000,"shell.hlp#51079" +HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\DesktopProcess",Grayed,0x10001,4 HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\DesktopProcess\Policy",,0x00000012 HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\DesktopProcess\Policy\SeparateProcess",,0x00000012 @@ -283,6 +284,7 @@ HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\Disable HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\DisableThumbCache","UncheckedValue",0x00010001,0x00000000 HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\DisableThumbCache","DefaultValue",0x00010001,0x00000000 HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\DisableThumbCache","HelpID",0x00000000,"shell.hlp#51155" +HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\DisableThumbCache",Grayed,0x10001,6 HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\FolderSizeTip",,0x00000012 HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\FolderSizeTip","Type",0x00000000,"checkbox" @@ -293,6 +295,7 @@ HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\FolderS HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\FolderSizeTip","CheckedValue",0x00010001,0x00000001 HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\FolderSizeTip","UncheckedValue",0x00010001,0x00000000 HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\FolderSizeTip","DefaultValue",0x00010001,0x00000001 +HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\FolderSizeTip",Grayed,0x10001,4 HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\FriendlyTree",,0x00000012 HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\FriendlyTree","Type",0x00000000,"checkbox" @@ -304,6 +307,7 @@ HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\Friendl HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\FriendlyTree","UncheckedValue",0x00010001,0x00000000 HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\FriendlyTree","HelpID",0x00000000,"shell.hlp#51149" HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\FriendlyTree","DefaultValue",0x00010001,0x00000001 +HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\FriendlyTree",Grayed,0x10001,4 HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\Hidden",,0x00000012 HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\Hidden","Text",0x00000000,"@shell32.dll,-30499" @@ -354,6 +358,7 @@ HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\NetCraw HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\NetCrawler","UncheckedValue",0x00010001,0x00000001 HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\NetCrawler","DefaultValue",0x00010001,0x00000000 HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\NetCrawler","HelpID",0x00000000,"shell.hlp#51147" +HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\NetCrawler",Grayed,0x10001,4 HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\NetCrawler\Policy",,0x00000012 HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\NetCrawler\Policy\NoNetCrawling",,0x00000012 @@ -368,6 +373,7 @@ HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\Persist HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\PersistBrowsers","UncheckedValue",0x00010001,0x00000000 HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\PersistBrowsers","HelpID",0x00000000,"shell.hlp#51152" HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\PersistBrowsers","DefaultValue",0x00010001,0x00000000 +HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\PersistBrowsers",Grayed,0x10001,4 HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\ShowCompColor",,0x00000012 HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\ShowCompColor","Type",0x00000000,"checkbox" @@ -379,6 +385,7 @@ HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\ShowCom HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\ShowCompColor","UncheckedValue",0x00010001,0x00000000 HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\ShowCompColor","DefaultValue",0x00010001,0x00000001 HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\ShowCompColor","HelpID",0x00000000,"shell.hlp#51130" +HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\ShowCompColor",Grayed,0x10001,4 HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\ShowFullPath",,0x00000012 HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\ShowFullPath","Type",0x00000000,"checkbox" @@ -412,6 +419,7 @@ HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\ShowInf HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\ShowInfoTip","UncheckedValue",0x00010001,0x00000000 HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\ShowInfoTip","DefaultValue",0x00010001,0x00000001 HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\ShowInfoTip","HelpID",0x00000000,"shell.hlp#51102" +HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\ShowInfoTip",Grayed,0x10001,4 HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\SuperHidden",,0x00000012 HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\SuperHidden","Type",0x00000000,"checkbox" @@ -438,6 +446,7 @@ HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\WebView HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\WebViewBarricade","UncheckedValue",0x00010001,0x00000000 HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\WebViewBarricade","HelpID",0x00000000,"shell.hlp#51148" HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\WebViewBarricade","DefaultValue",0x00010001,0x00000000 +HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\WebViewBarricade",Grayed,0x10001,6 ; Common shell folders HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders",,0x00000012 diff --git a/dll/win32/browseui/regtreeoptions.cpp b/dll/win32/browseui/regtreeoptions.cpp index 8e2ea1b796c..92c87837a74 100644 --- a/dll/win32/browseui/regtreeoptions.cpp +++ b/dll/win32/browseui/regtreeoptions.cpp @@ -1,59 +1,569 @@ /* - * ReactOS Explorer - * - * Copyright 2009 Andrew Hill - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * PROJECT: browseui + * LICENSE: LGPL-2.1+ (https://spdx.org/licenses/LGPL-2.1+) + * PURPOSE: Common registry based settings editor + * COPYRIGHT: Copyright 2024 Whindmar Saksit */ #include "precomp.h" +#define HKEY_GRAYED HKEY_REGTREEOPTION_GRAYED +#define MAXVALUEDATA 100 // Max size for CheckedValue/UncheckedValue/DefaultValue + +enum { + TYPE_CHECK = 0, + TYPE_RADIO, + TYPE_GROUP, + TYPE_INVALID, + STATEIMAGESPERTYPE = 4, + STATE_CHECKOFF = TYPE_CHECK * STATEIMAGESPERTYPE, + STATE_CHECKON, + STATE_RADIOOFF = TYPE_RADIO * STATEIMAGESPERTYPE, + STATE_RADIOON, + STATE_GROUP = TYPE_GROUP * STATEIMAGESPERTYPE, +}; + +C_ASSERT((STATE_CHECKON & 1) && (STATE_RADIOON & 1) && STATE_RADIOON < STATE_GROUP); + +static HBITMAP CreatDibBitmap(HDC hDC, UINT cx, UINT cy, UINT bpp) +{ + BITMAPINFO bi; + PVOID pvBits; + + ZeroMemory(&bi, sizeof(bi)); + bi.bmiHeader.biSize = sizeof(bi.bmiHeader); + bi.bmiHeader.biWidth = cx; + bi.bmiHeader.biHeight = cy; + bi.bmiHeader.biPlanes = 1; + bi.bmiHeader.biBitCount = bpp; + bi.bmiHeader.biCompression = BI_RGB; + return CreateDIBSection(hDC, &bi, DIB_RGB_COLORS, &pvBits, NULL, 0); +} + +static HIMAGELIST CreateStateImages(UINT ImageSize) +{ + enum { bpp = 32 }; + UINT Failed = FALSE, State; + HIMAGELIST hIL = ImageList_Create(ImageSize, ImageSize, ILC_MASK | bpp, 8, 0); + if (!hIL) + return hIL; + + INT BorderSize = max(1, min(ImageSize / 16, 4)); + RECT Rect; + HDC hDC = CreateCompatibleDC(NULL); + + HBITMAP hbmMask = CreateBitmap(ImageSize, ImageSize, 1, 1, NULL); + Failed |= hbmMask == NULL; + + HBITMAP hbmData = CreatDibBitmap(hDC, ImageSize, ImageSize, bpp); + Failed |= hbmData == NULL; + + const HGDIOBJ hbmOld = SelectObject(hDC, hbmMask); + Failed |= hbmOld == NULL; + + // Create the check images + SetRect(&Rect, 0, 0, ImageSize, ImageSize); + FillRect(hDC, &Rect, HBRUSH(GetStockObject(WHITE_BRUSH))); + InflateRect(&Rect, -BorderSize, -BorderSize); + FillRect(hDC, &Rect, HBRUSH(GetStockObject(BLACK_BRUSH))); + + SelectObject(hDC, hbmData); + State = DFCS_BUTTONCHECK | DFCS_FLAT | DFCS_MONO; + DrawFrameControl(hDC, &Rect, DFC_BUTTON, State); + Failed |= ImageList_Add(hIL, hbmData, hbmMask) < 0; + DrawFrameControl(hDC, &Rect, DFC_BUTTON, State | DFCS_CHECKED); + Failed |= ImageList_Add(hIL, hbmData, hbmMask) < 0; + DrawFrameControl(hDC, &Rect, DFC_BUTTON, State | DFCS_INACTIVE); + Failed |= ImageList_Add(hIL, hbmData, hbmMask) < 0; + DrawFrameControl(hDC, &Rect, DFC_BUTTON, State | DFCS_CHECKED | DFCS_INACTIVE); + Failed |= ImageList_Add(hIL, hbmData, hbmMask) < 0; + + // Create the radio images + SelectObject(hDC, hbmMask); + SetRect(&Rect, 0, 0, ImageSize, ImageSize); + FillRect(hDC, &Rect, HBRUSH(GetStockObject(WHITE_BRUSH))); + InflateRect(&Rect, -BorderSize, -BorderSize); + DrawFrameControl(hDC, &Rect, DFC_BUTTON, DFCS_BUTTONRADIOMASK | DFCS_FLAT | DFCS_MONO); + + SelectObject(hDC, hbmData); + State = DFCS_BUTTONRADIOIMAGE | DFCS_FLAT | DFCS_MONO; + DrawFrameControl(hDC, &Rect, DFC_BUTTON, State); + Failed |= ImageList_Add(hIL, hbmData, hbmMask) < 0; + DrawFrameControl(hDC, &Rect, DFC_BUTTON, State | DFCS_CHECKED); + Failed |= ImageList_Add(hIL, hbmData, hbmMask) < 0; + DrawFrameControl(hDC, &Rect, DFC_BUTTON, State | DFCS_INACTIVE); + Failed |= ImageList_Add(hIL, hbmData, hbmMask) < 0; + DrawFrameControl(hDC, &Rect, DFC_BUTTON, State | DFCS_CHECKED | DFCS_INACTIVE); + Failed |= ImageList_Add(hIL, hbmData, hbmMask) < 0; + + SelectObject(hDC, hbmOld); + DeleteObject(hbmMask); + DeleteObject(hbmData); + DeleteDC(hDC); + if (Failed) + { + ImageList_Destroy(hIL); + hIL = NULL; + } + return hIL; +} + +static inline DWORD NormalizeRegType(DWORD Type) +{ + switch (Type) + { + case REG_EXPAND_SZ: return REG_SZ; + case REG_DWORD: return REG_BINARY; + default: return Type; + } +} + +static inline DWORD GetRegDWORD(HKEY hKey, LPCWSTR Name, PDWORD Data) +{ + DWORD Size = sizeof(*Data); + return SHRegGetValueW(hKey, NULL, Name, SRRF_RT_DWORD, NULL, Data, &Size); +} + +static DWORD GetRegDWORD(HKEY hKey, LPCWSTR Name, DWORD Default) +{ + DWORD Data = Default, Size = sizeof(Data); + DWORD Err = SHRegGetValueW(hKey, NULL, Name, SRRF_RT_DWORD, NULL, &Data, &Size); + return Err ? Default : Data; +} + +static HRESULT GetRegString(HKEY hKey, LPCWSTR Name, LPWSTR Buffer, DWORD cchBuffer) +{ + DWORD Size = cchBuffer * sizeof(*Buffer); + DWORD Err = SHRegGetValueW(hKey, NULL, Name, SRRF_RT_REG_SZ, NULL, Buffer, &Size); + return Err ? HRESULT_FROM_WIN32(Err) : Size / sizeof(*Buffer); +} + +static int AddIconFromRegistry(HIMAGELIST hIL, HKEY hKey, LPCWSTR Name) +{ + WCHAR Path[MAX_PATH + 42]; + if (GetRegString(hKey, Name, Path, _countof(Path)) > 0) // Will %expand% for us + { + int idx = PathParseIconLocationW(Path); + HICON hIcon = NULL; + if (ExtractIconExW(Path, idx * -1, NULL, &hIcon, 1)) // Note: Index/Id is opposite of DefaultIcon style + { + idx = ImageList_AddIcon(hIL, hIcon); + DestroyIcon(hIcon); + if (idx != -1) + return idx; + } + } + return I_IMAGENONE; +} + +static HRESULT GetDefaultValue(HKEY hKey, DWORD &Type, LPVOID Data, DWORD &Size) +{ + DWORD Err = SHRegGetValueW(hKey, NULL, L"DefaultValue", SRRF_RT_ANY, &Type, Data, &Size); + return HRESULT_FROM_WIN32(Err); +} + +static HRESULT GetSetState(HKEY hKey, DWORD &Type, LPBYTE Data, DWORD &Size, BOOL Set) +{ + HRESULT hr; + UINT SysParam = GetRegDWORD(hKey, Set ? L"SPIActionSet" : L"SPIActionGet", DWORD(0)); + if (SysParam) + { + Size = sizeof(BOOL); + Type = REG_DWORD; + SHBoolSystemParametersInfo(SysParam, Data); + return S_OK; + } + +#if 0 // TODO + // learn.microsoft.com/en-us/windows/win32/api/shobjidl_core/nn-shobjidl_core-iregtreeitem + CLSID clsid; + if (SUCCEEDED(GetRegString(hKey, "CLSID", Temp, _countof(Temp))) && ..(Temp, &clsid)) + { + IRegTreeItem *pRTI; + if (SUCCEEDED(hr = IUnknown_QueryService(m_pUnkSite, clsid, IID_PPV_ARG(IRegTreeItem, &pti))) || + SUCCEEDED(hr = SHCoCreateInstance(NULL, &clsid, NULL, IID_PPV_ARG(IRegTreeItem, &pRTI)))) + { + BOOL *boolptr = (BOOL*)Data; + Size = sizeof(BOOL); + Type = REG_DWORD; + hr = Set ? pRTI->SetCheckState(*boolptr) : pRTI->GetCheckState(boolptr); + pRTI->Release(); + } + return hr; + } +#endif + + DWORD Mask = ~DWORD(0), Offset = 0; + BOOL HasMask = GetRegDWORD(hKey, L"Mask", &Mask) == ERROR_SUCCESS; + BOOL HasOffset = GetRegDWORD(hKey, L"Offset", &Offset) == ERROR_SUCCESS; + + HKEY hValueKey = (HKEY)LongToHandle(GetRegDWORD(hKey, L"HKeyRoot", HandleToLong(HKEY_CURRENT_USER))); + WCHAR SubKey[MAX_PATH], Name[100]; + hr = GetRegString(hKey, L"RegPath", SubKey, _countof(SubKey)); + if (FAILED(hr)) + return hr; + hr = GetRegString(hKey, L"ValueName", Name, _countof(Name)); + if (FAILED(hr)) + return hr; + DWORD Err, cb; + if (Set) + Err = RegCreateKeyExW(hValueKey, SubKey, 0, NULL, 0, KEY_READ | KEY_SET_VALUE, NULL, &hValueKey, NULL); + else + Err = RegOpenKeyExW(hValueKey, SubKey, 0, KEY_READ, &hValueKey); + if (Err) + return HRESULT_FROM_WIN32(Err); + + if (Set && (HasMask || HasOffset)) + { + Err = SHRegGetValueW(hValueKey, NULL, Name, SRRF_RT_ANY, NULL, NULL, &cb); + hr = HRESULT_FROM_WIN32(Err); + if (Err == ERROR_FILE_NOT_FOUND) + { + DWORD DefaultData = 0; + cb = sizeof(DefaultData); + hr = GetDefaultValue(hKey, Type, &DefaultData, cb); + if (SUCCEEDED(hr)) + { + Err = SHSetValueW(hValueKey, NULL, Name, Type, &DefaultData, cb); + hr = HRESULT_FROM_WIN32(Err); + } + } + + if (SUCCEEDED(hr)) + { + Err = ERROR_OUTOFMEMORY; + cb = max(cb, (Offset + 1) * sizeof(DWORD)); + if (PDWORD pBigData = (PDWORD)LocalAlloc(LPTR, cb)) // LPTR to zero extended data + { + Err = SHRegGetValueW(hValueKey, NULL, Name, SRRF_RT_ANY, &Type, pBigData, &cb); + Size = cb; + if (Err == ERROR_SUCCESS) + { + pBigData[Offset] &= ~Mask; + pBigData[Offset] |= *((PDWORD)Data); + Err = SHSetValueW(hValueKey, NULL, Name, Type, pBigData, cb); + } + LocalFree(pBigData); + } + hr = HRESULT_FROM_WIN32(Err); + } + } + else if (Set) + { + Err = SHSetValueW(hValueKey, NULL, Name, Type, Data, Size); + hr = HRESULT_FROM_WIN32(Err); + } + else + { + if (Offset && HasOffset) + { + Size = sizeof(DWORD); + Err = SHRegGetValueW(hValueKey, NULL, Name, SRRF_RT_ANY, NULL, NULL, &cb); + if (Err == ERROR_SUCCESS) + { + Err = ERROR_OUTOFMEMORY; + if (PDWORD pBigData = (PDWORD)LocalAlloc(LPTR, cb)) + { + Err = SHRegGetValueW(hValueKey, NULL, Name, SRRF_RT_ANY, &Type, pBigData, &cb); + if (Offset < cb / sizeof(DWORD) && Err == ERROR_SUCCESS) + *((PDWORD)Data) = pBigData[Offset]; + else + *((PDWORD)Data) = 0; // Value not present or offset too large + LocalFree(pBigData); + } + } + } + else + { + Err = SHRegGetValueW(hValueKey, NULL, Name, SRRF_RT_ANY, &Type, Data, &Size); + } + + hr = HRESULT_FROM_WIN32(Err); + if (HasMask && SUCCEEDED(hr)) + *((PDWORD)Data) &= Mask; + } + RegCloseKey(hValueKey); + return hr; +} + +static HRESULT GetCheckState(HKEY hKey, BOOL UseDefault = FALSE) +{ + BYTE CurrData[MAXVALUEDATA], CheckData[MAXVALUEDATA]; + DWORD CurrType, CheckType, CurrSize, CheckSize, Err, Checked; + + if (hKey == HKEY_GRAYED) + return HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED); + + CheckSize = sizeof(CheckData); + Err = SHRegGetValueW(hKey, NULL, L"CheckedValue", SRRF_RT_ANY, &CheckType, CheckData, &CheckSize); + if (Err) + return HRESULT_FROM_WIN32(Err); + + HRESULT hr = E_FAIL; + if (!UseDefault) + { + CurrSize = sizeof(CurrData); + hr = GetSetState(hKey, CurrType, CurrData, CurrSize, FALSE); + } + if (FAILED(hr)) + { + CurrSize = sizeof(CurrData); + hr = GetDefaultValue(hKey, CurrType, CurrData, CurrSize); + } + if (FAILED(hr)) + { + return hr; + } + + CurrType = NormalizeRegType(CurrType); + CheckType = NormalizeRegType(CheckType); + if (CurrType != CheckType) + { + return HRESULT_FROM_WIN32(ERROR_BAD_FORMAT); + } + else if (CheckType == REG_SZ) + { + *(LPWSTR)(&CheckData[sizeof(CheckData) - sizeof(WCHAR)]) = UNICODE_NULL; + if (CheckSize <= sizeof(CheckData) - sizeof(WCHAR)) + *(LPWSTR)(&CheckData[CheckSize]) = UNICODE_NULL; + Checked = !lstrcmpiW((LPWSTR)CheckData, (LPWSTR)CurrData); + } + else if (CheckType == REG_BINARY) + { + Checked = CheckSize == CurrSize && !memcmp(CheckData, CurrData, CurrSize); + } + else + { + return HRESULT_FROM_WIN32(ERROR_BAD_FORMAT); + } + return Checked ? S_OK : S_FALSE; +} + +static HRESULT SaveCheckState(HKEY hKey, BOOL Checked) +{ + BYTE Data[MAXVALUEDATA]; + DWORD Type = REG_DWORD, Size = sizeof(Data); + *((PDWORD)Data) = Checked; + LPCWSTR Name = Checked ? L"CheckedValue" : L"UncheckedValue"; + DWORD Err = SHRegGetValueW(hKey, NULL, Name, SRRF_RT_ANY, &Type, Data, &Size); + if (Err == ERROR_FILE_NOT_FOUND) + Err = ERROR_SUCCESS; + return Err ? HRESULT_FROM_WIN32(Err) : GetSetState(hKey, Type, Data, Size, TRUE); +} + +static void WalkTree(WALK_TREE_CMD Command, HWND hTree, HTREEITEM hTI) +{ + for (HTREEITEM hChildTI = TreeView_GetChild(hTree, hTI); hChildTI;) + { + WalkTree(Command, hTree, hChildTI); + hChildTI = TreeView_GetNextSibling(hTree, hChildTI); + } + + TVITEM tvi; + tvi.mask = TVIF_PARAM | TVIF_IMAGE | TVIF_SELECTEDIMAGE; + tvi.hItem = hTI; + if (!TreeView_GetItem(hTree, &tvi)) + return; + + HKEY hKey = (HKEY)tvi.lParam; + UINT State = tvi.iImage; + switch (Command) + { + case WALK_TREE_SAVE: + if (State == STATE_CHECKON || State == STATE_RADIOON) + SaveCheckState(hKey, TRUE); + else if (State == STATE_CHECKOFF) + SaveCheckState(hKey, FALSE); + break; + + case WALK_TREE_DESTROY: + if (hKey && hKey != HKEY_GRAYED) + { + RegCloseKey(hKey); + tvi.lParam = 0; + tvi.mask = TVIF_PARAM; + TreeView_SetItem(hTree, &tvi); + } + break; + + case WALK_TREE_DEFAULT: + case WALK_TREE_REFRESH: + if (State < STATE_GROUP) + { + HRESULT hr = GetCheckState(hKey, Command == WALK_TREE_DEFAULT); + if (SUCCEEDED(hr)) + { + tvi.iImage = tvi.iSelectedImage = (tvi.iImage & ~1) | (hr == S_OK); + TreeView_SetItem(hTree, &tvi); + } + } + break; + } +} + CRegTreeOptions::CRegTreeOptions() { + m_hTree = NULL; + m_hIL = NULL; } CRegTreeOptions::~CRegTreeOptions() { + if (m_hIL && m_hTree) + ImageList_Destroy(TreeView_SetImageList(m_hTree, NULL, TVSIL_NORMAL)); } -HRESULT STDMETHODCALLTYPE CRegTreeOptions::InitTree(HWND paramC, HKEY param10, char const *param14, char const *param18) +void CRegTreeOptions::AddItemsFromRegistry(HKEY hKey, HTREEITEM hParent, HTREEITEM hInsertAfter) { + for (DWORD Index = 0, cchName;;) + { + WCHAR Name[MAX_PATH], Temp[MAX_PATH]; + cchName = _countof(Name); + if (RegEnumKeyExW(hKey, Index++, Name, &cchName, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) + break; + + HKEY hItemKey, hCloseKey = NULL; + if (RegOpenKeyExW(hKey, Name, 0, KEY_READ, &hItemKey) != ERROR_SUCCESS) + continue; + + TVINSERTSTRUCT tvis; + TVITEM &tvi = tvis.item; + tvi.mask = TVIF_PARAM | TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE; + tvi.lParam = (LPARAM)hItemKey; + UINT Type = TYPE_INVALID; + if (GetRegString(hItemKey, L"Type", Temp, _countof(Temp)) > 0) + { + if (!lstrcmpi(Temp, L"checkbox")) + Type = TYPE_CHECK; + if (!lstrcmpi(Temp, L"radio")) + Type = TYPE_RADIO; + if (!lstrcmpi(Temp, L"group")) + Type = TYPE_GROUP; + } + BOOL Valid = Type != TYPE_INVALID; + + if (Type == TYPE_GROUP) + { + tvi.lParam = 0; + hCloseKey = hItemKey; + tvi.iImage = AddIconFromRegistry(m_hIL, hItemKey, L"Bitmap"); + } + else if (Valid) + { + HRESULT hr = GetCheckState(hItemKey); + Valid = SUCCEEDED(hr); + tvi.iImage = (Type * STATEIMAGESPERTYPE) | (hr == S_OK); + } + + if (Valid) + { + if (SUCCEEDED(SHLoadRegUIStringW(hItemKey, L"Text", Temp, _countof(Temp)))) + tvi.pszText = Temp; + else + tvi.pszText = Name; +#ifdef __REACTOS__ // Grayed is a ROS extension + DWORD grayed = GetRegDWORD(hItemKey, L"Grayed", DWORD(FALSE)); + if (grayed) + { + tvi.lParam = (LPARAM)HKEY_GRAYED; + hCloseKey = hItemKey; + tvi.iImage += 2; // Use disabled state image + if (grayed & 4) + tvi.iImage = (tvi.iImage & ~1) | ((grayed & 2) != 0); // Force a specific state + } +#endif + tvi.iSelectedImage = tvi.iImage; + tvis.hParent = hParent; + tvis.hInsertAfter = hInsertAfter; + Valid = (tvi.hItem = TreeView_InsertItem(m_hTree, &tvis)) != NULL; + } + + if (Valid && Type == TYPE_GROUP) + { + AddItemsFromRegistry(hItemKey, tvi.hItem, TVI_FIRST); + TreeView_Expand(m_hTree, tvi.hItem, TVE_EXPAND); + } + if (!Valid) + RegCloseKey(hItemKey); + if (hCloseKey && hItemKey != hCloseKey) + RegCloseKey(hCloseKey); + } + SendMessage(m_hTree, TVM_SORTCHILDREN, 0, (LPARAM)hParent); +} + +HRESULT STDMETHODCALLTYPE CRegTreeOptions::InitTree(HWND hTV, HKEY hKey, LPCSTR SubKey, char const *pUnknown) +{ + UNREFERENCED_PARAMETER(pUnknown); + m_hTree = hTV; + + m_hIL = CreateStateImages(GetSystemMetrics(SM_CXSMICON)); + HIMAGELIST hIL = TreeView_SetImageList(hTV, m_hIL, TVSIL_NORMAL); + if (hIL) + ImageList_Destroy(hIL); + + WCHAR Path[MAX_PATH]; + SHAnsiToUnicode(SubKey, Path, _countof(Path)); + if (RegOpenKeyExW(hKey, Path, 0, KEY_ENUMERATE_SUB_KEYS, &hKey) == ERROR_SUCCESS) + { + AddItemsFromRegistry(hKey, TVI_ROOT, TVI_ROOT); + RegCloseKey(hKey); + } + + TreeView_EnsureVisible(hTV, TreeView_GetRoot(hTV)); return E_NOTIMPL; } -HRESULT STDMETHODCALLTYPE CRegTreeOptions::WalkTree(WALK_TREE_CMD paramC) +HRESULT STDMETHODCALLTYPE CRegTreeOptions::WalkTree(WALK_TREE_CMD Command) { - return E_NOTIMPL; + for (HTREEITEM hTI = TreeView_GetRoot(m_hTree); hTI;) + { + ::WalkTree(Command, m_hTree, hTI); + hTI = TreeView_GetNextSibling(m_hTree, hTI); + } + return S_OK; } -HRESULT STDMETHODCALLTYPE CRegTreeOptions::ToggleItem(HTREEITEM paramC) +HRESULT STDMETHODCALLTYPE CRegTreeOptions::ToggleItem(HTREEITEM hTI) { - return E_NOTIMPL; + TVITEM tvi; + tvi.mask = TVIF_PARAM | TVIF_IMAGE | TVIF_SELECTEDIMAGE; + tvi.hItem = hTI; + if (!tvi.hItem || !TreeView_GetItem(m_hTree, &tvi)) + return E_INVALIDARG; + + if (tvi.iImage >= STATE_GROUP || (HKEY)tvi.lParam == HKEY_GRAYED) + return S_FALSE; + + if (tvi.iImage <= max(STATE_CHECKOFF, STATE_CHECKON)) + { + tvi.iImage ^= 1; + } + else + { + HTREEITEM hRadio = TreeView_GetChild(m_hTree, TreeView_GetParent(m_hTree, hTI)); + while (hRadio) // Turn off everyone in this group + { + tvi.hItem = hRadio; + tvi.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE; + if (TreeView_GetItem(m_hTree, &tvi) && tvi.iImage == STATE_RADIOON && hRadio != hTI) + { + tvi.iImage ^= 1; + tvi.iSelectedImage = tvi.iImage; + TreeView_SetItem(m_hTree, &tvi); + } + hRadio = TreeView_GetNextSibling(m_hTree, hRadio); + } + tvi.iImage = STATE_RADIOON; + } + + tvi.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE; + tvi.hItem = hTI; + tvi.iSelectedImage = tvi.iImage; + TreeView_SetItem(m_hTree, &tvi); + return S_OK; } -HRESULT STDMETHODCALLTYPE CRegTreeOptions::ShowHelp(HTREEITEM paramC, unsigned long param10) -{ - return E_NOTIMPL; -} - -HRESULT STDMETHODCALLTYPE CRegTreeOptions::SetSite(IUnknown *pUnkSite) -{ - return E_NOTIMPL; -} - -HRESULT STDMETHODCALLTYPE CRegTreeOptions::GetSite(REFIID riid, void **ppvSite) +HRESULT STDMETHODCALLTYPE CRegTreeOptions::ShowHelp(HTREEITEM hTI, unsigned long Unknown) { return E_NOTIMPL; } diff --git a/dll/win32/browseui/regtreeoptions.h b/dll/win32/browseui/regtreeoptions.h index 7c87c3e152b..61170891ae2 100644 --- a/dll/win32/browseui/regtreeoptions.h +++ b/dll/win32/browseui/regtreeoptions.h @@ -1,21 +1,8 @@ /* - * ReactOS Explorer - * - * Copyright 2009 Andrew Hill - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * PROJECT: browseui + * LICENSE: LGPL-2.1+ (https://spdx.org/licenses/LGPL-2.1+) + * PURPOSE: Common registry based settings editor + * COPYRIGHT: Copyright 2024 Whindmar Saksit */ #pragma once @@ -24,28 +11,27 @@ class CRegTreeOptions : public CComCoClass, public CComObjectRootEx, public IRegTreeOptions, - public IObjectWithSite + public CObjectWithSiteBase { private: + HWND m_hTree; + HIMAGELIST m_hIL; + public: CRegTreeOptions(); ~CRegTreeOptions(); - // *** IRegTreeOptions methods *** - STDMETHOD(InitTree)(HWND paramC, HKEY param10, char const *param14, char const *param18) override; - STDMETHOD(WalkTree)(WALK_TREE_CMD paramC) override; - STDMETHOD(ToggleItem)(HTREEITEM paramC) override; - STDMETHOD(ShowHelp)(HTREEITEM paramC, unsigned long param10) override; + void AddItemsFromRegistry(HKEY hKey, HTREEITEM hParent, HTREEITEM hInsertAfter); - // *** IObjectWithSite methods *** - STDMETHOD(SetSite)(IUnknown *pUnkSite) override; - STDMETHOD(GetSite)(REFIID riid, void **ppvSite) override; + // *** IRegTreeOptions methods *** + STDMETHOD(InitTree)(HWND hTV, HKEY hKey, LPCSTR SubKey, char const *pUnknown) override; + STDMETHOD(WalkTree)(WALK_TREE_CMD Command) override; + STDMETHOD(ToggleItem)(HTREEITEM hTI) override; + STDMETHOD(ShowHelp)(HTREEITEM hTI, unsigned long Unknown) override; DECLARE_REGISTRY_RESOURCEID(IDR_REGTREEOPTIONS) DECLARE_NOT_AGGREGATABLE(CRegTreeOptions) - DECLARE_PROTECT_FINAL_CONSTRUCT() - BEGIN_COM_MAP(CRegTreeOptions) COM_INTERFACE_ENTRY_IID(IID_IRegTreeOptions, IRegTreeOptions) COM_INTERFACE_ENTRY_IID(IID_IObjectWithSite, IObjectWithSite) diff --git a/dll/win32/shell32/CDefViewUtil.cpp b/dll/win32/shell32/CDefViewUtil.cpp index 3996b0d3891..6e4930c3340 100644 --- a/dll/win32/shell32/CDefViewUtil.cpp +++ b/dll/win32/shell32/CDefViewUtil.cpp @@ -9,28 +9,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(shell); -class CObjectWithSiteBase : - public IObjectWithSite -{ -public: - IUnknown* m_pUnkSite; - - CObjectWithSiteBase() : m_pUnkSite(NULL) {} - virtual ~CObjectWithSiteBase() { SetSite(NULL); } - - // IObjectWithSite - STDMETHODIMP SetSite(IUnknown *pUnkSite) override - { - IUnknown_Set(&m_pUnkSite, pUnkSite); - return S_OK; - } - STDMETHODIMP GetSite(REFIID riid, void **ppvSite) override - { - *ppvSite = NULL; - return m_pUnkSite ? m_pUnkSite->QueryInterface(riid, ppvSite) : E_FAIL; - } -}; - // This class adapts the legacy function callback to work as an IShellFolderViewCB class CShellFolderViewCBWrapper : public CComObjectRootEx, diff --git a/dll/win32/shell32/dialogs/folder_options.cpp b/dll/win32/shell32/dialogs/folder_options.cpp index 5514b62c918..865b69e109e 100644 --- a/dll/win32/shell32/dialogs/folder_options.cpp +++ b/dll/win32/shell32/dialogs/folder_options.cpp @@ -83,110 +83,6 @@ HBITMAP BitmapFromIcon(HICON hIcon, INT cx, INT cy) return hbm; } -HBITMAP CreateCheckImage(HDC hDC, BOOL bCheck, BOOL bEnabled) -{ - INT cxSmallIcon = GetSystemMetrics(SM_CXSMICON); - INT cySmallIcon = GetSystemMetrics(SM_CYSMICON); - - HBITMAP hbm = Create24BppBitmap(hDC, cxSmallIcon, cySmallIcon); - if (hbm == NULL) - return NULL; // failure - - RECT Rect, BoxRect; - SetRect(&Rect, 0, 0, cxSmallIcon, cySmallIcon); - BoxRect = Rect; - InflateRect(&BoxRect, -1, -1); - - HGDIOBJ hbmOld = SelectObject(hDC, hbm); - { - UINT uState = DFCS_BUTTONCHECK | DFCS_FLAT | DFCS_MONO; - if (bCheck) - uState |= DFCS_CHECKED; - if (!bEnabled) - uState |= DFCS_INACTIVE; - DrawFrameControl(hDC, &BoxRect, DFC_BUTTON, uState); - } - SelectObject(hDC, hbmOld); - - return hbm; // success -} - -HBITMAP CreateCheckMask(HDC hDC) -{ - INT cxSmallIcon = GetSystemMetrics(SM_CXSMICON); - INT cySmallIcon = GetSystemMetrics(SM_CYSMICON); - - HBITMAP hbm = CreateBitmap(cxSmallIcon, cySmallIcon, 1, 1, NULL); - if (hbm == NULL) - return NULL; // failure - - RECT Rect, BoxRect; - SetRect(&Rect, 0, 0, cxSmallIcon, cySmallIcon); - BoxRect = Rect; - InflateRect(&BoxRect, -1, -1); - - HGDIOBJ hbmOld = SelectObject(hDC, hbm); - { - FillRect(hDC, &Rect, HBRUSH(GetStockObject(WHITE_BRUSH))); - FillRect(hDC, &BoxRect, HBRUSH(GetStockObject(BLACK_BRUSH))); - } - SelectObject(hDC, hbmOld); - - return hbm; // success -} - -HBITMAP CreateRadioImage(HDC hDC, BOOL bCheck, BOOL bEnabled) -{ - INT cxSmallIcon = GetSystemMetrics(SM_CXSMICON); - INT cySmallIcon = GetSystemMetrics(SM_CYSMICON); - - HBITMAP hbm = Create24BppBitmap(hDC, cxSmallIcon, cySmallIcon); - if (hbm == NULL) - return NULL; // failure - - RECT Rect, BoxRect; - SetRect(&Rect, 0, 0, cxSmallIcon, cySmallIcon); - BoxRect = Rect; - InflateRect(&BoxRect, -1, -1); - - HGDIOBJ hbmOld = SelectObject(hDC, hbm); - { - UINT uState = DFCS_BUTTONRADIOIMAGE | DFCS_FLAT | DFCS_MONO; - if (bCheck) - uState |= DFCS_CHECKED; - if (!bEnabled) - uState |= DFCS_INACTIVE; - DrawFrameControl(hDC, &BoxRect, DFC_BUTTON, uState); - } - SelectObject(hDC, hbmOld); - - return hbm; // success -} - -HBITMAP CreateRadioMask(HDC hDC) -{ - INT cxSmallIcon = GetSystemMetrics(SM_CXSMICON); - INT cySmallIcon = GetSystemMetrics(SM_CYSMICON); - - HBITMAP hbm = CreateBitmap(cxSmallIcon, cySmallIcon, 1, 1, NULL); - if (hbm == NULL) - return NULL; // failure - - RECT Rect, BoxRect; - SetRect(&Rect, 0, 0, cxSmallIcon, cySmallIcon); - BoxRect = Rect; - InflateRect(&BoxRect, -1, -1); - - HGDIOBJ hbmOld = SelectObject(hDC, hbm); - { - FillRect(hDC, &Rect, HBRUSH(GetStockObject(WHITE_BRUSH))); - UINT uState = DFCS_BUTTONRADIOMASK | DFCS_FLAT | DFCS_MONO; - DrawFrameControl(hDC, &BoxRect, DFC_BUTTON, uState); - } - SelectObject(hDC, hbmOld); - - return hbm; // success -} ///////////////////////////////////////////////////////////////////////////// @@ -234,7 +130,7 @@ enum { static DWORD CALLBACK ShowFolderOptionsDialogThreadProc(LPVOID param) { - CCoInit com; // Required when started from rundll32 (SHAutoComplete in PickIconDlg) + CCoInit com; // Required when started from rundll32 (IRegTreeOptions, SHAutoComplete (in PickIconDlg)) PROPSHEETHEADERW pinfo; HPROPSHEETPAGE hppages[3]; HPROPSHEETPAGE hpage; diff --git a/dll/win32/shell32/dialogs/folder_options.h b/dll/win32/shell32/dialogs/folder_options.h index 7b5af73c144..adee2ad29f7 100644 --- a/dll/win32/shell32/dialogs/folder_options.h +++ b/dll/win32/shell32/dialogs/folder_options.h @@ -46,10 +46,6 @@ FolderOptionsFileTypesDlg( HBITMAP Create24BppBitmap(HDC hDC, INT cx, INT cy); HBITMAP BitmapFromIcon(HICON hIcon, INT cx, INT cy); -HBITMAP CreateCheckImage(HDC hDC, BOOL bCheck, BOOL bEnabled = TRUE); -HBITMAP CreateCheckMask(HDC hDC); -HBITMAP CreateRadioImage(HDC hDC, BOOL bCheck, BOOL bEnabled = TRUE); -HBITMAP CreateRadioMask(HDC hDC); extern LPCWSTR g_pszShell32; extern LPCWSTR g_pszSpace; diff --git a/dll/win32/shell32/dialogs/view.cpp b/dll/win32/shell32/dialogs/view.cpp index a455e445ab4..edb3b49a748 100644 --- a/dll/win32/shell32/dialogs/view.cpp +++ b/dll/win32/shell32/dialogs/view.cpp @@ -23,604 +23,33 @@ WINE_DEFAULT_DEBUG_CHANNEL (fprop); -///////////////////////////////////////////////////////////////////////////// -// View Tree - -// predefined icon IDs (See ViewDlg_CreateTreeImageList function below) -#define I_CHECKED 0 -#define I_UNCHECKED 1 -#define I_CHECKED_DISABLED 2 -#define I_UNCHECKED_DISABLED 3 -#define I_RADIO_CHECKED 4 -#define I_RADIO_UNCHECKED 5 -#define I_RADIO_CHECKED_DISABLED 6 -#define I_RADIO_UNCHECKED_DISABLED 7 -#define PREDEFINED_ICON_COUNT 8 - -// uniquely-defined icon entry for View Advanced Settings -typedef struct VIEWTREE_ICON +static inline CFolderOptions* +GetFolderOptions(HWND hwndDlg) { - WCHAR szPath[MAX_PATH]; - UINT nIconIndex; -} VIEWTREE_ICON, *PVIEWTREE_ICON; - -// types of View Advanced Setting entry -typedef enum VIEWTREE_ENTRY_TYPE -{ - AETYPE_GROUP, - AETYPE_CHECKBOX, - AETYPE_RADIO, -} VIEWTREE_ENTRY_TYPE, *PVIEWTREE_ENTRY_TYPE; - -// an entry info of View Advanced Settings -typedef struct VIEWTREE_ENTRY -{ - DWORD dwID; // entry ID - DWORD dwParentID; // parent entry ID - DWORD dwResourceID; // resource ID - WCHAR szKeyName[64]; // entry key name - DWORD dwType; // VIEWTREE_ENTRY_TYPE - WCHAR szText[MAX_PATH]; // text - INT nIconID; // icon ID (See VIEWTREE_ICON) - - HKEY hkeyRoot; // registry root key - WCHAR szRegPath[MAX_PATH]; // registry path - WCHAR szValueName[64]; // registry value name - - DWORD dwCheckedValue; // checked value - DWORD dwUncheckedValue; // unchecked value - DWORD dwDefaultValue; // defalut value - BOOL bHasUncheckedValue; // If FALSE, UncheckedValue is invalid - - HTREEITEM hItem; // for TreeView - BOOL bGrayed; // disabled? - BOOL bChecked; // checked? -} VIEWTREE_ENTRY, *PVIEWTREE_ENTRY; - -// definition of view advanced entries -static PVIEWTREE_ENTRY s_ViewTreeEntries = NULL; -static INT s_ViewTreeEntryCount = 0; - -// definition of icon stock -static PVIEWTREE_ICON s_ViewTreeIcons = NULL; -static INT s_ViewTreeIconCount = 0; -static HIMAGELIST s_hTreeImageList = NULL; - -static INT -ViewTree_FindIcon(LPCWSTR pszPath, UINT nIconIndex) -{ - for (INT i = PREDEFINED_ICON_COUNT; i < s_ViewTreeIconCount; ++i) - { - PVIEWTREE_ICON pIcon = &s_ViewTreeIcons[i]; - if (pIcon->nIconIndex == nIconIndex && - lstrcmpiW(pIcon->szPath, pszPath) == 0) - { - return i; // icon ID - } - } - return -1; // not found + return (CFolderOptions*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); } -static INT -ViewTree_AddIcon(LPCWSTR pszPath, UINT nIconIndex) +static inline IRegTreeOptions* +GetRegTreeOptions(HWND hwndDlg) { - PVIEWTREE_ICON pAllocated; - - // return the ID if already existed - INT nIconID = ViewTree_FindIcon(pszPath, nIconIndex); - if (nIconID != -1) - return nIconID; // already exists - - // extract a small icon - HICON hIconSmall = NULL; - ExtractIconExW(pszPath, nIconIndex, NULL, &hIconSmall, 1); - if (hIconSmall == NULL) - return -1; // failure - - // resize s_ViewTreeIcons - size_t Size = (s_ViewTreeIconCount + 1) * sizeof(VIEWTREE_ICON); - pAllocated = (PVIEWTREE_ICON)realloc(s_ViewTreeIcons, Size); - if (pAllocated == NULL) - return -1; // failure - else - s_ViewTreeIcons = pAllocated; - - // save icon information - PVIEWTREE_ICON pIcon = &s_ViewTreeIcons[s_ViewTreeIconCount]; - lstrcpynW(pIcon->szPath, pszPath, _countof(pIcon->szPath)); - pIcon->nIconIndex = nIconIndex; - - // add the icon to the image list - ImageList_AddIcon(s_hTreeImageList, hIconSmall); - - // increment the counter - nIconID = s_ViewTreeIconCount; - ++s_ViewTreeIconCount; - - DestroyIcon(hIconSmall); - - return nIconID; // newly-added icon ID + return (IRegTreeOptions*)GetWindowLongPtr(hwndDlg, DWLP_USER); } -static PVIEWTREE_ENTRY -ViewTree_GetItem(DWORD dwID) +static void +ViewDlg_OnDestroy(HWND hwndDlg) { - if (dwID == DWORD(-1)) - return NULL; - - for (INT i = 0; i < s_ViewTreeEntryCount; ++i) + if (IRegTreeOptions *pRTO = GetRegTreeOptions(hwndDlg)) { - PVIEWTREE_ENTRY pEntry = &s_ViewTreeEntries[i]; - if (pEntry->dwID == dwID) - return pEntry; + pRTO->WalkTree(WALK_TREE_DESTROY); + pRTO->Release(); + SetWindowLongPtr(hwndDlg, DWLP_USER, 0); } - return NULL; // failure -} - -static INT -ViewTree_GetImage(PVIEWTREE_ENTRY pEntry) -{ - switch (pEntry->dwType) - { - case AETYPE_GROUP: - return pEntry->nIconID; - - case AETYPE_CHECKBOX: - if (pEntry->bGrayed) - { - if (pEntry->bChecked) - return I_CHECKED_DISABLED; - else - return I_UNCHECKED_DISABLED; - } - else - { - if (pEntry->bChecked) - return I_CHECKED; - else - return I_UNCHECKED; - } - - case AETYPE_RADIO: - if (pEntry->bGrayed) - { - if (pEntry->bChecked) - return I_RADIO_CHECKED_DISABLED; - else - return I_RADIO_UNCHECKED_DISABLED; - } - else - { - if (pEntry->bChecked) - return I_RADIO_CHECKED; - else - return I_RADIO_UNCHECKED; - } - } - return -1; // failure -} - -static VOID -ViewTree_InsertEntry(HWND hwndTreeView, PVIEWTREE_ENTRY pEntry) -{ - PVIEWTREE_ENTRY pParent = ViewTree_GetItem(pEntry->dwParentID); - HTREEITEM hParent = TVI_ROOT; - if (pParent) - hParent = pParent->hItem; - - TV_INSERTSTRUCT Insertion; - ZeroMemory(&Insertion, sizeof(Insertion)); - Insertion.hParent = hParent; - Insertion.hInsertAfter = TVI_LAST; - Insertion.item.mask = - TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM; - Insertion.item.pszText = pEntry->szText; - - INT iImage = ViewTree_GetImage(pEntry); - Insertion.item.iImage = Insertion.item.iSelectedImage = iImage; - Insertion.item.lParam = pEntry->dwID; - pEntry->hItem = TreeView_InsertItem(hwndTreeView, &Insertion); -} - -static VOID -ViewTree_InsertAll(HWND hwndTreeView) -{ - TreeView_DeleteAllItems(hwndTreeView); - - // insert the entries - PVIEWTREE_ENTRY pEntry; - for (INT i = 0; i < s_ViewTreeEntryCount; ++i) - { - pEntry = &s_ViewTreeEntries[i]; - ViewTree_InsertEntry(hwndTreeView, pEntry); - } - - // expand all - for (INT i = 0; i < s_ViewTreeEntryCount; ++i) - { - pEntry = &s_ViewTreeEntries[i]; - if (pEntry->dwType == AETYPE_GROUP) - { - TreeView_Expand(hwndTreeView, pEntry->hItem, TVE_EXPAND); - } - } -} - -static BOOL -ViewTree_LoadTree(HKEY hKey, LPCWSTR pszKeyName, DWORD dwParentID) -{ - DWORD dwIndex = ~0UL; - WCHAR szKeyName[64], szText[MAX_PATH], *pch; - DWORD Size, Value; - PVIEWTREE_ENTRY pAllocated; - - // resize s_ViewTreeEntries - Size = (s_ViewTreeEntryCount + 1) * sizeof(VIEWTREE_ENTRY); - pAllocated = (PVIEWTREE_ENTRY)realloc(s_ViewTreeEntries, Size); - if (pAllocated == NULL) - return FALSE; // failure - else - s_ViewTreeEntries = pAllocated; - - PVIEWTREE_ENTRY pEntry = &s_ViewTreeEntries[s_ViewTreeEntryCount]; - - // dwID, dwParentID, szKeyName - pEntry->dwID = s_ViewTreeEntryCount; - pEntry->dwParentID = dwParentID; - lstrcpynW(pEntry->szKeyName, pszKeyName, _countof(pEntry->szKeyName)); - - // Text, ResourceID - pEntry->szText[0] = 0; - pEntry->dwResourceID = 0; - szText[0] = 0; - Size = sizeof(szText); - RegQueryValueExW(hKey, L"Text", NULL, NULL, LPBYTE(szText), &Size); - if (szText[0] == L'@') - { - pch = wcsrchr(szText, L','); - if (pch) - { - *pch = 0; - dwIndex = abs(_wtoi(pch + 1)); - pEntry->dwResourceID = dwIndex; - } - HINSTANCE hInst = LoadLibraryW(&szText[1]); - LoadStringW(hInst, dwIndex, szText, _countof(szText)); - FreeLibrary(hInst); - } - else - { - pEntry->dwResourceID = DWORD(-1); - } - lstrcpynW(pEntry->szText, szText, _countof(pEntry->szText)); - - // Type - szText[0] = 0; - RegQueryValueExW(hKey, L"Type", NULL, NULL, LPBYTE(szText), &Size); - if (lstrcmpiW(szText, L"checkbox") == 0) - pEntry->dwType = AETYPE_CHECKBOX; - else if (lstrcmpiW(szText, L"radio") == 0) - pEntry->dwType = AETYPE_RADIO; - else if (lstrcmpiW(szText, L"group") == 0) - pEntry->dwType = AETYPE_GROUP; - else - return FALSE; // failure - - pEntry->nIconID = -1; - if (pEntry->dwType == AETYPE_GROUP) - { - // Bitmap (Icon) - UINT nIconIndex = 0; - Size = sizeof(szText); - szText[0] = 0; - RegQueryValueExW(hKey, L"Bitmap", NULL, NULL, LPBYTE(szText), &Size); - - WCHAR szExpanded[MAX_PATH]; - ExpandEnvironmentStringsW(szText, szExpanded, _countof(szExpanded)); - pch = wcsrchr(szExpanded, L','); - if (pch) - { - *pch = 0; - nIconIndex = abs(_wtoi(pch + 1)); - } - pEntry->nIconID = ViewTree_AddIcon(szExpanded, nIconIndex); - } - - if (pEntry->dwType == AETYPE_GROUP) - { - pEntry->hkeyRoot = NULL; - pEntry->szRegPath[0] = 0; - pEntry->szValueName[0] = 0; - pEntry->dwCheckedValue = 0; - pEntry->bHasUncheckedValue = FALSE; - pEntry->dwUncheckedValue = 0; - pEntry->dwDefaultValue = 0; - pEntry->hItem = NULL; - pEntry->bGrayed = FALSE; - pEntry->bChecked = FALSE; - } - else - { - // HKeyRoot - HKEY HKeyRoot = HKEY_CURRENT_USER; - Size = sizeof(HKeyRoot); - RegQueryValueExW(hKey, L"HKeyRoot", NULL, NULL, LPBYTE(&HKeyRoot), &Size); - pEntry->hkeyRoot = HKeyRoot; - - // RegPath - pEntry->szRegPath[0] = 0; - Size = sizeof(szText); - RegQueryValueExW(hKey, L"RegPath", NULL, NULL, LPBYTE(szText), &Size); - lstrcpynW(pEntry->szRegPath, szText, _countof(pEntry->szRegPath)); - - // ValueName - pEntry->szValueName[0] = 0; - Size = sizeof(szText); - RegQueryValueExW(hKey, L"ValueName", NULL, NULL, LPBYTE(szText), &Size); - lstrcpynW(pEntry->szValueName, szText, _countof(pEntry->szValueName)); - - // CheckedValue - Size = sizeof(Value); - Value = 0x00000001; - RegQueryValueExW(hKey, L"CheckedValue", NULL, NULL, LPBYTE(&Value), &Size); - pEntry->dwCheckedValue = Value; - - // UncheckedValue - Size = sizeof(Value); - Value = 0x00000000; - pEntry->bHasUncheckedValue = TRUE; - if (RegQueryValueExW(hKey, L"UncheckedValue", NULL, - NULL, LPBYTE(&Value), &Size) != ERROR_SUCCESS) - { - pEntry->bHasUncheckedValue = FALSE; - } - pEntry->dwUncheckedValue = Value; - - // DefaultValue - Size = sizeof(Value); - Value = 0x00000001; - RegQueryValueExW(hKey, L"DefaultValue", NULL, NULL, LPBYTE(&Value), &Size); - pEntry->dwDefaultValue = Value; - - // hItem - pEntry->hItem = NULL; - - // bGrayed, bChecked - HKEY hkeyTarget; - Value = pEntry->dwDefaultValue; - pEntry->bGrayed = TRUE; - if (RegOpenKeyExW(HKEY(pEntry->hkeyRoot), pEntry->szRegPath, 0, - KEY_READ, &hkeyTarget) == ERROR_SUCCESS) - { - Size = sizeof(Value); - if (RegQueryValueExW(hkeyTarget, pEntry->szValueName, NULL, NULL, - LPBYTE(&Value), &Size) == ERROR_SUCCESS) - { - pEntry->bGrayed = FALSE; - } - RegCloseKey(hkeyTarget); - } - pEntry->bChecked = (Value == pEntry->dwCheckedValue); - } - - // Grayed (ReactOS extension) - Size = sizeof(Value); - Value = FALSE; - RegQueryValueExW(hKey, L"Grayed", NULL, NULL, LPBYTE(&Value), &Size); - if (!pEntry->bGrayed) - pEntry->bGrayed = Value; - - BOOL bIsGroup = (pEntry->dwType == AETYPE_GROUP); - dwParentID = pEntry->dwID; - ++s_ViewTreeEntryCount; - - if (!bIsGroup) - return TRUE; // success - - // load the children - dwIndex = 0; - while (RegEnumKeyW(hKey, dwIndex, szKeyName, - _countof(szKeyName)) == ERROR_SUCCESS) - { - HKEY hkeyChild; - if (RegOpenKeyExW(hKey, szKeyName, 0, KEY_READ, - &hkeyChild) != ERROR_SUCCESS) - { - ++dwIndex; - continue; // failure - } - - ViewTree_LoadTree(hkeyChild, szKeyName, dwParentID); - RegCloseKey(hkeyChild); - - ++dwIndex; - } - - return TRUE; // success -} - -static BOOL ViewTree_LoadAll(VOID) -{ - // free if already existed - if (s_ViewTreeEntries) - { - free(s_ViewTreeEntries); - s_ViewTreeEntries = NULL; - } - s_ViewTreeEntryCount = 0; - - HKEY hKey; - if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, - L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced", - 0, KEY_READ, &hKey) != ERROR_SUCCESS) - { - return FALSE; // failure - } - - // load the children - WCHAR szKeyName[64]; - DWORD dwIndex = 0; - while (RegEnumKeyW(hKey, dwIndex, szKeyName, - _countof(szKeyName)) == ERROR_SUCCESS) - { - HKEY hkeyChild; - if (RegOpenKeyExW(hKey, szKeyName, 0, KEY_READ, - &hkeyChild) != ERROR_SUCCESS) - { - ++dwIndex; - continue; // failure - } - - ViewTree_LoadTree(hkeyChild, szKeyName, DWORD(-1)); - RegCloseKey(hkeyChild); - - ++dwIndex; - } - - RegCloseKey(hKey); - - return TRUE; // success -} - -static int ViewTree_Compare(const void *x, const void *y) -{ - PVIEWTREE_ENTRY pEntry1 = (PVIEWTREE_ENTRY)x; - PVIEWTREE_ENTRY pEntry2 = (PVIEWTREE_ENTRY)y; - - DWORD dwParentID1 = pEntry1->dwParentID; - DWORD dwParentID2 = pEntry2->dwParentID; - - if (dwParentID1 == dwParentID2) - return lstrcmpi(pEntry1->szText, pEntry2->szText); - - DWORD i, m, n; - const UINT MAX_DEPTH = 32; - PVIEWTREE_ENTRY pArray1[MAX_DEPTH]; - PVIEWTREE_ENTRY pArray2[MAX_DEPTH]; - - // Make ancestor lists - for (i = m = n = 0; i < MAX_DEPTH; ++i) - { - PVIEWTREE_ENTRY pParent1 = ViewTree_GetItem(dwParentID1); - PVIEWTREE_ENTRY pParent2 = ViewTree_GetItem(dwParentID2); - if (!pParent1 && !pParent2) - break; - - if (pParent1) - { - pArray1[m++] = pParent1; - dwParentID1 = pParent1->dwParentID; - } - if (pParent2) - { - pArray2[n++] = pParent2; - dwParentID2 = pParent2->dwParentID; - } - } - - UINT k = min(m, n); - for (i = 0; i < k; ++i) - { - INT nCompare = lstrcmpi(pArray1[m - i - 1]->szText, pArray2[n - i - 1]->szText); - if (nCompare < 0) - return -1; - if (nCompare > 0) - return 1; - } - - if (m < n) - return -1; - if (m > n) - return 1; - return lstrcmpi(pEntry1->szText, pEntry2->szText); -} - -static VOID -ViewTree_SortAll(VOID) -{ - qsort(s_ViewTreeEntries, s_ViewTreeEntryCount, sizeof(VIEWTREE_ENTRY), ViewTree_Compare); -} - -///////////////////////////////////////////////////////////////////////////// -// ViewDlg - -static HIMAGELIST -ViewDlg_CreateTreeImageList(VOID) -{ - HIMAGELIST hImageList; - hImageList = ImageList_Create(16, 16, ILC_COLOR24 | ILC_MASK, 9, 1); - if (hImageList == NULL) - return NULL; // failure - - // free if existed - if (s_ViewTreeIcons) - { - free(s_ViewTreeIcons); - s_ViewTreeIcons = NULL; - } - s_ViewTreeIconCount = 0; - - // allocate now - PVIEWTREE_ICON pAllocated; - size_t Size = PREDEFINED_ICON_COUNT * sizeof(VIEWTREE_ICON); - pAllocated = (PVIEWTREE_ICON)calloc(1, Size); - if (pAllocated == NULL) - return NULL; // failure - - s_ViewTreeIconCount = PREDEFINED_ICON_COUNT; - s_ViewTreeIcons = pAllocated; - - // add the predefined icons - - HDC hDC = CreateCompatibleDC(NULL); - HBITMAP hbmMask = CreateCheckMask(hDC); - - HBITMAP hbmChecked, hbmUnchecked; - - hbmChecked = CreateCheckImage(hDC, TRUE); - ImageList_Add(hImageList, hbmChecked, hbmMask); - DeleteObject(hbmChecked); - - hbmUnchecked = CreateCheckImage(hDC, FALSE); - ImageList_Add(hImageList, hbmUnchecked, hbmMask); - DeleteObject(hbmUnchecked); - - hbmChecked = CreateCheckImage(hDC, TRUE, FALSE); - ImageList_Add(hImageList, hbmChecked, hbmMask); - DeleteObject(hbmChecked); - - hbmUnchecked = CreateCheckImage(hDC, FALSE, FALSE); - ImageList_Add(hImageList, hbmUnchecked, hbmMask); - DeleteObject(hbmUnchecked); - - DeleteObject(hbmMask); - hbmMask = CreateRadioMask(hDC); - - hbmChecked = CreateRadioImage(hDC, TRUE); - ImageList_Add(hImageList, hbmChecked, hbmMask); - DeleteObject(hbmChecked); - - hbmUnchecked = CreateRadioImage(hDC, FALSE); - ImageList_Add(hImageList, hbmUnchecked, hbmMask); - DeleteObject(hbmUnchecked); - - hbmChecked = CreateRadioImage(hDC, TRUE, FALSE); - ImageList_Add(hImageList, hbmChecked, hbmMask); - DeleteObject(hbmChecked); - - hbmUnchecked = CreateRadioImage(hDC, FALSE, FALSE); - ImageList_Add(hImageList, hbmUnchecked, hbmMask); - DeleteObject(hbmUnchecked); - - DeleteObject(hbmMask); - - return hImageList; } static BOOL ViewDlg_OnInitDialog(HWND hwndDlg, LPPROPSHEETPAGE psp) { - SetWindowLongPtr(hwndDlg, GWL_USERDATA, psp->lParam); + SetWindowLongPtr(hwndDlg, GWLP_USERDATA, psp->lParam); CFolderOptions *pFO = (CFolderOptions*)psp->lParam; if (!pFO || !pFO->CanSetDefFolderSettings()) @@ -630,76 +59,25 @@ ViewDlg_OnInitDialog(HWND hwndDlg, LPPROPSHEETPAGE psp) EnableWindow(GetDlgItem(hwndDlg, IDC_VIEW_APPLY_TO_ALL), FALSE); } - HWND hwndTreeView = GetDlgItem(hwndDlg, IDC_VIEW_TREEVIEW); + IRegTreeOptions *pRTO = NULL; + if (SUCCEEDED(SHCoCreateInstance(NULL, &CLSID_CRegTreeOptions, NULL, IID_PPV_ARG(IRegTreeOptions, &pRTO)))) + { + SetWindowLongPtr(hwndDlg, DWLP_USER, (LPARAM)pRTO); - s_hTreeImageList = ViewDlg_CreateTreeImageList(); - TreeView_SetImageList(hwndTreeView, s_hTreeImageList, TVSIL_NORMAL); + CHAR apath[MAX_PATH]; + SHUnicodeToAnsi(REGSTR_PATH_EXPLORER L"\\Advanced", apath, _countof(apath)); + HWND hwndTreeView = GetDlgItem(hwndDlg, IDC_VIEW_TREEVIEW); + pRTO->InitTree(hwndTreeView, HKEY_LOCAL_MACHINE, apath, NULL); + } - ViewTree_LoadAll(); - ViewTree_SortAll(); - ViewTree_InsertAll(hwndTreeView); - - return TRUE; // set focus + return TRUE; // Set focus } static BOOL ViewDlg_ToggleCheckItem(HWND hwndDlg, HTREEITEM hItem) { - HWND hwndTreeView = GetDlgItem(hwndDlg, IDC_VIEW_TREEVIEW); - - // get the item - TV_ITEM Item; - INT i; - ZeroMemory(&Item, sizeof(Item)); - Item.mask = TVIF_HANDLE | TVIF_IMAGE | TVIF_PARAM; - Item.hItem = hItem; - if (!TreeView_GetItem(hwndTreeView, &Item)) - return FALSE; // no such item - - VIEWTREE_ENTRY *pEntry = ViewTree_GetItem(Item.lParam); - if (pEntry == NULL) - return FALSE; // no such item - if (pEntry->bGrayed) - return FALSE; // disabled - - // toggle check mark - Item.mask = TVIF_HANDLE | TVIF_IMAGE | TVIF_SELECTEDIMAGE; - switch (pEntry->dwType) - { - case AETYPE_CHECKBOX: - pEntry->bChecked = !pEntry->bChecked; - break; - - case AETYPE_RADIO: - // reset all the entries of the same parent - for (i = 0; i < s_ViewTreeEntryCount; ++i) - { - VIEWTREE_ENTRY *pEntry2 = &s_ViewTreeEntries[i]; - if (pEntry->dwParentID == pEntry2->dwParentID) - { - pEntry2->bChecked = FALSE; - - Item.hItem = pEntry2->hItem; - INT iImage = ViewTree_GetImage(pEntry2); - Item.iImage = Item.iSelectedImage = iImage; - TreeView_SetItem(hwndTreeView, &Item); - } - } - pEntry->bChecked = TRUE; - break; - - default: - return FALSE; // failure - } - Item.iImage = Item.iSelectedImage = ViewTree_GetImage(pEntry); - Item.hItem = hItem; - TreeView_SetItem(hwndTreeView, &Item); - - // redraw the item - RECT rcItem; - TreeView_GetItemRect(hwndTreeView, hItem, &rcItem, FALSE); - InvalidateRect(hwndTreeView, &rcItem, TRUE); - return TRUE; // success + IRegTreeOptions *pRTO = GetRegTreeOptions(hwndDlg); + return pRTO && SUCCEEDED(pRTO->ToggleItem(hItem)); } static VOID @@ -711,17 +89,14 @@ ViewDlg_OnTreeViewClick(HWND hwndDlg) TV_HITTESTINFO HitTest; ZeroMemory(&HitTest, sizeof(HitTest)); DWORD dwPos = GetMessagePos(); - HitTest.pt.x = LOWORD(dwPos); - HitTest.pt.y = HIWORD(dwPos); + HitTest.pt.x = GET_X_LPARAM(dwPos); + HitTest.pt.y = GET_Y_LPARAM(dwPos); ScreenToClient(hwndTreeView, &HitTest.pt); HTREEITEM hItem = TreeView_HitTest(hwndTreeView, &HitTest); // toggle the check mark if possible if (ViewDlg_ToggleCheckItem(hwndDlg, hItem)) - { - // property sheet was changed PropSheet_Changed(GetParent(hwndDlg), hwndDlg); - } } static void @@ -731,12 +106,15 @@ ViewDlg_OnTreeViewKeyDown(HWND hwndDlg, TV_KEYDOWN *KeyDown) if (KeyDown->wVKey == VK_SPACE) { - // [Space] key was pressed HTREEITEM hItem = TreeView_GetSelection(hwndTreeView); if (ViewDlg_ToggleCheckItem(hwndDlg, hItem)) - { PropSheet_Changed(GetParent(hwndDlg), hwndDlg); - } + } + else if (KeyDown->wVKey == VK_F5) + { + IRegTreeOptions *pRTO = GetRegTreeOptions(hwndDlg); + if (pRTO) + pRTO->WalkTree(WALK_TREE_REFRESH); } } @@ -753,8 +131,7 @@ ViewDlg_OnTreeCustomDraw(HWND hwndDlg, NMTVCUSTOMDRAW *Draw) if (!(nmcd.uItemState & CDIS_SELECTED)) // not selected { LPARAM lParam = nmcd.lItemlParam; - VIEWTREE_ENTRY *pEntry = ViewTree_GetItem(lParam); - if (pEntry && pEntry->bGrayed) // disabled + if ((HKEY)lParam == HKEY_REGTREEOPTION_GRAYED) // disabled { // draw as grayed Draw->clrText = GetSysColor(COLOR_GRAYTEXT); @@ -773,89 +150,10 @@ ViewDlg_OnTreeCustomDraw(HWND hwndDlg, NMTVCUSTOMDRAW *Draw) static VOID ViewDlg_RestoreDefaults(HWND hwndDlg) { - HWND hwndTreeView = GetDlgItem(hwndDlg, IDC_VIEW_TREEVIEW); - - for (INT i = 0; i < s_ViewTreeEntryCount; ++i) + if (IRegTreeOptions *pRTO = GetRegTreeOptions(hwndDlg)) { - // ignore if the type is group - VIEWTREE_ENTRY *pEntry = &s_ViewTreeEntries[i]; - if (pEntry->dwType == AETYPE_GROUP) - continue; - - // set default value on registry - HKEY hKey; - if (RegOpenKeyExW(HKEY(pEntry->hkeyRoot), pEntry->szRegPath, - 0, KEY_WRITE, &hKey) != ERROR_SUCCESS) - { - continue; - } - RegSetValueExW(hKey, pEntry->szValueName, 0, REG_DWORD, - LPBYTE(&pEntry->dwDefaultValue), sizeof(DWORD)); - RegCloseKey(hKey); - - // update check status - pEntry->bChecked = (pEntry->dwCheckedValue == pEntry->dwDefaultValue); - - // update the image - TV_ITEM Item; - ZeroMemory(&Item, sizeof(Item)); - Item.mask = TVIF_HANDLE | TVIF_IMAGE | TVIF_SELECTEDIMAGE; - Item.hItem = pEntry->hItem; - Item.iImage = Item.iSelectedImage = ViewTree_GetImage(pEntry); - TreeView_SetItem(hwndTreeView, &Item); - } - - PropSheet_Changed(GetParent(hwndDlg), hwndDlg); -} - -static VOID -ScanAdvancedSettings(SHELLSTATE *pSS, DWORD *pdwMask) -{ - for (INT i = 0; i < s_ViewTreeEntryCount; ++i) - { - const VIEWTREE_ENTRY *pEntry = &s_ViewTreeEntries[i]; - if (pEntry->dwType == AETYPE_GROUP || pEntry->bGrayed) - continue; - - BOOL bChecked = pEntry->bChecked; - - // FIXME: Add more items - if (lstrcmpiW(pEntry->szKeyName, L"SuperHidden") == 0) - { - pSS->fShowSuperHidden = !bChecked ? 1 : 0; - *pdwMask |= SSF_SHOWSUPERHIDDEN; - continue; - } - if (lstrcmpiW(pEntry->szKeyName, L"DesktopProcess") == 0) - { - pSS->fSepProcess = bChecked ? 1 : 0; - *pdwMask |= SSF_SEPPROCESS; - continue; - } - if (lstrcmpiW(pEntry->szKeyName, L"SHOWALL") == 0) - { - pSS->fShowAllObjects = bChecked ? 1 : 0; - *pdwMask |= SSF_SHOWALLOBJECTS; - continue; - } - if (lstrcmpiW(pEntry->szKeyName, L"HideFileExt") == 0) - { - pSS->fShowExtensions = !bChecked ? 1 : 0; - *pdwMask |= SSF_SHOWEXTENSIONS; - continue; - } - if (lstrcmpiW(pEntry->szKeyName, L"ShowCompColor") == 0) - { - pSS->fShowCompColor = bChecked ? 1 : 0; - *pdwMask |= SSF_SHOWCOMPCOLOR; - continue; - } - if (lstrcmpiW(pEntry->szKeyName, L"ShowInfoTip") == 0) - { - pSS->fShowInfoTip = bChecked ? 1 : 0; - *pdwMask |= SSF_SHOWINFOTIP; - continue; - } + pRTO->WalkTree(WALK_TREE_DEFAULT); + PropSheet_Changed(GetParent(hwndDlg), hwndDlg); } } @@ -889,65 +187,19 @@ PostCabinetMessage(UINT Msg, WPARAM wParam, LPARAM lParam) static VOID ViewDlg_Apply(HWND hwndDlg) { - for (INT i = 0; i < s_ViewTreeEntryCount; ++i) - { - // ignore the entry if the type is group or the entry is grayed - VIEWTREE_ENTRY *pEntry = &s_ViewTreeEntries[i]; - if (pEntry->dwType == AETYPE_GROUP || pEntry->bGrayed) - continue; + IRegTreeOptions *pRTO = GetRegTreeOptions(hwndDlg); + if (!pRTO || FAILED(pRTO->WalkTree(WALK_TREE_SAVE))) + return; - // open the registry key - HKEY hkeyTarget; - if (RegOpenKeyExW(HKEY(pEntry->hkeyRoot), pEntry->szRegPath, 0, - KEY_WRITE, &hkeyTarget) != ERROR_SUCCESS) - { - continue; - } + SHSettingsChanged(0, 0); // Invalidate restrictions + SHGetSetSettings(NULL, 0, TRUE); // Invalidate SHELLSTATE - // checked or unchecked? - DWORD dwValue, dwSize; - if (pEntry->bChecked) - { - dwValue = pEntry->dwCheckedValue; - } - else - { - if (pEntry->bHasUncheckedValue) - { - dwValue = pEntry->dwUncheckedValue; - } - else - { - // there is no unchecked value - RegCloseKey(hkeyTarget); - continue; // ignore - } - } - - // set the value - dwSize = sizeof(dwValue); - RegSetValueExW(hkeyTarget, pEntry->szValueName, 0, REG_DWORD, - LPBYTE(&dwValue), dwSize); - - // close now - RegCloseKey(hkeyTarget); - } - - // scan advanced settings for user's settings - DWORD dwMask = 0; - SHELLSTATE ShellState; - ZeroMemory(&ShellState, sizeof(ShellState)); - ScanAdvancedSettings(&ShellState, &dwMask); - - // update user's settings - SHGetSetSettings(&ShellState, dwMask, TRUE); - - // invalidate cached restrictions - SHSettingsChanged(0, 0); - - // notify all - SHSendMessageBroadcastW(WM_WININICHANGE, 0, 0); + CABINETSTATE cs; + cs.cLength = sizeof(cs); + if (ReadCabinetState(&cs, sizeof(cs))) + WriteCabinetState(&cs); // Write the settings and invalidate global counter + SHSendMessageBroadcastW(WM_SETTINGCHANGE, 0, 0); PostCabinetMessage(WM_COMMAND, FCIDM_DESKBROWSER_REFRESH, 0); } @@ -960,13 +212,16 @@ FolderOptionsViewDlg( LPARAM lParam) { INT_PTR Result; - NMTVCUSTOMDRAW *Draw; switch (uMsg) { case WM_INITDIALOG: return ViewDlg_OnInitDialog(hwndDlg, (LPPROPSHEETPAGE)lParam); + case WM_DESTROY: + ViewDlg_OnDestroy(hwndDlg); + break; + case WM_COMMAND: switch (LOWORD(wParam)) { @@ -979,7 +234,7 @@ FolderOptionsViewDlg( { HRESULT hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); bool ResetToDefault = LOWORD(wParam) == IDC_VIEW_RESET_ALL; - CFolderOptions *pFO = (CFolderOptions*)GetWindowLongPtr(hwndDlg, GWL_USERDATA); + CFolderOptions *pFO = GetFolderOptions(hwndDlg); if (pFO) hr = pFO->ApplyDefFolderSettings(ResetToDefault); // Use IBrowserService2 if (ResetToDefault && hr == HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED)) @@ -999,8 +254,7 @@ FolderOptionsViewDlg( break; case NM_CUSTOMDRAW: // custom draw (for graying) - Draw = (NMTVCUSTOMDRAW *)lParam; - Result = ViewDlg_OnTreeCustomDraw(hwndDlg, Draw); + Result = ViewDlg_OnTreeCustomDraw(hwndDlg, (NMTVCUSTOMDRAW*)lParam); SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, Result); return Result; diff --git a/dll/win32/shlwapi/ordinal.c b/dll/win32/shlwapi/ordinal.c index 17223417254..72263f8efe4 100644 --- a/dll/win32/shlwapi/ordinal.c +++ b/dll/win32/shlwapi/ordinal.c @@ -6371,3 +6371,47 @@ DWORD WINAPI SHGetObjectCompatFlags(IUnknown *pUnk, const CLSID *clsid) return ret; } + +#ifdef __REACTOS__ +/************************************************************************** + * SHBoolSystemParametersInfo (SHLWAPI.537) + * + * Specialized SPI values from https://undoc.airesoft.co.uk/shlwapi.dll/SHBoolSystemParametersInfo.php + */ +EXTERN_C BOOL WINAPI SHBoolSystemParametersInfo(UINT uiAction, PVOID pvParam) +{ + BOOL retval; + PVOID pvOrgParam = pvParam; + UINT uiParam = 0; + ANIMATIONINFO animinfo; + + switch (uiAction) + { + case SPI_GETANIMATION: + case SPI_SETANIMATION: + uiParam = animinfo.cbSize = sizeof(animinfo); + animinfo.iMinAnimate = *(BOOL*)pvParam; /* SPI_SET */ + pvParam = &animinfo; + break; + case SPI_SETDRAGFULLWINDOWS: + case SPI_SETFONTSMOOTHING: + uiParam = *(BOOL*)pvParam; + break; + case SPI_GETDRAGFULLWINDOWS: + case SPI_GETFONTSMOOTHING: + /* pvParam already correct */ + break; + default: + if (uiAction < 0x1000) + return FALSE; + else if (uiAction & 1) /* SPI_SET */ + pvParam = (PVOID)(SIZE_T)(*(BOOL*)pvParam); + break; + } + + retval = SystemParametersInfoW(uiAction, uiParam, pvParam, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE); + if (uiAction == SPI_GETANIMATION) + *(BOOL*)pvOrgParam = animinfo.iMinAnimate; + return retval; +} +#endif diff --git a/dll/win32/shlwapi/shlwapi.spec b/dll/win32/shlwapi/shlwapi.spec index 6915d3fc099..209299fe389 100644 --- a/dll/win32/shlwapi/shlwapi.spec +++ b/dll/win32/shlwapi/shlwapi.spec @@ -534,7 +534,7 @@ 534 stdcall -noname SHPropertyBag_ReadBOOL(ptr wstr ptr) 535 stdcall -noname SHPropertyBag_Delete(ptr wstr) 536 stdcall -noname IUnknown_QueryServicePropertyBag(ptr long ptr ptr) -537 stub -noname SHBoolSystemParametersInfo +537 stdcall -noname SHBoolSystemParametersInfo(long ptr) 538 stdcall -noname IUnknown_QueryServiceForWebBrowserApp(ptr ptr ptr) 539 stub -noname IUnknown_ShowBrowserBar 540 stdcall -noname SHInvokeCommandOnContextMenu(ptr ptr ptr long str) diff --git a/sdk/include/reactos/shellutils.h b/sdk/include/reactos/shellutils.h index f4da9914bf8..ce7c3811208 100644 --- a/sdk/include/reactos/shellutils.h +++ b/sdk/include/reactos/shellutils.h @@ -622,6 +622,39 @@ struct CCoInitBase typedef CCoInitBase CCoInit; typedef CCoInitBase COleInit; +class CObjectWithSiteBase : + public IObjectWithSite +{ +public: + IUnknown* m_pUnkSite; + + CObjectWithSiteBase() : m_pUnkSite(NULL) {} + virtual ~CObjectWithSiteBase() { SetSite(NULL); } + + // IObjectWithSite + STDMETHODIMP SetSite(IUnknown *pUnkSite) override + { +#if defined(__WINE_SHLWAPI_H) && !defined(NO_SHLWAPI) + IUnknown_Set(&m_pUnkSite, pUnkSite); +#else + IUnknown *punkOrg = m_pUnkSite; + if (punkOrg) + punkOrg->Release(); + m_pUnkSite = pUnkSite; + if (pUnkSite) + pUnkSite->AddRef(); +#endif + return S_OK; + } + STDMETHODIMP GetSite(REFIID riid, void **ppvSite) override + { + *ppvSite = NULL; + return m_pUnkSite ? m_pUnkSite->QueryInterface(riid, ppvSite) : E_FAIL; + } +}; + + + #endif /* __cplusplus */ #define S_LESSTHAN 0xffff diff --git a/sdk/include/reactos/shlobj_undoc.h b/sdk/include/reactos/shlobj_undoc.h index a8928315b55..1da5b4c4bf8 100644 --- a/sdk/include/reactos/shlobj_undoc.h +++ b/sdk/include/reactos/shlobj_undoc.h @@ -453,12 +453,14 @@ DECLARE_INTERFACE_(IExplorerToolbar, IUnknown) */ typedef enum tagWALK_TREE_CMD { - WALK_TREE_OPTION0 = 0, - WALK_TREE_OPTION1 = 1, - WALK_TREE_OPTION2 = 2, - WALK_TREE_OPTION3 = 3 + WALK_TREE_SAVE = 0, + WALK_TREE_DESTROY = 1, + WALK_TREE_DEFAULT = 2, + WALK_TREE_REFRESH = 3 } WALK_TREE_CMD; +#define HKEY_REGTREEOPTION_GRAYED ( (HKEY)INVALID_HANDLE_VALUE ) /* ROS extension */ + #define INTERFACE IRegTreeOptions DECLARE_INTERFACE_(IRegTreeOptions, IUnknown) { @@ -467,10 +469,10 @@ DECLARE_INTERFACE_(IRegTreeOptions, IUnknown) STDMETHOD_(ULONG,AddRef)(THIS) PURE; STDMETHOD_(ULONG,Release)(THIS) PURE; /*** IRegTreeOptions ***/ - STDMETHOD(InitTree)(THIS_ HWND paramC, HKEY param10, char const *param14, char const *param18) PURE; - STDMETHOD(WalkTree)(THIS_ WALK_TREE_CMD paramC) PURE; - STDMETHOD(ToggleItem)(THIS_ HTREEITEM paramC) PURE; - STDMETHOD(ShowHelp)(THIS_ HTREEITEM paramC, unsigned long param10) PURE; + STDMETHOD(InitTree)(THIS_ HWND hTV, HKEY hKey, LPCSTR SubKey, char const *pUnknown) PURE; + STDMETHOD(WalkTree)(THIS_ WALK_TREE_CMD Command) PURE; + STDMETHOD(ToggleItem)(THIS_ HTREEITEM hTI) PURE; + STDMETHOD(ShowHelp)(THIS_ HTREEITEM hTI, unsigned long Unknown) PURE; }; #undef INTERFACE diff --git a/sdk/include/reactos/shlwapi_undoc.h b/sdk/include/reactos/shlwapi_undoc.h index be30b8311dc..94162ffc34f 100644 --- a/sdk/include/reactos/shlwapi_undoc.h +++ b/sdk/include/reactos/shlwapi_undoc.h @@ -115,6 +115,7 @@ HRESULT WINAPI IsQSForward(REFGUID pguidCmdGroup,ULONG cCmds, OLECMD *prgCmds); BOOL WINAPI SHIsChildOrSelf(HWND hParent, HWND hChild); HRESULT WINAPI SHForwardContextMenuMsg(IUnknown* pUnk, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* pResult, BOOL useIContextMenu2); VOID WINAPI SHSetDefaultDialogFont(HWND hWnd, INT id); +EXTERN_C BOOL WINAPI SHBoolSystemParametersInfo(UINT uiAction, PVOID pvParam); HRESULT WINAPI SHRegGetCLSIDKeyW(REFGUID guid, LPCWSTR lpszValue, BOOL bUseHKCU, BOOL bCreate, PHKEY phKey);