https://git.reactos.org/?p=reactos.git;a=commitdiff;h=698cbc6184722f29389ccd...
commit 698cbc6184722f29389ccd75ca96d88d6cd4b010 Author: Katayama Hirofumi MZ katayama.hirofumi.mz@gmail.com AuthorDate: Wed Jun 6 21:04:50 2018 +0900 Commit: Hermès BÉLUSCA - MAÏTO hermes.belusca-maito@reactos.org CommitDate: Wed Jun 6 14:04:50 2018 +0200
[SHELL32] Split dialogs/folder_options.cpp (#582)
The dialogs/folder_options.cpp source file in shell32 is too big to manage. We will split it to smaller files. CORE-12906 --- dll/win32/shell32/CMakeLists.txt | 5 +- dll/win32/shell32/dialogs/filetypes.cpp | 1778 ++++++++++++++++ dll/win32/shell32/dialogs/folder_options.cpp | 2934 +------------------------- dll/win32/shell32/dialogs/folder_options.h | 55 + dll/win32/shell32/dialogs/general.cpp | 147 ++ dll/win32/shell32/dialogs/view.cpp | 985 +++++++++ dll/win32/shell32/lang/bg-BG.rc | 8 +- dll/win32/shell32/lang/ca-ES.rc | 8 +- dll/win32/shell32/lang/cs-CZ.rc | 8 +- dll/win32/shell32/lang/da-DK.rc | 8 +- dll/win32/shell32/lang/de-DE.rc | 8 +- dll/win32/shell32/lang/el-GR.rc | 8 +- dll/win32/shell32/lang/en-GB.rc | 8 +- dll/win32/shell32/lang/en-US.rc | 8 +- dll/win32/shell32/lang/es-ES.rc | 8 +- dll/win32/shell32/lang/et-EE.rc | 8 +- dll/win32/shell32/lang/fi-FI.rc | 8 +- dll/win32/shell32/lang/fr-FR.rc | 8 +- dll/win32/shell32/lang/he-IL.rc | 8 +- dll/win32/shell32/lang/hu-HU.rc | 8 +- dll/win32/shell32/lang/it-IT.rc | 8 +- dll/win32/shell32/lang/ja-JP.rc | 8 +- dll/win32/shell32/lang/ko-KR.rc | 8 +- dll/win32/shell32/lang/nl-NL.rc | 8 +- dll/win32/shell32/lang/no-NO.rc | 8 +- dll/win32/shell32/lang/pl-PL.rc | 8 +- dll/win32/shell32/lang/pt-BR.rc | 8 +- dll/win32/shell32/lang/pt-PT.rc | 8 +- dll/win32/shell32/lang/ro-RO.rc | 8 +- dll/win32/shell32/lang/ru-RU.rc | 8 +- dll/win32/shell32/lang/sk-SK.rc | 8 +- dll/win32/shell32/lang/sl-SI.rc | 10 +- dll/win32/shell32/lang/sq-AL.rc | 8 +- dll/win32/shell32/lang/sv-SE.rc | 8 +- dll/win32/shell32/lang/tr-TR.rc | 8 +- dll/win32/shell32/lang/uk-UA.rc | 8 +- dll/win32/shell32/lang/zh-CN.rc | 8 +- dll/win32/shell32/lang/zh-TW.rc | 8 +- dll/win32/shell32/precomp.h | 1 + dll/win32/shell32/shresdef.h | 6 + sdk/include/psdk/shlobj.h | 4 + 41 files changed, 3158 insertions(+), 3015 deletions(-)
diff --git a/dll/win32/shell32/CMakeLists.txt b/dll/win32/shell32/CMakeLists.txt index 76ebf226e3..65d5f0e3b8 100644 --- a/dll/win32/shell32/CMakeLists.txt +++ b/dll/win32/shell32/CMakeLists.txt @@ -31,10 +31,13 @@ list(APPEND SOURCE dialogs/dialogs.cpp dialogs/drive.cpp dialogs/drvdefext.cpp - dialogs/folder_options.cpp dialogs/filedefext.cpp + dialogs/filetypes.cpp + dialogs/folder_options.cpp dialogs/fprop.cpp + dialogs/general.cpp dialogs/recycler_prop.cpp + dialogs/view.cpp CDropTargetHelper.cpp CEnumIDListBase.cpp CExtractIcon.cpp diff --git a/dll/win32/shell32/dialogs/filetypes.cpp b/dll/win32/shell32/dialogs/filetypes.cpp new file mode 100644 index 0000000000..8c00df723e --- /dev/null +++ b/dll/win32/shell32/dialogs/filetypes.cpp @@ -0,0 +1,1778 @@ +/* + * 'File Types' tab property sheet of Folder Options + * + * Copyright 2007 Johannes Anderwald johannes.anderwald@reactos.org + * Copyright 2016-2018 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 + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "precomp.h" + +WINE_DEFAULT_DEBUG_CHANNEL (fprop); + +// DefaultIcon = %SystemRoot%\system32\SHELL32.dll,-210 +// Verbs: Open / RunAs +// Cmd: rundll32.exe shell32.dll,Options_RunDLL 0 + +///////////////////////////////////////////////////////////////////////////// + +typedef struct FILE_TYPE_ENTRY +{ + WCHAR FileExtension[30]; + WCHAR FileDescription[100]; + WCHAR ClassKey[MAX_PATH]; + WCHAR ClassName[64]; + DWORD EditFlags; + WCHAR AppName[64]; + HICON hIconLarge; + HICON hIconSmall; + WCHAR ProgramPath[MAX_PATH]; + WCHAR IconPath[MAX_PATH]; + INT nIconIndex; +} FILE_TYPE_ENTRY, *PFILE_TYPE_ENTRY; + +static BOOL +DeleteExt(HWND hwndDlg, LPCWSTR pszExt) +{ + if (*pszExt != L'.') + return FALSE; + + // open ".ext" key + HKEY hKey; + if (RegOpenKeyExW(HKEY_CLASSES_ROOT, pszExt, 0, KEY_READ, &hKey) != ERROR_SUCCESS) + return FALSE; + + // query "extfile" key name + WCHAR szValue[64] = { 0 }; + DWORD cbValue = sizeof(szValue); + RegQueryValueExW(hKey, NULL, NULL, NULL, LPBYTE(szValue), &cbValue); + RegCloseKey(hKey); + + // delete "extfile" key (if any) + if (szValue[0]) + SHDeleteKeyW(HKEY_CLASSES_ROOT, szValue); + + // delete ".ext" key + return SHDeleteKeyW(HKEY_CLASSES_ROOT, pszExt) == ERROR_SUCCESS; +} + +static inline HICON +DoExtractIcon(PFILE_TYPE_ENTRY Entry, LPCWSTR IconPath, + INT iIndex = 0, BOOL bSmall = FALSE) +{ + HICON hIcon = NULL; + + if (iIndex < 0) + { + // A negative value will be interpreted as a negated resource ID. + iIndex = -iIndex; + + INT cx, cy; + HINSTANCE hDLL = LoadLibraryExW(IconPath, NULL, LOAD_LIBRARY_AS_DATAFILE); + if (bSmall) + { + cx = GetSystemMetrics(SM_CXSMICON); + cy = GetSystemMetrics(SM_CYSMICON); + } + else + { + cx = GetSystemMetrics(SM_CXICON); + cy = GetSystemMetrics(SM_CYICON); + } + hIcon = HICON(LoadImageW(hDLL, MAKEINTRESOURCEW(iIndex), IMAGE_ICON, + cx, cy, 0)); + FreeLibrary(hDLL); + } + else + { + // A positive value is icon index. + if (bSmall) + ExtractIconExW(IconPath, iIndex, NULL, &hIcon, 1); + else + ExtractIconExW(IconPath, iIndex, &hIcon, NULL, 1); + } + return hIcon; +} + +static void +DoFileTypeIconLocation(PFILE_TYPE_ENTRY Entry, LPCWSTR IconLocation) +{ + // Expand the REG_EXPAND_SZ string by environment variables + WCHAR szLocation[MAX_PATH + 32]; + if (!ExpandEnvironmentStringsW(IconLocation, szLocation, _countof(szLocation))) + return; + + Entry->nIconIndex = PathParseIconLocationW(szLocation); + StringCbCopyW(Entry->IconPath, sizeof(Entry->IconPath), szLocation); + Entry->hIconLarge = DoExtractIcon(Entry, szLocation, Entry->nIconIndex, FALSE); + Entry->hIconSmall = DoExtractIcon(Entry, szLocation, Entry->nIconIndex, TRUE); +} + +static BOOL +GetFileTypeIconsEx(PFILE_TYPE_ENTRY Entry, LPCWSTR IconLocation) +{ + Entry->hIconLarge = Entry->hIconSmall = NULL; + + if (lstrcmpiW(Entry->FileExtension, L".exe") == 0 || + lstrcmpiW(Entry->FileExtension, L".scr") == 0) + { + // It's an executable + Entry->hIconLarge = LoadIconW(shell32_hInstance, MAKEINTRESOURCEW(IDI_SHELL_EXE)); + INT cx = GetSystemMetrics(SM_CXSMICON); + INT cy = GetSystemMetrics(SM_CYSMICON); + Entry->hIconSmall = HICON(LoadImageW(shell32_hInstance, MAKEINTRESOURCEW(IDI_SHELL_EXE), + IMAGE_ICON, cx, cy, 0)); + StringCbCopyW(Entry->IconPath, sizeof(Entry->IconPath), g_pszShell32); + Entry->nIconIndex = -IDI_SHELL_EXE; + } + else if (lstrcmpW(IconLocation, L"%1") == 0) + { + return FALSE; // self icon + } + else + { + DoFileTypeIconLocation(Entry, IconLocation); + } + + return Entry->hIconLarge && Entry->hIconSmall; +} + +static BOOL +GetFileTypeIconsByKey(HKEY hKey, PFILE_TYPE_ENTRY Entry) +{ + Entry->hIconLarge = Entry->hIconSmall = NULL; + + // Open the "DefaultIcon" registry key + HKEY hDefIconKey; + LONG nResult = RegOpenKeyExW(hKey, L"DefaultIcon", 0, KEY_READ, &hDefIconKey); + if (nResult != ERROR_SUCCESS) + return FALSE; + + // Get the icon location + WCHAR szLocation[MAX_PATH + 32] = { 0 }; + DWORD dwSize = sizeof(szLocation); + nResult = RegQueryValueExW(hDefIconKey, NULL, NULL, NULL, LPBYTE(szLocation), &dwSize); + + RegCloseKey(hDefIconKey); + + if (nResult != ERROR_SUCCESS || szLocation[0] == 0) + return FALSE; + + return GetFileTypeIconsEx(Entry, szLocation); +} + +static BOOL +QueryFileDescription(LPCWSTR ProgramPath, LPWSTR pszName, INT cchName) +{ + SHFILEINFOW FileInfo = { 0 }; + if (SHGetFileInfoW(ProgramPath, 0, &FileInfo, sizeof(FileInfo), SHGFI_DISPLAYNAME)) + { + StringCchCopyW(pszName, cchName, FileInfo.szDisplayName); + return TRUE; + } + + return !!GetFileTitleW(ProgramPath, pszName, cchName); +} + +static void +SetFileTypeEntryDefaultIcon(PFILE_TYPE_ENTRY Entry) +{ + Entry->hIconLarge = LoadIconW(shell32_hInstance, MAKEINTRESOURCEW(IDI_SHELL_FOLDER_OPTIONS)); + INT cxSmall = GetSystemMetrics(SM_CXSMICON); + INT cySmall = GetSystemMetrics(SM_CYSMICON); + Entry->hIconSmall = HICON(LoadImageW(shell32_hInstance, MAKEINTRESOURCEW(IDI_SHELL_FOLDER_OPTIONS), + IMAGE_ICON, cxSmall, cySmall, 0)); + StringCbCopyW(Entry->IconPath, sizeof(Entry->IconPath), g_pszShell32); + Entry->nIconIndex = -IDI_SHELL_FOLDER_OPTIONS; +} + +///////////////////////////////////////////////////////////////////////////// +// EditTypeDlg + +#define LISTBOX_MARGIN 2 + +typedef struct EDITTYPE_DIALOG +{ + HWND hwndLV; + PFILE_TYPE_ENTRY pEntry; + CSimpleMap<CStringW, CStringW> CommandLineMap; + WCHAR szIconPath[MAX_PATH]; + INT nIconIndex; + WCHAR szDefaultVerb[64]; +} EDITTYPE_DIALOG, *PEDITTYPE_DIALOG; + +static void +EditTypeDlg_OnChangeIcon(HWND hwndDlg, PEDITTYPE_DIALOG pEditType) +{ + WCHAR szPath[MAX_PATH]; + INT IconIndex; + + ExpandEnvironmentStringsW(pEditType->szIconPath, szPath, _countof(szPath)); + IconIndex = pEditType->nIconIndex; + if (PickIconDlg(hwndDlg, szPath, _countof(szPath), &IconIndex)) + { + // replace Windows directory with "%SystemRoot%" (for portability) + WCHAR szWinDir[MAX_PATH]; + GetWindowsDirectoryW(szWinDir, _countof(szWinDir)); + if (wcsstr(szPath, szWinDir) == 0) + { + CStringW str(L"%SystemRoot%"); + str += &szPath[wcslen(szWinDir)]; + StringCbCopyW(szPath, sizeof(szPath), LPCWSTR(str)); + } + + // update FILE_TYPE_ENTRY + PFILE_TYPE_ENTRY pEntry = pEditType->pEntry; + DestroyIcon(pEntry->hIconLarge); + DestroyIcon(pEntry->hIconSmall); + pEntry->hIconLarge = DoExtractIcon(pEntry, szPath, IconIndex, FALSE); + pEntry->hIconSmall = DoExtractIcon(pEntry, szPath, IconIndex, TRUE); + + // update EDITTYPE_DIALOG + StringCbCopyW(pEditType->szIconPath, sizeof(pEditType->szIconPath), szPath); + pEditType->nIconIndex = IconIndex; + + // set icon to dialog + SendDlgItemMessageW(hwndDlg, IDC_EDITTYPE_ICON, STM_SETICON, (WPARAM)pEntry->hIconLarge, 0); + } +} + +static BOOL +EditTypeDlg_OnDrawItem(HWND hwndDlg, LPDRAWITEMSTRUCT pDraw, PEDITTYPE_DIALOG pEditType) +{ + WCHAR szText[64]; + HFONT hFont, hFont2; + + if (!pDraw) + return FALSE; + + // fill rect and set colors + if (pDraw->itemState & ODS_SELECTED) + { + FillRect(pDraw->hDC, &pDraw->rcItem, HBRUSH(COLOR_HIGHLIGHT + 1)); + SetTextColor(pDraw->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT)); + SetBkColor(pDraw->hDC, GetSysColor(COLOR_HIGHLIGHT)); + } + else + { + FillRect(pDraw->hDC, &pDraw->rcItem, HBRUSH(COLOR_WINDOW + 1)); + SetTextColor(pDraw->hDC, GetSysColor(COLOR_WINDOWTEXT)); + SetBkColor(pDraw->hDC, GetSysColor(COLOR_WINDOW)); + } + + // get listbox text + HWND hwndListBox = GetDlgItem(hwndDlg, IDC_EDITTYPE_LISTBOX); + SendMessageW(hwndListBox, LB_GETTEXT, pDraw->itemID, (LPARAM)szText); + + // is it default? + hFont = (HFONT)SendMessageW(hwndListBox, WM_GETFONT, 0, 0); + if (lstrcmpiW(pEditType->szDefaultVerb, szText) == 0) + { + // default. set bold + LOGFONTW lf; + GetObject(hFont, sizeof(lf), &lf); + lf.lfWeight = FW_BOLD; + hFont2 = CreateFontIndirectW(&lf); + if (hFont2) + { + HGDIOBJ hFontOld = SelectObject(pDraw->hDC, hFont2); + InflateRect(&pDraw->rcItem, -LISTBOX_MARGIN, -LISTBOX_MARGIN); + DrawTextW(pDraw->hDC, szText, -1, &pDraw->rcItem, + DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_NOPREFIX); + InflateRect(&pDraw->rcItem, LISTBOX_MARGIN, LISTBOX_MARGIN); + SelectObject(pDraw->hDC, hFontOld); + DeleteObject(hFont2); + } + } + else + { + // non-default + InflateRect(&pDraw->rcItem, -LISTBOX_MARGIN, -LISTBOX_MARGIN); + DrawTextW(pDraw->hDC, szText, -1, &pDraw->rcItem, + DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_NOPREFIX); + InflateRect(&pDraw->rcItem, LISTBOX_MARGIN, LISTBOX_MARGIN); + } + + // draw focus rect + if (pDraw->itemState & ODS_FOCUS) + { + DrawFocusRect(pDraw->hDC, &pDraw->rcItem); + } + return TRUE; +} + +static BOOL +EditTypeDlg_OnMeasureItem(HWND hwndDlg, LPMEASUREITEMSTRUCT pMeasure, PEDITTYPE_DIALOG pEditType) +{ + if (!pMeasure) + return FALSE; + + HWND hwndLB = GetDlgItem(hwndDlg, IDC_EDITTYPE_LISTBOX); + + HDC hDC = GetDC(hwndLB); + if (hDC) + { + TEXTMETRICW tm; + GetTextMetricsW(hDC, &tm); + pMeasure->itemHeight = tm.tmHeight + LISTBOX_MARGIN * 2; + ReleaseDC(hwndLB, hDC); + return TRUE; + } + return FALSE; +} + +///////////////////////////////////////////////////////////////////////////// +// NewExtDlg + +typedef struct NEWEXT_DIALOG +{ + HWND hwndLV; + RECT rcDlg; + BOOL bAdvanced; + INT dy; + WCHAR szExt[16]; + WCHAR szFileType[64]; +} NEWEXT_DIALOG, *PNEWEXT_DIALOG; + +static VOID +NewExtDlg_OnAdvanced(HWND hwndDlg, PNEWEXT_DIALOG pNewExt) +{ + // If "Advanced" button was clicked, then we shrink or expand the dialog. + RECT rc, rc1, rc2; + + GetWindowRect(hwndDlg, &rc); + rc.bottom = rc.top + (pNewExt->rcDlg.bottom - pNewExt->rcDlg.top); + + GetWindowRect(GetDlgItem(hwndDlg, IDOK), &rc1); + MapWindowPoints(NULL, hwndDlg, (LPPOINT)&rc1, 2); + + GetWindowRect(GetDlgItem(hwndDlg, IDCANCEL), &rc2); + MapWindowPoints(NULL, hwndDlg, (LPPOINT)&rc2, 2); + + if (pNewExt->bAdvanced) + { + rc1.top += pNewExt->dy; + rc1.bottom += pNewExt->dy; + + rc2.top += pNewExt->dy; + rc2.bottom += pNewExt->dy; + + ShowWindow(GetDlgItem(hwndDlg, IDC_NEWEXT_ASSOC), SW_SHOWNOACTIVATE); + ShowWindow(GetDlgItem(hwndDlg, IDC_NEWEXT_COMBOBOX), SW_SHOWNOACTIVATE); + + CStringW strLeft(MAKEINTRESOURCEW(IDS_NEWEXT_ADVANCED_LEFT)); + SetDlgItemTextW(hwndDlg, IDC_NEWEXT_ADVANCED, strLeft); + + SetFocus(GetDlgItem(hwndDlg, IDC_NEWEXT_COMBOBOX)); + } + else + { + rc1.top -= pNewExt->dy; + rc1.bottom -= pNewExt->dy; + + rc2.top -= pNewExt->dy; + rc2.bottom -= pNewExt->dy; + + ShowWindow(GetDlgItem(hwndDlg, IDC_NEWEXT_ASSOC), SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDC_NEWEXT_COMBOBOX), SW_HIDE); + + CStringW strRight(MAKEINTRESOURCEW(IDS_NEWEXT_ADVANCED_RIGHT)); + SetDlgItemTextW(hwndDlg, IDC_NEWEXT_ADVANCED, strRight); + + rc.bottom -= pNewExt->dy; + + CStringW strText(MAKEINTRESOURCEW(IDS_NEWEXT_NEW)); + SetDlgItemTextW(hwndDlg, IDC_NEWEXT_COMBOBOX, strText); + } + + HDWP hDWP = BeginDeferWindowPos(3); + + if (hDWP) + hDWP = DeferWindowPos(hDWP, GetDlgItem(hwndDlg, IDOK), NULL, + rc1.left, rc1.top, rc1.right - rc1.left, rc1.bottom - rc1.top, + SWP_NOACTIVATE | SWP_NOZORDER); + if (hDWP) + hDWP = DeferWindowPos(hDWP, GetDlgItem(hwndDlg, IDCANCEL), NULL, + rc2.left, rc2.top, rc2.right - rc2.left, rc2.bottom - rc2.top, + SWP_NOACTIVATE | SWP_NOZORDER); + if (hDWP) + hDWP = DeferWindowPos(hDWP, hwndDlg, NULL, + rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, + SWP_NOACTIVATE | SWP_NOZORDER); + + if (hDWP) + EndDeferWindowPos(hDWP); +} + +static BOOL +NewExtDlg_OnInitDialog(HWND hwndDlg, PNEWEXT_DIALOG pNewExt) +{ + pNewExt->bAdvanced = FALSE; + + // get window rectangle + GetWindowRect(hwndDlg, &pNewExt->rcDlg); + + // get delta Y + RECT rc1, rc2; + GetWindowRect(GetDlgItem(hwndDlg, IDC_NEWEXT_EDIT), &rc1); + GetWindowRect(GetDlgItem(hwndDlg, IDC_NEWEXT_COMBOBOX), &rc2); + pNewExt->dy = rc2.top - rc1.top; + + // initialize + CStringW strText(MAKEINTRESOURCEW(IDS_NEWEXT_NEW)); + SendDlgItemMessageW(hwndDlg, IDC_NEWEXT_COMBOBOX, CB_ADDSTRING, 0, (LPARAM)(LPCWSTR)strText); + SendDlgItemMessageW(hwndDlg, IDC_NEWEXT_COMBOBOX, CB_SETCURSEL, 0, 0); + SendDlgItemMessageW(hwndDlg, IDC_NEWEXT_EDIT, EM_SETLIMITTEXT, _countof(pNewExt->szExt) - 1, 0); + + // shrink it first time + NewExtDlg_OnAdvanced(hwndDlg, pNewExt); + + return TRUE; +} + +static BOOL +NewExtDlg_OnOK(HWND hwndDlg, PNEWEXT_DIALOG pNewExt) +{ + LV_FINDINFO find; + INT iItem; + + GetDlgItemTextW(hwndDlg, IDC_NEWEXT_EDIT, pNewExt->szExt, _countof(pNewExt->szExt)); + StrTrimW(pNewExt->szExt, g_pszSpace); + _wcsupr(pNewExt->szExt); + + GetDlgItemTextW(hwndDlg, IDC_NEWEXT_COMBOBOX, pNewExt->szFileType, _countof(pNewExt->szFileType)); + StrTrimW(pNewExt->szFileType, g_pszSpace); + + if (pNewExt->szExt[0] == 0) + { + CStringW strText(MAKEINTRESOURCEW(IDS_NEWEXT_SPECIFY_EXT)); + CStringW strTitle(MAKEINTRESOURCEW(IDS_FILE_TYPES)); + MessageBoxW(hwndDlg, strText, strTitle, MB_ICONERROR); + return FALSE; + } + + ZeroMemory(&find, sizeof(find)); + find.flags = LVFI_STRING; + if (pNewExt->szExt[0] == L'.') + { + find.psz = &pNewExt->szExt[1]; + } + else + { + find.psz = pNewExt->szExt; + } + + iItem = ListView_FindItem(pNewExt->hwndLV, -1, &find); + if (iItem >= 0) + { + // already exists + + // get file type + WCHAR szFileType[64]; + LV_ITEM item; + ZeroMemory(&item, sizeof(item)); + item.mask = LVIF_TEXT; + item.pszText = szFileType; + item.cchTextMax = _countof(szFileType); + item.iItem = iItem; + item.iSubItem = 1; + ListView_GetItem(pNewExt->hwndLV, &item); + + // get text + CStringW strText; + strText.Format(IDS_NEWEXT_ALREADY_ASSOC, find.psz, szFileType, find.psz, szFileType); + + // get title + CStringW strTitle; + strTitle.LoadString(IDS_NEWEXT_EXT_IN_USE); + + if (MessageBoxW(hwndDlg, strText, strTitle, MB_ICONWARNING | MB_YESNO) == IDNO) + { + return FALSE; + } + + // Delete the extension + CStringW strExt(L"."); + strExt += find.psz; + strExt.MakeLower(); + DeleteExt(hwndDlg, strExt); + + // Delete the item + ListView_DeleteItem(pNewExt->hwndLV, iItem); + } + + EndDialog(hwndDlg, IDOK); + return TRUE; +} + +// IDD_NEWEXTENSION +static INT_PTR CALLBACK +NewExtDlgProc( + HWND hwndDlg, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + static PNEWEXT_DIALOG s_pNewExt = NULL; + + switch (uMsg) + { + case WM_INITDIALOG: + s_pNewExt = (PNEWEXT_DIALOG)lParam; + NewExtDlg_OnInitDialog(hwndDlg, s_pNewExt); + return TRUE; + + case WM_COMMAND: + switch (LOWORD(wParam)) + { + case IDOK: + NewExtDlg_OnOK(hwndDlg, s_pNewExt); + break; + + case IDCANCEL: + EndDialog(hwndDlg, IDCANCEL); + break; + + case IDC_NEWEXT_ADVANCED: + s_pNewExt->bAdvanced = !s_pNewExt->bAdvanced; + NewExtDlg_OnAdvanced(hwndDlg, s_pNewExt); + break; + } + break; + } + return 0; +} + +static BOOL +FileTypesDlg_InsertToLV(HWND hListView, LPCWSTR szName, INT iItem, LPCWSTR szFile) +{ + PFILE_TYPE_ENTRY Entry; + HKEY hKey; + LVITEMW lvItem; + DWORD dwSize; + DWORD dwType; + + if (szName[0] != L'.') + { + // FIXME handle URL protocol handlers + return FALSE; + } + + // get imagelists of listview + HIMAGELIST himlLarge = ListView_GetImageList(hListView, LVSIL_NORMAL); + HIMAGELIST himlSmall = ListView_GetImageList(hListView, LVSIL_SMALL); + + // allocate file type entry + Entry = (PFILE_TYPE_ENTRY)HeapAlloc(GetProcessHeap(), 0, sizeof(FILE_TYPE_ENTRY)); + if (!Entry) + return FALSE; + + // open key + if (RegOpenKeyExW(HKEY_CLASSES_ROOT, szName, 0, KEY_READ, &hKey) != ERROR_SUCCESS) + { + HeapFree(GetProcessHeap(), 0, Entry); + return FALSE; + } + + // FIXME check for duplicates + + // query for the default key + dwSize = sizeof(Entry->ClassKey); + if (RegQueryValueExW(hKey, NULL, NULL, NULL, LPBYTE(Entry->ClassKey), &dwSize) != ERROR_SUCCESS) + { + // no link available + Entry->ClassKey[0] = 0; + } + + Entry->ClassName[0] = 0; + if (Entry->ClassKey[0]) + { + HKEY hTemp; + // try open linked key + if (RegOpenKeyExW(HKEY_CLASSES_ROOT, Entry->ClassKey, 0, KEY_READ, &hTemp) == ERROR_SUCCESS) + { + DWORD dwSize = sizeof(Entry->ClassName); + RegQueryValueExW(hTemp, NULL, NULL, NULL, LPBYTE(Entry->ClassName), &dwSize); + + // use linked key + RegCloseKey(hKey); + hKey = hTemp; + } + } + + // read friendly type name + if (RegLoadMUIStringW(hKey, L"FriendlyTypeName", Entry->FileDescription, + sizeof(Entry->FileDescription), NULL, 0, NULL) != ERROR_SUCCESS) + { + // read file description + dwSize = sizeof(Entry->FileDescription); + Entry->FileDescription[0] = 0; + + // read default key + 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); + } + + // convert extension to upper case + wcscpy(Entry->FileExtension, szName); + _wcsupr(Entry->FileExtension); + + // get icon + if (!GetFileTypeIconsByKey(hKey, Entry)) + { + // set default icon + SetFileTypeEntryDefaultIcon(Entry); + } + + // close key + RegCloseKey(hKey); + + // get program path and app name + DWORD cch = _countof(Entry->ProgramPath); + if (S_OK == AssocQueryStringW(ASSOCF_INIT_IGNOREUNKNOWN, ASSOCSTR_EXECUTABLE, + Entry->FileExtension, NULL, Entry->ProgramPath, &cch)) + { + QueryFileDescription(Entry->ProgramPath, Entry->AppName, _countof(Entry->AppName)); + } + else + { + Entry->ProgramPath[0] = Entry->AppName[0] = 0; + } + + // add icon to imagelist + INT iLargeImage = -1, iSmallImage = -1; + if (Entry->hIconLarge && Entry->hIconSmall) + { + iLargeImage = ImageList_AddIcon(himlLarge, Entry->hIconLarge); + iSmallImage = ImageList_AddIcon(himlSmall, Entry->hIconSmall); + ASSERT(iLargeImage == iSmallImage); + } + + // Do not add excluded entries + if (Entry->EditFlags & 0x00000001) //FTA_Exclude + { + DestroyIcon(Entry->hIconLarge); + DestroyIcon(Entry->hIconSmall); + HeapFree(GetProcessHeap(), 0, Entry); + return FALSE; + } + + if (!Entry->FileDescription[0]) + { + // construct default 'FileExtensionFile' by formatting the uppercase extension + // with IDS_FILE_EXT_TYPE, outputting something like a l18n 'INI File' + + StringCbPrintf(Entry->FileDescription, sizeof(Entry->FileDescription), szFile, &Entry->FileExtension[1]); + } + + ZeroMemory(&lvItem, sizeof(LVITEMW)); + lvItem.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE; + lvItem.iSubItem = 0; + lvItem.pszText = &Entry->FileExtension[1]; + lvItem.iItem = iItem; + lvItem.lParam = (LPARAM)Entry; + lvItem.iImage = iSmallImage; + SendMessageW(hListView, LVM_INSERTITEMW, 0, (LPARAM)&lvItem); + + ZeroMemory(&lvItem, sizeof(LVITEMW)); + lvItem.mask = LVIF_TEXT; + lvItem.pszText = Entry->FileDescription; + lvItem.iItem = iItem; + lvItem.iSubItem = 1; + ListView_SetItem(hListView, &lvItem); + + return TRUE; +} + +static BOOL +FileTypesDlg_AddExt(HWND hwndDlg, LPCWSTR pszExt, LPCWSTR pszFileType) +{ + DWORD dwValue = 1; + HKEY hKey; + WCHAR szKey[13]; // max. "ft4294967295" + "\0" + LONG nResult; + + // Search the next "ft%06u" key name + do + { + StringCbPrintfW(szKey, sizeof(szKey), L"ft%06u", dwValue); + + nResult = RegOpenKeyEx(HKEY_CLASSES_ROOT, szKey, 0, KEY_READ, &hKey); + if (nResult != ERROR_SUCCESS) + break; + + RegCloseKey(hKey); + ++dwValue; + } while (dwValue != 0); + + RegCloseKey(hKey); + + if (dwValue == 0) + return FALSE; + + // Create new "ft%06u" key + nResult = RegCreateKeyEx(HKEY_CLASSES_ROOT, szKey, 0, NULL, 0, KEY_WRITE, NULL, &hKey, NULL); + if (ERROR_SUCCESS != nResult) + return FALSE; + + RegCloseKey(hKey); + + // Create the ".ext" key + WCHAR szExt[16]; + if (*pszExt == L'.') + ++pszExt; + StringCbPrintfW(szExt, sizeof(szExt), L".%s", pszExt); + _wcslwr(szExt); + nResult = RegCreateKeyEx(HKEY_CLASSES_ROOT, szExt, 0, NULL, 0, KEY_WRITE, NULL, &hKey, NULL); + _wcsupr(szExt); + if (ERROR_SUCCESS != nResult) + return FALSE; + + // Set the default value of ".ext" to "ft%06u" + DWORD dwSize = (lstrlen(szKey) + 1) * sizeof(WCHAR); + RegSetValueExW(hKey, NULL, 0, REG_SZ, (LPBYTE)szKey, dwSize); + + RegCloseKey(hKey); + + // Make up the file type name + WCHAR szFile[100]; + CStringW strFormat(MAKEINTRESOURCEW(IDS_FILE_EXT_TYPE)); + StringCbPrintfW(szFile, sizeof(szFile), strFormat, &szExt[1]); + + // Insert an item to the listview + HWND hListView = GetDlgItem(hwndDlg, IDC_FILETYPES_LISTVIEW); + INT iItem = ListView_GetItemCount(hListView); + if (!FileTypesDlg_InsertToLV(hListView, szExt, iItem, szFile)) + return FALSE; + + LV_ITEM item; + ZeroMemory(&item, sizeof(item)); + item.mask = LVIF_STATE | LVIF_TEXT; + item.iItem = iItem; + item.state = LVIS_SELECTED | LVIS_FOCUSED; + item.stateMask = LVIS_SELECTED | LVIS_FOCUSED; + item.pszText = &szExt[1]; + ListView_SetItem(hListView, &item); + + item.pszText = szFile; + item.iSubItem = 1; + ListView_SetItem(hListView, &item); + + ListView_EnsureVisible(hListView, iItem, FALSE); + + return TRUE; +} + +static BOOL +FileTypesDlg_RemoveExt(HWND hwndDlg) +{ + HWND hListView = GetDlgItem(hwndDlg, IDC_FILETYPES_LISTVIEW); + + INT iItem = ListView_GetNextItem(hListView, -1, LVNI_SELECTED); + if (iItem == -1) + return FALSE; + + WCHAR szExt[20]; + szExt[0] = L'.'; + ListView_GetItemText(hListView, iItem, 0, &szExt[1], _countof(szExt) - 1); + _wcslwr(szExt); + + DeleteExt(hwndDlg, szExt); + ListView_DeleteItem(hListView, iItem); + return TRUE; +} + +///////////////////////////////////////////////////////////////////////////// +// common code of NewActionDlg and EditActionDlg + +typedef struct ACTION_DIALOG +{ + HWND hwndLB; + WCHAR ClassName[64]; + WCHAR szAction[64]; + WCHAR szApp[MAX_PATH]; + BOOL bUseDDE; +} ACTION_DIALOG, *PACTION_DIALOG; + +static void +ActionDlg_OnBrowse(HWND hwndDlg, PACTION_DIALOG pNewAct, BOOL bEdit = FALSE) +{ + WCHAR szFile[MAX_PATH]; + szFile[0] = 0; + + WCHAR szFilter[MAX_PATH]; + LoadStringW(shell32_hInstance, IDS_EXE_FILTER, szFilter, _countof(szFilter)); + + CStringW strTitle(MAKEINTRESOURCEW(IDS_OPEN_WITH)); + + OPENFILENAMEW ofn; + ZeroMemory(&ofn, sizeof(ofn)); + ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400W; + ofn.hwndOwner = hwndDlg; + ofn.lpstrFilter = szFilter; + ofn.lpstrFile = szFile; + ofn.nMaxFile = _countof(szFile); + ofn.lpstrTitle = strTitle; + ofn.Flags = OFN_ENABLESIZING | OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY; + ofn.lpstrDefExt = L"exe"; + if (GetOpenFileNameW(&ofn)) + { + if (bEdit) + { + CStringW str = szFile; + str += L" "%1""; + SetDlgItemTextW(hwndDlg, IDC_ACTION_APP, str); + } + else + { + SetDlgItemTextW(hwndDlg, IDC_ACTION_APP, szFile); + } + } +} + +///////////////////////////////////////////////////////////////////////////// +// NewActionDlg + +static void +NewActionDlg_OnOK(HWND hwndDlg, PACTION_DIALOG pNewAct) +{ + // check action + GetDlgItemTextW(hwndDlg, IDC_ACTION_ACTION, pNewAct->szAction, _countof(pNewAct->szAction)); + StrTrimW(pNewAct->szAction, g_pszSpace); + if (pNewAct->szAction[0] == 0) + { + // action was empty, error + HWND hwndCtrl = GetDlgItem(hwndDlg, IDC_ACTION_ACTION); + SendMessageW(hwndCtrl, EM_SETSEL, 0, -1); + SetFocus(hwndCtrl); + CStringW strText(MAKEINTRESOURCEW(IDS_SPECIFY_ACTION)); + CStringW strTitle(MAKEINTRESOURCEW(IDS_FILE_TYPES)); + MessageBoxW(hwndDlg, strText, strTitle, MB_ICONERROR); + return; + } + + // check app + GetDlgItemTextW(hwndDlg, IDC_ACTION_APP, pNewAct->szApp, _countof(pNewAct->szApp)); + StrTrimW(pNewAct->szApp, g_pszSpace); + if (pNewAct->szApp[0] == 0 || + GetFileAttributesW(pNewAct->szApp) == INVALID_FILE_ATTRIBUTES) + { + // app was empty or invalid + HWND hwndCtrl = GetDlgItem(hwndDlg, IDC_ACTION_APP); + SendMessageW(hwndCtrl, EM_SETSEL, 0, -1); + SetFocus(hwndCtrl); + CStringW strText(MAKEINTRESOURCEW(IDS_INVALID_PROGRAM)); + CStringW strTitle(MAKEINTRESOURCEW(IDS_FILE_TYPES)); + MessageBoxW(hwndDlg, strText, strTitle, MB_ICONERROR); + return; + } + + EndDialog(hwndDlg, IDOK); +} + +// IDD_ACTION +static INT_PTR CALLBACK +NewActionDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + static PACTION_DIALOG s_pNewAct = NULL; + + switch (uMsg) + { + case WM_INITDIALOG: + s_pNewAct = (PACTION_DIALOG)lParam; + s_pNewAct->bUseDDE = FALSE; + EnableWindow(GetDlgItem(hwndDlg, IDC_ACTION_USE_DDE), FALSE); + return TRUE; + + case WM_COMMAND: + switch (LOWORD(wParam)) + { + case IDOK: + NewActionDlg_OnOK(hwndDlg, s_pNewAct); + break; + + case IDCANCEL: + EndDialog(hwndDlg, IDCANCEL); + break; + + case IDC_ACTION_BROWSE: + ActionDlg_OnBrowse(hwndDlg, s_pNewAct, FALSE); + break; + } + break; + } + return 0; +} + +///////////////////////////////////////////////////////////////////////////// +// EditActionDlg + +static void +EditActionDlg_OnOK(HWND hwndDlg, PACTION_DIALOG pEditAct) +{ + // check action + GetDlgItemTextW(hwndDlg, IDC_ACTION_ACTION, pEditAct->szAction, _countof(pEditAct->szAction)); + StrTrimW(pEditAct->szAction, g_pszSpace); + if (pEditAct->szAction[0] == 0) + { + // action was empty. show error + HWND hwndCtrl = GetDlgItem(hwndDlg, IDC_ACTION_ACTION); + SendMessageW(hwndCtrl, EM_SETSEL, 0, -1); + SetFocus(hwndCtrl); + CStringW strText(MAKEINTRESOURCEW(IDS_SPECIFY_ACTION)); + CStringW strTitle(MAKEINTRESOURCEW(IDS_FILE_TYPES)); + MessageBoxW(hwndDlg, strText, strTitle, MB_ICONERROR); + } + + // check app + GetDlgItemTextW(hwndDlg, IDC_ACTION_APP, pEditAct->szApp, _countof(pEditAct->szApp)); + StrTrimW(pEditAct->szApp, g_pszSpace); + if (pEditAct->szApp[0] == 0) + { + // app was empty. show error + HWND hwndCtrl = GetDlgItem(hwndDlg, IDC_ACTION_APP); + SendMessageW(hwndCtrl, EM_SETSEL, 0, -1); + SetFocus(hwndCtrl); + CStringW strText(MAKEINTRESOURCEW(IDS_INVALID_PROGRAM)); + CStringW strTitle(MAKEINTRESOURCEW(IDS_FILE_TYPES)); + MessageBoxW(hwndDlg, strText, strTitle, MB_ICONERROR); + } + + EndDialog(hwndDlg, IDOK); +} + +// IDD_ACTION +static INT_PTR CALLBACK +EditActionDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + static PACTION_DIALOG s_pEditAct = NULL; + + switch (uMsg) + { + case WM_INITDIALOG: + s_pEditAct = (PACTION_DIALOG)lParam; + s_pEditAct->bUseDDE = FALSE; + SetDlgItemTextW(hwndDlg, IDC_ACTION_ACTION, s_pEditAct->szAction); + SetDlgItemTextW(hwndDlg, IDC_ACTION_APP, s_pEditAct->szApp); + EnableWindow(GetDlgItem(hwndDlg, IDC_ACTION_USE_DDE), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_ACTION_ACTION), FALSE); + { + // set title + CStringW str(MAKEINTRESOURCEW(IDS_EDITING_ACTION)); + str += s_pEditAct->ClassName; + SetWindowTextW(hwndDlg, str); + } + return TRUE; + + case WM_COMMAND: + switch (LOWORD(wParam)) + { + case IDOK: + EditActionDlg_OnOK(hwndDlg, s_pEditAct); + break; + + case IDCANCEL: + EndDialog(hwndDlg, IDCANCEL); + break; + + case IDC_ACTION_BROWSE: + ActionDlg_OnBrowse(hwndDlg, s_pEditAct, TRUE); + break; + } + break; + } + return 0; +} + +///////////////////////////////////////////////////////////////////////////// +// EditTypeDlg + +static BOOL +EditTypeDlg_UpdateEntryIcon(HWND hwndDlg, PEDITTYPE_DIALOG pEditType, + LPCWSTR IconPath, INT IconIndex) +{ + PFILE_TYPE_ENTRY pEntry = pEditType->pEntry; + + BOOL bIconSet = FALSE; + if (IconPath && IconPath[0]) + { + DestroyIcon(pEntry->hIconLarge); + DestroyIcon(pEntry->hIconSmall); + pEntry->hIconLarge = DoExtractIcon(pEntry, IconPath, IconIndex, FALSE); + pEntry->hIconSmall = DoExtractIcon(pEntry, IconPath, IconIndex, TRUE); + + bIconSet = (pEntry->hIconLarge && pEntry->hIconSmall); + } + if (bIconSet) + { + StringCbCopyW(pEntry->IconPath, sizeof(pEntry->IconPath), IconPath); + pEntry->nIconIndex = IconIndex; + } + else + { + SetFileTypeEntryDefaultIcon(pEntry); + } + + HWND hListView = pEditType->hwndLV; + HIMAGELIST himlLarge = ListView_GetImageList(hListView, LVSIL_NORMAL); + HIMAGELIST himlSmall = ListView_GetImageList(hListView, LVSIL_SMALL); + + INT iLargeImage = ImageList_AddIcon(himlLarge, pEntry->hIconLarge); + INT iSmallImage = ImageList_AddIcon(himlSmall, pEntry->hIconSmall); + ASSERT(iLargeImage == iSmallImage); + + INT iItem = ListView_GetNextItem(hListView, -1, LVNI_SELECTED); + if (iItem != -1) + { + LV_ITEMW Item = { LVIF_IMAGE, iItem }; + Item.iImage = iSmallImage; + ListView_SetItem(hListView, &Item); + } + return TRUE; +} + +static BOOL +EditTypeDlg_WriteClass(HWND hwndDlg, PEDITTYPE_DIALOG pEditType, + LPCWSTR ClassKey, LPCWSTR ClassName, INT cchName) +{ + PFILE_TYPE_ENTRY pEntry = pEditType->pEntry; + + if (ClassKey[0] == 0) + return FALSE; + + // create or open class key + HKEY hClassKey; + if (RegCreateKeyExW(HKEY_CLASSES_ROOT, ClassKey, 0, NULL, 0, KEY_WRITE, NULL, + &hClassKey, NULL) != ERROR_SUCCESS) + { + return FALSE; + } + + // create "DefaultIcon" key + if (pEntry->IconPath[0]) + { + HKEY hDefaultIconKey; + if (RegCreateKeyExW(hClassKey, L"DefaultIcon", 0, NULL, 0, KEY_WRITE, NULL, + &hDefaultIconKey, NULL) == ERROR_SUCCESS) + { + WCHAR szText[MAX_PATH]; + StringCbPrintfW(szText, sizeof(szText), L"%s,%d", + pEntry->IconPath, pEntry->nIconIndex); + + // set icon location + DWORD dwSize = (lstrlenW(szText) + 1) * sizeof(WCHAR); + RegSetValueExW(hDefaultIconKey, NULL, 0, REG_EXPAND_SZ, LPBYTE(szText), dwSize); + + RegCloseKey(hDefaultIconKey); + } + } + + // create "shell" key + HKEY hShellKey; + if (RegCreateKeyExW(hClassKey, L"shell", 0, NULL, 0, KEY_WRITE, NULL, + &hShellKey, NULL) != ERROR_SUCCESS) + { + RegCloseKey(hClassKey); + return FALSE; + } + + // delete shell commands + WCHAR szVerbName[64]; + DWORD dwIndex = 0; + while (RegEnumKeyW(hShellKey, dwIndex, szVerbName, _countof(szVerbName)) == ERROR_SUCCESS) + { + if (pEditType->CommandLineMap.FindKey(szVerbName) == -1) + { + // doesn't exist in CommandLineMap, then delete it + if (SHDeleteKeyW(hShellKey, szVerbName) == ERROR_SUCCESS) + { + --dwIndex; + } + } + ++dwIndex; + } + + // set default action + RegSetValueExW(hShellKey, NULL, 0, REG_SZ, + LPBYTE(pEditType->szDefaultVerb), sizeof(pEditType->szDefaultVerb)); + + // write shell commands + const INT nCount = pEditType->CommandLineMap.GetSize(); + for (INT i = 0; i < nCount; ++i) + { + CStringW& key = pEditType->CommandLineMap.GetKeyAt(i); + CStringW& value = pEditType->CommandLineMap.GetValueAt(i); + + // create verb key + HKEY hVerbKey; + if (RegCreateKeyExW(hShellKey, key, 0, NULL, 0, KEY_WRITE, NULL, + &hVerbKey, NULL) == ERROR_SUCCESS) + { + // create command key + HKEY hCommandKey; + if (RegCreateKeyExW(hVerbKey, L"command", 0, NULL, 0, KEY_WRITE, NULL, + &hCommandKey, NULL) == ERROR_SUCCESS) + { + // write the default value + DWORD dwSize = (value.GetLength() + 1) * sizeof(WCHAR); + RegSetValueExW(hCommandKey, NULL, 0, REG_EXPAND_SZ, LPBYTE(LPCWSTR(value)), dwSize); + + RegCloseKey(hCommandKey); + } + + RegCloseKey(hVerbKey); + } + } + + // set class name to class key + RegSetValueExW(hClassKey, NULL, 0, REG_SZ, LPBYTE(ClassName), cchName); + + RegCloseKey(hShellKey); + RegCloseKey(hClassKey); + + return TRUE; +} + +static BOOL +EditTypeDlg_ReadClass(HWND hwndDlg, PEDITTYPE_DIALOG pEditType, LPCWSTR ClassKey) +{ + // open class key + HKEY hClassKey; + if (RegOpenKeyExW(HKEY_CLASSES_ROOT, ClassKey, 0, KEY_READ, &hClassKey) != ERROR_SUCCESS) + return FALSE; + + // open "shell" key + HKEY hShellKey; + if (RegOpenKeyExW(hClassKey, L"shell", 0, KEY_READ, &hShellKey) != ERROR_SUCCESS) + { + RegCloseKey(hClassKey); + return FALSE; + } + + WCHAR DefaultVerb[64]; + DWORD dwSize = sizeof(DefaultVerb); + if (RegQueryValueExW(hShellKey, NULL, NULL, NULL, + LPBYTE(DefaultVerb), &dwSize) == ERROR_SUCCESS) + { + StringCbCopyW(pEditType->szDefaultVerb, sizeof(pEditType->szDefaultVerb), DefaultVerb); + } + else + { + StringCbCopyW(pEditType->szDefaultVerb, sizeof(pEditType->szDefaultVerb), L"open"); + } + + // enumerate shell verbs + WCHAR szVerbName[64]; + DWORD dwIndex = 0; + while (RegEnumKeyW(hShellKey, dwIndex, szVerbName, _countof(szVerbName)) == ERROR_SUCCESS) + { + // open verb key + HKEY hVerbKey; + LONG nResult = RegOpenKeyExW(hShellKey, szVerbName, 0, KEY_READ, &hVerbKey); + if (nResult == ERROR_SUCCESS) + { + // open command key + HKEY hCommandKey; + nResult = RegOpenKeyExW(hVerbKey, L"command", 0, KEY_READ, &hCommandKey); + if (nResult == ERROR_SUCCESS) + { + // get command line + WCHAR szValue[MAX_PATH + 32]; + dwSize = sizeof(szValue); + nResult = RegQueryValueExW(hCommandKey, NULL, NULL, NULL, LPBYTE(szValue), &dwSize); + if (nResult == ERROR_SUCCESS) + { + pEditType->CommandLineMap.SetAt(szVerbName, szValue); + } + + RegCloseKey(hCommandKey); + } + + RegCloseKey(hVerbKey); + } + SendDlgItemMessageW(hwndDlg, IDC_EDITTYPE_LISTBOX, LB_ADDSTRING, 0, LPARAM(szVerbName)); + ++dwIndex; + } + + RegCloseKey(hShellKey); + RegCloseKey(hClassKey); + + return TRUE; +} + +static void +EditTypeDlg_OnOK(HWND hwndDlg, PEDITTYPE_DIALOG pEditType) +{ + PFILE_TYPE_ENTRY pEntry = pEditType->pEntry; + + // get class name + GetDlgItemTextW(hwndDlg, IDC_EDITTYPE_TEXT, pEntry->ClassName, _countof(pEntry->ClassName)); + StrTrimW(pEntry->ClassName, g_pszSpace); + + // update entry icon + EditTypeDlg_UpdateEntryIcon(hwndDlg, pEditType, pEditType->szIconPath, pEditType->nIconIndex); + + // write registry + EditTypeDlg_WriteClass(hwndDlg, pEditType, pEntry->ClassKey, pEntry->ClassName, + _countof(pEntry->ClassName)); + + // update the icon cache + SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_FLUSHNOWAIT, NULL, NULL); + + EndDialog(hwndDlg, IDOK); +} + +static BOOL +EditTypeDlg_OnRemove(HWND hwndDlg, PEDITTYPE_DIALOG pEditType) +{ + // get current selection + INT iItem = SendDlgItemMessageW(hwndDlg, IDC_EDITTYPE_LISTBOX, LB_GETCURSEL, 0, 0); + if (iItem == LB_ERR) + return FALSE; + + // ask user for removal + CStringW strText(MAKEINTRESOURCEW(IDS_REMOVE_ACTION)); + CStringW strTitle(MAKEINTRESOURCEW(IDS_FILE_TYPES)); + if (MessageBoxW(hwndDlg, strText, strTitle, MB_ICONINFORMATION | MB_YESNO) == IDNO) + return FALSE; + + // get text + WCHAR szText[64]; + szText[0] = 0; + SendDlgItemMessageW(hwndDlg, IDC_EDITTYPE_LISTBOX, LB_GETTEXT, iItem, (LPARAM)szText); + StrTrimW(szText, g_pszSpace); + + // remove it + pEditType->CommandLineMap.Remove(szText); + SendDlgItemMessageW(hwndDlg, IDC_EDITTYPE_LISTBOX, LB_DELETESTRING, iItem, 0); + return TRUE; +} + +static void +EditTypeDlg_OnCommand(HWND hwndDlg, UINT id, UINT code, PEDITTYPE_DIALOG pEditType) +{ + INT iItem, iIndex; + ACTION_DIALOG action; + switch (id) + { + case IDOK: + EditTypeDlg_OnOK(hwndDlg, pEditType); + break; + + case IDCANCEL: + EndDialog(hwndDlg, IDCANCEL); + break; + + case IDC_EDITTYPE_CHANGE_ICON: + EditTypeDlg_OnChangeIcon(hwndDlg, pEditType); + break; + + case IDC_EDITTYPE_NEW: + action.bUseDDE = FALSE; + action.hwndLB = GetDlgItem(hwndDlg, IDC_EDITTYPE_LISTBOX); + StringCbPrintfW(action.ClassName, sizeof(action.ClassName), pEditType->pEntry->ClassName); + // open 'New Action' dialog + if (IDOK == DialogBoxParamW(shell32_hInstance, MAKEINTRESOURCEW(IDD_ACTION), hwndDlg, + NewActionDlgProc, LPARAM(&action))) + { + if (SendMessageW(action.hwndLB, LB_FINDSTRING, -1, (LPARAM)action.szAction) != LB_ERR) + { + // already exists, error + HWND hwndCtrl = GetDlgItem(hwndDlg, IDC_ACTION_ACTION); + SendMessageW(hwndCtrl, EM_SETSEL, 0, -1); + SetFocus(hwndCtrl); + + CStringW strText, strTitle(MAKEINTRESOURCEW(IDS_FILE_TYPES)); + strText.Format(IDS_ACTION_EXISTS, action.szAction); + MessageBoxW(hwndDlg, strText, strTitle, MB_ICONERROR); + } + else + { + // add it + CStringW strCommandLine = action.szApp; + strCommandLine += L" "%1""; + pEditType->CommandLineMap.SetAt(action.szAction, strCommandLine); + SendMessageW(action.hwndLB, LB_ADDSTRING, 0, LPARAM(action.szAction)); + if (SendMessageW(action.hwndLB, LB_GETCOUNT, 0, 0) == 1) + { + // set default + StringCbCopyW(pEditType->szDefaultVerb, sizeof(pEditType->szDefaultVerb), action.szAction); + InvalidateRect(action.hwndLB, NULL, TRUE); + } + } + } + break; + + case IDC_EDITTYPE_LISTBOX: + if (code == LBN_SELCHANGE) + { + action.hwndLB = GetDlgItem(hwndDlg, IDC_EDITTYPE_LISTBOX); + INT iItem = SendMessageW(action.hwndLB, LB_GETCURSEL, 0, 0); + SendMessageW(action.hwndLB, LB_GETTEXT, iItem, LPARAM(action.szAction)); + if (lstrcmpiW(action.szAction, pEditType->szDefaultVerb) == 0) + { + EnableWindow(GetDlgItem(hwndDlg, IDC_EDITTYPE_SET_DEFAULT), FALSE); + } + else + { + EnableWindow(GetDlgItem(hwndDlg, IDC_EDITTYPE_SET_DEFAULT), TRUE); + } + break; + } + else if (code != LBN_DBLCLK) + { + break; + } + // FALL THROUGH + + case IDC_EDITTYPE_EDIT_BUTTON: + action.bUseDDE = FALSE; + action.hwndLB = GetDlgItem(hwndDlg, IDC_EDITTYPE_LISTBOX); + StringCbPrintfW(action.ClassName, sizeof(action.ClassName), pEditType->pEntry->ClassName); + iItem = SendMessageW(action.hwndLB, LB_GETCURSEL, 0, 0); + if (iItem == LB_ERR) + break; + + // get action + SendMessageW(action.hwndLB, LB_GETTEXT, iItem, LPARAM(action.szAction)); + + // get app + { + iIndex = pEditType->CommandLineMap.FindKey(action.szAction); + CStringW str = pEditType->CommandLineMap.GetValueAt(iIndex); + StringCbCopyW(action.szApp, sizeof(action.szApp), LPCWSTR(str)); + } + + // open dialog + if (IDOK == DialogBoxParamW(shell32_hInstance, MAKEINTRESOURCEW(IDD_ACTION), hwndDlg, + EditActionDlgProc, LPARAM(&action))) + { + SendMessageW(action.hwndLB, LB_DELETESTRING, iItem, 0); + SendMessageW(action.hwndLB, LB_INSERTSTRING, iItem, LPARAM(action.szAction)); + pEditType->CommandLineMap.SetAt(action.szAction, action.szApp); + } + break; + + case IDC_EDITTYPE_REMOVE: + EditTypeDlg_OnRemove(hwndDlg, pEditType); + break; + + case IDC_EDITTYPE_SET_DEFAULT: + action.hwndLB = GetDlgItem(hwndDlg, IDC_EDITTYPE_LISTBOX); + iItem = SendMessageW(action.hwndLB, LB_GETCURSEL, 0, 0); + if (iItem == LB_ERR) + break; + + SendMessageW(action.hwndLB, LB_GETTEXT, iItem, LPARAM(action.szAction)); + + // set default + StringCbCopyW(pEditType->szDefaultVerb, sizeof(pEditType->szDefaultVerb), action.szAction); + EnableWindow(GetDlgItem(hwndDlg, IDC_EDITTYPE_SET_DEFAULT), FALSE); + InvalidateRect(action.hwndLB, NULL, TRUE); + break; + } +} + +static BOOL +EditTypeDlg_OnInitDialog(HWND hwndDlg, PEDITTYPE_DIALOG pEditType) +{ + PFILE_TYPE_ENTRY pEntry = pEditType->pEntry; + StringCbCopyW(pEditType->szIconPath, sizeof(pEditType->szIconPath), pEntry->IconPath); + pEditType->nIconIndex = pEntry->nIconIndex; + StringCbCopyW(pEditType->szDefaultVerb, sizeof(pEditType->szDefaultVerb), L"open"); + + // set info + SendDlgItemMessageW(hwndDlg, IDC_EDITTYPE_ICON, STM_SETICON, (WPARAM)pEntry->hIconLarge, 0); + SetDlgItemTextW(hwndDlg, IDC_EDITTYPE_TEXT, pEntry->ClassName); + EditTypeDlg_ReadClass(hwndDlg, pEditType, pEntry->ClassKey); + InvalidateRect(GetDlgItem(hwndDlg, IDC_EDITTYPE_LISTBOX), NULL, TRUE); + + // is listbox empty? + if (SendDlgItemMessageW(hwndDlg, IDC_EDITTYPE_LISTBOX, LB_GETCOUNT, 0, 0) == 0) + { + EnableWindow(GetDlgItem(hwndDlg, IDC_EDITTYPE_EDIT_BUTTON), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_EDITTYPE_REMOVE), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_EDITTYPE_SET_DEFAULT), FALSE); + } + else + { + // select first item + SendDlgItemMessageW(hwndDlg, IDC_EDITTYPE_LISTBOX, LB_SETCURSEL, 0, 0); + } + + EnableWindow(GetDlgItem(hwndDlg, IDC_EDITTYPE_SAME_WINDOW), FALSE); + + return TRUE; +} + +// IDD_EDITTYPE +static INT_PTR CALLBACK +EditTypeDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + static PEDITTYPE_DIALOG s_pEditType = NULL; + LPDRAWITEMSTRUCT pDraw; + LPMEASUREITEMSTRUCT pMeasure; + + switch (uMsg) + { + case WM_INITDIALOG: + s_pEditType = (PEDITTYPE_DIALOG)lParam; + return EditTypeDlg_OnInitDialog(hwndDlg, s_pEditType); + + case WM_DRAWITEM: + pDraw = LPDRAWITEMSTRUCT(lParam); + return EditTypeDlg_OnDrawItem(hwndDlg, pDraw, s_pEditType); + + case WM_MEASUREITEM: + pMeasure = LPMEASUREITEMSTRUCT(lParam); + return EditTypeDlg_OnMeasureItem(hwndDlg, pMeasure, s_pEditType); + + case WM_COMMAND: + EditTypeDlg_OnCommand(hwndDlg, LOWORD(wParam), HIWORD(wParam), s_pEditType); + break; + } + + return 0; +} + +///////////////////////////////////////////////////////////////////////////// +// FileTypesDlg + +static INT CALLBACK +FileTypesDlg_CompareItems(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) +{ + PFILE_TYPE_ENTRY Entry1, Entry2; + int x; + + Entry1 = (PFILE_TYPE_ENTRY)lParam1; + Entry2 = (PFILE_TYPE_ENTRY)lParam2; + + x = wcsicmp(Entry1->FileExtension, Entry2->FileExtension); + if (x != 0) + return x; + + return wcsicmp(Entry1->FileDescription, Entry2->FileDescription); +} + +static VOID +FileTypesDlg_InitListView(HWND hwndDlg, HWND hListView) +{ + RECT clientRect; + LVCOLUMNW col; + WCHAR szName[50]; + DWORD dwStyle; + INT columnSize = 140; + + if (!LoadStringW(shell32_hInstance, IDS_COLUMN_EXTENSION, szName, _countof(szName))) + { + // default to english + wcscpy(szName, L"Extensions"); + } + + // make sure its null terminated + szName[_countof(szName) - 1] = 0; + + GetClientRect(hListView, &clientRect); + ZeroMemory(&col, sizeof(LV_COLUMN)); + columnSize = 120; + col.iSubItem = 0; + col.mask = LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM | LVCF_FMT; + col.fmt = LVCFMT_FIXED_WIDTH; + col.cx = columnSize | LVCFMT_LEFT; + col.cchTextMax = wcslen(szName); + col.pszText = szName; + SendMessageW(hListView, LVM_INSERTCOLUMNW, 0, (LPARAM)&col); + + if (!LoadStringW(shell32_hInstance, IDS_FILE_TYPES, szName, _countof(szName))) + { + // default to english + wcscpy(szName, L"File Types"); + ERR("Failed to load localized string!\n"); + } + + col.iSubItem = 1; + col.cx = clientRect.right - clientRect.left - columnSize; + col.cchTextMax = wcslen(szName); + col.pszText = szName; + SendMessageW(hListView, LVM_INSERTCOLUMNW, 1, (LPARAM)&col); + + // set full select style + dwStyle = (DWORD)SendMessage(hListView, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0); + dwStyle = dwStyle | LVS_EX_FULLROWSELECT; + SendMessage(hListView, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, dwStyle); +} + +static PFILE_TYPE_ENTRY +FileTypesDlg_DoList(HWND hwndDlg) +{ + HWND hListView; + DWORD dwIndex = 0; + WCHAR szName[50]; + WCHAR szFile[100]; + DWORD dwName; + LVITEMW lvItem; + INT iItem = 0; + HIMAGELIST himlLarge, himlSmall; + + // create imagelists + himlLarge = ImageList_Create(GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), + ILC_COLOR32 | ILC_MASK, 256, 20); + himlSmall = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), + ILC_COLOR32 | ILC_MASK, 256, 20); + + // set imagelists to listview. + hListView = GetDlgItem(hwndDlg, IDC_FILETYPES_LISTVIEW); + ListView_SetImageList(hListView, himlLarge, LVSIL_NORMAL); + ListView_SetImageList(hListView, himlSmall, LVSIL_SMALL); + + FileTypesDlg_InitListView(hwndDlg, hListView); + + szFile[0] = 0; + if (!LoadStringW(shell32_hInstance, IDS_FILE_EXT_TYPE, szFile, _countof(szFile))) + { + // default to english + wcscpy(szFile, L"%s File"); + } + szFile[(_countof(szFile)) - 1] = 0; + + dwName = _countof(szName); + + while (RegEnumKeyExW(HKEY_CLASSES_ROOT, dwIndex++, szName, &dwName, + NULL, NULL, NULL, NULL) == ERROR_SUCCESS) + { + if (FileTypesDlg_InsertToLV(hListView, szName, iItem, szFile)) + ++iItem; + dwName = _countof(szName); + } + + // Leave if the list is empty + if (iItem == 0) + return NULL; + + // sort list + ListView_SortItems(hListView, FileTypesDlg_CompareItems, NULL); + + // select first item + ZeroMemory(&lvItem, sizeof(LVITEMW)); + lvItem.mask = LVIF_STATE; + lvItem.stateMask = (UINT)-1; + lvItem.state = LVIS_FOCUSED | LVIS_SELECTED; + lvItem.iItem = 0; + ListView_SetItem(hListView, &lvItem); + + lvItem.mask = LVIF_PARAM; + ListView_GetItem(hListView, &lvItem); + + return (PFILE_TYPE_ENTRY)lvItem.lParam; +} + +static inline PFILE_TYPE_ENTRY +FileTypesDlg_GetEntry(HWND hListView, INT iItem = -1) +{ + if (iItem == -1) + { + iItem = ListView_GetNextItem(hListView, -1, LVNI_SELECTED); + if (iItem == -1) + return NULL; + } + + LV_ITEMW lvItem = { LVIF_PARAM, iItem }; + if (ListView_GetItem(hListView, &lvItem)) + return (PFILE_TYPE_ENTRY)lvItem.lParam; + + return NULL; +} + +static void +FileTypesDlg_OnDelete(HWND hwndDlg) +{ + CStringW strRemoveExt(MAKEINTRESOURCEW(IDS_REMOVE_EXT)); + CStringW strTitle(MAKEINTRESOURCEW(IDS_FILE_TYPES)); + if (MessageBoxW(hwndDlg, strRemoveExt, strTitle, MB_ICONQUESTION | MB_YESNO) == IDYES) + { + FileTypesDlg_RemoveExt(hwndDlg); + } +} + +static void +FileTypesDlg_OnItemChanging(HWND hwndDlg, PFILE_TYPE_ENTRY pEntry) +{ + WCHAR Buffer[255]; + static HBITMAP s_hbmProgram = NULL; + + // format buffer and set groupbox text + CStringW strFormat(MAKEINTRESOURCEW(IDS_FILE_DETAILS)); + StringCbPrintfW(Buffer, sizeof(Buffer), strFormat, &pEntry->FileExtension[1]); + SetDlgItemTextW(hwndDlg, IDC_FILETYPES_DETAILS_GROUPBOX, Buffer); + + // format buffer and set description + strFormat.LoadString(IDS_FILE_DETAILSADV); + StringCbPrintfW(Buffer, sizeof(Buffer), strFormat, + &pEntry->FileExtension[1], pEntry->FileDescription, + pEntry->FileDescription); + SetDlgItemTextW(hwndDlg, IDC_FILETYPES_DESCRIPTION, Buffer); + + // delete previous program image + if (s_hbmProgram) + { + DeleteObject(s_hbmProgram); + s_hbmProgram = NULL; + } + + // set program image + HICON hIconSm = NULL; + ExtractIconExW(pEntry->ProgramPath, 0, NULL, &hIconSm, 1); + s_hbmProgram = BitmapFromIcon(hIconSm, 16, 16); + DestroyIcon(hIconSm); + SendDlgItemMessageW(hwndDlg, IDC_FILETYPES_ICON, STM_SETIMAGE, IMAGE_BITMAP, LPARAM(s_hbmProgram)); + + // set program name + if (pEntry->AppName[0]) + SetDlgItemTextW(hwndDlg, IDC_FILETYPES_APPNAME, pEntry->AppName); + else + SetDlgItemTextW(hwndDlg, IDC_FILETYPES_APPNAME, L"ReactOS"); + + // Enable the Delete button + if (pEntry->EditFlags & 0x00000010) // FTA_NoRemove + EnableWindow(GetDlgItem(hwndDlg, IDC_FILETYPES_DELETE), FALSE); + else + EnableWindow(GetDlgItem(hwndDlg, IDC_FILETYPES_DELETE), TRUE); +} + +// IDD_FOLDER_OPTIONS_FILETYPES +INT_PTR CALLBACK +FolderOptionsFileTypesDlg( + HWND hwndDlg, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + LPNMLISTVIEW lppl; + PFILE_TYPE_ENTRY pEntry; + OPENASINFO Info; + NEWEXT_DIALOG newext; + EDITTYPE_DIALOG edittype; + + switch (uMsg) + { + case WM_INITDIALOG: + pEntry = FileTypesDlg_DoList(hwndDlg); + + // Disable the Delete button if the listview is empty + // the selected item should not be deleted by the user + if (pEntry == NULL || (pEntry->EditFlags & 0x00000010)) // FTA_NoRemove + EnableWindow(GetDlgItem(hwndDlg, IDC_FILETYPES_DELETE), FALSE); + return TRUE; + + case WM_COMMAND: + switch (LOWORD(wParam)) + { + case IDC_FILETYPES_NEW: + newext.hwndLV = GetDlgItem(hwndDlg, IDC_FILETYPES_LISTVIEW); + if (IDOK == DialogBoxParamW(shell32_hInstance, MAKEINTRESOURCEW(IDD_NEWEXTENSION), + hwndDlg, NewExtDlgProc, (LPARAM)&newext)) + { + FileTypesDlg_AddExt(hwndDlg, newext.szExt, newext.szFileType); + } + break; + + case IDC_FILETYPES_DELETE: + FileTypesDlg_OnDelete(hwndDlg); + break; + + case IDC_FILETYPES_CHANGE: + pEntry = FileTypesDlg_GetEntry(GetDlgItem(hwndDlg, IDC_FILETYPES_LISTVIEW)); + if (pEntry) + { + Info.oaifInFlags = OAIF_ALLOW_REGISTRATION | OAIF_REGISTER_EXT; + Info.pcszClass = pEntry->FileExtension; + SHOpenWithDialog(hwndDlg, &Info); + } + break; + + case IDC_FILETYPES_ADVANCED: + edittype.hwndLV = GetDlgItem(hwndDlg, IDC_FILETYPES_LISTVIEW); + edittype.pEntry = FileTypesDlg_GetEntry(edittype.hwndLV); + DialogBoxParamW(shell32_hInstance, MAKEINTRESOURCEW(IDD_EDITTYPE), + hwndDlg, EditTypeDlgProc, (LPARAM)&edittype); + break; + } + break; + + case WM_NOTIFY: + lppl = (LPNMLISTVIEW) lParam; + switch (lppl->hdr.code) + { + case LVN_KEYDOWN: + { + LV_KEYDOWN *pKeyDown = (LV_KEYDOWN *)lParam; + if (pKeyDown->wVKey == VK_DELETE) + { + FileTypesDlg_OnDelete(hwndDlg); + } + break; + } + + case NM_DBLCLK: + edittype.hwndLV = GetDlgItem(hwndDlg, IDC_FILETYPES_LISTVIEW); + edittype.pEntry = FileTypesDlg_GetEntry(edittype.hwndLV); + DialogBoxParamW(shell32_hInstance, MAKEINTRESOURCEW(IDD_EDITTYPE), + hwndDlg, EditTypeDlgProc, (LPARAM)&edittype); + break; + + case LVN_DELETEALLITEMS: + return FALSE; // send LVN_DELETEITEM + + case LVN_DELETEITEM: + pEntry = FileTypesDlg_GetEntry(lppl->hdr.hwndFrom, lppl->iItem); + if (pEntry) + { + DestroyIcon(pEntry->hIconLarge); + DestroyIcon(pEntry->hIconSmall); + HeapFree(GetProcessHeap(), 0, pEntry); + } + return FALSE; + + case LVN_ITEMCHANGING: + pEntry = FileTypesDlg_GetEntry(lppl->hdr.hwndFrom, lppl->iItem); + if (!pEntry) + { + return TRUE; + } + + if (!(lppl->uOldState & LVIS_FOCUSED) && (lppl->uNewState & LVIS_FOCUSED)) + { + FileTypesDlg_OnItemChanging(hwndDlg, pEntry); + } + break; + + case PSN_SETACTIVE: + // On page activation, set the focus to the listview + SetFocus(GetDlgItem(hwndDlg, IDC_FILETYPES_LISTVIEW)); + break; + } + break; + } + + return FALSE; +} diff --git a/dll/win32/shell32/dialogs/folder_options.cpp b/dll/win32/shell32/dialogs/folder_options.cpp index 0675eacf67..1fb4e7344f 100644 --- a/dll/win32/shell32/dialogs/folder_options.cpp +++ b/dll/win32/shell32/dialogs/folder_options.cpp @@ -1,5 +1,5 @@ /* - * Open With Context Menu extension + * Folder Options * * Copyright 2007 Johannes Anderwald johannes.anderwald@reactos.org * Copyright 2016-2018 Katayama Hirofumi MZ katayama.hirofumi.mz@gmail.com @@ -23,148 +23,22 @@
WINE_DEFAULT_DEBUG_CHANNEL (fprop);
-/// Folder Options: -/// CLASSKEY = HKEY_CLASSES_ROOT\CLSID{6DFD7C5C-2451-11d3-A299-00C04F8EF6AF} -/// DefaultIcon = %SystemRoot%\system32\SHELL32.dll,-210 -/// Verbs: Open / RunAs -/// Cmd: rundll32.exe shell32.dll,Options_RunDLL 0 +// Folder Options: +// CLASSKEY = HKEY_CLASSES_ROOT\CLSID{6DFD7C5C-2451-11d3-A299-00C04F8EF6AF}
-/// ShellFolder Attributes: 0x0 +///////////////////////////////////////////////////////////////////////////// +// strings
-typedef struct -{ - WCHAR FileExtension[30]; - WCHAR FileDescription[100]; - WCHAR ClassKey[MAX_PATH]; - WCHAR ClassName[64]; - DWORD EditFlags; - WCHAR AppName[64]; - HICON hIconLarge; - HICON hIconSmall; - WCHAR ProgramPath[MAX_PATH]; - WCHAR IconPath[MAX_PATH]; - INT nIconIndex; -} FOLDER_FILE_TYPE_ENTRY, *PFOLDER_FILE_TYPE_ENTRY; - -// uniquely-defined icon entry for Advanced Settings -typedef struct ADVANCED_ICON -{ - 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 +// path to shell32 +LPCWSTR g_pszShell32 = L"%SystemRoot%\system32\shell32.dll";
- // extract a small icon - HICON hIconSmall = NULL; - ExtractIconExW(pszPath, nIconIndex, NULL, &hIconSmall, 1); - if (hIconSmall == NULL) - return -1; // failure +// the space characters +LPCWSTR g_pszSpace = L" \t\n\r\f\v";
- // 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; +///////////////////////////////////////////////////////////////////////////// +// utility functions
- // 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) +HBITMAP Create24BppBitmap(HDC hDC, INT cx, INT cy) { BITMAPINFO bi; LPVOID pvBits; @@ -181,7 +55,7 @@ Create24BppBitmap(HDC hDC, INT cx, INT cy) return hbm; }
-static HBITMAP BitmapFromIcon(HICON hIcon, INT cx, INT cy) +HBITMAP BitmapFromIcon(HICON hIcon, INT cx, INT cy) { HDC hDC = CreateCompatibleDC(NULL); if (!hDC) @@ -209,8 +83,7 @@ static HBITMAP BitmapFromIcon(HICON hIcon, INT cx, INT cy) return hbm; }
-static HBITMAP -CreateCheckImage(HDC hDC, BOOL bCheck, BOOL bEnabled = TRUE) +HBITMAP CreateCheckImage(HDC hDC, BOOL bCheck, BOOL bEnabled) { INT cxSmallIcon = GetSystemMetrics(SM_CXSMICON); INT cySmallIcon = GetSystemMetrics(SM_CYSMICON); @@ -238,8 +111,7 @@ CreateCheckImage(HDC hDC, BOOL bCheck, BOOL bEnabled = TRUE) return hbm; // success }
-static HBITMAP -CreateCheckMask(HDC hDC) +HBITMAP CreateCheckMask(HDC hDC) { INT cxSmallIcon = GetSystemMetrics(SM_CXSMICON); INT cySmallIcon = GetSystemMetrics(SM_CYSMICON); @@ -263,8 +135,7 @@ CreateCheckMask(HDC hDC) return hbm; // success }
-static HBITMAP -CreateRadioImage(HDC hDC, BOOL bCheck, BOOL bEnabled = TRUE) +HBITMAP CreateRadioImage(HDC hDC, BOOL bCheck, BOOL bEnabled) { INT cxSmallIcon = GetSystemMetrics(SM_CXSMICON); INT cySmallIcon = GetSystemMetrics(SM_CYSMICON); @@ -292,8 +163,7 @@ CreateRadioImage(HDC hDC, BOOL bCheck, BOOL bEnabled = TRUE) return hbm; // success }
-static HBITMAP -CreateRadioMask(HDC hDC) +HBITMAP CreateRadioMask(HDC hDC) { INT cxSmallIcon = GetSystemMetrics(SM_CXSMICON); INT cySmallIcon = GetSystemMetrics(SM_CYSMICON); @@ -318,2755 +188,46 @@ CreateRadioMask(HDC hDC) 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 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( - HWND hwndDlg, - UINT uMsg, - WPARAM wParam, - 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 BOOL -ViewDlg_OnInitDialog(HWND hwndDlg) -{ - HWND hwndTreeView = GetDlgItem(hwndDlg, 14003); - - s_hImageList = CreateTreeImageList(); - TreeView_SetImageList(hwndTreeView, s_hImageList, TVSIL_NORMAL); - - Advanced_LoadAll(); - Advanced_SortAll(); - Advanced_InsertAll(hwndTreeView); - - return TRUE; // set focus -} - -static BOOL -ViewDlg_ToggleCheckItem(HWND hwndDlg, HTREEITEM hItem) +ShowFolderOptionsDialog(HWND hWnd, HINSTANCE hInst) { - 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 + PROPSHEETHEADERW pinfo; + HPROPSHEETPAGE hppages[3]; + HPROPSHEETPAGE hpage; + UINT num_pages = 0; + WCHAR szOptions[100];
- ADVANCED_ENTRY *pEntry = Advanced_GetItem(Item.lParam); - if (pEntry == NULL) - return FALSE; // no such item - if (pEntry->bGrayed) - return FALSE; // disabled + hpage = SH_CreatePropertySheetPage(IDD_FOLDER_OPTIONS_GENERAL, FolderOptionsGeneralDlg, 0, NULL); + if (hpage) + hppages[num_pages++] = hpage;
- // toggle check mark - Item.mask = TVIF_HANDLE | TVIF_IMAGE | TVIF_SELECTEDIMAGE; - switch (pEntry->dwType) - { - case AETYPE_CHECKBOX: - pEntry->bChecked = !pEntry->bChecked; - break; + hpage = SH_CreatePropertySheetPage(IDD_FOLDER_OPTIONS_VIEW, FolderOptionsViewDlg, 0, NULL); + if (hpage) + hppages[num_pages++] = hpage;
- 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; + hpage = SH_CreatePropertySheetPage(IDD_FOLDER_OPTIONS_FILETYPES, FolderOptionsFileTypesDlg, 0, NULL); + if (hpage) + hppages[num_pages++] = hpage;
- Item.hItem = pEntry2->hItem; - INT iImage = Advanced_GetImage(pEntry2); - Item.iImage = Item.iSelectedImage = iImage; - TreeView_SetItem(hwndTreeView, &Item); - } - } - pEntry->bChecked = TRUE; - break; + szOptions[0] = 0; + LoadStringW(shell32_hInstance, IDS_FOLDER_OPTIONS, szOptions, _countof(szOptions)); + szOptions[_countof(szOptions) - 1] = 0;
- default: - return FALSE; // failure - } - Item.iImage = Item.iSelectedImage = Advanced_GetImage(pEntry); - Item.hItem = hItem; - TreeView_SetItem(hwndTreeView, &Item); + memset(&pinfo, 0x0, sizeof(PROPSHEETHEADERW)); + pinfo.dwSize = sizeof(PROPSHEETHEADERW); + pinfo.dwFlags = PSH_NOCONTEXTHELP; + pinfo.nPages = num_pages; + pinfo.phpage = hppages; + pinfo.pszCaption = szOptions;
- // redraw the item - RECT rcItem; - TreeView_GetItemRect(hwndTreeView, hItem, &rcItem, FALSE); - InvalidateRect(hwndTreeView, &rcItem, TRUE); - return TRUE; // success + PropertySheetW(&pinfo); }
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 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) -{ - INT_PTR Result; - NMTVCUSTOMDRAW *Draw; - - switch(uMsg) - { - case WM_INITDIALOG: - 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 -VOID -InitializeFileTypesListCtrlColumns(HWND hDlgCtrl) -{ - RECT clientRect; - LVCOLUMNW col; - WCHAR szName[50]; - DWORD dwStyle; - int columnSize = 140; - - - if (!LoadStringW(shell32_hInstance, IDS_COLUMN_EXTENSION, szName, sizeof(szName) / sizeof(WCHAR))) - { - /* default to english */ - wcscpy(szName, L"Extensions"); - } - - /* make sure its null terminated */ - szName[(sizeof(szName)/sizeof(WCHAR))-1] = 0; - - GetClientRect(hDlgCtrl, &clientRect); - ZeroMemory(&col, sizeof(LV_COLUMN)); - columnSize = 140; //FIXME - col.iSubItem = 0; - col.mask = LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM | LVCF_FMT; - col.fmt = LVCFMT_FIXED_WIDTH; - col.cx = columnSize | LVCFMT_LEFT; - col.cchTextMax = wcslen(szName); - col.pszText = szName; - (void)SendMessageW(hDlgCtrl, LVM_INSERTCOLUMNW, 0, (LPARAM)&col); - - if (!LoadStringW(shell32_hInstance, IDS_FILE_TYPES, szName, sizeof(szName) / sizeof(WCHAR))) - { - /* default to english */ - wcscpy(szName, L"File Types"); - ERR("Failed to load localized string!\n"); - } - - col.iSubItem = 1; - col.cx = clientRect.right - clientRect.left - columnSize; - col.cchTextMax = wcslen(szName); - col.pszText = szName; - (void)SendMessageW(hDlgCtrl, LVM_INSERTCOLUMNW, 1, (LPARAM)&col); - - /* set full select style */ - dwStyle = (DWORD) SendMessage(hDlgCtrl, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0); - dwStyle = dwStyle | LVS_EX_FULLROWSELECT; - SendMessage(hDlgCtrl, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, dwStyle); -} - -static BOOL -DeleteExt(HWND hwndDlg, LPCWSTR pszExt) -{ - if (*pszExt != L'.') - return FALSE; - - // open ".ext" key - HKEY hKey; - if (RegOpenKeyExW(HKEY_CLASSES_ROOT, pszExt, 0, KEY_READ, &hKey) != ERROR_SUCCESS) - return FALSE; - - // query "extfile" key name - WCHAR szValue[64] = { 0 }; - DWORD cbValue = sizeof(szValue); - RegQueryValueExW(hKey, NULL, NULL, NULL, LPBYTE(szValue), &cbValue); - RegCloseKey(hKey); - - // delete "extfile" key (if any) - if (szValue[0]) - SHDeleteKeyW(HKEY_CLASSES_ROOT, szValue); - - // delete ".ext" key - return SHDeleteKeyW(HKEY_CLASSES_ROOT, pszExt) == ERROR_SUCCESS; -} - -static inline HICON -DoExtractIcon(PFOLDER_FILE_TYPE_ENTRY Entry, LPCWSTR IconPath, - INT iIndex = 0, BOOL bSmall = FALSE) -{ - HICON hIcon = NULL; - - if (iIndex < 0) - { - // A negative value will be interpreted as a negated resource ID. - iIndex = -iIndex; - - INT cx, cy; - HINSTANCE hDLL = LoadLibraryExW(IconPath, NULL, LOAD_LIBRARY_AS_DATAFILE); - if (bSmall) - { - cx = GetSystemMetrics(SM_CXSMICON); - cy = GetSystemMetrics(SM_CYSMICON); - } - else - { - cx = GetSystemMetrics(SM_CXICON); - cy = GetSystemMetrics(SM_CYICON); - } - hIcon = HICON(LoadImageW(hDLL, MAKEINTRESOURCEW(iIndex), IMAGE_ICON, - cx, cy, 0)); - FreeLibrary(hDLL); - } - else - { - // A positive value is icon index. - if (bSmall) - ExtractIconExW(IconPath, iIndex, NULL, &hIcon, 1); - else - ExtractIconExW(IconPath, iIndex, &hIcon, NULL, 1); - } - return hIcon; -} - -static void -DoFileTypeIconLocation(PFOLDER_FILE_TYPE_ENTRY Entry, LPCWSTR IconLocation) -{ - // Expand the REG_EXPAND_SZ string by environment variables - WCHAR szLocation[MAX_PATH + 32]; - if (!ExpandEnvironmentStringsW(IconLocation, szLocation, _countof(szLocation))) - { - return; - } - - Entry->nIconIndex = PathParseIconLocationW(szLocation); - StringCchCopyW(Entry->IconPath, _countof(Entry->IconPath), szLocation); - Entry->hIconLarge = DoExtractIcon(Entry, szLocation, Entry->nIconIndex, FALSE); - Entry->hIconSmall = DoExtractIcon(Entry, szLocation, Entry->nIconIndex, TRUE); -} - -static BOOL -GetFileTypeIconsEx(PFOLDER_FILE_TYPE_ENTRY Entry, LPCWSTR IconLocation) -{ - Entry->hIconLarge = Entry->hIconSmall = NULL; - - if (lstrcmpiW(Entry->FileExtension, L".exe") == 0 || - lstrcmpiW(Entry->FileExtension, L".scr") == 0) - { - // It's an executable - Entry->hIconLarge = LoadIconW(shell32_hInstance, MAKEINTRESOURCEW(IDI_SHELL_EXE)); - Entry->hIconSmall = HICON(LoadImageW(shell32_hInstance, MAKEINTRESOURCEW(IDI_SHELL_EXE), IMAGE_ICON, - GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0)); - StringCchCopyW(Entry->IconPath, _countof(Entry->IconPath), L"%SystemRoot%\system32\shell32.dll"); - Entry->nIconIndex = -IDI_SHELL_EXE; - } - else if (lstrcmpW(IconLocation, L"%1") == 0) - { - return FALSE; // self icon - } - else - { - DoFileTypeIconLocation(Entry, IconLocation); - } - - return Entry->hIconLarge && Entry->hIconSmall; -} - -static BOOL -GetFileTypeIconsByKey(HKEY hKey, PFOLDER_FILE_TYPE_ENTRY Entry) -{ - Entry->hIconLarge = Entry->hIconSmall = NULL; - - // Open the "DefaultIcon" registry key - HKEY hDefIconKey; - LONG nResult = RegOpenKeyExW(hKey, L"DefaultIcon", 0, KEY_READ, &hDefIconKey); - if (nResult != ERROR_SUCCESS) - return FALSE; - - // Get the icon location - WCHAR szLocation[MAX_PATH + 32] = { 0 }; - DWORD dwSize = sizeof(szLocation); - nResult = RegQueryValueExW(hDefIconKey, NULL, NULL, NULL, LPBYTE(szLocation), &dwSize); - - RegCloseKey(hDefIconKey); - - if (nResult != ERROR_SUCCESS || szLocation[0] == 0) - return FALSE; - - return GetFileTypeIconsEx(Entry, szLocation); -} - -static BOOL -QueryFileDescription(LPCWSTR ProgramPath, LPWSTR pszName, INT cchName) -{ - SHFILEINFOW FileInfo = { 0 }; - if (SHGetFileInfoW(ProgramPath, 0, &FileInfo, sizeof(FileInfo), SHGFI_DISPLAYNAME)) - { - StringCchCopyW(pszName, cchName, FileInfo.szDisplayName); - return TRUE; - } - - return !!GetFileTitleW(ProgramPath, pszName, cchName); -} - -static void -SetFileTypeEntryDefaultIcon(PFOLDER_FILE_TYPE_ENTRY Entry) -{ - Entry->hIconLarge = LoadIconW(shell32_hInstance, MAKEINTRESOURCEW(IDI_SHELL_FOLDER_OPTIONS)); - INT cxSmall = GetSystemMetrics(SM_CXSMICON); - INT cySmall = GetSystemMetrics(SM_CYSMICON); - Entry->hIconSmall = HICON(LoadImageW(shell32_hInstance, MAKEINTRESOURCEW(IDI_SHELL_FOLDER_OPTIONS), - IMAGE_ICON, cxSmall, cySmall, 0)); - StringCchCopyW(Entry->IconPath, _countof(Entry->IconPath), L"%SystemRoot%\system32\shell32.dll"); - Entry->nIconIndex = -IDI_SHELL_FOLDER_OPTIONS; -} - -static BOOL -InsertFileType(HWND hListView, LPCWSTR szName, INT iItem, LPCWSTR szFile) -{ - PFOLDER_FILE_TYPE_ENTRY Entry; - HKEY hKey; - LVITEMW lvItem; - DWORD dwSize; - DWORD dwType; - - if (szName[0] != L'.') - { - /* FIXME handle URL protocol handlers */ - return FALSE; - } - - // get imagelists of listview - HIMAGELIST himlLarge = ListView_GetImageList(hListView, LVSIL_NORMAL); - HIMAGELIST himlSmall = ListView_GetImageList(hListView, LVSIL_SMALL); - - /* allocate file type entry */ - Entry = (PFOLDER_FILE_TYPE_ENTRY)HeapAlloc(GetProcessHeap(), 0, sizeof(FOLDER_FILE_TYPE_ENTRY)); - if (!Entry) - return FALSE; - - /* open key */ - if (RegOpenKeyExW(HKEY_CLASSES_ROOT, szName, 0, KEY_READ, &hKey) != ERROR_SUCCESS) - { - HeapFree(GetProcessHeap(), 0, Entry); - return FALSE; - } - - /* FIXME check for duplicates */ - - /* query for the default key */ - dwSize = sizeof(Entry->ClassKey); - if (RegQueryValueExW(hKey, NULL, NULL, NULL, (LPBYTE)Entry->ClassKey, &dwSize) != ERROR_SUCCESS) - { - /* no link available */ - Entry->ClassKey[0] = 0; - } - - Entry->ClassName[0] = 0; - if (Entry->ClassKey[0]) - { - HKEY hTemp; - /* try open linked key */ - if (RegOpenKeyExW(HKEY_CLASSES_ROOT, Entry->ClassKey, 0, KEY_READ, &hTemp) == ERROR_SUCCESS) - { - DWORD dwSize = sizeof(Entry->ClassName); - RegQueryValueExW(hTemp, NULL, NULL, NULL, LPBYTE(Entry->ClassName), &dwSize); - - /* use linked key */ - RegCloseKey(hKey); - hKey = hTemp; - } - } - - /* read friendly type name */ - if (RegLoadMUIStringW(hKey, L"FriendlyTypeName", Entry->FileDescription, sizeof(Entry->FileDescription), NULL, 0, NULL) != ERROR_SUCCESS) - { - /* read file description */ - dwSize = sizeof(Entry->FileDescription); - Entry->FileDescription[0] = 0; - - /* read default key */ - 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); - } - - /* convert extension to upper case */ - wcscpy(Entry->FileExtension, szName); - _wcsupr(Entry->FileExtension); - - /* get icon */ - if (!GetFileTypeIconsByKey(hKey, Entry)) - { - // set default icon - SetFileTypeEntryDefaultIcon(Entry); - } - - /* close key */ - RegCloseKey(hKey); - - // get program path and app name - DWORD cch = _countof(Entry->ProgramPath); - if (S_OK == AssocQueryStringW(ASSOCF_INIT_IGNOREUNKNOWN, ASSOCSTR_EXECUTABLE, - Entry->FileExtension, NULL, Entry->ProgramPath, &cch)) - { - QueryFileDescription(Entry->ProgramPath, Entry->AppName, _countof(Entry->AppName)); - } - else - { - Entry->ProgramPath[0] = Entry->AppName[0] = 0; - } - - // add icon to imagelist - INT iLargeImage = -1, iSmallImage = -1; - if (Entry->hIconLarge && Entry->hIconSmall) - { - iLargeImage = ImageList_AddIcon(himlLarge, Entry->hIconLarge); - iSmallImage = ImageList_AddIcon(himlSmall, Entry->hIconSmall); - ASSERT(iLargeImage == iSmallImage); - } - - /* Do not add excluded entries */ - if (Entry->EditFlags & 0x00000001) //FTA_Exclude - { - DestroyIcon(Entry->hIconLarge); - DestroyIcon(Entry->hIconSmall); - HeapFree(GetProcessHeap(), 0, Entry); - return FALSE; - } - - if (!Entry->FileDescription[0]) - { - /* 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.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE; - lvItem.iSubItem = 0; - lvItem.pszText = &Entry->FileExtension[1]; - lvItem.iItem = iItem; - lvItem.lParam = (LPARAM)Entry; - lvItem.iImage = iSmallImage; - SendMessageW(hListView, LVM_INSERTITEMW, 0, (LPARAM)&lvItem); - - ZeroMemory(&lvItem, sizeof(LVITEMW)); - lvItem.mask = LVIF_TEXT; - lvItem.pszText = Entry->FileDescription; - lvItem.iItem = iItem; - lvItem.iSubItem = 1; - ListView_SetItem(hListView, &lvItem); - - return TRUE; -} - -static -int -CALLBACK -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; - - x = wcsicmp(Entry1->FileExtension, Entry2->FileExtension); - if (x != 0) - return x; - - return wcsicmp(Entry1->FileDescription, Entry2->FileDescription); -} - -static -PFOLDER_FILE_TYPE_ENTRY -InitializeFileTypesListCtrl(HWND hwndDlg) -{ - HWND hDlgCtrl; - DWORD dwIndex = 0; - WCHAR szName[50]; - WCHAR szFile[100]; - DWORD dwName; - LVITEMW lvItem; - INT iItem = 0; - HIMAGELIST himlLarge, himlSmall; - - // create imagelists - himlLarge = ImageList_Create(GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), - ILC_COLOR32 | ILC_MASK, 256, 20); - himlSmall = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), - ILC_COLOR32 | ILC_MASK, 256, 20); - - // set imagelists to listview. - hDlgCtrl = GetDlgItem(hwndDlg, IDC_FILETYPES_LISTVIEW); - ListView_SetImageList(hDlgCtrl, himlLarge, LVSIL_NORMAL); - ListView_SetImageList(hDlgCtrl, himlSmall, LVSIL_SMALL); - - InitializeFileTypesListCtrlColumns(hDlgCtrl); - - szFile[0] = 0; - if (!LoadStringW(shell32_hInstance, IDS_FILE_EXT_TYPE, szFile, _countof(szFile))) - { - /* default to english */ - wcscpy(szFile, L"%s File"); - } - szFile[(_countof(szFile)) - 1] = 0; - - dwName = _countof(szName); - - while (RegEnumKeyExW(HKEY_CLASSES_ROOT, dwIndex++, szName, &dwName, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) - { - if (InsertFileType(hDlgCtrl, szName, iItem, szFile)) - ++iItem; - 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.state = LVIS_FOCUSED | LVIS_SELECTED; - lvItem.iItem = 0; - ListView_SetItem(hDlgCtrl, &lvItem); - - lvItem.mask = LVIF_PARAM; - ListView_GetItem(hDlgCtrl, &lvItem); - - return (PFOLDER_FILE_TYPE_ENTRY)lvItem.lParam; -} - -static inline -PFOLDER_FILE_TYPE_ENTRY -GetListViewEntry(HWND hListView, INT iItem = -1) -{ - if (iItem == -1) - { - iItem = ListView_GetNextItem(hListView, -1, LVNI_SELECTED); - if (iItem == -1) - return NULL; - } - - LV_ITEMW lvItem = { LVIF_PARAM, iItem }; - if (ListView_GetItem(hListView, &lvItem)) - return (PFOLDER_FILE_TYPE_ENTRY)lvItem.lParam; - - return NULL; -} - -struct NEWEXT_DIALOG -{ - HWND hwndLV; - RECT rcDlg; - BOOL bAdvanced; - INT dy; - WCHAR szExt[16]; - WCHAR szFileType[64]; -}; - -static VOID -NewExtDlg_OnAdvanced(HWND hwndDlg, NEWEXT_DIALOG *pNewExt) -{ - // If "Advanced" button was clicked, then we shrink or expand the dialog. - WCHAR szText[64]; - RECT rc, rc1, rc2; - - GetWindowRect(hwndDlg, &rc); - rc.bottom = rc.top + (pNewExt->rcDlg.bottom - pNewExt->rcDlg.top); - - GetWindowRect(GetDlgItem(hwndDlg, IDOK), &rc1); - MapWindowPoints(NULL, hwndDlg, (POINT *)&rc1, 2); - - GetWindowRect(GetDlgItem(hwndDlg, IDCANCEL), &rc2); - MapWindowPoints(NULL, hwndDlg, (POINT *)&rc2, 2); - - if (pNewExt->bAdvanced) - { - rc1.top += pNewExt->dy; - rc1.bottom += pNewExt->dy; - - rc2.top += pNewExt->dy; - rc2.bottom += pNewExt->dy; - - ShowWindow(GetDlgItem(hwndDlg, IDC_NEWEXT_ASSOC), SW_SHOWNOACTIVATE); - ShowWindow(GetDlgItem(hwndDlg, IDC_NEWEXT_COMBOBOX), SW_SHOWNOACTIVATE); - - LoadStringW(shell32_hInstance, IDS_NEWEXT_ADVANCED_LEFT, szText, _countof(szText)); - SetDlgItemTextW(hwndDlg, IDC_NEWEXT_ADVANCED, szText); - - SetFocus(GetDlgItem(hwndDlg, IDC_NEWEXT_COMBOBOX)); - } - else - { - rc1.top -= pNewExt->dy; - rc1.bottom -= pNewExt->dy; - - rc2.top -= pNewExt->dy; - rc2.bottom -= pNewExt->dy; - - ShowWindow(GetDlgItem(hwndDlg, IDC_NEWEXT_ASSOC), SW_HIDE); - ShowWindow(GetDlgItem(hwndDlg, IDC_NEWEXT_COMBOBOX), SW_HIDE); - - LoadStringW(shell32_hInstance, IDS_NEWEXT_ADVANCED_RIGHT, szText, _countof(szText)); - SetDlgItemTextW(hwndDlg, IDC_NEWEXT_ADVANCED, szText); - - rc.bottom -= pNewExt->dy; - - LoadStringW(shell32_hInstance, IDS_NEWEXT_NEW, szText, _countof(szText)); - SetDlgItemTextW(hwndDlg, IDC_NEWEXT_COMBOBOX, szText); - } - - HDWP hDWP = BeginDeferWindowPos(3); - - if (hDWP) - hDWP = DeferWindowPos(hDWP, GetDlgItem(hwndDlg, IDOK), NULL, - rc1.left, rc1.top, rc1.right - rc1.left, rc1.bottom - rc1.top, - SWP_NOACTIVATE | SWP_NOZORDER); - if (hDWP) - hDWP = DeferWindowPos(hDWP, GetDlgItem(hwndDlg, IDCANCEL), NULL, - rc2.left, rc2.top, rc2.right - rc2.left, rc2.bottom - rc2.top, - SWP_NOACTIVATE | SWP_NOZORDER); - if (hDWP) - hDWP = DeferWindowPos(hDWP, hwndDlg, NULL, - rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, - SWP_NOACTIVATE | SWP_NOZORDER); - - if (hDWP) - EndDeferWindowPos(hDWP); -} - -static BOOL -NewExtDlg_OnInitDialog(HWND hwndDlg, NEWEXT_DIALOG *pNewExt) -{ - WCHAR szText[64]; - - pNewExt->bAdvanced = FALSE; - - GetWindowRect(hwndDlg, &pNewExt->rcDlg); - - RECT rc1, rc2; - GetWindowRect(GetDlgItem(hwndDlg, IDC_NEWEXT_EDIT), &rc1); - GetWindowRect(GetDlgItem(hwndDlg, IDC_NEWEXT_COMBOBOX), &rc2); - pNewExt->dy = rc2.top - rc1.top; - - LoadStringW(shell32_hInstance, IDS_NEWEXT_NEW, szText, _countof(szText)); - SendDlgItemMessageW(hwndDlg, IDC_NEWEXT_COMBOBOX, CB_ADDSTRING, 0, (LPARAM)szText); - SendDlgItemMessageW(hwndDlg, IDC_NEWEXT_COMBOBOX, CB_SETCURSEL, 0, 0); - - SendDlgItemMessageW(hwndDlg, IDC_NEWEXT_EDIT, EM_SETLIMITTEXT, _countof(pNewExt->szExt) - 1, 0); - - NewExtDlg_OnAdvanced(hwndDlg, pNewExt); - - return TRUE; -} - -static LPCWSTR s_pszSpace = L" \t\n\r\f\v"; - -static BOOL -NewExtDlg_OnOK(HWND hwndDlg, NEWEXT_DIALOG *pNewExt) -{ - LV_FINDINFO find; - INT iItem; - - GetDlgItemTextW(hwndDlg, IDC_NEWEXT_EDIT, pNewExt->szExt, _countof(pNewExt->szExt)); - StrTrimW(pNewExt->szExt, s_pszSpace); - CharUpperW(pNewExt->szExt); - - GetDlgItemTextW(hwndDlg, IDC_NEWEXT_COMBOBOX, pNewExt->szFileType, _countof(pNewExt->szFileType)); - StrTrimW(pNewExt->szFileType, s_pszSpace); - - if (pNewExt->szExt[0] == 0) - { - WCHAR szText[128], szTitle[128]; - LoadStringW(shell32_hInstance, IDS_NEWEXT_SPECIFY_EXT, szText, _countof(szText)); - szText[_countof(szText) - 1] = 0; - LoadStringW(shell32_hInstance, IDS_FILE_TYPES, szTitle, _countof(szTitle)); - szTitle[_countof(szTitle) - 1] = 0; - MessageBoxW(hwndDlg, szText, szTitle, MB_ICONERROR); - return FALSE; - } - - ZeroMemory(&find, sizeof(find)); - find.flags = LVFI_STRING; - if (pNewExt->szExt[0] == L'.') - { - find.psz = &pNewExt->szExt[1]; - } - else - { - find.psz = pNewExt->szExt; - } - - iItem = ListView_FindItem(pNewExt->hwndLV, -1, &find); - if (iItem >= 0) - { - // already exists - WCHAR szText[256], szFormat[256], szTitle[64], szFileType[64]; - - // get file type - LV_ITEM item; - ZeroMemory(&item, sizeof(item)); - item.mask = LVIF_TEXT; - item.pszText = szFileType; - item.cchTextMax = _countof(szFileType); - item.iItem = iItem; - item.iSubItem = 1; - ListView_GetItem(pNewExt->hwndLV, &item); - - // get text - LoadStringW(shell32_hInstance, IDS_NEWEXT_ALREADY_ASSOC, szFormat, _countof(szFormat)); - szText[_countof(szFormat) - 1] = 0; - StringCchPrintfW(szText, _countof(szText), szFormat, find.psz, szFileType, find.psz, szFileType); - - // get title - LoadStringW(shell32_hInstance, IDS_NEWEXT_EXT_IN_USE, szTitle, _countof(szTitle)); - szTitle[_countof(szTitle) - 1] = 0; - - if (MessageBoxW(hwndDlg, szText, szTitle, MB_ICONWARNING | MB_YESNO) == IDNO) - { - return FALSE; - } - - // Delete the extension - CStringW strExt(L"."); - strExt += find.psz; - strExt.MakeLower(); - DeleteExt(hwndDlg, strExt); - - // Delete the item - ListView_DeleteItem(pNewExt->hwndLV, iItem); - } - - EndDialog(hwndDlg, IDOK); - return TRUE; -} - -// IDD_NEWEXTENSION dialog -INT_PTR -CALLBACK -NewExtensionDlgProc( - HWND hwndDlg, - UINT uMsg, - WPARAM wParam, - LPARAM lParam) -{ - static NEWEXT_DIALOG *s_pNewExt = NULL; - - switch (uMsg) - { - case WM_INITDIALOG: - s_pNewExt = (NEWEXT_DIALOG *)lParam; - NewExtDlg_OnInitDialog(hwndDlg, s_pNewExt); - return TRUE; - - case WM_COMMAND: - switch (LOWORD(wParam)) - { - case IDOK: - NewExtDlg_OnOK(hwndDlg, s_pNewExt); - break; - - case IDCANCEL: - EndDialog(hwndDlg, IDCANCEL); - break; - - case IDC_NEWEXT_ADVANCED: - s_pNewExt->bAdvanced = !s_pNewExt->bAdvanced; - NewExtDlg_OnAdvanced(hwndDlg, s_pNewExt); - break; - } - break; - } - return 0; -} - -static BOOL -FileTypesDlg_AddExt(HWND hwndDlg, LPCWSTR pszExt, LPCWSTR pszFileType) -{ - DWORD dwValue = 1; - HKEY hKey; - WCHAR szKey[13]; // max. "ft4294967295" + "\0" - LONG nResult; - - // Search the next "ft%06u" key name - do - { - StringCchPrintfW(szKey, _countof(szKey), TEXT("ft%06u"), dwValue); - - nResult = RegOpenKeyEx(HKEY_CLASSES_ROOT, szKey, 0, KEY_READ, &hKey); - if (nResult != ERROR_SUCCESS) - break; - - RegCloseKey(hKey); - ++dwValue; - } while (dwValue != 0); - - RegCloseKey(hKey); - - if (dwValue == 0) - return FALSE; - - // Create new "ft%06u" key - nResult = RegCreateKeyEx(HKEY_CLASSES_ROOT, szKey, 0, NULL, 0, KEY_WRITE, NULL, &hKey, NULL); - if (ERROR_SUCCESS != nResult) - return FALSE; - - RegCloseKey(hKey); - - // Create the ".ext" key - WCHAR szExt[16]; - if (*pszExt == L'.') - ++pszExt; - StringCchPrintfW(szExt, _countof(szExt), TEXT(".%s"), pszExt); - CharLowerW(szExt); - nResult = RegCreateKeyEx(HKEY_CLASSES_ROOT, szExt, 0, NULL, 0, KEY_WRITE, NULL, &hKey, NULL); - CharUpperW(szExt); - if (ERROR_SUCCESS != nResult) - return FALSE; - - // Set the default value of ".ext" to "ft%06u" - DWORD dwSize = (lstrlen(szKey) + 1) * sizeof(WCHAR); - RegSetValueExW(hKey, NULL, 0, REG_SZ, (BYTE *)szKey, dwSize); - - RegCloseKey(hKey); - - // Make up the file type name - WCHAR szFile[100], szFileFormat[100]; - LoadStringW(shell32_hInstance, IDS_FILE_EXT_TYPE, szFileFormat, _countof(szFileFormat)); - szFile[_countof(szFileFormat) - 1] = 0; - StringCchPrintfW(szFile, _countof(szFile), szFileFormat, &szExt[1]); - - // Insert an item to the listview - HWND hListView = GetDlgItem(hwndDlg, IDC_FILETYPES_LISTVIEW); - INT iItem = ListView_GetItemCount(hListView); - if (!InsertFileType(hListView, szExt, iItem, szFile)) - return FALSE; - - LV_ITEM item; - ZeroMemory(&item, sizeof(item)); - item.mask = LVIF_STATE | LVIF_TEXT; - item.iItem = iItem; - item.state = LVIS_SELECTED | LVIS_FOCUSED; - item.stateMask = LVIS_SELECTED | LVIS_FOCUSED; - item.pszText = &szExt[1]; - ListView_SetItem(hListView, &item); - - item.pszText = szFile; - item.iSubItem = 1; - ListView_SetItem(hListView, &item); - - ListView_EnsureVisible(hListView, iItem, FALSE); - - return TRUE; -} - -static BOOL -FileTypesDlg_RemoveExt(HWND hwndDlg) -{ - HWND hListView = GetDlgItem(hwndDlg, IDC_FILETYPES_LISTVIEW); - - INT iItem = ListView_GetNextItem(hListView, -1, LVNI_SELECTED); - if (iItem == -1) - return FALSE; - - WCHAR szExt[20]; - szExt[0] = L'.'; - ListView_GetItemText(hListView, iItem, 0, &szExt[1], _countof(szExt) - 1); - CharLowerW(szExt); - - DeleteExt(hwndDlg, szExt); - ListView_DeleteItem(hListView, iItem); - return TRUE; -} - -static void -FileTypesDlg_OnItemChanging(HWND hwndDlg, PFOLDER_FILE_TYPE_ENTRY pEntry) -{ - WCHAR Buffer[255]; - static HBITMAP s_hbmProgram = NULL; - - // format buffer and set groupbox text - CStringW strFormat(MAKEINTRESOURCEW(IDS_FILE_DETAILS)); - StringCchPrintfW(Buffer, _countof(Buffer), strFormat, &pEntry->FileExtension[1]); - SetDlgItemTextW(hwndDlg, IDC_FILETYPES_DETAILS_GROUPBOX, Buffer); - - // format buffer and set description - strFormat.LoadString(IDS_FILE_DETAILSADV); - StringCchPrintfW(Buffer, _countof(Buffer), strFormat, - &pEntry->FileExtension[1], pEntry->FileDescription, - pEntry->FileDescription); - SetDlgItemTextW(hwndDlg, IDC_FILETYPES_DESCRIPTION, Buffer); - - // delete previous program image - if (s_hbmProgram) - { - DeleteObject(s_hbmProgram); - s_hbmProgram = NULL; - } - - // set program image - HICON hIconSm = NULL; - ExtractIconExW(pEntry->ProgramPath, 0, NULL, &hIconSm, 1); - s_hbmProgram = BitmapFromIcon(hIconSm, 16, 16); - DestroyIcon(hIconSm); - SendDlgItemMessageW(hwndDlg, IDC_FILETYPES_ICON, STM_SETIMAGE, IMAGE_BITMAP, LPARAM(s_hbmProgram)); - - // set program name - if (pEntry->AppName[0]) - SetDlgItemTextW(hwndDlg, IDC_FILETYPES_APPNAME, pEntry->AppName); - else - SetDlgItemTextW(hwndDlg, IDC_FILETYPES_APPNAME, L"ReactOS"); - - /* Enable the Delete button */ - if (pEntry->EditFlags & 0x00000010) // FTA_NoRemove - EnableWindow(GetDlgItem(hwndDlg, IDC_FILETYPES_DELETE), FALSE); - else - EnableWindow(GetDlgItem(hwndDlg, IDC_FILETYPES_DELETE), TRUE); -} - -struct EDITTYPE_DIALOG -{ - HWND hwndLV; - FOLDER_FILE_TYPE_ENTRY *pEntry; - CSimpleMap<CStringW, CStringW> CommandLineMap; - WCHAR szIconPath[MAX_PATH]; - INT nIconIndex; - WCHAR szDefaultVerb[64]; -}; - -static BOOL -EditTypeDlg_ReadClass(HWND hwndDlg, EDITTYPE_DIALOG *pEditType, LPCWSTR ClassKey) -{ - // open class key - HKEY hClassKey; - if (RegOpenKeyExW(HKEY_CLASSES_ROOT, ClassKey, 0, KEY_READ, &hClassKey) != ERROR_SUCCESS) - return FALSE; - - // open "shell" key - HKEY hShellKey; - if (RegOpenKeyExW(hClassKey, L"shell", 0, KEY_READ, &hShellKey) != ERROR_SUCCESS) - { - RegCloseKey(hClassKey); - return FALSE; - } - - WCHAR DefaultVerb[64]; - DWORD dwSize = sizeof(DefaultVerb); - if (RegQueryValueExW(hShellKey, NULL, NULL, NULL, LPBYTE(DefaultVerb), &dwSize) == ERROR_SUCCESS) - { - StringCchCopyW(pEditType->szDefaultVerb, _countof(pEditType->szDefaultVerb), DefaultVerb); - } - else - { - StringCchCopyW(pEditType->szDefaultVerb, _countof(pEditType->szDefaultVerb), L"open"); - } - - // enumerate shell verbs - WCHAR szVerbName[64]; - DWORD dwIndex = 0; - while (RegEnumKeyW(hShellKey, dwIndex, szVerbName, _countof(szVerbName)) == ERROR_SUCCESS) - { - // open verb key - HKEY hVerbKey; - LONG nResult = RegOpenKeyExW(hShellKey, szVerbName, 0, KEY_READ, &hVerbKey); - if (nResult == ERROR_SUCCESS) - { - // open command key - HKEY hCommandKey; - nResult = RegOpenKeyExW(hVerbKey, L"command", 0, KEY_READ, &hCommandKey); - if (nResult == ERROR_SUCCESS) - { - // get command line - WCHAR szValue[MAX_PATH + 32]; - dwSize = sizeof(szValue); - nResult = RegQueryValueExW(hCommandKey, NULL, NULL, NULL, LPBYTE(szValue), &dwSize); - if (nResult == ERROR_SUCCESS) - { - pEditType->CommandLineMap.SetAt(szVerbName, szValue); - } - - RegCloseKey(hCommandKey); - } - - RegCloseKey(hVerbKey); - } - SendDlgItemMessageW(hwndDlg, IDC_EDITTYPE_LISTBOX, LB_ADDSTRING, 0, LPARAM(szVerbName)); - ++dwIndex; - } - - RegCloseKey(hShellKey); - RegCloseKey(hClassKey); - - return TRUE; -} - -static BOOL -EditTypeDlg_WriteClass(HWND hwndDlg, EDITTYPE_DIALOG *pEditType, - LPCWSTR ClassKey, LPCWSTR ClassName, INT cchName) -{ - FOLDER_FILE_TYPE_ENTRY *pEntry = pEditType->pEntry; - - if (ClassKey[0] == 0) - return FALSE; - - // create or open class key - HKEY hClassKey; - if (RegCreateKeyExW(HKEY_CLASSES_ROOT, ClassKey, 0, NULL, 0, KEY_WRITE, NULL, &hClassKey, NULL) != ERROR_SUCCESS) - return FALSE; - - // create "DefaultIcon" key - if (pEntry->IconPath[0]) - { - HKEY hDefaultIconKey; - if (RegCreateKeyExW(hClassKey, L"DefaultIcon", 0, NULL, 0, KEY_WRITE, NULL, &hDefaultIconKey, NULL) == ERROR_SUCCESS) - { - WCHAR szText[MAX_PATH]; - StringCchPrintfW(szText, _countof(szText), L"%s,%d", pEntry->IconPath, pEntry->nIconIndex); - - // set icon location - DWORD dwSize = (lstrlenW(szText) + 1) * sizeof(WCHAR); - RegSetValueExW(hDefaultIconKey, NULL, 0, REG_EXPAND_SZ, LPBYTE(szText), dwSize); - - RegCloseKey(hDefaultIconKey); - } - } - - // create "shell" key - HKEY hShellKey; - if (RegCreateKeyExW(hClassKey, L"shell", 0, NULL, 0, KEY_WRITE, NULL, &hShellKey, NULL) != ERROR_SUCCESS) - { - RegCloseKey(hClassKey); - return FALSE; - } - - // delete shell commands - WCHAR szVerbName[64]; - DWORD dwIndex = 0; - while (RegEnumKeyW(hShellKey, dwIndex, szVerbName, _countof(szVerbName)) == ERROR_SUCCESS) - { - if (pEditType->CommandLineMap.FindKey(szVerbName) == -1) - { - // doesn't exist in CommandLineMap, then delete it - if (SHDeleteKeyW(hShellKey, szVerbName) == ERROR_SUCCESS) - { - --dwIndex; - } - } - ++dwIndex; - } - - // set default action - RegSetValueExW(hShellKey, NULL, 0, REG_SZ, LPBYTE(pEditType->szDefaultVerb), sizeof(pEditType->szDefaultVerb)); - - // write shell commands - const INT nCount = pEditType->CommandLineMap.GetSize(); - for (INT i = 0; i < nCount; ++i) - { - CStringW& key = pEditType->CommandLineMap.GetKeyAt(i); - CStringW& value = pEditType->CommandLineMap.GetValueAt(i); - - // create verb key - HKEY hVerbKey; - if (RegCreateKeyExW(hShellKey, key, 0, NULL, 0, KEY_WRITE, NULL, &hVerbKey, NULL) == ERROR_SUCCESS) - { - // create command key - HKEY hCommandKey; - if (RegCreateKeyExW(hVerbKey, L"command", 0, NULL, 0, KEY_WRITE, NULL, &hCommandKey, NULL) == ERROR_SUCCESS) - { - // write the default value - DWORD dwSize = (value.GetLength() + 1) * sizeof(WCHAR); - RegSetValueExW(hCommandKey, NULL, 0, REG_EXPAND_SZ, LPBYTE(LPCWSTR(value)), dwSize); - - RegCloseKey(hCommandKey); - } - - RegCloseKey(hVerbKey); - } - } - - // set class name to class key - RegSetValueExW(hClassKey, NULL, 0, REG_SZ, LPBYTE(ClassName), cchName); - - RegCloseKey(hShellKey); - RegCloseKey(hClassKey); - - return TRUE; -} - -static BOOL -EditTypeDlg_OnInitDialog(HWND hwndDlg, EDITTYPE_DIALOG *pEditType) -{ - FOLDER_FILE_TYPE_ENTRY *pEntry = pEditType->pEntry; - StringCchCopyW(pEditType->szIconPath, _countof(pEditType->szIconPath), pEntry->IconPath); - pEditType->nIconIndex = pEntry->nIconIndex; - StringCchCopyW(pEditType->szDefaultVerb, _countof(pEditType->szDefaultVerb), L"open"); - - // set info - SendDlgItemMessageW(hwndDlg, IDC_EDITTYPE_ICON, STM_SETICON, (WPARAM)pEntry->hIconLarge, 0); - SetDlgItemTextW(hwndDlg, IDC_EDITTYPE_TEXT, pEntry->ClassName); - EditTypeDlg_ReadClass(hwndDlg, pEditType, pEntry->ClassKey); - InvalidateRect(GetDlgItem(hwndDlg, IDC_EDITTYPE_LISTBOX), NULL, TRUE); - - // is listbox empty? - if (SendDlgItemMessageW(hwndDlg, IDC_EDITTYPE_LISTBOX, LB_GETCOUNT, 0, 0) == 0) - { - EnableWindow(GetDlgItem(hwndDlg, IDC_EDITTYPE_EDIT_BUTTON), FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_EDITTYPE_REMOVE), FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_EDITTYPE_SET_DEFAULT), FALSE); - } - else - { - // select first item - SendDlgItemMessageW(hwndDlg, IDC_EDITTYPE_LISTBOX, LB_SETCURSEL, 0, 0); - } - - EnableWindow(GetDlgItem(hwndDlg, IDC_EDITTYPE_SAME_WINDOW), FALSE); - - return TRUE; -} - -static BOOL -EditTypeDlg_OnRemove(HWND hwndDlg, EDITTYPE_DIALOG *pEditType) -{ - // get current selection - INT iItem = SendDlgItemMessageW(hwndDlg, IDC_EDITTYPE_LISTBOX, LB_GETCURSEL, 0, 0); - if (iItem == LB_ERR) - return FALSE; - - // ask user for removal - CStringW strText(MAKEINTRESOURCEW(IDS_REMOVE_ACTION)); - CStringW strTitle(MAKEINTRESOURCEW(IDS_FILE_TYPES)); - if (MessageBoxW(hwndDlg, strText, strTitle, MB_ICONINFORMATION | MB_YESNO) == IDNO) - return FALSE; - - // get text - WCHAR szText[64]; - szText[0] = 0; - SendDlgItemMessageW(hwndDlg, IDC_EDITTYPE_LISTBOX, LB_GETTEXT, iItem, (LPARAM)szText); - StrTrimW(szText, s_pszSpace); - - // remove it - pEditType->CommandLineMap.Remove(szText); - SendDlgItemMessageW(hwndDlg, IDC_EDITTYPE_LISTBOX, LB_DELETESTRING, iItem, 0); - return TRUE; -} - -static BOOL -EditTypeDlg_UpdateEntryIcon(HWND hwndDlg, EDITTYPE_DIALOG *pEditType, LPCWSTR IconPath, INT IconIndex) -{ - FOLDER_FILE_TYPE_ENTRY *pEntry = pEditType->pEntry; - - BOOL bIconSet = FALSE; - if (IconPath && IconPath[0]) - { - DestroyIcon(pEntry->hIconLarge); - DestroyIcon(pEntry->hIconSmall); - pEntry->hIconLarge = DoExtractIcon(pEntry, IconPath, IconIndex, FALSE); - pEntry->hIconSmall = DoExtractIcon(pEntry, IconPath, IconIndex, TRUE); - - bIconSet = (pEntry->hIconLarge && pEntry->hIconSmall); - } - if (bIconSet) - { - StringCchCopyW(pEntry->IconPath, _countof(pEntry->IconPath), IconPath); - pEntry->nIconIndex = IconIndex; - } - else - { - SetFileTypeEntryDefaultIcon(pEntry); - } - - HWND hListView = pEditType->hwndLV; - HIMAGELIST himlLarge = ListView_GetImageList(hListView, LVSIL_NORMAL); - HIMAGELIST himlSmall = ListView_GetImageList(hListView, LVSIL_SMALL); - - INT iLargeImage = ImageList_AddIcon(himlLarge, pEntry->hIconLarge); - INT iSmallImage = ImageList_AddIcon(himlSmall, pEntry->hIconSmall); - ASSERT(iLargeImage == iSmallImage); - - INT iItem = ListView_GetNextItem(hListView, -1, LVNI_SELECTED); - if (iItem != -1) - { - LV_ITEMW Item = { LVIF_IMAGE, iItem }; - Item.iImage = iSmallImage; - ListView_SetItem(hListView, &Item); - } - return TRUE; -} - -static void -EditTypeDlg_OnOK(HWND hwndDlg, EDITTYPE_DIALOG *pEditType) -{ - FOLDER_FILE_TYPE_ENTRY *pEntry = pEditType->pEntry; - - // get class name - GetDlgItemTextW(hwndDlg, IDC_EDITTYPE_TEXT, pEntry->ClassName, _countof(pEntry->ClassName)); - StrTrimW(pEntry->ClassName, s_pszSpace); - - // update entry icon - EditTypeDlg_UpdateEntryIcon(hwndDlg, pEditType, pEditType->szIconPath, pEditType->nIconIndex); - - // write registry - EditTypeDlg_WriteClass(hwndDlg, pEditType, pEntry->ClassKey, pEntry->ClassName, _countof(pEntry->ClassName)); - - // update the icon cache - SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_FLUSHNOWAIT, NULL, NULL); - - EndDialog(hwndDlg, IDOK); -} - -struct ACTION_DIALOG -{ - HWND hwndLB; - WCHAR ClassName[64]; - WCHAR szAction[64]; - WCHAR szApp[MAX_PATH]; - BOOL bUseDDE; -}; - -static void -NewAct_OnOK(HWND hwndDlg, ACTION_DIALOG *pNewAct) -{ - GetDlgItemTextW(hwndDlg, IDC_ACTION_ACTION, pNewAct->szAction, _countof(pNewAct->szAction)); - GetDlgItemTextW(hwndDlg, IDC_ACTION_APP, pNewAct->szApp, _countof(pNewAct->szApp)); - StrTrimW(pNewAct->szAction, s_pszSpace); - StrTrimW(pNewAct->szApp, s_pszSpace); - if (pNewAct->szAction[0] == 0) - { - // action is empty, error - HWND hwndCtrl = GetDlgItem(hwndDlg, IDC_ACTION_ACTION); - SendMessageW(hwndCtrl, EM_SETSEL, 0, -1); - SetFocus(hwndCtrl); - CStringW strText(MAKEINTRESOURCEW(IDS_SPECIFY_ACTION)); - CStringW strTitle(MAKEINTRESOURCEW(IDS_FILE_TYPES)); - MessageBoxW(hwndDlg, strText, strTitle, MB_ICONERROR); - return; - } - if (pNewAct->szApp[0] == 0 || GetFileAttributesW(pNewAct->szApp) == 0xFFFFFFFF) - { - // app is invalid - HWND hwndCtrl = GetDlgItem(hwndDlg, IDC_ACTION_APP); - SendMessageW(hwndCtrl, EM_SETSEL, 0, -1); - SetFocus(hwndCtrl); - CStringW strText(MAKEINTRESOURCEW(IDS_INVALID_PROGRAM)); - CStringW strTitle(MAKEINTRESOURCEW(IDS_FILE_TYPES)); - MessageBoxW(hwndDlg, strText, strTitle, MB_ICONERROR); - return; - } - EndDialog(hwndDlg, IDOK); -} - -static void -Action_OnBrowse(HWND hwndDlg, ACTION_DIALOG *pNewAct, BOOL bEdit = FALSE) -{ - WCHAR szFile[MAX_PATH]; - szFile[0] = 0; - - WCHAR szFilter[MAX_PATH]; - LoadStringW(shell32_hInstance, IDS_EXE_FILTER, szFilter, _countof(szFilter)); - - CStringW strTitle(MAKEINTRESOURCEW(IDS_OPEN_WITH)); - - OPENFILENAMEW ofn; - ZeroMemory(&ofn, sizeof(ofn)); - ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400W; - ofn.hwndOwner = hwndDlg; - ofn.lpstrFilter = szFilter; - ofn.lpstrFile = szFile; - ofn.nMaxFile = _countof(szFile); - ofn.lpstrTitle = strTitle; - ofn.Flags = OFN_ENABLESIZING | OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY; - ofn.lpstrDefExt = L"exe"; - if (GetOpenFileNameW(&ofn)) - { - if (bEdit) - { - CStringW str = szFile; - str += L" "%1""; - SetDlgItemTextW(hwndDlg, IDC_ACTION_APP, str); - } - else - { - SetDlgItemTextW(hwndDlg, IDC_ACTION_APP, szFile); - } - } -} - -INT_PTR CALLBACK -NewActionDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - static ACTION_DIALOG *s_pNewAct = NULL; - - switch (uMsg) - { - case WM_INITDIALOG: - s_pNewAct = (ACTION_DIALOG *)lParam; - s_pNewAct->bUseDDE = FALSE; - EnableWindow(GetDlgItem(hwndDlg, IDC_ACTION_USE_DDE), FALSE); - return TRUE; - - case WM_COMMAND: - switch (LOWORD(wParam)) - { - case IDOK: - NewAct_OnOK(hwndDlg, s_pNewAct); - break; - - case IDCANCEL: - EndDialog(hwndDlg, IDCANCEL); - break; - - case IDC_ACTION_BROWSE: - Action_OnBrowse(hwndDlg, s_pNewAct, FALSE); - break; - } - break; - } - return 0; -} - -static void -EditAct_OnOK(HWND hwndDlg, ACTION_DIALOG *pEditAct) -{ - GetDlgItemTextW(hwndDlg, IDC_ACTION_ACTION, pEditAct->szAction, _countof(pEditAct->szAction)); - GetDlgItemTextW(hwndDlg, IDC_ACTION_APP, pEditAct->szApp, _countof(pEditAct->szApp)); - StrTrimW(pEditAct->szAction, s_pszSpace); - StrTrimW(pEditAct->szApp, s_pszSpace); - if (pEditAct->szAction[0] == 0) - { - HWND hwndCtrl = GetDlgItem(hwndDlg, IDC_ACTION_ACTION); - SendMessageW(hwndCtrl, EM_SETSEL, 0, -1); - SetFocus(hwndCtrl); - CStringW strText(MAKEINTRESOURCEW(IDS_SPECIFY_ACTION)); - CStringW strTitle(MAKEINTRESOURCEW(IDS_FILE_TYPES)); - MessageBoxW(hwndDlg, strText, strTitle, MB_ICONERROR); - } - if (pEditAct->szApp[0] == 0) - { - HWND hwndCtrl = GetDlgItem(hwndDlg, IDC_ACTION_APP); - SendMessageW(hwndCtrl, EM_SETSEL, 0, -1); - SetFocus(hwndCtrl); - CStringW strText(MAKEINTRESOURCEW(IDS_INVALID_PROGRAM)); - CStringW strTitle(MAKEINTRESOURCEW(IDS_FILE_TYPES)); - MessageBoxW(hwndDlg, strText, strTitle, MB_ICONERROR); - } - EndDialog(hwndDlg, IDOK); -} - -INT_PTR CALLBACK -EditActionDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - static ACTION_DIALOG *s_pEditAct = NULL; - - switch (uMsg) - { - case WM_INITDIALOG: - s_pEditAct = (ACTION_DIALOG *)lParam; - s_pEditAct->bUseDDE = FALSE; - SetDlgItemTextW(hwndDlg, IDC_ACTION_ACTION, s_pEditAct->szAction); - SetDlgItemTextW(hwndDlg, IDC_ACTION_APP, s_pEditAct->szApp); - EnableWindow(GetDlgItem(hwndDlg, IDC_ACTION_USE_DDE), FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_ACTION_ACTION), FALSE); - { - // set title - CStringW str(MAKEINTRESOURCEW(IDS_EDITING_ACTION)); - str += s_pEditAct->ClassName; - SetWindowTextW(hwndDlg, str); - } - return TRUE; - - case WM_COMMAND: - switch (LOWORD(wParam)) - { - case IDOK: - EditAct_OnOK(hwndDlg, s_pEditAct); - break; - - case IDCANCEL: - EndDialog(hwndDlg, IDCANCEL); - break; - - case IDC_ACTION_BROWSE: - Action_OnBrowse(hwndDlg, s_pEditAct, TRUE); - break; - } - break; - } - return 0; -} - -static void -EditTypeDlg_OnChangeIcon(HWND hwndDlg, EDITTYPE_DIALOG *pEditType) -{ - WCHAR szPath[MAX_PATH]; - INT IconIndex; - - ExpandEnvironmentStringsW(pEditType->szIconPath, szPath, _countof(szPath)); - IconIndex = pEditType->nIconIndex; - if (PickIconDlg(hwndDlg, szPath, _countof(szPath), &IconIndex)) - { - // replace Windows directory with "%SystemRoot%" (for portability) - WCHAR szWinDir[MAX_PATH]; - GetWindowsDirectoryW(szWinDir, _countof(szWinDir)); - if (wcsstr(szPath, szWinDir) == 0) - { - CStringW str(L"%SystemRoot%"); - str += &szPath[wcslen(szWinDir)]; - StringCchCopyW(szPath, _countof(szPath), LPCWSTR(str)); - } - - // update FOLDER_FILE_TYPE_ENTRY - FOLDER_FILE_TYPE_ENTRY *pEntry = pEditType->pEntry; - DestroyIcon(pEntry->hIconLarge); - DestroyIcon(pEntry->hIconSmall); - pEntry->hIconLarge = DoExtractIcon(pEntry, szPath, IconIndex, FALSE); - pEntry->hIconSmall = DoExtractIcon(pEntry, szPath, IconIndex, TRUE); - - // update EDITTYPE_DIALOG - StringCchCopyW(pEditType->szIconPath, _countof(pEditType->szIconPath), szPath); - pEditType->nIconIndex = IconIndex; - - // set icon to dialog - SendDlgItemMessageW(hwndDlg, IDC_EDITTYPE_ICON, STM_SETICON, (WPARAM)pEntry->hIconLarge, 0); - } -} - -static BOOL -EditTypeDlg_OnDrawItem(HWND hwndDlg, LPDRAWITEMSTRUCT pDraw, EDITTYPE_DIALOG *pEditType) -{ - WCHAR szText[64]; - HFONT hFont, hFont2; - - if (!pDraw) - return FALSE; - - // fill rect and set colors - if (pDraw->itemState & ODS_SELECTED) - { - FillRect(pDraw->hDC, &pDraw->rcItem, HBRUSH(COLOR_HIGHLIGHT + 1)); - SetTextColor(pDraw->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT)); - SetBkColor(pDraw->hDC, GetSysColor(COLOR_HIGHLIGHT)); - } - else - { - FillRect(pDraw->hDC, &pDraw->rcItem, HBRUSH(COLOR_WINDOW + 1)); - SetTextColor(pDraw->hDC, GetSysColor(COLOR_WINDOWTEXT)); - SetBkColor(pDraw->hDC, GetSysColor(COLOR_WINDOW)); - } - - // get listbox text - SendDlgItemMessageW(hwndDlg, IDC_EDITTYPE_LISTBOX, LB_GETTEXT, pDraw->itemID, (LPARAM)szText); - - // is it default? - hFont = (HFONT)SendDlgItemMessageW(hwndDlg, IDC_EDITTYPE_LISTBOX, WM_GETFONT, 0, 0); - if (lstrcmpiW(pEditType->szDefaultVerb, szText) == 0) - { - // default. set bold - LOGFONTW lf; - GetObject(hFont, sizeof(lf), &lf); - lf.lfWeight = FW_BOLD; - hFont2 = CreateFontIndirectW(&lf); - if (hFont2) - { - HGDIOBJ hFontOld = SelectObject(pDraw->hDC, hFont2); - InflateRect(&pDraw->rcItem, -2, -2); - DrawTextW(pDraw->hDC, szText, -1, &pDraw->rcItem, DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_NOPREFIX); - InflateRect(&pDraw->rcItem, 2, 2); - SelectObject(pDraw->hDC, hFontOld); - DeleteObject(hFont2); - } - } - else - { - // non-default - InflateRect(&pDraw->rcItem, -2, -2); - DrawTextW(pDraw->hDC, szText, -1, &pDraw->rcItem, DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_NOPREFIX); - InflateRect(&pDraw->rcItem, 2, 2); - } - - // draw focus rect - if (pDraw->itemState & ODS_FOCUS) - { - DrawFocusRect(pDraw->hDC, &pDraw->rcItem); - } - return TRUE; -} - -static BOOL -EditTypeDlg_OnMeasureItem(HWND hwndDlg, LPMEASUREITEMSTRUCT pMeasure, EDITTYPE_DIALOG *pEditType) -{ - if (!pMeasure) - return FALSE; - - HWND hwndLB = GetDlgItem(hwndDlg, IDC_EDITTYPE_LISTBOX); - - RECT rc; - GetClientRect(hwndLB, &rc); - - HDC hDC = GetDC(hwndLB); - if (hDC) - { - TEXTMETRICW tm; - GetTextMetricsW(hDC, &tm); - pMeasure->itemWidth = rc.right - rc.left; - pMeasure->itemHeight = tm.tmHeight + 4; - ReleaseDC(hwndLB, hDC); - return TRUE; - } - return FALSE; -} - -static void -EditTypeDlg_OnCommand(HWND hwndDlg, UINT id, UINT code, EDITTYPE_DIALOG *pEditType) -{ - INT iItem, iIndex; - ACTION_DIALOG action; - switch (id) - { - case IDOK: - EditTypeDlg_OnOK(hwndDlg, pEditType); - break; - - case IDCANCEL: - EndDialog(hwndDlg, IDCANCEL); - break; - - case IDC_EDITTYPE_CHANGE_ICON: - EditTypeDlg_OnChangeIcon(hwndDlg, pEditType); - break; - - case IDC_EDITTYPE_NEW: - action.bUseDDE = FALSE; - action.hwndLB = GetDlgItem(hwndDlg, IDC_EDITTYPE_LISTBOX); - StringCchPrintfW(action.ClassName, _countof(action.ClassName), pEditType->pEntry->ClassName); - // open 'New Action' dialog - if (IDOK == DialogBoxParamW(shell32_hInstance, MAKEINTRESOURCEW(IDD_ACTION), hwndDlg, - NewActionDlgProc, LPARAM(&action))) - { - if (SendMessageW(action.hwndLB, LB_FINDSTRING, -1, (LPARAM)action.szAction) != LB_ERR) - { - // already exists, error - HWND hwndCtrl = GetDlgItem(hwndDlg, IDC_ACTION_ACTION); - SendMessageW(hwndCtrl, EM_SETSEL, 0, -1); - SetFocus(hwndCtrl); - - CStringW strText, strTitle(MAKEINTRESOURCEW(IDS_FILE_TYPES)); - strText.Format(IDS_ACTION_EXISTS, action.szAction); - MessageBoxW(hwndDlg, strText, strTitle, MB_ICONERROR); - } - else - { - // add it - CStringW strCommandLine = action.szApp; - strCommandLine += L" "%1""; - pEditType->CommandLineMap.SetAt(action.szAction, strCommandLine); - SendMessageW(action.hwndLB, LB_ADDSTRING, 0, LPARAM(action.szAction)); - if (SendMessageW(action.hwndLB, LB_GETCOUNT, 0, 0) == 1) - { - // set default - StringCchCopyW(pEditType->szDefaultVerb, _countof(pEditType->szDefaultVerb), action.szAction); - InvalidateRect(action.hwndLB, NULL, TRUE); - } - } - } - break; - - case IDC_EDITTYPE_LISTBOX: - if (code == LBN_SELCHANGE) - { - action.hwndLB = GetDlgItem(hwndDlg, IDC_EDITTYPE_LISTBOX); - INT iItem = SendMessageW(action.hwndLB, LB_GETCURSEL, 0, 0); - SendMessageW(action.hwndLB, LB_GETTEXT, iItem, LPARAM(action.szAction)); - if (lstrcmpiW(action.szAction, pEditType->szDefaultVerb) == 0) - { - EnableWindow(GetDlgItem(hwndDlg, IDC_EDITTYPE_SET_DEFAULT), FALSE); - } - else - { - EnableWindow(GetDlgItem(hwndDlg, IDC_EDITTYPE_SET_DEFAULT), TRUE); - } - break; - } - else if (code != LBN_DBLCLK) - { - break; - } - // FALL THROUGH - - case IDC_EDITTYPE_EDIT_BUTTON: - action.bUseDDE = FALSE; - action.hwndLB = GetDlgItem(hwndDlg, IDC_EDITTYPE_LISTBOX); - StringCchPrintfW(action.ClassName, _countof(action.ClassName), pEditType->pEntry->ClassName); - iItem = SendMessageW(action.hwndLB, LB_GETCURSEL, 0, 0); - if (iItem == LB_ERR) - break; - - // get action - SendMessageW(action.hwndLB, LB_GETTEXT, iItem, LPARAM(action.szAction)); - - // get app - { - iIndex = pEditType->CommandLineMap.FindKey(action.szAction); - CStringW str = pEditType->CommandLineMap.GetValueAt(iIndex); - StringCchCopyW(action.szApp, _countof(action.szApp), LPCWSTR(str)); - } - - // open dialog - if (IDOK == DialogBoxParamW(shell32_hInstance, MAKEINTRESOURCEW(IDD_ACTION), hwndDlg, - EditActionDlgProc, LPARAM(&action))) - { - SendMessageW(action.hwndLB, LB_DELETESTRING, iItem, 0); - SendMessageW(action.hwndLB, LB_INSERTSTRING, iItem, LPARAM(action.szAction)); - pEditType->CommandLineMap.SetAt(action.szAction, action.szApp); - } - break; - - case IDC_EDITTYPE_REMOVE: - EditTypeDlg_OnRemove(hwndDlg, pEditType); - break; - - case IDC_EDITTYPE_SET_DEFAULT: - action.hwndLB = GetDlgItem(hwndDlg, IDC_EDITTYPE_LISTBOX); - iItem = SendMessageW(action.hwndLB, LB_GETCURSEL, 0, 0); - if (iItem == LB_ERR) - break; - - SendMessageW(action.hwndLB, LB_GETTEXT, iItem, LPARAM(action.szAction)); - - // set default - StringCchCopyW(pEditType->szDefaultVerb, _countof(pEditType->szDefaultVerb), action.szAction); - EnableWindow(GetDlgItem(hwndDlg, IDC_EDITTYPE_SET_DEFAULT), FALSE); - InvalidateRect(action.hwndLB, NULL, TRUE); - break; - } -} - -INT_PTR CALLBACK -EditTypeDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - static EDITTYPE_DIALOG *s_pEditType = NULL; - LPDRAWITEMSTRUCT pDraw; - LPMEASUREITEMSTRUCT pMeasure; - - switch (uMsg) - { - case WM_INITDIALOG: - s_pEditType = (EDITTYPE_DIALOG *)lParam; - return EditTypeDlg_OnInitDialog(hwndDlg, s_pEditType); - - case WM_DRAWITEM: - pDraw = LPDRAWITEMSTRUCT(lParam); - return EditTypeDlg_OnDrawItem(hwndDlg, pDraw, s_pEditType); - - case WM_MEASUREITEM: - pMeasure = LPMEASUREITEMSTRUCT(lParam); - return EditTypeDlg_OnMeasureItem(hwndDlg, pMeasure, s_pEditType); - - case WM_COMMAND: - EditTypeDlg_OnCommand(hwndDlg, LOWORD(wParam), HIWORD(wParam), s_pEditType); - break; - } - - return 0; -} - -static void -EditTypeDlg_OnDelete(HWND hwndDlg) -{ - CStringW strRemoveExt(MAKEINTRESOURCEW(IDS_REMOVE_EXT)); - CStringW strTitle(MAKEINTRESOURCEW(IDS_FILE_TYPES)); - if (MessageBoxW(hwndDlg, strRemoveExt, strTitle, MB_ICONQUESTION | MB_YESNO) == IDYES) - { - FileTypesDlg_RemoveExt(hwndDlg); - } -} - -// IDD_FOLDER_OPTIONS_FILETYPES dialog -INT_PTR -CALLBACK -FolderOptionsFileTypesDlg( - HWND hwndDlg, - UINT uMsg, - WPARAM wParam, - LPARAM lParam) -{ - LPNMLISTVIEW lppl; - PFOLDER_FILE_TYPE_ENTRY pItem; - OPENASINFO Info; - NEWEXT_DIALOG newext; - EDITTYPE_DIALOG edittype; - - switch(uMsg) - { - case WM_INITDIALOG: - 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, IDC_FILETYPES_DELETE), FALSE); - return TRUE; - - case WM_COMMAND: - switch(LOWORD(wParam)) - { - case IDC_FILETYPES_NEW: - newext.hwndLV = GetDlgItem(hwndDlg, IDC_FILETYPES_LISTVIEW); - if (IDOK == DialogBoxParamW(shell32_hInstance, MAKEINTRESOURCEW(IDD_NEWEXTENSION), - hwndDlg, NewExtensionDlgProc, (LPARAM)&newext)) - { - FileTypesDlg_AddExt(hwndDlg, newext.szExt, newext.szFileType); - } - break; - - case IDC_FILETYPES_DELETE: - EditTypeDlg_OnDelete(hwndDlg); - break; - - case IDC_FILETYPES_CHANGE: - pItem = GetListViewEntry(GetDlgItem(hwndDlg, IDC_FILETYPES_LISTVIEW)); - if (pItem) - { - Info.oaifInFlags = OAIF_ALLOW_REGISTRATION | OAIF_REGISTER_EXT; - Info.pcszClass = pItem->FileExtension; - SHOpenWithDialog(hwndDlg, &Info); - } - break; - - case IDC_FILETYPES_ADVANCED: - edittype.hwndLV = GetDlgItem(hwndDlg, IDC_FILETYPES_LISTVIEW); - edittype.pEntry = GetListViewEntry(edittype.hwndLV); - DialogBoxParamW(shell32_hInstance, MAKEINTRESOURCEW(IDD_EDITTYPE), - hwndDlg, EditTypeDlgProc, (LPARAM)&edittype); - break; - } - break; - - case WM_NOTIFY: - lppl = (LPNMLISTVIEW) lParam; - switch (lppl->hdr.code) - { - case LVN_KEYDOWN: - { - LV_KEYDOWN *pKeyDown = (LV_KEYDOWN *)lParam; - if (pKeyDown->wVKey == VK_DELETE) - { - EditTypeDlg_OnDelete(hwndDlg); - } - break; - } - - case NM_DBLCLK: - edittype.hwndLV = GetDlgItem(hwndDlg, IDC_FILETYPES_LISTVIEW); - edittype.pEntry = GetListViewEntry(edittype.hwndLV); - DialogBoxParamW(shell32_hInstance, MAKEINTRESOURCEW(IDD_EDITTYPE), - hwndDlg, EditTypeDlgProc, (LPARAM)&edittype); - break; - - case LVN_DELETEALLITEMS: - return FALSE; // send LVN_DELETEITEM - - case LVN_DELETEITEM: - pItem = GetListViewEntry(lppl->hdr.hwndFrom, lppl->iItem); - if (pItem) - { - DestroyIcon(pItem->hIconLarge); - DestroyIcon(pItem->hIconSmall); - HeapFree(GetProcessHeap(), 0, pItem); - } - return FALSE; - - case LVN_ITEMCHANGING: - pItem = GetListViewEntry(lppl->hdr.hwndFrom, lppl->iItem); - if (!pItem) - { - return TRUE; - } - - if (!(lppl->uOldState & LVIS_FOCUSED) && (lppl->uNewState & LVIS_FOCUSED)) - { - FileTypesDlg_OnItemChanging(hwndDlg, pItem); - } - break; - - case PSN_SETACTIVE: - /* On page activation, set the focus to the listview */ - SetFocus(GetDlgItem(hwndDlg, IDC_FILETYPES_LISTVIEW)); - break; - } - break; - } - - return FALSE; -} - -static -VOID -ShowFolderOptionsDialog(HWND hWnd, HINSTANCE hInst) -{ - PROPSHEETHEADERW pinfo; - HPROPSHEETPAGE hppages[3]; - HPROPSHEETPAGE hpage; - UINT num_pages = 0; - WCHAR szOptions[100]; - - hpage = SH_CreatePropertySheetPage(IDD_FOLDER_OPTIONS_GENERAL, FolderOptionsGeneralDlg, 0, NULL); - if (hpage) - hppages[num_pages++] = hpage; - - hpage = SH_CreatePropertySheetPage(IDD_FOLDER_OPTIONS_VIEW, FolderOptionsViewDlg, 0, NULL); - if (hpage) - hppages[num_pages++] = hpage; - - hpage = SH_CreatePropertySheetPage(IDD_FOLDER_OPTIONS_FILETYPES, FolderOptionsFileTypesDlg, 0, NULL); - if (hpage) - hppages[num_pages++] = hpage; - - szOptions[0] = L'\0'; - LoadStringW(shell32_hInstance, IDS_FOLDER_OPTIONS, szOptions, sizeof(szOptions) / sizeof(WCHAR)); - szOptions[(sizeof(szOptions)/sizeof(WCHAR))-1] = L'\0'; - - memset(&pinfo, 0x0, sizeof(PROPSHEETHEADERW)); - pinfo.dwSize = sizeof(PROPSHEETHEADERW); - pinfo.dwFlags = PSH_NOCONTEXTHELP; - pinfo.nPages = num_pages; - pinfo.phpage = hppages; - pinfo.pszCaption = szOptions; - - PropertySheetW(&pinfo); -} - -static -VOID Options_RunDLLCommon(HWND hWnd, HINSTANCE hInst, int fOptions, DWORD nCmdShow) { switch(fOptions) @@ -3089,7 +250,8 @@ Options_RunDLLCommon(HWND hWnd, HINSTANCE hInst, int fOptions, DWORD nCmdShow) /************************************************************************* * Options_RunDLL (SHELL32.@) */ -EXTERN_C VOID WINAPI Options_RunDLL(HWND hWnd, HINSTANCE hInst, LPCSTR cmd, DWORD nCmdShow) +EXTERN_C VOID WINAPI +Options_RunDLL(HWND hWnd, HINSTANCE hInst, LPCSTR cmd, DWORD nCmdShow) { Options_RunDLLCommon(hWnd, hInst, StrToIntA(cmd), nCmdShow); } @@ -3097,7 +259,8 @@ EXTERN_C VOID WINAPI Options_RunDLL(HWND hWnd, HINSTANCE hInst, LPCSTR cmd, DWOR /************************************************************************* * Options_RunDLLA (SHELL32.@) */ -EXTERN_C VOID WINAPI Options_RunDLLA(HWND hWnd, HINSTANCE hInst, LPCSTR cmd, DWORD nCmdShow) +EXTERN_C VOID WINAPI +Options_RunDLLA(HWND hWnd, HINSTANCE hInst, LPCSTR cmd, DWORD nCmdShow) { Options_RunDLLCommon(hWnd, hInst, StrToIntA(cmd), nCmdShow); } @@ -3105,7 +268,8 @@ EXTERN_C VOID WINAPI Options_RunDLLA(HWND hWnd, HINSTANCE hInst, LPCSTR cmd, DWO /************************************************************************* * Options_RunDLLW (SHELL32.@) */ -EXTERN_C VOID WINAPI Options_RunDLLW(HWND hWnd, HINSTANCE hInst, LPCWSTR cmd, DWORD nCmdShow) +EXTERN_C VOID WINAPI +Options_RunDLLW(HWND hWnd, HINSTANCE hInst, LPCWSTR cmd, DWORD nCmdShow) { Options_RunDLLCommon(hWnd, hInst, StrToIntW(cmd), nCmdShow); } diff --git a/dll/win32/shell32/dialogs/folder_options.h b/dll/win32/shell32/dialogs/folder_options.h new file mode 100644 index 0000000000..7b5af73c14 --- /dev/null +++ b/dll/win32/shell32/dialogs/folder_options.h @@ -0,0 +1,55 @@ +/* + * Folder Options + * + * Copyright 2007 Johannes Anderwald johannes.anderwald@reactos.org + * Copyright 2016-2018 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 + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +// IDD_FOLDER_OPTIONS_GENERAL +INT_PTR +CALLBACK +FolderOptionsGeneralDlg( + HWND hwndDlg, + UINT uMsg, + WPARAM wParam, + LPARAM lParam); + +// IDD_FOLDER_OPTIONS_VIEW +INT_PTR CALLBACK +FolderOptionsViewDlg( + HWND hwndDlg, + UINT uMsg, + WPARAM wParam, + LPARAM lParam); + +// IDD_FOLDER_OPTIONS_FILETYPES +INT_PTR CALLBACK +FolderOptionsFileTypesDlg( + HWND hwndDlg, + UINT uMsg, + WPARAM wParam, + LPARAM lParam); + +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/general.cpp b/dll/win32/shell32/dialogs/general.cpp new file mode 100644 index 0000000000..e44f21cd82 --- /dev/null +++ b/dll/win32/shell32/dialogs/general.cpp @@ -0,0 +1,147 @@ +/* + * 'General' tab property sheet of Folder Options + * + * Copyright 2007 Johannes Anderwald johannes.anderwald@reactos.org + * Copyright 2016-2018 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 + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "precomp.h" + +WINE_DEFAULT_DEBUG_CHANNEL (fprop); + +static VOID +GeneralDlg_UpdateIcons(HWND hDlg) +{ + 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) + { + HWND hwndTaskIcon = GetDlgItem(hDlg, IDC_FOLDER_OPTIONS_TASKICON); ... 1788 lines suppressed ...