* Open With Context Menu extension
*
* Copyright 2007 Johannes Anderwald <johannes.anderwald@reactos.org>
+ * Copyright 2016-2017 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
WINE_DEFAULT_DEBUG_CHANNEL (fprop);
-#define MAX_PROPERTY_SHEET_PAGE (32)
-
/// Folder Options:
/// CLASSKEY = HKEY_CLASSES_ROOT\CLSID\{6DFD7C5C-2451-11d3-A299-00C04F8EF6AF}
/// DefaultIcon = %SystemRoot%\system32\SHELL32.dll,-210
WCHAR FileExtension[30];
WCHAR FileDescription[100];
WCHAR ClassKey[MAX_PATH];
+ DWORD EditFlags;
} FOLDER_FILE_TYPE_ENTRY, *PFOLDER_FILE_TYPE_ENTRY;
-typedef struct
+// uniquely-defined icon entry for Advanced Settings
+typedef struct ADVANCED_ICON
{
- LPCWSTR szKeyName;
- UINT ResourceID;
-} FOLDER_VIEW_ENTRY, PFOLDER_VIEW_ENTRY;
-/*
-static FOLDER_VIEW_ENTRY s_Options[] =
-{
- { L"AlwaysShowMenus", IDS_ALWAYSSHOWMENUS },
- { L"AutoCheckSelect", -1 },
- { L"ClassicViewState", -1 },
- { L"DontPrettyPath", -1 },
- { L"Filter", -1 },
- { L"FolderContentsInfoTip", IDS_FOLDERCONTENTSTIP },
- { L"FriendlyTree", -1 },
- { L"Hidden", -1, },
- { L"HideFileExt", IDS_HIDEFILEEXT },
- { L"HideIcons", -1},
- { L"IconsOnly", -1},
- { L"ListviewAlphaSelect", -1},
- { L"ListviewShadow", -1},
- { L"ListviewWatermark", -1},
- { L"MapNetDrvBtn", -1},
- { L"PersistBrowsers", -1},
- { L"SeperateProcess", IDS_SEPERATEPROCESS},
- { L"ServerAdminUI", -1},
- { L"SharingWizardOn", IDS_USESHAREWIZARD},
- { L"ShowCompColor", IDS_COMPCOLOR},
- { L"ShowInfoTip", IDS_SHOWINFOTIP},
- { L"ShowPreviewHandlers", -1},
- { L"ShowSuperHidden", IDS_HIDEOSFILES},
- { L"ShowTypeOverlay", -1},
- { L"Start_ShowMyGames", -1},
- { L"StartMenuInit", -1},
- { L"SuperHidden", -1},
- { L"TypeAhead", -1},
- { L"Webview", -1},
- { NULL, -1}
-
-};
-*/
+ WCHAR szPath[MAX_PATH];
+ UINT nIconIndex;
+} ADVANCED_ICON;
+
+// predefined icon IDs (See 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
+
+// definition of icon stock
+static ADVANCED_ICON * s_AdvancedIcons = NULL;
+static INT s_AdvancedIconCount = 0;
+static HIMAGELIST s_hImageList = NULL;
+
+static INT
+Advanced_FindIcon(LPCWSTR pszPath, UINT nIconIndex)
+{
+ for (INT i = PREDEFINED_ICON_COUNT; i < s_AdvancedIconCount; ++i)
+ {
+ ADVANCED_ICON *pIcon = &s_AdvancedIcons[i];
+ if (pIcon->nIconIndex == nIconIndex &&
+ lstrcmpiW(pIcon->szPath, pszPath) == 0)
+ {
+ return i; // icon ID
+ }
+ }
+ return -1; // not found
+}
+
+static INT
+Advanced_AddIcon(LPCWSTR pszPath, UINT nIconIndex)
+{
+ ADVANCED_ICON *pAllocated;
+
+ // return the ID if already existed
+ INT nIconID = Advanced_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_AdvancedIcons
+ size_t Size = (s_AdvancedIconCount + 1) * sizeof(ADVANCED_ICON);
+ pAllocated = (ADVANCED_ICON *)realloc(s_AdvancedIcons, Size);
+ if (pAllocated == NULL)
+ return -1; // failure
+ else
+ s_AdvancedIcons = pAllocated;
+
+ // save icon information
+ ADVANCED_ICON *pIcon = &s_AdvancedIcons[s_AdvancedIconCount];
+ lstrcpynW(pIcon->szPath, pszPath, _countof(pIcon->szPath));
+ pIcon->nIconIndex = nIconIndex;
+
+ // add the icon to the image list
+ ImageList_AddIcon(s_hImageList, hIconSmall);
+
+ // increment the counter
+ nIconID = s_AdvancedIconCount;
+ ++s_AdvancedIconCount;
+
+ DestroyIcon(hIconSmall);
+
+ return nIconID; // newly-added icon ID
+}
+
+// types of Advanced Setting entry
+typedef enum ADVANCED_ENTRY_TYPE
+{
+ AETYPE_GROUP,
+ AETYPE_CHECKBOX,
+ AETYPE_RADIO,
+} ADVANCED_ENTRY_TYPE;
+
+// an entry info of Advanced Settings
+typedef struct ADVANCED_ENTRY
+{
+ DWORD dwID; // entry ID
+ DWORD dwParentID; // parent entry ID
+ DWORD dwResourceID; // resource ID
+ WCHAR szKeyName[64]; // entry key name
+ DWORD dwType; // ADVANCED_ENTRY_TYPE
+ WCHAR szText[MAX_PATH]; // text
+ INT nIconID; // icon ID (See ADVANCED_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?
+} ADVANCED_ENTRY, *PADVANCED_ENTRY;
+
+// definition of advanced entries
+static ADVANCED_ENTRY * s_Advanced = NULL;
+static INT s_AdvancedCount = 0;
+
+static HBITMAP
+Create24BppBitmap(HDC hDC, INT cx, INT cy)
+{
+ BITMAPINFO bi;
+ LPVOID pvBits;
+
+ ZeroMemory(&bi, sizeof(bi));
+ bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ bi.bmiHeader.biWidth = cx;
+ bi.bmiHeader.biHeight = cy;
+ bi.bmiHeader.biPlanes = 1;
+ bi.bmiHeader.biBitCount = 24;
+ bi.bmiHeader.biCompression = BI_RGB;
+
+ HBITMAP hbm = CreateDIBSection(hDC, &bi, DIB_RGB_COLORS, &pvBits, NULL, 0);
+ return hbm;
+}
+
+static HBITMAP
+CreateCheckImage(HDC hDC, BOOL bCheck, BOOL bEnabled = TRUE)
+{
+ 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
+}
+
+static 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
+}
+
+static HBITMAP
+CreateRadioImage(HDC hDC, BOOL bCheck, BOOL bEnabled = TRUE)
+{
+ 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
+}
+
+static 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
+}
+
+static HIMAGELIST
+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_AdvancedIcons)
+ {
+ free(s_AdvancedIcons);
+ s_AdvancedIcons = NULL;
+ }
+ s_AdvancedIconCount = 0;
+
+ // allocate now
+ ADVANCED_ICON *pAllocated;
+ size_t Size = PREDEFINED_ICON_COUNT * sizeof(ADVANCED_ICON);
+ pAllocated = (ADVANCED_ICON *)calloc(1, Size);
+ if (pAllocated == NULL)
+ return NULL; // failure
+
+ s_AdvancedIconCount = PREDEFINED_ICON_COUNT;
+ s_AdvancedIcons = 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 ADVANCED_ENTRY *
+Advanced_GetItem(DWORD dwID)
+{
+ if (dwID == DWORD(-1))
+ return NULL;
+
+ for (INT i = 0; i < s_AdvancedCount; ++i)
+ {
+ ADVANCED_ENTRY *pEntry = &s_Advanced[i];
+ if (pEntry->dwID == dwID)
+ return pEntry;
+ }
+ return NULL; // failure
+}
+
+static INT
+Advanced_GetImage(ADVANCED_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
+Advanced_InsertEntry(HWND hwndTreeView, ADVANCED_ENTRY *pEntry)
+{
+ ADVANCED_ENTRY *pParent = Advanced_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 = Advanced_GetImage(pEntry);
+ Insertion.item.iImage = Insertion.item.iSelectedImage = iImage;
+ Insertion.item.lParam = pEntry->dwID;
+ pEntry->hItem = TreeView_InsertItem(hwndTreeView, &Insertion);
+}
+
+static VOID
+Advanced_InsertAll(HWND hwndTreeView)
+{
+ TreeView_DeleteAllItems(hwndTreeView);
+
+ // insert the entries
+ ADVANCED_ENTRY *pEntry;
+ for (INT i = 0; i < s_AdvancedCount; ++i)
+ {
+ pEntry = &s_Advanced[i];
+ Advanced_InsertEntry(hwndTreeView, pEntry);
+ }
+
+ // expand all
+ for (INT i = 0; i < s_AdvancedCount; ++i)
+ {
+ pEntry = &s_Advanced[i];
+ if (pEntry->dwType == AETYPE_GROUP)
+ {
+ TreeView_Expand(hwndTreeView, pEntry->hItem, TVE_EXPAND);
+ }
+ }
+}
+
+static BOOL
+Advanced_LoadTree(HKEY hKey, LPCWSTR pszKeyName, DWORD dwParentID)
+{
+ DWORD dwIndex;
+ WCHAR szKeyName[64], szText[MAX_PATH], *pch;
+ DWORD Size, Value;
+ ADVANCED_ENTRY *pAllocated;
+
+ // resize s_Advanced
+ Size = (s_AdvancedCount + 1) * sizeof(ADVANCED_ENTRY);
+ pAllocated = (ADVANCED_ENTRY *)realloc(s_Advanced, Size);
+ if (pAllocated == NULL)
+ return FALSE; // failure
+ else
+ s_Advanced = pAllocated;
+
+ ADVANCED_ENTRY *pEntry = &s_Advanced[s_AdvancedCount];
+
+ // dwID, dwParentID, szKeyName
+ pEntry->dwID = s_AdvancedCount;
+ 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 = Advanced_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
+ Value = DWORD(HKEY_CURRENT_USER);
+ Size = sizeof(Value);
+ RegQueryValueExW(hKey, L"HKeyRoot", NULL, NULL, LPBYTE(&Value), &Size);
+ pEntry->hkeyRoot = HKEY(Value);
+
+ // 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_AdvancedCount;
+
+ 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
+ }
+
+ Advanced_LoadTree(hkeyChild, szKeyName, dwParentID);
+ RegCloseKey(hkeyChild);
+
+ ++dwIndex;
+ }
+
+ return TRUE; // success
+}
+
+static BOOL
+Advanced_LoadAll(VOID)
+{
+ static const WCHAR s_szAdvanced[] =
+ L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced";
+
+ // free if already existed
+ if (s_Advanced)
+ {
+ free(s_Advanced);
+ s_Advanced = NULL;
+ }
+ s_AdvancedCount = 0;
+
+ HKEY hKey;
+ if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, s_szAdvanced, 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
+ }
+
+ Advanced_LoadTree(hkeyChild, szKeyName, DWORD(-1));
+ RegCloseKey(hkeyChild);
+
+ ++dwIndex;
+ }
+
+ RegCloseKey(hKey);
+
+ return TRUE; // success
+}
+
+static int
+Advanced_Compare(const void *x, const void *y)
+{
+ ADVANCED_ENTRY *pEntry1 = (ADVANCED_ENTRY *)x;
+ ADVANCED_ENTRY *pEntry2 = (ADVANCED_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;
+ ADVANCED_ENTRY *pArray1[MAX_DEPTH];
+ ADVANCED_ENTRY *pArray2[MAX_DEPTH];
+
+ // Make ancestor lists
+ for (i = m = n = 0; i < MAX_DEPTH; ++i)
+ {
+ ADVANCED_ENTRY *pParent1 = Advanced_GetItem(dwParentID1);
+ ADVANCED_ENTRY *pParent2 = Advanced_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
+Advanced_SortAll(VOID)
+{
+ qsort(s_Advanced, s_AdvancedCount, sizeof(ADVANCED_ENTRY), Advanced_Compare);
+}
EXTERN_C HPSXA WINAPI SHCreatePropSheetExtArrayEx(HKEY hKey, LPCWSTR pszSubKey, UINT max_iface, IDataObject *pDataObj);
-static
+static VOID
+UpdateGeneralIcons(HWND hDlg)
+{
+ HWND hwndTaskIcon, hwndFolderIcon, hwndClickIcon;
+ HICON hTaskIcon = NULL, hFolderIcon = NULL, hClickIcon = NULL;
+ LPTSTR lpTaskIconName = NULL, lpFolderIconName = NULL, lpClickIconName = NULL;
+
+ // show task setting icon
+ if(IsDlgButtonChecked(hDlg, IDC_FOLDER_OPTIONS_COMMONTASKS) == BST_CHECKED)
+ lpTaskIconName = MAKEINTRESOURCE(IDI_SHELL_SHOW_COMMON_TASKS);
+ else if(IsDlgButtonChecked(hDlg, IDC_FOLDER_OPTIONS_CLASSICFOLDERS) == BST_CHECKED)
+ lpTaskIconName = MAKEINTRESOURCE(IDI_SHELL_CLASSIC_FOLDERS);
+
+ if (lpTaskIconName)
+ {
+ hTaskIcon = (HICON)LoadImage(shell32_hInstance,
+ lpTaskIconName,
+ IMAGE_ICON,
+ 0,
+ 0,
+ LR_DEFAULTCOLOR);
+ if (hTaskIcon)
+ {
+ hwndTaskIcon = GetDlgItem(hDlg,
+ IDC_FOLDER_OPTIONS_TASKICON);
+ if (hwndTaskIcon)
+ {
+ SendMessage(hwndTaskIcon,
+ STM_SETIMAGE,
+ IMAGE_ICON,
+ (LPARAM)hTaskIcon);
+ }
+ }
+ }
+
+ // show Folder setting icons
+ if(IsDlgButtonChecked(hDlg, IDC_FOLDER_OPTIONS_SAMEWINDOW) == BST_CHECKED)
+ lpFolderIconName = MAKEINTRESOURCE(IDI_SHELL_OPEN_IN_SOME_WINDOW);
+ else if(IsDlgButtonChecked(hDlg, IDC_FOLDER_OPTIONS_OWNWINDOW) == BST_CHECKED)
+ lpFolderIconName = MAKEINTRESOURCE(IDI_SHELL_OPEN_IN_NEW_WINDOW);
+
+ if (lpFolderIconName)
+ {
+ hFolderIcon = (HICON)LoadImage(shell32_hInstance,
+ lpFolderIconName,
+ IMAGE_ICON,
+ 0,
+ 0,
+ LR_DEFAULTCOLOR);
+ if (hFolderIcon)
+ {
+ hwndFolderIcon = GetDlgItem(hDlg,
+ IDC_FOLDER_OPTIONS_FOLDERICON);
+ if (hwndFolderIcon)
+ {
+ SendMessage(hwndFolderIcon,
+ STM_SETIMAGE,
+ IMAGE_ICON,
+ (LPARAM)hFolderIcon);
+ }
+ }
+ }
+
+ // Show click setting icon
+ if(IsDlgButtonChecked(hDlg, IDC_FOLDER_OPTIONS_SINGLECLICK) == BST_CHECKED)
+ lpClickIconName = MAKEINTRESOURCE(IDI_SHELL_SINGLE_CLICK_TO_OPEN);
+ else if(IsDlgButtonChecked(hDlg, IDC_FOLDER_OPTIONS_DOUBLECLICK) == BST_CHECKED)
+ lpClickIconName = MAKEINTRESOURCE(IDI_SHELL_DOUBLE_CLICK_TO_OPEN);
+
+ if (lpClickIconName)
+ {
+ hClickIcon = (HICON)LoadImage(shell32_hInstance,
+ lpClickIconName,
+ IMAGE_ICON,
+ 0,
+ 0,
+ LR_DEFAULTCOLOR);
+ if (hClickIcon)
+ {
+ hwndClickIcon = GetDlgItem(hDlg,
+ IDC_FOLDER_OPTIONS_CLICKICON);
+ if (hwndClickIcon)
+ {
+ SendMessage(hwndClickIcon,
+ STM_SETIMAGE,
+ IMAGE_ICON,
+ (LPARAM)hClickIcon);
+ }
+ }
+ }
+
+ // Clean up
+ if(hTaskIcon)
+ DeleteObject(hTaskIcon);
+ if(hFolderIcon)
+ DeleteObject(hFolderIcon);
+ if(hClickIcon)
+ DeleteObject(hClickIcon);
+
+ return;
+}
+
INT_PTR
CALLBACK
FolderOptionsGeneralDlg(
LPARAM lParam
)
{
+ switch(uMsg)
+ {
+ case WM_INITDIALOG:
+ // FIXME
+ break;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case IDC_FOLDER_OPTIONS_COMMONTASKS:
+ case IDC_FOLDER_OPTIONS_CLASSICFOLDERS:
+ case IDC_FOLDER_OPTIONS_SAMEWINDOW:
+ case IDC_FOLDER_OPTIONS_OWNWINDOW:
+ case IDC_FOLDER_OPTIONS_SINGLECLICK:
+ case IDC_FOLDER_OPTIONS_DOUBLECLICK:
+ if (HIWORD(wParam) == BN_CLICKED)
+ {
+ UpdateGeneralIcons(hwndDlg);
+
+ /* Enable the 'Apply' button */
+ PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
+ }
+ break;
+ }
+ break;
+
+ case WM_NOTIFY:
+ {
+ LPNMHDR pnmh = (LPNMHDR)lParam;
+
+ switch (pnmh->code)
+ {
+ case PSN_SETACTIVE:
+ break;
+
+ case PSN_APPLY:
+ break;
+ }
+ break;
+ }
+
+ case WM_DESTROY:
+ break;
+
+ default:
+ return FALSE;
+ }
return FALSE;
}
-static
-VOID
-InitializeFolderOptionsListCtrl(HWND hwndDlg)
+static BOOL
+ViewDlg_OnInitDialog(HWND hwndDlg)
{
- RECT clientRect;
- LVCOLUMNW col;
- WCHAR szName[50];
- HWND hDlgCtrl;
+ HWND hwndTreeView = GetDlgItem(hwndDlg, 14003);
- hDlgCtrl = GetDlgItem(hwndDlg, 14003);
+ s_hImageList = CreateTreeImageList();
+ TreeView_SetImageList(hwndTreeView, s_hImageList, TVSIL_NORMAL);
- if (!LoadStringW(shell32_hInstance, IDS_COLUMN_EXTENSION, szName, sizeof(szName) / sizeof(WCHAR)))
- szName[0] = 0;
- szName[(sizeof(szName)/sizeof(WCHAR))-1] = 0;
+ Advanced_LoadAll();
+ Advanced_SortAll();
+ Advanced_InsertAll(hwndTreeView);
- GetClientRect(hDlgCtrl, &clientRect);
- ZeroMemory(&col, sizeof(LV_COLUMN));
- col.mask = LVCF_SUBITEM | LVCF_WIDTH | LVCF_FMT;
- col.iSubItem = 0;
- col.pszText = szName;
- col.fmt = LVCFMT_LEFT;
- col.cx = (clientRect.right - clientRect.left) - GetSystemMetrics(SM_CXVSCROLL);
- (void)SendMessageW(hDlgCtrl, LVM_INSERTCOLUMN, 0, (LPARAM)&col);
+ return TRUE; // set focus
+}
+static BOOL
+ViewDlg_ToggleCheckItem(HWND hwndDlg, HTREEITEM hItem)
+{
+ HWND hwndTreeView = GetDlgItem(hwndDlg, 14003);
+
+ // 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
+
+ ADVANCED_ENTRY *pEntry = Advanced_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_AdvancedCount; ++i)
+ {
+ ADVANCED_ENTRY *pEntry2 = &s_Advanced[i];
+ if (pEntry->dwParentID == pEntry2->dwParentID)
+ {
+ pEntry2->bChecked = FALSE;
+ Item.hItem = pEntry2->hItem;
+ INT iImage = Advanced_GetImage(pEntry2);
+ Item.iImage = Item.iSelectedImage = iImage;
+ TreeView_SetItem(hwndTreeView, &Item);
+ }
+ }
+ pEntry->bChecked = TRUE;
+ break;
+ default:
+ return FALSE; // failure
+ }
+ Item.iImage = Item.iSelectedImage = Advanced_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
+}
+static VOID
+ViewDlg_OnTreeViewClick(HWND hwndDlg)
+{
+ HWND hwndTreeView = GetDlgItem(hwndDlg, 14003);
+
+ // do hit test to get the clicked item
+ TV_HITTESTINFO HitTest;
+ ZeroMemory(&HitTest, sizeof(HitTest));
+ DWORD dwPos = GetMessagePos();
+ HitTest.pt.x = LOWORD(dwPos);
+ HitTest.pt.y = HIWORD(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
-INT_PTR
-CALLBACK
+static void
+ViewDlg_OnTreeViewKeyDown(HWND hwndDlg, TV_KEYDOWN *KeyDown)
+{
+ HWND hwndTreeView = GetDlgItem(hwndDlg, 14003);
+
+ if (KeyDown->wVKey == VK_SPACE)
+ {
+ // [Space] key was pressed
+ HTREEITEM hItem = TreeView_GetSelection(hwndTreeView);
+ if (ViewDlg_ToggleCheckItem(hwndDlg, hItem))
+ {
+ PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
+ }
+ }
+}
+
+static INT_PTR
+ViewDlg_OnTreeCustomDraw(HWND hwndDlg, NMTVCUSTOMDRAW *Draw)
+{
+ NMCUSTOMDRAW& nmcd = Draw->nmcd;
+ switch (nmcd.dwDrawStage)
+ {
+ case CDDS_PREPAINT:
+ return CDRF_NOTIFYITEMDRAW; // for CDDS_ITEMPREPAINT
+
+ case CDDS_ITEMPREPAINT:
+ if (!(nmcd.uItemState & CDIS_SELECTED)) // not selected
+ {
+ LPARAM lParam = nmcd.lItemlParam;
+ ADVANCED_ENTRY *pEntry = Advanced_GetItem(lParam);
+ if (pEntry && pEntry->bGrayed) // disabled
+ {
+ // draw as grayed
+ Draw->clrText = GetSysColor(COLOR_GRAYTEXT);
+ Draw->clrTextBk = GetSysColor(COLOR_WINDOW);
+ return CDRF_NEWFONT;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ return CDRF_DODEFAULT;
+}
+
+static VOID
+Advanced_RestoreDefaults(HWND hwndDlg)
+{
+ HWND hwndTreeView = GetDlgItem(hwndDlg, 14003);
+
+ for (INT i = 0; i < s_AdvancedCount; ++i)
+ {
+ // ignore if the type is group
+ ADVANCED_ENTRY *pEntry = &s_Advanced[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 = Advanced_GetImage(pEntry);
+ TreeView_SetItem(hwndTreeView, &Item);
+ }
+
+ PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
+}
+
+/* FIXME: These macros should not be defined here */
+#ifndef SSF_SHOWSUPERHIDDEN
+ #define SSF_SHOWSUPERHIDDEN 0x00040000
+#endif
+#ifndef SSF_SEPPROCESS
+ #define SSF_SEPPROCESS 0x00080000
+#endif
+
+static VOID
+ScanAdvancedSettings(SHELLSTATE *pSS, DWORD *pdwMask)
+{
+ for (INT i = 0; i < s_AdvancedCount; ++i)
+ {
+ const ADVANCED_ENTRY *pEntry = &s_Advanced[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;
+ }
+ }
+}
+
+extern "C"
+VOID WINAPI SHGetSetSettings(LPSHELLSTATE lpss, DWORD dwMask, BOOL bSet);
+
+static BOOL CALLBACK RefreshBrowsersCallback (HWND hWnd, LPARAM msg)
+{
+ WCHAR ClassName[100];
+ if (GetClassName(hWnd, ClassName, 100))
+ {
+ if (!wcscmp(ClassName, L"Progman") ||
+ !wcscmp(ClassName, L"CabinetWClass") ||
+ !wcscmp(ClassName, L"ExploreWClass"))
+ {
+ PostMessage(hWnd, WM_COMMAND, FCIDM_DESKBROWSER_REFRESH, 0);
+ }
+ }
+ return TRUE;
+}
+
+static VOID
+ViewDlg_Apply(HWND hwndDlg)
+{
+ for (INT i = 0; i < s_AdvancedCount; ++i)
+ {
+ // ignore the entry if the type is group or the entry is grayed
+ ADVANCED_ENTRY *pEntry = &s_Advanced[i];
+ if (pEntry->dwType == AETYPE_GROUP || pEntry->bGrayed)
+ continue;
+
+ // open the registry key
+ HKEY hkeyTarget;
+ if (RegOpenKeyExW(HKEY(pEntry->hkeyRoot), pEntry->szRegPath, 0,
+ KEY_WRITE, &hkeyTarget) != ERROR_SUCCESS)
+ {
+ continue;
+ }
+
+ // 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);
+
+ // notify all
+ SendMessage(HWND_BROADCAST, WM_WININICHANGE, 0, 0);
+
+ EnumWindows(RefreshBrowsersCallback, NULL);
+}
+
+INT_PTR CALLBACK
FolderOptionsViewDlg(
- HWND hwndDlg,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam
-)
+ HWND hwndDlg,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam)
{
+ INT_PTR Result;
+ NMTVCUSTOMDRAW *Draw;
+
switch(uMsg)
{
case WM_INITDIALOG:
- InitializeFolderOptionsListCtrl(hwndDlg);
- return TRUE;
+ return ViewDlg_OnInitDialog(hwndDlg);
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case 14004: // Restore Defaults
+ Advanced_RestoreDefaults(hwndDlg);
+ break;
+ }
+ break;
+ case WM_NOTIFY:
+ switch (LPNMHDR(lParam)->code)
+ {
+ case NM_CLICK: // clicked on treeview
+ ViewDlg_OnTreeViewClick(hwndDlg);
+ break;
+ case NM_CUSTOMDRAW: // custom draw (for graying)
+ Draw = (NMTVCUSTOMDRAW *)lParam;
+ Result = ViewDlg_OnTreeCustomDraw(hwndDlg, Draw);
+ SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, Result);
+ return Result;
+ case TVN_KEYDOWN: // key is down
+ ViewDlg_OnTreeViewKeyDown(hwndDlg, (TV_KEYDOWN *)lParam);
+ break;
+ case PSN_APPLY: // [Apply] is clicked
+ ViewDlg_Apply(hwndDlg);
+ break;
+ default:
+ break;
+ }
+ break;
}
return FALSE;
-
}
static
if (!LoadStringW(shell32_hInstance, IDS_FILE_TYPES, szName, sizeof(szName) / sizeof(WCHAR)))
{
/* default to english */
- wcscpy(szName, L"FileTypes");
+ wcscpy(szName, L"File Types");
+ ERR("Failed to load localized string!\n");
}
col.iSubItem = 1;
HKEY hKey;
LVITEMW lvItem;
DWORD dwSize;
+ DWORD dwType;
if (szName[0] != L'.')
{
RegQueryValueExW(hKey, NULL, NULL, NULL, (LPBYTE)Entry->FileDescription, &dwSize);
}
+ /* Read the EditFlags value */
+ Entry->EditFlags = 0;
+ if (!RegQueryValueExW(hKey, L"EditFlags", NULL, &dwType, NULL, &dwSize))
+ {
+ if ((dwType == REG_DWORD || dwType == REG_BINARY) && dwSize == sizeof(DWORD))
+ RegQueryValueExW(hKey, L"EditFlags", NULL, NULL, (LPBYTE)&Entry->EditFlags, &dwSize);
+ }
+
/* close key */
RegCloseKey(hKey);
+ /* Do not add excluded entries */
+ if (Entry->EditFlags & 0x00000001) //FTA_Exclude
+ {
+ HeapFree(GetProcessHeap(), 0, Entry);
+ return;
+ }
+
/* convert extension to upper case */
wcscpy(Entry->FileExtension, szName);
_wcsupr(Entry->FileExtension);
if (!Entry->FileDescription[0])
{
- /* construct default 'FileExtensionFile' */
- wcscpy(Entry->FileDescription, &Entry->FileExtension[1]);
- wcscat(Entry->FileDescription, L" ");
- wcscat(Entry->FileDescription, szFile);
+ /* construct default 'FileExtensionFile' by formatting the uppercase extension
+ with IDS_FILE_EXT_TYPE, outputting something like a l18n 'INI File' */
+
+ StringCchPrintf(Entry->FileDescription, _countof(Entry->FileDescription), szFile, &Entry->FileExtension[1]);
}
ZeroMemory(&lvItem, sizeof(LVITEMW));
lvItem.pszText = Entry->FileDescription;
lvItem.iItem = *iItem;
lvItem.iSubItem = 1;
+ ListView_SetItem(hDlgCtrl, &lvItem);
- (void)SendMessageW(hDlgCtrl, LVM_SETITEMW, 0, (LPARAM)&lvItem);
(*iItem)++;
}
ListViewCompareProc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
PFOLDER_FILE_TYPE_ENTRY Entry1, Entry2;
+ int x;
Entry1 = (PFOLDER_FILE_TYPE_ENTRY)lParam1;
Entry2 = (PFOLDER_FILE_TYPE_ENTRY)lParam2;
- return wcsicmp(Entry1->FileExtension, Entry2->FileExtension);
+ x = wcsicmp(Entry1->FileExtension, Entry2->FileExtension);
+ if (x != 0)
+ return x;
+
+ return wcsicmp(Entry1->FileDescription, Entry2->FileDescription);
}
static
-BOOL
+PFOLDER_FILE_TYPE_ENTRY
InitializeFileTypesListCtrl(HWND hwndDlg)
{
HWND hDlgCtrl;
InitializeFileTypesListCtrlColumns(hDlgCtrl);
szFile[0] = 0;
- if (!LoadStringW(shell32_hInstance, IDS_SHV_COLUMN1, szFile, sizeof(szFile) / sizeof(WCHAR)))
+ if (!LoadStringW(shell32_hInstance, IDS_FILE_EXT_TYPE, szFile, _countof(szFile)))
{
/* default to english */
- wcscpy(szFile, L"File");
+ wcscpy(szFile, L"%s File");
}
- szFile[(sizeof(szFile)/sizeof(WCHAR))-1] = 0;
+ szFile[(_countof(szFile)) - 1] = 0;
- dwName = sizeof(szName) / sizeof(WCHAR);
+ dwName = _countof(szName);
- while(RegEnumKeyExW(HKEY_CLASSES_ROOT, dwIndex++, szName, &dwName, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
+ while (RegEnumKeyExW(HKEY_CLASSES_ROOT, dwIndex++, szName, &dwName, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
{
InsertFileType(hDlgCtrl, szName, &iItem, szFile);
- dwName = sizeof(szName) / sizeof(WCHAR);
+ dwName = _countof(szName);
}
+ /* Leave if the list is empty */
+ if (iItem == 0)
+ return NULL;
+
/* sort list */
ListView_SortItems(hDlgCtrl, ListViewCompareProc, NULL);
/* select first item */
ZeroMemory(&lvItem, sizeof(LVITEMW));
lvItem.mask = LVIF_STATE;
- lvItem.stateMask = (UINT) - 1;
+ lvItem.stateMask = (UINT)-1;
lvItem.state = LVIS_FOCUSED | LVIS_SELECTED;
lvItem.iItem = 0;
- (void)SendMessageW(hDlgCtrl, LVM_SETITEMW, 0, (LPARAM)&lvItem);
+ ListView_SetItem(hDlgCtrl, &lvItem);
- return TRUE;
+ lvItem.mask = LVIF_PARAM;
+ ListView_GetItem(hDlgCtrl, &lvItem);
+
+ return (PFOLDER_FILE_TYPE_ENTRY)lvItem.lParam;
}
static
return NULL;
}
-static
INT_PTR
CALLBACK
FolderOptionsFileTypesDlg(
HWND hwndDlg,
UINT uMsg,
WPARAM wParam,
- LPARAM lParam
-)
+ LPARAM lParam)
{
LPNMLISTVIEW lppl;
LVITEMW lvItem;
switch(uMsg)
{
case WM_INITDIALOG:
- InitializeFileTypesListCtrl(hwndDlg);
+ pItem = InitializeFileTypesListCtrl(hwndDlg);
+
+ /* Disable the Delete button if the listview is empty or
+ the selected item should not be deleted by the user */
+ if (pItem == NULL || (pItem->EditFlags & 0x00000010)) // FTA_NoRemove
+ EnableWindow(GetDlgItem(hwndDlg, 14002), FALSE);
return TRUE;
+
case WM_COMMAND:
switch(LOWORD(wParam))
{
}
break;
}
-
break;
+
case WM_NOTIFY:
lppl = (LPNMLISTVIEW) lParam;
swprintf(Buffer, FormatBuffer, &pItem->FileExtension[1], &pItem->FileDescription[0], &pItem->FileDescription[0]);
/* update dialog */
SetDlgItemTextW(hwndDlg, 14007, Buffer);
+
+ /* Enable the Delete button */
+ if (pItem->EditFlags & 0x00000010) // FTA_NoRemove
+ EnableWindow(GetDlgItem(hwndDlg, 14002), FALSE);
+ else
+ EnableWindow(GetDlgItem(hwndDlg, 14002), TRUE);
}
}
+ else if (lppl->hdr.code == PSN_SETACTIVE)
+ {
+ /* On page activation, set the focus to the listview */
+ SetFocus(GetDlgItem(hwndDlg, 14000));
+ }
break;
}