https://git.reactos.org/?p=reactos.git;a=commitdiff;h=43d07fe695d427c2f8099066d376d6b036db7d74

commit 43d07fe695d427c2f8099066d376d6b036db7d74
Author:     Whindmar Saksit <whinds...@proton.me>
AuthorDate: Mon Oct 14 18:03:28 2024 +0200
Commit:     GitHub <nore...@github.com>
CommitDate: Mon Oct 14 18:03:28 2024 +0200

    [SHELL32] File Types dialog: Add functionality, optimize loading time 
(#6122)
    
    - Support loading protocols like XP
    - Support most of the relevant EditFlags
    - Support reading/writing the AlwaysShowExt and BrowserFlags properties
    - Loads the list much faster with optimized code and delaying the large 
icon and description string
    - Reduce the number of magic buffer sizes by replacing them with defines 
that are in the ballpark of being correct
    - Implemented column sorting
    - Removed custom icon extraction code
    - Removed IDS_FILE_EXT_TYPE string because it must be the same as 
IDS_ANY_FILE
    - Don't touch verb keys that are not edited to retain the original REG type
    - Don't clobber unchanged %1 icon location when editing a type
    
    CORE-19756
---
 dll/win32/shell32/CDefaultContextMenu.cpp |    5 -
 dll/win32/shell32/dialogs/filetypes.cpp   | 1267 +++++++++++++++++------------
 dll/win32/shell32/lang/bg-BG.rc           |    4 -
 dll/win32/shell32/lang/ca-ES.rc           |    6 +-
 dll/win32/shell32/lang/cs-CZ.rc           |    4 -
 dll/win32/shell32/lang/da-DK.rc           |    6 +-
 dll/win32/shell32/lang/de-DE.rc           |    4 -
 dll/win32/shell32/lang/el-GR.rc           |    6 +-
 dll/win32/shell32/lang/en-GB.rc           |    6 +-
 dll/win32/shell32/lang/en-US.rc           |    6 +-
 dll/win32/shell32/lang/es-ES.rc           |    4 -
 dll/win32/shell32/lang/et-EE.rc           |    4 -
 dll/win32/shell32/lang/eu-ES.rc           |    4 -
 dll/win32/shell32/lang/fi-FI.rc           |    6 +-
 dll/win32/shell32/lang/fr-FR.rc           |    4 -
 dll/win32/shell32/lang/he-IL.rc           |    4 -
 dll/win32/shell32/lang/hi-IN.rc           |    4 -
 dll/win32/shell32/lang/hu-HU.rc           |    4 -
 dll/win32/shell32/lang/id-ID.rc           |    4 -
 dll/win32/shell32/lang/it-IT.rc           |    4 -
 dll/win32/shell32/lang/ja-JP.rc           |    4 -
 dll/win32/shell32/lang/ko-KR.rc           |    6 +-
 dll/win32/shell32/lang/nl-NL.rc           |    6 +-
 dll/win32/shell32/lang/no-NO.rc           |    6 +-
 dll/win32/shell32/lang/pl-PL.rc           |    4 -
 dll/win32/shell32/lang/pt-BR.rc           |    4 -
 dll/win32/shell32/lang/pt-PT.rc           |    4 -
 dll/win32/shell32/lang/ro-RO.rc           |    5 +-
 dll/win32/shell32/lang/ru-RU.rc           |    4 -
 dll/win32/shell32/lang/sk-SK.rc           |    6 +-
 dll/win32/shell32/lang/sl-SI.rc           |    6 +-
 dll/win32/shell32/lang/sq-AL.rc           |    4 -
 dll/win32/shell32/lang/sv-SE.rc           |    6 +-
 dll/win32/shell32/lang/tr-TR.rc           |    4 -
 dll/win32/shell32/lang/uk-UA.rc           |    4 -
 dll/win32/shell32/lang/zh-CN.rc           |    4 -
 dll/win32/shell32/lang/zh-HK.rc           |    4 -
 dll/win32/shell32/lang/zh-TW.rc           |    4 -
 dll/win32/shell32/precomp.h               |    1 +
 dll/win32/shell32/shresdef.h              |    1 -
 dll/win32/shell32/utils.h                 |   47 ++
 sdk/include/psdk/shlwapi.h                |   26 +
 42 files changed, 820 insertions(+), 696 deletions(-)

diff --git a/dll/win32/shell32/CDefaultContextMenu.cpp 
b/dll/win32/shell32/CDefaultContextMenu.cpp
index 9bc9c97ab68..93d6ebe3bd4 100644
--- a/dll/win32/shell32/CDefaultContextMenu.cpp
+++ b/dll/win32/shell32/CDefaultContextMenu.cpp
@@ -23,11 +23,6 @@ SHELL_GetRegCLSID(HKEY hKey, LPCWSTR SubKey, LPCWSTR Value, 
CLSID &clsid)
     return !err ? CLSIDFromString(buf, &clsid) : HRESULT_FROM_WIN32(err);
 }
 
-static inline bool RegValueExists(HKEY hKey, LPCWSTR Name)
-{
-    return RegQueryValueExW(hKey, Name, NULL, NULL, NULL, NULL) == 
ERROR_SUCCESS;
-}
-
 static BOOL InsertMenuItemAt(HMENU hMenu, UINT Pos, UINT Flags)
 {
     MENUITEMINFOW mii;
diff --git a/dll/win32/shell32/dialogs/filetypes.cpp 
b/dll/win32/shell32/dialogs/filetypes.cpp
index 47bdd00179f..33a7a1376bc 100644
--- a/dll/win32/shell32/dialogs/filetypes.cpp
+++ b/dll/win32/shell32/dialogs/filetypes.cpp
@@ -20,30 +20,128 @@
  */
 
 #include "precomp.h"
+#include <atlpath.h>
 
 WINE_DEFAULT_DEBUG_CHANNEL (fprop);
 
-// DefaultIcon = %SystemRoot%\system32\SHELL32.dll,-210
-// Verbs: Open / RunAs
-//        Cmd: rundll32.exe shell32.dll,Options_RunDLL 0
+// rundll32.exe shell32.dll,Options_RunDLL 0
 
 /////////////////////////////////////////////////////////////////////////////
 
-typedef struct FILE_TYPE_ENTRY
+#define FTA_MODIFYMASK (FTA_OpenIsSafe) // Bits modified by EditTypeDlg
+#define NOASSOCRESID IDI_SHELL_DOCUMENT
+#define SUPPORT_EXTENSIONWITHOUTPROGID 1 // NT5 does not support these but NT6 
does
+
+#define ASSOC_CCHMAX (32 + 1) // Extension or protocol 
(INTERNET_MAX_SCHEME_LENGTH)
+#define TYPENAME_CCHMAX max(100, RTL_FIELD_SIZE(SHFILEINFOA, szTypeName))
+#define ICONLOCATION_CCHMAX (MAX_PATH + 1 + 11)
+
+typedef struct _FILE_TYPE_ENTRY
 {
-    WCHAR FileExtension[30];
-    WCHAR FileDescription[100];
+    WCHAR FileExtension[ASSOC_CCHMAX];
+    WCHAR FileDescription[TYPENAME_CCHMAX];
     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;
+
+    bool IsExtension() const
+    {
+        return FileExtension[0] == '.';
+    }
+    LPCWSTR GetAssocForDisplay() const
+    {
+        return FileExtension + (FileExtension[0] == '.');
+    }
+    void InvalidateTypeName()
+    {
+        FileDescription[0] = FileDescription[1] = UNICODE_NULL;
+    }
+    void InvalidateDefaultApp()
+    {
+        ProgramPath[0] = ProgramPath[1] = AppName[0] = AppName[1] = 
UNICODE_NULL;
+    }
+    void Initialize()
+    {
+        ClassKey[0] = UNICODE_NULL;
+        IconPath[0] = UNICODE_NULL;
+        nIconIndex = 0;
+        InvalidateTypeName();
+        InvalidateDefaultApp();
+    }
+    void DestroyIcons()
+    {
+        if (hIconSmall)
+            DestroyIcon(hIconSmall);
+        hIconSmall = NULL;
+    }
 } FILE_TYPE_ENTRY, *PFILE_TYPE_ENTRY;
 
+typedef struct _FILE_TYPE_GLOBALS
+{
+    HIMAGELIST himlSmall;
+    UINT IconSize;
+    HICON hDefExtIconSmall;
+    HBITMAP hOpenWithImage;
+    HANDLE hHeap;
+    WCHAR DefExtTypeNameFmt[TYPENAME_CCHMAX];
+    WCHAR NoneString[42];
+    INT8 SortCol, SortReverse;
+    UINT Restricted;
+} FILE_TYPE_GLOBALS, *PFILE_TYPE_GLOBALS;
+
+static DWORD
+GetRegDWORD(HKEY hKey, LPCWSTR Name, DWORD &Value, DWORD DefaultValue = 0, 
BOOL Strict = FALSE)
+{
+    DWORD cb = sizeof(DWORD), type;
+    LRESULT ec = RegQueryValueExW(hKey, Name, 0, &type, (BYTE*)&Value, &cb);
+    if (ec == ERROR_SUCCESS)
+    {
+        if ((type == REG_DWORD && cb == sizeof(DWORD)) ||
+            (!Strict && type == REG_BINARY && (cb && cb <= sizeof(DWORD))))
+        {
+            Value &= (0xffffffffUL >> (32 - cb * 8));
+            return ec;
+        }
+    }
+    Value = DefaultValue;
+    return ec ? ec : ERROR_BAD_FORMAT;
+}
+
+static DWORD
+GetRegDWORD(HKEY hKey, LPCWSTR Name, DWORD DefaultValue = 0)
+{
+    GetRegDWORD(hKey, Name, DefaultValue, DefaultValue, FALSE);
+    return DefaultValue;
+}
+
+static HRESULT
+GetClassKey(const FILE_TYPE_ENTRY &FTE, LPCWSTR &SubKey)
+{
+    HRESULT hr = S_OK;
+    LPCWSTR path = FTE.IsExtension() ? FTE.ClassKey : FTE.FileExtension;
+#if SUPPORT_EXTENSIONWITHOUTPROGID
+    if (!*path && FTE.IsExtension())
+    {
+        path = FTE.FileExtension;
+        hr = S_FALSE;
+    }
+#endif
+    ASSERT(*path);
+    SubKey = path;
+    return hr;
+}
+
+static void
+QuoteAppPathForCommand(CStringW &path)
+{
+    if (path.Find(' ') >= 0 && path.Find('\"') < 0)
+        path = CStringW(L"\"") + path + L"\"";
+}
+
 static BOOL
 DeleteExt(HWND hwndDlg, LPCWSTR pszExt)
 {
@@ -56,14 +154,15 @@ DeleteExt(HWND hwndDlg, LPCWSTR pszExt)
         return FALSE;
 
     // query "extfile" key name
-    WCHAR szValue[64] = { 0 };
-    DWORD cbValue = sizeof(szValue);
-    RegQueryValueExW(hKey, NULL, NULL, NULL, LPBYTE(szValue), &cbValue);
+    WCHAR ProgId[MAX_PATH] = { 0 };
+    DWORD cb = sizeof(ProgId);
+    RegQueryValueExW(hKey, NULL, NULL, NULL, LPBYTE(ProgId), &cb);
     RegCloseKey(hKey);
 
+    // FIXME: Should verify that no other extensions are using this ProgId
     // delete "extfile" key (if any)
-    if (szValue[0])
-        SHDeleteKeyW(HKEY_CLASSES_ROOT, szValue);
+    if (ProgId[0])
+        SHDeleteKeyW(HKEY_CLASSES_ROOT, ProgId);
 
     // delete ".ext" key
     BOOL ret = (SHDeleteKeyW(HKEY_CLASSES_ROOT, pszExt) == ERROR_SUCCESS);
@@ -75,133 +174,184 @@ DeleteExt(HWND hwndDlg, LPCWSTR pszExt)
 }
 
 static inline HICON
-DoExtractIcon(PFILE_TYPE_ENTRY Entry, LPCWSTR IconPath,
-              INT iIndex = 0, BOOL bSmall = FALSE)
+DoExtractIcon(LPCWSTR IconPath, INT iIndex, UINT cx, UINT cy)
 {
-    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;
+    return SHELL32_SHExtractIcon(IconPath, iIndex, cx, cy);
 }
 
-static void
-DoFileTypeIconLocation(PFILE_TYPE_ENTRY Entry, LPCWSTR IconLocation)
+static HICON
+DoExtractIcon(LPCWSTR IconPath, INT iIndex = 0, BOOL bSmall = FALSE)
 {
-    // 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);
+    UINT cx = GetSystemMetrics(bSmall ? SM_CXSMICON : SM_CXICON);
+    UINT cy = GetSystemMetrics(bSmall ? SM_CYSMICON : SM_CYICON);
+    return DoExtractIcon(IconPath, iIndex, cx, cy);
 }
 
 static BOOL
-GetFileTypeIconsEx(PFILE_TYPE_ENTRY Entry, LPCWSTR IconLocation)
+GetFileTypeIconsEx(PFILE_TYPE_ENTRY Entry, LPCWSTR IconLocation, UINT IconSize)
 {
-    Entry->hIconLarge = Entry->hIconSmall = NULL;
-
-    if (lstrcmpiW(Entry->FileExtension, L".exe") == 0 ||
-        lstrcmpiW(Entry->FileExtension, L".scr") == 0)
+    Entry->hIconSmall = NULL;
+    if (lstrcmpW(IconLocation, L"%1") == 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
+        LPCWSTR ext = Entry->FileExtension;
+        if (!lstrcmpiW(ext, L".exe") || !lstrcmpiW(ext, L".scr"))
+        {
+            Entry->hIconSmall = HICON(LoadImageW(shell32_hInstance, 
MAKEINTRESOURCEW(IDI_SHELL_EXE),
+                                                 IMAGE_ICON, IconSize, 
IconSize, 0));
+            Entry->nIconIndex = -IDI_SHELL_EXE;
+        }
+        // Set the icon path to %1 on purpose so PickIconDlg will issue a 
warning
+        StringCbCopyW(Entry->IconPath, sizeof(Entry->IconPath), IconLocation);
     }
     else
     {
-        DoFileTypeIconLocation(Entry, IconLocation);
+        // Expand the REG_EXPAND_SZ string by environment variables
+        if (ExpandEnvironmentStringsW(IconLocation, Entry->IconPath, 
_countof(Entry->IconPath)))
+        {
+            Entry->nIconIndex = PathParseIconLocationW(Entry->IconPath);
+            Entry->hIconSmall = DoExtractIcon(Entry->IconPath, 
Entry->nIconIndex, IconSize, IconSize);
+        }
     }
-
-    return Entry->hIconLarge && Entry->hIconSmall;
+    return Entry->hIconSmall != NULL;
 }
 
 static BOOL
-GetFileTypeIconsByKey(HKEY hKey, PFILE_TYPE_ENTRY Entry)
+GetFileTypeIconsByKey(HKEY hKey, PFILE_TYPE_ENTRY Entry, UINT IconSize)
 {
-    Entry->hIconLarge = Entry->hIconSmall = NULL;
+    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 };
+    WCHAR szLocation[ICONLOCATION_CCHMAX];
     DWORD dwSize = sizeof(szLocation);
     nResult = RegQueryValueExW(hDefIconKey, NULL, NULL, NULL, 
LPBYTE(szLocation), &dwSize);
+    szLocation[_countof(szLocation) - 1] = UNICODE_NULL;
 
     RegCloseKey(hDefIconKey);
-
-    if (nResult != ERROR_SUCCESS || szLocation[0] == 0)
+    if (nResult != ERROR_SUCCESS || !szLocation[0])
         return FALSE;
 
-    return GetFileTypeIconsEx(Entry, szLocation);
+    return GetFileTypeIconsEx(Entry, szLocation, IconSize);
+}
+
+static LPCWSTR
+GetProgramPath(PFILE_TYPE_ENTRY Entry)
+{
+    if (!Entry->ProgramPath[1] && !Entry->ProgramPath[0])
+    {
+        DWORD cch = _countof(Entry->ProgramPath);
+        if (FAILED(AssocQueryStringW(ASSOCF_INIT_IGNOREUNKNOWN, 
ASSOCSTR_EXECUTABLE,
+                                     Entry->FileExtension, NULL, 
Entry->ProgramPath, &cch)))
+        {
+            Entry->ProgramPath[0] = UNICODE_NULL;
+            Entry->ProgramPath[1] = TRUE;
+        }
+    }
+    return Entry->ProgramPath;
 }
 
 static BOOL
 QueryFileDescription(LPCWSTR ProgramPath, LPWSTR pszName, INT cchName)
 {
-    SHFILEINFOW FileInfo = { 0 };
-    if (SHGetFileInfoW(ProgramPath, 0, &FileInfo, sizeof(FileInfo), 
SHGFI_DISPLAYNAME))
+    SHFILEINFOW fi;
+    fi.szDisplayName[0] = UNICODE_NULL;
+    if (SHGetFileInfoW(ProgramPath, 0, &fi, sizeof(fi), SHGFI_DISPLAYNAME))
     {
-        StringCchCopyW(pszName, cchName, FileInfo.szDisplayName);
+        StringCchCopyW(pszName, cchName, fi.szDisplayName);
         return TRUE;
     }
-
     return !!GetFileTitleW(ProgramPath, pszName, cchName);
 }
 
+static LPCWSTR
+GetAppName(PFILE_TYPE_ENTRY Entry)
+{
+    if (!Entry->AppName[1] && !Entry->AppName[0])
+    {
+        LPCWSTR exe = GetProgramPath(Entry);
+        if (!*exe || !QueryFileDescription(exe, Entry->AppName, 
_countof(Entry->AppName)))
+        {
+            Entry->AppName[0] = UNICODE_NULL;
+            Entry->AppName[1] = TRUE;
+        }
+    }
+    return Entry->AppName;
+}
+
+static LPWSTR
+GetTypeName(PFILE_TYPE_ENTRY Entry, PFILE_TYPE_GLOBALS pG)
+{
+    if (!Entry->FileDescription[1] && !Entry->FileDescription[0])
+    {
+        Entry->FileDescription[1] = TRUE;
+        if (Entry->IsExtension())
+        {
+            SHFILEINFOW fi;
+            if (SHGetFileInfoW(Entry->FileExtension, 0, &fi, sizeof(fi), 
SHGFI_TYPENAME |
+                               SHGFI_USEFILEATTRIBUTES) && *fi.szTypeName)
+            {
+                StringCchCopyW(Entry->FileDescription, 
_countof(Entry->FileDescription), fi.szTypeName);
+            }
+            else
+            {
+                // FIXME: Remove this hack when SHGetFileInfo is able to 
handle extensions without a ProgId (.ASM etc)
+                StringCchPrintfW(Entry->FileDescription, 
_countof(Entry->FileDescription),
+                                 pG->DefExtTypeNameFmt, 
&Entry->FileExtension[1]);
+            }
+        }
+        else
+        {
+            // FIXME: Fix and use ASSOCSTR_FRIENDLYDOCNAME
+            DWORD cb = sizeof(Entry->FileDescription), Fallback = TRUE;
+            LPCWSTR ClassKey;
+            HRESULT hr = GetClassKey(*Entry, ClassKey);
+            HKEY hKey;
+            if (SUCCEEDED(hr) && !RegOpenKeyExW(HKEY_CLASSES_ROOT, ClassKey, 
0, KEY_READ, &hKey))
+            {
+                Fallback = RegQueryValueExW(hKey, NULL, 0, NULL, 
(BYTE*)Entry->FileDescription, &cb) != ERROR_SUCCESS ||
+                           !*Entry->FileDescription;
+                RegCloseKey(hKey);
+            }
+            if (Fallback)
+            {
+                StringCchCopyW(Entry->FileDescription, 
_countof(Entry->FileDescription), Entry->FileExtension);
+            }
+        }
+    }
+    return Entry->FileDescription;
+}
+
 static void
-SetFileTypeEntryDefaultIcon(PFILE_TYPE_ENTRY Entry)
+InitializeDefaultIcons(PFILE_TYPE_GLOBALS pG)
 {
-    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;
+    const INT ResId = NOASSOCRESID;
+    if (!pG->hDefExtIconSmall)
+    {
+        pG->hDefExtIconSmall = HICON(LoadImageW(shell32_hInstance, 
MAKEINTRESOURCEW(ResId),
+                                                IMAGE_ICON, pG->IconSize, 
pG->IconSize, 0));
+    }
+
+    if (!ImageList_GetImageCount(pG->himlSmall))
+    {
+        int idx = ImageList_AddIcon(pG->himlSmall, pG->hDefExtIconSmall);
+        ASSERT(idx == 0);
+    }
+}
+
+static BOOL
+Normalize(PFILE_TYPE_ENTRY Entry)
+{
+    // We don't need this information until somebody tries to edit the entry
+    if (!Entry->IconPath[0])
+    {
+        StringCbCopyW(Entry->IconPath, sizeof(Entry->IconPath), g_pszShell32);
+        Entry->nIconIndex = NOASSOCRESID > 1 ? -NOASSOCRESID : 0;
+    }
+    return TRUE;
 }
 
 /////////////////////////////////////////////////////////////////////////////
@@ -209,56 +359,56 @@ SetFileTypeEntryDefaultIcon(PFILE_TYPE_ENTRY Entry)
 
 #define LISTBOX_MARGIN  2
 
+enum EDITTYPEFLAGS { ETF_ALWAYSEXT = 1 << 0, ETF_BROWSESAME = 1 << 1 };
+
 typedef struct EDITTYPE_DIALOG
 {
     HWND hwndLV;
+    PFILE_TYPE_GLOBALS pG;
     PFILE_TYPE_ENTRY pEntry;
     CSimpleMap<CStringW, CStringW> CommandLineMap;
+    CAtlList<CStringW> ModifiedVerbs;
     WCHAR szIconPath[MAX_PATH];
     INT nIconIndex;
-    WCHAR szDefaultVerb[64];
+    WCHAR szDefaultVerb[VERBKEY_CCHMAX];
+    WCHAR TypeName[TYPENAME_CCHMAX];
 } EDITTYPE_DIALOG, *PEDITTYPE_DIALOG;
 
 static void
 EditTypeDlg_OnChangeIcon(HWND hwndDlg, PEDITTYPE_DIALOG pEditType)
 {
     WCHAR szPath[MAX_PATH];
-    INT IconIndex;
-
+    INT IconIndex = pEditType->nIconIndex;
     ExpandEnvironmentStringsW(pEditType->szIconPath, szPath, _countof(szPath));
-    IconIndex = pEditType->nIconIndex;
     if (PickIconDlg(hwndDlg, szPath, _countof(szPath), &IconIndex))
     {
+        HICON hIconLarge = DoExtractIcon(szPath, IconIndex, FALSE);
+
         // replace Windows directory with "%SystemRoot%" (for portability)
         WCHAR szWinDir[MAX_PATH];
-        GetWindowsDirectoryW(szWinDir, _countof(szWinDir));
-        if (wcsstr(szPath, szWinDir) == 0)
+        UINT lenWinDir = GetWindowsDirectoryW(szWinDir, _countof(szWinDir));
+        if (StrStrIW(szPath, szWinDir) == szPath)
         {
-            CStringW str(L"%SystemRoot%");
-            str += &szPath[wcslen(szWinDir)];
-            StringCbCopyW(szPath, sizeof(szPath), LPCWSTR(str));
+            CPathW str(L"%SystemRoot%");
+            str.Append(&szPath[lenWinDir]);
+            StringCbCopyW(szPath, sizeof(szPath), 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);
+        HICON hOld = (HICON)SendDlgItemMessageW(hwndDlg, IDC_EDITTYPE_ICON, 
STM_SETICON, (WPARAM)hIconLarge, 0);
+        if (hOld)
+            DestroyIcon(hOld);
     }
 }
 
 static BOOL
 EditTypeDlg_OnDrawItem(HWND hwndDlg, LPDRAWITEMSTRUCT pDraw, PEDITTYPE_DIALOG 
pEditType)
 {
-    WCHAR szText[64];
+    WCHAR szText[MAX_PATH];
     HFONT hFont, hFont2;
 
     if (!pDraw)
@@ -367,6 +517,7 @@ NewExtDlg_OnAdvanced(HWND hwndDlg, PNEWEXT_DIALOG pNewExt)
     GetWindowRect(GetDlgItem(hwndDlg, IDCANCEL), &rc2);
     MapWindowPoints(NULL, hwndDlg, (LPPOINT)&rc2, 2);
 
+    HWND hClassCombo = GetDlgItem(hwndDlg, IDC_NEWEXT_COMBOBOX);
     if (pNewExt->bAdvanced)
     {
         rc1.top += pNewExt->dy;
@@ -376,12 +527,12 @@ NewExtDlg_OnAdvanced(HWND hwndDlg, PNEWEXT_DIALOG pNewExt)
         rc2.bottom += pNewExt->dy;
 
         ShowWindow(GetDlgItem(hwndDlg, IDC_NEWEXT_ASSOC), SW_SHOWNOACTIVATE);
-        ShowWindow(GetDlgItem(hwndDlg, IDC_NEWEXT_COMBOBOX), 
SW_SHOWNOACTIVATE);
+        ShowWindow(hClassCombo, SW_SHOWNOACTIVATE);
 
         CStringW strLeft(MAKEINTRESOURCEW(IDS_NEWEXT_ADVANCED_LEFT));
         SetDlgItemTextW(hwndDlg, IDC_NEWEXT_ADVANCED, strLeft);
 
-        SetFocus(GetDlgItem(hwndDlg, IDC_NEWEXT_COMBOBOX));
+        SetFocus(hClassCombo);
     }
     else
     {
@@ -392,15 +543,14 @@ NewExtDlg_OnAdvanced(HWND hwndDlg, PNEWEXT_DIALOG pNewExt)
         rc2.bottom -= pNewExt->dy;
 
         ShowWindow(GetDlgItem(hwndDlg, IDC_NEWEXT_ASSOC), SW_HIDE);
-        ShowWindow(GetDlgItem(hwndDlg, IDC_NEWEXT_COMBOBOX), SW_HIDE);
+        ShowWindow(hClassCombo, 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);
+        SendMessageW(hClassCombo, CB_SETCURSEL, 0, 0); // Reset the combo to 
the "new class" mode
     }
 
     HDWP hDWP = BeginDeferWindowPos(3);
@@ -458,8 +608,12 @@ NewExtDlg_OnOK(HWND hwndDlg, PNEWEXT_DIALOG pNewExt)
     StrTrimW(pNewExt->szExt, g_pszSpace);
     _wcsupr(pNewExt->szExt);
 
+#if 0
+    // FIXME: Implement the "choose existing class" mode
     GetDlgItemTextW(hwndDlg, IDC_NEWEXT_COMBOBOX, pNewExt->szFileType, 
_countof(pNewExt->szFileType));
     StrTrimW(pNewExt->szFileType, g_pszSpace);
+#endif
+    pNewExt->szFileType[0] = UNICODE_NULL; // "new class" mode
 
     if (pNewExt->szExt[0] == 0)
     {
@@ -486,7 +640,7 @@ NewExtDlg_OnOK(HWND hwndDlg, PNEWEXT_DIALOG pNewExt)
         // already exists
 
         // get file type
-        WCHAR szFileType[64];
+        WCHAR szFileType[TYPENAME_CCHMAX];
         LV_ITEM item;
         ZeroMemory(&item, sizeof(item));
         item.mask = LVIF_TEXT;
@@ -513,10 +667,8 @@ NewExtDlg_OnOK(HWND hwndDlg, PNEWEXT_DIALOG pNewExt)
         CStringW strExt(L".");
         strExt += find.psz;
         strExt.MakeLower();
-        DeleteExt(hwndDlg, strExt);
-
-        // Delete the item
-        ListView_DeleteItem(pNewExt->hwndLV, iItem);
+        if (DeleteExt(hwndDlg, strExt))
+            ListView_DeleteItem(pNewExt->hwndLV, iItem);
     }
 
     EndDialog(hwndDlg, IDOK);
@@ -561,192 +713,134 @@ NewExtDlgProc(
     return 0;
 }
 
-static BOOL
-FileTypesDlg_InsertToLV(HWND hListView, LPCWSTR szName, INT iItem, LPCWSTR 
szFile)
+static PFILE_TYPE_ENTRY
+FileTypesDlg_InsertToLV(HWND hListView, LPCWSTR Assoc, INT iItem, 
PFILE_TYPE_GLOBALS pG)
 {
     PFILE_TYPE_ENTRY Entry;
-    HKEY hKey;
+    HKEY hKey, hTemp;
     LVITEMW lvItem;
     DWORD dwSize;
-    DWORD dwType;
 
-    if (szName[0] != L'.')
+    if (RegOpenKeyExW(HKEY_CLASSES_ROOT, Assoc, 0, KEY_READ, &hKey) != 
ERROR_SUCCESS)
     {
-        // FIXME handle URL protocol handlers
-        return FALSE;
+        return NULL;
     }
-
-    // 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)
+    if (Assoc[0] != L'.' && !RegValueExists(hKey, L"URL Protocol"))
     {
-        HeapFree(GetProcessHeap(), 0, Entry);
-        return FALSE;
+        RegCloseKey(hKey);
+        return NULL;
     }
 
-    // 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)
+    Entry = (PFILE_TYPE_ENTRY)HeapAlloc(pG->hHeap, 0, sizeof(FILE_TYPE_ENTRY));
+    if (!Entry)
     {
-        // no link available
-        Entry->ClassKey[0] = 0;
+        RegCloseKey(hKey);
+        return NULL;
     }
+    Entry->Initialize();
 
-    Entry->ClassName[0] = 0;
-    if (Entry->ClassKey[0])
+    if (Assoc[0] == L'.')
     {
-        HKEY hTemp;
-        // try open linked key
-        if (RegOpenKeyExW(HKEY_CLASSES_ROOT, Entry->ClassKey, 0, KEY_READ, 
&hTemp) == ERROR_SUCCESS)
+        dwSize = sizeof(Entry->ClassKey);
+        if (RegQueryValueExW(hKey, NULL, NULL, NULL, LPBYTE(Entry->ClassKey), 
&dwSize))
+        {
+            Entry->ClassKey[0] = UNICODE_NULL; // No ProgId
+        }
+#if SUPPORT_EXTENSIONWITHOUTPROGID
+        if (Entry->ClassKey[0] && !RegOpenKeyExW(HKEY_CLASSES_ROOT, 
Entry->ClassKey, 0, KEY_READ, &hTemp))
         {
-            DWORD dwSize = sizeof(Entry->ClassName);
-            RegQueryValueExW(hTemp, NULL, NULL, NULL, 
LPBYTE(Entry->ClassName), &dwSize);
-
-            // use linked key
             RegCloseKey(hKey);
             hKey = hTemp;
         }
+#else
+        if (!Entry->ClassKey[0])
+        {
+            HeapFree(pG->hHeap, 0, Entry);
+            RegCloseKey(hKey);
+            return NULL;
+        }
+#endif
     }
 
-    // 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))
+    Entry->EditFlags = GetRegDWORD(hKey, L"EditFlags", 0);
+    if (Entry->EditFlags & FTA_Exclude)
     {
-        if ((dwType == REG_DWORD || dwType == REG_BINARY) && dwSize == 
sizeof(DWORD))
-            RegQueryValueExW(hKey, L"EditFlags", NULL, NULL, 
(LPBYTE)&Entry->EditFlags, &dwSize);
+        HeapFree(pG->hHeap, 0, Entry);
+        RegCloseKey(hKey);
+        return NULL;
     }
 
-    // convert extension to upper case
-    wcscpy(Entry->FileExtension, szName);
-    _wcsupr(Entry->FileExtension);
+    wcscpy(Entry->FileExtension, Assoc);
 
     // get icon
-    if (!GetFileTypeIconsByKey(hKey, Entry))
-    {
-        // set default icon
-        SetFileTypeEntryDefaultIcon(Entry);
-    }
+    Entry->IconPath[0] = UNICODE_NULL;
+    BOOL defaultIcon = !GetFileTypeIconsByKey(hKey, Entry, pG->IconSize);
 
-    // 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)
+    INT iSmallImage = 0;
+    if (!defaultIcon && Entry->hIconSmall)
     {
-        iLargeImage = ImageList_AddIcon(himlLarge, Entry->hIconLarge);
-        iSmallImage = ImageList_AddIcon(himlSmall, Entry->hIconSmall);
-        ASSERT(iLargeImage == iSmallImage);
-        DBG_UNREFERENCED_LOCAL_VARIABLE(iLargeImage);
+        iSmallImage = ImageList_AddIcon(pG->himlSmall, Entry->hIconSmall);
     }
 
-    // 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'
-
-        StringCbPrintfW(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.iSubItem = 0;
     lvItem.lParam = (LPARAM)Entry;
     lvItem.iImage = iSmallImage;
+    lvItem.pszText = Assoc[0] == L'.' ? _wcsupr(&Entry->FileExtension[1]) : 
pG->NoneString;
     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;
+    lvItem.pszText = LPSTR_TEXTCALLBACK;
     ListView_SetItem(hListView, &lvItem);
 
-    return TRUE;
+    return Entry;
 }
 
 static BOOL
-FileTypesDlg_AddExt(HWND hwndDlg, LPCWSTR pszExt, LPCWSTR pszFileType)
+FileTypesDlg_AddExt(HWND hwndDlg, LPCWSTR pszExt, LPCWSTR pszProgId, 
PFILE_TYPE_GLOBALS pG)
 {
     DWORD dwValue = 1;
     HKEY hKey;
     WCHAR szKey[13];    // max. "ft4294967295" + "\0"
     LONG nResult;
 
-    // Search the next "ft%06u" key name
-    do
+    if (!*pszProgId)
     {
-        StringCbPrintfW(szKey, sizeof(szKey), L"ft%06u", dwValue);
-
-        nResult = RegOpenKeyEx(HKEY_CLASSES_ROOT, szKey, 0, KEY_READ, &hKey);
-        if (nResult != ERROR_SUCCESS)
-            break;
+        pszProgId = szKey;
+        // Search the next "ft%06u" key name
+        do
+        {
+            StringCbPrintfW(szKey, sizeof(szKey), L"ft%06u", dwValue);
 
-        RegCloseKey(hKey);
-        ++dwValue;
-    } while (dwValue != 0);
+            nResult = RegOpenKeyEx(HKEY_CLASSES_ROOT, szKey, 0, KEY_READ, 
&hKey);
+            if (nResult != ERROR_SUCCESS)
+                break;
 
-    RegCloseKey(hKey);
+            RegCloseKey(hKey);
+            ++dwValue;
+        } while (dwValue != 0);
 
-    if (dwValue == 0)
-        return FALSE;
+        RegCloseKey(hKey);
 
-    // 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;
+        if (dwValue == 0)
+            return FALSE;
 
-    RegCloseKey(hKey);
+        // 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'.')
+    WCHAR szExt[ASSOC_CCHMAX];
+    if (*pszExt == L'.') // The user is allowed to type the extension with or 
without the . in the new dialog!
         ++pszExt;
     StringCbPrintfW(szExt, sizeof(szExt), L".%s", pszExt);
     _wcslwr(szExt);
@@ -756,37 +850,18 @@ FileTypesDlg_AddExt(HWND hwndDlg, LPCWSTR pszExt, LPCWSTR 
pszFileType)
         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);
+    RegSetString(hKey, NULL, pszProgId, REG_SZ);
 
     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))
+    if (!FileTypesDlg_InsertToLV(hListView, szExt, iItem, pG))
         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_SetItemState(hListView, iItem, -1, LVIS_FOCUSED | LVIS_SELECTED);
     ListView_EnsureVisible(hListView, iItem, FALSE);
-
     return TRUE;
 }
 
@@ -799,13 +874,15 @@ FileTypesDlg_RemoveExt(HWND hwndDlg)
     if (iItem == -1)
         return FALSE;
 
-    WCHAR szExt[20];
+    WCHAR szExt[MAX_PATH];
     szExt[0] = L'.';
     ListView_GetItemText(hListView, iItem, 0, &szExt[1], _countof(szExt) - 1);
     _wcslwr(szExt);
 
-    DeleteExt(hwndDlg, szExt);
-    ListView_DeleteItem(hListView, iItem);
+    if (DeleteExt(hwndDlg, szExt))
+    {
+        ListView_DeleteItem(hListView, iItem);
+    }
     return TRUE;
 }
 
@@ -815,8 +892,9 @@ FileTypesDlg_RemoveExt(HWND hwndDlg)
 typedef struct ACTION_DIALOG
 {
     HWND hwndLB;
-    WCHAR ClassName[64];
-    WCHAR szAction[64];
+    PFILE_TYPE_GLOBALS pG;
+    PFILE_TYPE_ENTRY pEntry;
+    WCHAR szAction[VERBKEY_CCHMAX];
     WCHAR szApp[MAX_PATH];
     BOOL bUseDDE;
 } ACTION_DIALOG, *PACTION_DIALOG;
@@ -825,7 +903,7 @@ static void
 ActionDlg_OnBrowse(HWND hwndDlg, PACTION_DIALOG pNewAct, BOOL bEdit = FALSE)
 {
     WCHAR szFile[MAX_PATH];
-    szFile[0] = 0;
+    szFile[0] = UNICODE_NULL;
 
     WCHAR szFilter[MAX_PATH];
     LoadStringW(shell32_hInstance, IDS_EXE_FILTER, szFilter, 
_countof(szFilter));
@@ -847,6 +925,7 @@ ActionDlg_OnBrowse(HWND hwndDlg, PACTION_DIALOG pNewAct, 
BOOL bEdit = FALSE)
         if (bEdit)
         {
             CStringW str = szFile;
+            QuoteAppPathForCommand(str);
             str += L" \"%1\"";
             SetDlgItemTextW(hwndDlg, IDC_ACTION_APP, str);
         }
@@ -986,7 +1065,7 @@ EditActionDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, 
LPARAM lParam)
             {
                 // set title
                 CStringW str(MAKEINTRESOURCEW(IDS_EDITING_ACTION));
-                str += s_pEditAct->ClassName;
+                str += GetTypeName(s_pEditAct->pEntry, s_pEditAct->pG);
                 SetWindowTextW(hwndDlg, str);
             }
             return TRUE;
@@ -1014,40 +1093,51 @@ EditActionDlgProc(HWND hwndDlg, UINT uMsg, WPARAM 
wParam, LPARAM lParam)
 /////////////////////////////////////////////////////////////////////////////
 // EditTypeDlg
 
-static BOOL
-EditTypeDlg_UpdateEntryIcon(HWND hwndDlg, PEDITTYPE_DIALOG pEditType,
-                            LPCWSTR IconPath, INT IconIndex)
+static void
+EditTypeDlg_Restrict(HWND hwndDlg, PEDITTYPE_DIALOG pEditType)
 {
     PFILE_TYPE_ENTRY pEntry = pEditType->pEntry;
+    static const WORD map[] = {
+        FTA_NoEditIcon, IDC_EDITTYPE_CHANGE_ICON,
+        FTA_NoEditDesc, IDC_EDITTYPE_TEXT,
+        FTA_NoNewVerb, IDC_EDITTYPE_NEW,
+        FTA_NoEditVerb, IDC_EDITTYPE_EDIT_BUTTON,
+        FTA_NoRemoveVerb, IDC_EDITTYPE_REMOVE,
+        FTA_NoEditDflt, IDC_EDITTYPE_SET_DEFAULT
+    };
+    for (SIZE_T i = 0; i < _countof(map); i += 2)
+    {
+        if (pEntry->EditFlags & map[i + 0])
+            EnableWindow(GetDlgItem(hwndDlg, map[i + 1]), FALSE);
+    }
+}
 
-    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);
+static BOOL
+EditTypeDlg_UpdateEntryIcon(HWND hwndDlg, PEDITTYPE_DIALOG pEditType)
+{
+    PFILE_TYPE_ENTRY pEntry = pEditType->pEntry;
+    WCHAR buf[MAX_PATH];
 
-        bIconSet = (pEntry->hIconLarge && pEntry->hIconSmall);
-    }
-    if (bIconSet)
-    {
-        StringCbCopyW(pEntry->IconPath, sizeof(pEntry->IconPath), IconPath);
-        pEntry->nIconIndex = IconIndex;
-    }
-    else
+    pEntry->IconPath[0] = UNICODE_NULL; // I want the default icon
+    Normalize(pEntry);
+    pEntry->DestroyIcons();
+    pEntry->hIconSmall = DoExtractIcon(pEntry->IconPath, pEntry->nIconIndex, 
TRUE);
+    if (ExpandEnvironmentStringsW(pEditType->szIconPath, buf, _countof(buf)) 
&& buf[0])
     {
-        SetFileTypeEntryDefaultIcon(pEntry);
+        HICON hIco = DoExtractIcon(buf, pEditType->nIconIndex, TRUE);
+        if (hIco)
+        {
+            pEntry->DestroyIcons();
+            pEntry->hIconSmall = hIco;
+        }
     }
+    StringCbCopyW(pEntry->IconPath, sizeof(pEntry->IconPath), 
pEditType->szIconPath);
+    pEntry->nIconIndex = pEditType->nIconIndex;
 
     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);
+    InitializeDefaultIcons(pEditType->pG);
+    HIMAGELIST himlSmall = pEditType->pG->himlSmall;
     INT iSmallImage = ImageList_AddIcon(himlSmall, pEntry->hIconSmall);
-    ASSERT(iLargeImage == iSmallImage);
-    DBG_UNREFERENCED_LOCAL_VARIABLE(iLargeImage);
 
     INT iItem = ListView_GetNextItem(hListView, -1, LVNI_SELECTED);
     if (iItem != -1)
@@ -1061,41 +1151,73 @@ EditTypeDlg_UpdateEntryIcon(HWND hwndDlg, 
PEDITTYPE_DIALOG pEditType,
 
 static BOOL
 EditTypeDlg_WriteClass(HWND hwndDlg, PEDITTYPE_DIALOG pEditType,
-                       LPCWSTR ClassKey, LPCWSTR ClassName, INT cchName)
+                       LPCWSTR TypeName, EDITTYPEFLAGS Etf)
 {
     PFILE_TYPE_ENTRY pEntry = pEditType->pEntry;
-
-    if (ClassKey[0] == 0)
-        return FALSE;
-
-    // create or open class key
+    LPCWSTR ClassKey;
+    HRESULT hr = GetClassKey(*pEntry, ClassKey);
+    BOOL OnlyExt = hr != S_OK;
     HKEY hClassKey;
-    if (RegCreateKeyExW(HKEY_CLASSES_ROOT, ClassKey, 0, NULL, 0, KEY_WRITE, 
NULL,
-                        &hClassKey, NULL) != ERROR_SUCCESS)
+    if (FAILED(hr) || RegCreateKeyExW(HKEY_CLASSES_ROOT, ClassKey, 0, NULL, 0,
+                                      KEY_QUERY_VALUE |KEY_WRITE, NULL,
+                                      &hClassKey, NULL) != ERROR_SUCCESS)
     {
         return FALSE;
     }
 
-    // create "DefaultIcon" key
-    if (pEntry->IconPath[0])
+    // Refresh the EditFlags
+    DWORD dw;
+    if (GetRegDWORD(hClassKey, L"EditFlags", dw, 0, FALSE) == ERROR_SUCCESS)
+        pEntry->EditFlags = (dw & ~FTA_MODIFYMASK) | (pEntry->EditFlags & 
FTA_MODIFYMASK);
+
+    if (!OnlyExt)
     {
-        HKEY hDefaultIconKey;
-        if (RegCreateKeyExW(hClassKey, L"DefaultIcon", 0, NULL, 0, KEY_WRITE, 
NULL,
-                            &hDefaultIconKey, NULL) == ERROR_SUCCESS)
+        // Set class properties
+        RegSetOrDelete(hClassKey, L"EditFlags", REG_DWORD, pEntry->EditFlags ? 
&pEntry->EditFlags : NULL, 4);
+        if (pEntry->IsExtension())
+        {
+            RegSetOrDelete(hClassKey, L"AlwaysShowExt", REG_SZ, (Etf & 
ETF_ALWAYSEXT) ? L"" : NULL, 0);
+        }
+        if (RegKeyExists(hClassKey, L"DocObject"))
+        {
+            LRESULT ec = GetRegDWORD(hClassKey, L"BrowserFlags", dw, 0, TRUE);
+            if (ec == ERROR_SUCCESS || ec == ERROR_FILE_NOT_FOUND)
+            {
+                dw = (dw & ~8) | ((Etf & ETF_BROWSESAME) ? 0 : 8); // Note: 8 
means NOT
+                RegSetOrDelete(hClassKey, L"BrowserFlags", REG_DWORD, dw ? &dw 
: NULL, sizeof(dw));
+            }
+        }
+        if (!(pEntry->EditFlags & FTA_NoEditDesc))
         {
-            WCHAR szText[MAX_PATH];
-            StringCbPrintfW(szText, sizeof(szText), L"%s,%d",
-                             pEntry->IconPath, pEntry->nIconIndex);
+            RegSetString(hClassKey, NULL, TypeName, REG_SZ);
+            pEntry->InvalidateTypeName();
+        }
+    }
 
-            // set icon location
-            DWORD dwSize = (lstrlenW(szText) + 1) * sizeof(WCHAR);
-            RegSetValueExW(hDefaultIconKey, NULL, 0, REG_EXPAND_SZ, 
LPBYTE(szText), dwSize);
+    if (pEntry->IconPath[0] && !(pEntry->EditFlags & FTA_NoEditIcon))
+    {
+        HKEY hDefaultIconKey;
+        if (RegCreateKeyExW(hClassKey, L"DefaultIcon", 0, NULL, 0, KEY_WRITE,
+                            NULL, &hDefaultIconKey, NULL) == ERROR_SUCCESS)
+        {
+            DWORD type = REG_SZ;
+            WCHAR buf[ICONLOCATION_CCHMAX];
+            LPCWSTR fmt = L"%s,%d";
+            if (!lstrcmpW(pEntry->IconPath, L"%1"))
+            {
+                fmt = L"%s"; // No icon index for "%1"
+            }
+            else if (StrChrW(pEntry->IconPath, L'%'))
+            {
+                type = REG_EXPAND_SZ;
+            }
+            StringCbPrintfW(buf, sizeof(buf), fmt, pEntry->IconPath, 
pEntry->nIconIndex);
 
+            RegSetString(hDefaultIconKey, NULL, buf, type);
             RegCloseKey(hDefaultIconKey);
         }
     }
 
-    // create "shell" key
     HKEY hShellKey;
     if (RegCreateKeyExW(hClassKey, L"shell", 0, NULL, 0, KEY_WRITE, NULL,
                         &hShellKey, NULL) != ERROR_SUCCESS)
@@ -1104,8 +1226,14 @@ EditTypeDlg_WriteClass(HWND hwndDlg, PEDITTYPE_DIALOG 
pEditType,
         return FALSE;
     }
 
+    // set default action
+    if (!(pEntry->EditFlags & FTA_NoEditDflt))
+    {
+        RegSetString(hShellKey, NULL, pEditType->szDefaultVerb, REG_SZ);
+    }
+
     // delete shell commands
-    WCHAR szVerbName[64];
+    WCHAR szVerbName[VERBKEY_CCHMAX];
     DWORD dwIndex = 0;
     while (RegEnumKeyW(hShellKey, dwIndex, szVerbName, _countof(szVerbName)) 
== ERROR_SUCCESS)
     {
@@ -1120,16 +1248,17 @@ EditTypeDlg_WriteClass(HWND hwndDlg, PEDITTYPE_DIALOG 
pEditType,
         ++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);
+        const CStringW& key = pEditType->CommandLineMap.GetKeyAt(i);
+        const CStringW& cmd = pEditType->CommandLineMap.GetValueAt(i);
+        if (!pEditType->ModifiedVerbs.Find(key))
+        {
+            ASSERT(RegKeyExists(hShellKey, key));
+            continue;
+        }
 
         // create verb key
         HKEY hVerbKey;
@@ -1141,10 +1270,12 @@ EditTypeDlg_WriteClass(HWND hwndDlg, PEDITTYPE_DIALOG 
pEditType,
             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);
-
+                DWORD dwSize = (cmd.GetLength() + 1) * sizeof(WCHAR);
+                DWORD dwType = REG_SZ;
+                int exp;
+                if ((exp = cmd.Find('%', 0)) >= 0 && cmd.Find('%', exp + 1) >= 
0)
+                    dwType = REG_EXPAND_SZ;
+                RegSetValueExW(hCommandKey, NULL, 0, dwType, 
LPBYTE(LPCWSTR(cmd)), dwSize);
                 RegCloseKey(hCommandKey);
             }
 
@@ -1152,23 +1283,30 @@ EditTypeDlg_WriteClass(HWND hwndDlg, PEDITTYPE_DIALOG 
pEditType,
         }
     }
 
-    // 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)
+EditTypeDlg_ReadClass(HWND hwndDlg, PEDITTYPE_DIALOG pEditType, EDITTYPEFLAGS 
&Etf)
 {
-    // open class key
+    PFILE_TYPE_ENTRY pEntry = pEditType->pEntry;
+    LPCWSTR ClassKey;
+    HRESULT hr = GetClassKey(*pEntry, ClassKey);
     HKEY hClassKey;
-    if (RegOpenKeyExW(HKEY_CLASSES_ROOT, ClassKey, 0, KEY_READ, &hClassKey) != 
ERROR_SUCCESS)
+    if (FAILED(hr) || RegOpenKeyExW(HKEY_CLASSES_ROOT, ClassKey, 0, KEY_READ, 
&hClassKey))
         return FALSE;
 
+    UINT etfbits = (RegValueExists(hClassKey, L"AlwaysShowExt")) ? 
ETF_ALWAYSEXT : 0;
+
+    // 8 in BrowserFlags listed in KB 162059 seems to be our bit
+    BOOL docobj = RegKeyExists(hClassKey, L"DocObject");
+    EnableWindow(GetDlgItem(hwndDlg, IDC_EDITTYPE_SAME_WINDOW), docobj);
+    etfbits |= (docobj && (GetRegDWORD(hClassKey, L"BrowserFlags") & 8)) ? 0 : 
ETF_BROWSESAME;
+
+    Etf = EDITTYPEFLAGS(etfbits);
+
     // open "shell" key
     HKEY hShellKey;
     if (RegOpenKeyExW(hClassKey, L"shell", 0, KEY_READ, &hShellKey) != 
ERROR_SUCCESS)
@@ -1177,7 +1315,7 @@ EditTypeDlg_ReadClass(HWND hwndDlg, PEDITTYPE_DIALOG 
pEditType, LPCWSTR ClassKey
         return FALSE;
     }
 
-    WCHAR DefaultVerb[64];
+    WCHAR DefaultVerb[VERBKEY_CCHMAX];
     DWORD dwSize = sizeof(DefaultVerb);
     if (RegQueryValueExW(hShellKey, NULL, NULL, NULL,
                          LPBYTE(DefaultVerb), &dwSize) == ERROR_SUCCESS)
@@ -1190,7 +1328,7 @@ EditTypeDlg_ReadClass(HWND hwndDlg, PEDITTYPE_DIALOG 
pEditType, LPCWSTR ClassKey
     }
 
     // enumerate shell verbs
-    WCHAR szVerbName[64];
+    WCHAR szVerbName[VERBKEY_CCHMAX];
     DWORD dwIndex = 0;
     while (RegEnumKeyW(hShellKey, dwIndex, szVerbName, _countof(szVerbName)) 
== ERROR_SUCCESS)
     {
@@ -1205,7 +1343,7 @@ EditTypeDlg_ReadClass(HWND hwndDlg, PEDITTYPE_DIALOG 
pEditType, LPCWSTR ClassKey
             if (nResult == ERROR_SUCCESS)
             {
                 // get command line
-                WCHAR szValue[MAX_PATH + 32];
+                WCHAR szValue[MAX_PATH * 2];
                 dwSize = sizeof(szValue);
                 nResult = RegQueryValueExW(hCommandKey, NULL, NULL, NULL, 
LPBYTE(szValue), &dwSize);
                 if (nResult == ERROR_SUCCESS)
@@ -1222,9 +1360,16 @@ EditTypeDlg_ReadClass(HWND hwndDlg, PEDITTYPE_DIALOG 
pEditType, LPCWSTR ClassKey
         ++dwIndex;
     }
 
+    WCHAR TypeName[TYPENAME_CCHMAX];
+    dwSize = sizeof(TypeName);
+    if (!RegQueryValueExW(hClassKey, NULL, NULL, NULL, LPBYTE(TypeName), 
&dwSize))
+    {
+        TypeName[_countof(TypeName) - 1] = UNICODE_NULL; // Terminate
+        SetDlgItemTextW(hwndDlg, IDC_EDITTYPE_TEXT, TypeName);
+    }
+
     RegCloseKey(hShellKey);
     RegCloseKey(hClassKey);
-
     return TRUE;
 }
 
@@ -1233,16 +1378,26 @@ 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);
+    WCHAR TypeName[TYPENAME_CCHMAX];
+    GetDlgItemTextW(hwndDlg, IDC_EDITTYPE_TEXT, TypeName, _countof(TypeName));
+    StrTrimW(TypeName, g_pszSpace);
+
+    UINT etf = 0;
+    pEntry->EditFlags &= ~(FTA_MODIFYMASK);
+    if (!SendDlgItemMessageW(hwndDlg, IDC_EDITTYPE_CONFIRM_OPEN, BM_GETCHECK, 
0, 0))
+        pEntry->EditFlags |= FTA_OpenIsSafe;
+    if (SendDlgItemMessageW(hwndDlg, IDC_EDITTYPE_SHOW_EXT, BM_GETCHECK, 0, 0))
+        etf |= ETF_ALWAYSEXT;
+    if (SendDlgItemMessageW(hwndDlg, IDC_EDITTYPE_SAME_WINDOW, BM_GETCHECK, 0, 
0))
+        etf |= ETF_BROWSESAME;
 
     // update entry icon
-    EditTypeDlg_UpdateEntryIcon(hwndDlg, pEditType, pEditType->szIconPath, 
pEditType->nIconIndex);
+    EditTypeDlg_UpdateEntryIcon(hwndDlg, pEditType);
 
     // write registry
-    EditTypeDlg_WriteClass(hwndDlg, pEditType, pEntry->ClassKey, 
pEntry->ClassName,
-                           _countof(pEntry->ClassName));
+    EditTypeDlg_WriteClass(hwndDlg, pEditType, TypeName, (EDITTYPEFLAGS)etf);
+
+    pEntry->InvalidateDefaultApp();
 
     // update the icon cache
     SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_FLUSHNOWAIT, NULL, NULL);
@@ -1265,7 +1420,7 @@ EditTypeDlg_OnRemove(HWND hwndDlg, PEDITTYPE_DIALOG 
pEditType)
         return FALSE;
 
     // get text
-    WCHAR szText[64];
+    WCHAR szText[VERBKEY_CCHMAX];
     szText[0] = 0;
     SendDlgItemMessageW(hwndDlg, IDC_EDITTYPE_LISTBOX, LB_GETTEXT, iItem, 
(LPARAM)szText);
     StrTrimW(szText, g_pszSpace);
@@ -1296,10 +1451,10 @@ EditTypeDlg_OnCommand(HWND hwndDlg, UINT id, UINT code, 
PEDITTYPE_DIALOG pEditTy
             break;
 
         case IDC_EDITTYPE_NEW:
+            // open 'New Action' dialog
             action.bUseDDE = FALSE;
             action.hwndLB = GetDlgItem(hwndDlg, IDC_EDITTYPE_LISTBOX);
-            StringCbPrintfW(action.ClassName, sizeof(action.ClassName), 
pEditType->pEntry->ClassName);
-            // open 'New Action' dialog
+            action.pEntry = pEditType->pEntry;
             if (IDOK == DialogBoxParamW(shell32_hInstance, 
MAKEINTRESOURCEW(IDD_ACTION), hwndDlg,
                                         NewActionDlgProc, LPARAM(&action)))
             {
@@ -1318,8 +1473,10 @@ EditTypeDlg_OnCommand(HWND hwndDlg, UINT id, UINT code, 
PEDITTYPE_DIALOG pEditTy
                 {
                     // add it
                     CStringW strCommandLine = action.szApp;
+                    QuoteAppPathForCommand(strCommandLine);
                     strCommandLine += L" \"%1\"";
                     pEditType->CommandLineMap.SetAt(action.szAction, 
strCommandLine);
+                    pEditType->ModifiedVerbs.AddHead(action.szAction);
                     SendMessageW(action.hwndLB, LB_ADDSTRING, 0, 
LPARAM(action.szAction));
                     if (SendMessageW(action.hwndLB, LB_GETCOUNT, 0, 0) == 1)
                     {
@@ -1345,6 +1502,7 @@ EditTypeDlg_OnCommand(HWND hwndDlg, UINT id, UINT code, 
PEDITTYPE_DIALOG pEditTy
                 {
                     EnableWindow(GetDlgItem(hwndDlg, 
IDC_EDITTYPE_SET_DEFAULT), TRUE);
                 }
+                EditTypeDlg_Restrict(hwndDlg, pEditType);
                 break;
             }
             else if (code != LBN_DBLCLK)
@@ -1356,7 +1514,8 @@ EditTypeDlg_OnCommand(HWND hwndDlg, UINT id, UINT code, 
PEDITTYPE_DIALOG pEditTy
         case IDC_EDITTYPE_EDIT_BUTTON:
             action.bUseDDE = FALSE;
             action.hwndLB = GetDlgItem(hwndDlg, IDC_EDITTYPE_LISTBOX);
-            StringCbPrintfW(action.ClassName, sizeof(action.ClassName), 
pEditType->pEntry->ClassName);
+            action.pG = pEditType->pG;
+            action.pEntry = pEditType->pEntry;
             iItem = SendMessageW(action.hwndLB, LB_GETCURSEL, 0, 0);
             if (iItem == LB_ERR)
                 break;
@@ -1378,6 +1537,7 @@ EditTypeDlg_OnCommand(HWND hwndDlg, UINT id, UINT code, 
PEDITTYPE_DIALOG pEditTy
                 SendMessageW(action.hwndLB, LB_DELETESTRING, iItem, 0);
                 SendMessageW(action.hwndLB, LB_INSERTSTRING, iItem, 
LPARAM(action.szAction));
                 pEditType->CommandLineMap.SetAt(action.szAction, action.szApp);
+                pEditType->ModifiedVerbs.AddHead(action.szAction);
             }
             break;
 
@@ -1405,16 +1565,23 @@ static BOOL
 EditTypeDlg_OnInitDialog(HWND hwndDlg, PEDITTYPE_DIALOG pEditType)
 {
     PFILE_TYPE_ENTRY pEntry = pEditType->pEntry;
-    StringCbCopyW(pEditType->szIconPath, sizeof(pEditType->szIconPath), 
pEntry->IconPath);
+    EDITTYPEFLAGS Etf;
+    ExpandEnvironmentStringsW(pEntry->IconPath, pEditType->szIconPath, 
_countof(pEditType->szIconPath));
     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);
+    HICON hIco = DoExtractIcon(pEditType->szIconPath, pEditType->nIconIndex);
+    SendDlgItemMessageW(hwndDlg, IDC_EDITTYPE_ICON, STM_SETICON, (WPARAM)hIco, 
0);
+    EditTypeDlg_ReadClass(hwndDlg, pEditType, Etf);
+    SendDlgItemMessageW(hwndDlg, IDC_EDITTYPE_CONFIRM_OPEN, BM_SETCHECK, 
!(pEntry->EditFlags & FTA_OpenIsSafe), 0);
+    SendDlgItemMessageW(hwndDlg, IDC_EDITTYPE_SHOW_EXT, BM_SETCHECK, !!(Etf & 
ETF_ALWAYSEXT), 0);
+    EnableWindow(GetDlgItem(hwndDlg, IDC_EDITTYPE_SHOW_EXT), 
pEntry->IsExtension());
+    SendDlgItemMessageW(hwndDlg, IDC_EDITTYPE_SAME_WINDOW, BM_SETCHECK, !!(Etf 
& ETF_BROWSESAME), 0);
     InvalidateRect(GetDlgItem(hwndDlg, IDC_EDITTYPE_LISTBOX), NULL, TRUE);
 
+    // select first item
+    SendDlgItemMessageW(hwndDlg, IDC_EDITTYPE_LISTBOX, LB_SETCURSEL, 0, 0);
     // is listbox empty?
     if (SendDlgItemMessageW(hwndDlg, IDC_EDITTYPE_LISTBOX, LB_GETCOUNT, 0, 0) 
== 0)
     {
@@ -1422,14 +1589,7 @@ EditTypeDlg_OnInitDialog(HWND hwndDlg, PEDITTYPE_DIALOG 
pEditType)
         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);
-
+    EditTypeDlg_Restrict(hwndDlg, pEditType);
     return TRUE;
 }
 
@@ -1447,6 +1607,14 @@ EditTypeDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, 
LPARAM lParam)
             s_pEditType = (PEDITTYPE_DIALOG)lParam;
             return EditTypeDlg_OnInitDialog(hwndDlg, s_pEditType);
 
+        case WM_DESTROY:
+        {
+            HICON hOld = (HICON)SendDlgItemMessageW(hwndDlg, 
IDC_EDITTYPE_ICON, STM_GETICON, 0, 0);
+            if (hOld)
+                DestroyIcon(hOld);
+            break;
+        }
+
         case WM_DRAWITEM:
             pDraw = LPDRAWITEMSTRUCT(lParam);
             return EditTypeDlg_OnDrawItem(hwndDlg, pDraw, s_pEditType);
@@ -1469,129 +1637,150 @@ EditTypeDlgProc(HWND hwndDlg, UINT uMsg, WPARAM 
wParam, LPARAM lParam)
 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;
+    PFILE_TYPE_GLOBALS pG = (PFILE_TYPE_GLOBALS)lParamSort;
+    PFILE_TYPE_ENTRY entry1 = (PFILE_TYPE_ENTRY)lParam1, entry2 = 
(PFILE_TYPE_ENTRY)lParam2;
+    int x = 0;
+    if (pG->SortCol == 1)
+        x = wcsicmp(GetTypeName(entry1, pG), GetTypeName(entry2, pG));
+    if (!x && !(x = entry1->IsExtension() - entry2->IsExtension()))
+        x = wcsicmp(entry1->FileExtension, entry2->FileExtension);
+    return x * pG->SortReverse;
+}
 
-    return wcsicmp(Entry1->FileDescription, Entry2->FileDescription);
+static void
+FileTypesDlg_Sort(PFILE_TYPE_GLOBALS pG, HWND hListView, INT Column = -1)
+{
+    pG->SortReverse = pG->SortCol == Column ? pG->SortReverse * -1 : 1;
+    pG->SortCol = Column < 0 ? 0 : (INT8) Column;
+    ListView_SortItems(hListView, FileTypesDlg_CompareItems, (LPARAM)pG);
 }
 
 static VOID
 FileTypesDlg_InitListView(HWND hwndDlg, HWND hListView)
 {
     RECT clientRect;
-    LVCOLUMNW col;
-    WCHAR szName[50];
-    DWORD dwStyle;
-    INT columnSize;
+    LPCWSTR columnName;
+    WCHAR szBuf[50];
 
-    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;
+    LVCOLUMNW col;
+    col.mask = LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM | LVCF_FMT;
+    col.fmt = 0;
 
     GetClientRect(hListView, &clientRect);
-    ZeroMemory(&col, sizeof(LV_COLUMN));
-    columnSize      = (clientRect.right - clientRect.left) / 4;
+    INT column0Size = (clientRect.right - clientRect.left) / 4;
+
+    columnName = L"Extensions"; // Default to English
+    if (LoadStringW(shell32_hInstance, IDS_COLUMN_EXTENSION, szBuf, 
_countof(szBuf)))
+        columnName = szBuf;
+    col.pszText     = const_cast<LPWSTR>(columnName);
     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;
+    col.cx          = column0Size;
     SendMessageW(hListView, LVM_INSERTCOLUMNW, 0, (LPARAM)&col);
 
-    if (!LoadStringW(shell32_hInstance, IDS_FILE_TYPES, szName, 
_countof(szName)))
+    columnName = L"File Types"; // Default to English
+    if (LoadStringW(shell32_hInstance, IDS_FILE_TYPES, szBuf, _countof(szBuf)))
+    {
+        columnName = szBuf;
+    }
+    else
     {
-        // default to english
-        wcscpy(szName, L"File Types");
         ERR("Failed to load localized string!\n");
     }
-
+    col.pszText     = const_cast<LPWSTR>(columnName);
     col.iSubItem    = 1;
-    col.cx          = clientRect.right - clientRect.left - columnSize - 
GetSystemMetrics(SM_CYVSCROLL);
-    col.cchTextMax  = wcslen(szName);
-    col.pszText     = szName;
+    col.cx          = clientRect.right - clientRect.left - column0Size - 
GetSystemMetrics(SM_CYVSCROLL);
     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);
+    const UINT lvexstyle = LVS_EX_FULLROWSELECT | LVS_EX_LABELTIP;
+    ListView_SetExtendedListViewStyleEx(hListView, lvexstyle, lvexstyle);
 }
 
-static PFILE_TYPE_ENTRY
-FileTypesDlg_DoList(HWND hwndDlg)
+static void
+FileTypesDlg_SetGroupboxText(HWND hwndDlg, LPCWSTR Assoc)
 {
-    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;
+    CStringW buf;
+    buf.Format(IDS_FILE_DETAILS, Assoc);
+    SetDlgItemTextW(hwndDlg, IDC_FILETYPES_DETAILS_GROUPBOX, buf.GetString());
+}
 
-    dwName = _countof(szName);
+static void
+FileTypesDlg_Refresh(HWND hwndDlg, HWND hListView, PFILE_TYPE_GLOBALS pG)
+{
+    ListView_DeleteAllItems(hListView);
+    ImageList_RemoveAll(pG->himlSmall);
+    InitializeDefaultIcons(pG);
+    FileTypesDlg_SetGroupboxText(hwndDlg, L"");
+    SetDlgItemTextW(hwndDlg, IDC_FILETYPES_DESCRIPTION, L"");
+    SetDlgItemTextW(hwndDlg, IDC_FILETYPES_APPNAME, L"");
+    EnableWindow(GetDlgItem(hwndDlg, IDC_FILETYPES_DELETE), FALSE);
+    RedrawWindow(hwndDlg, NULL, NULL, RDW_ALLCHILDREN | RDW_INVALIDATE | 
RDW_UPDATENOW);
+#if DBG
+    DWORD statTickStart = GetTickCount();
+#endif
 
+    INT iItem = 0;
+    WCHAR szName[ASSOC_CCHMAX];
+    DWORD dwName = _countof(szName);
+    DWORD dwIndex = 0;
+    SendMessage(hListView, WM_SETREDRAW, FALSE, 0);
     while (RegEnumKeyExW(HKEY_CLASSES_ROOT, dwIndex++, szName, &dwName,
                          NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
     {
-        if (FileTypesDlg_InsertToLV(hListView, szName, iItem, szFile))
+        if (FileTypesDlg_InsertToLV(hListView, szName, iItem, pG))
             ++iItem;
         dwName = _countof(szName);
     }
+    FileTypesDlg_Sort(pG, hListView);
+    SendMessage(hListView, WM_SETREDRAW, TRUE, 0);
+    RedrawWindow(hListView, NULL, NULL, RDW_ALLCHILDREN | RDW_ERASE | 
RDW_FRAME | RDW_INVALIDATE);
 
-    // Leave if the list is empty
-    if (iItem == 0)
-        return NULL;
+#if DBG
+    DbgPrint("FT loaded %u (%ums)\n", iItem, GetTickCount() - statTickStart);
+#endif
+    // select first item
+    ListView_SetItemState(hListView, 0, -1, LVIS_FOCUSED | LVIS_SELECTED);
+}
 
-    // sort list
-    ListView_SortItems(hListView, FileTypesDlg_CompareItems, NULL);
+static PFILE_TYPE_GLOBALS
+FileTypesDlg_Initialize(HWND hwndDlg)
+{
+    HWND hListView = GetDlgItem(hwndDlg, IDC_FILETYPES_LISTVIEW);
+    PFILE_TYPE_GLOBALS pG = (PFILE_TYPE_GLOBALS)SHAlloc(sizeof(*pG));
+    if (!pG)
+        return pG;
 
-    // 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);
+    pG->SortReverse = 1;
+    pG->hDefExtIconSmall = NULL;
+    pG->hOpenWithImage = NULL;
+    pG->IconSize = GetSystemMetrics(SM_CXSMICON); // Shell icons are always 
square
+    pG->himlSmall = ImageList_Create(pG->IconSize, pG->IconSize, ILC_COLOR32 | 
ILC_MASK, 256, 20);
+    pG->hHeap = GetProcessHeap();
+
+    if (!LoadStringW(shell32_hInstance, IDS_ANY_FILE,
+                     pG->DefExtTypeNameFmt, _countof(pG->DefExtTypeNameFmt)))
+    {
+        LPCWSTR fallback = L"%s File"; // Default to English
+        StringCchCopyW(pG->DefExtTypeNameFmt, _countof(pG->DefExtTypeNameFmt), 
fallback);
+    }
+    pG->NoneString[0] = UNICODE_NULL;
+    LoadStringW(shell32_hInstance, IDS_NONE, pG->NoneString, 
_countof(pG->NoneString));
+
+    if (!(pG->Restricted = SHRestricted(REST_NOFILEASSOCIATE)))
+    {
+        HKEY hKey;
+        if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, L"Software\\Classes", 0, NULL, 
0, KEY_WRITE, NULL, &hKey, NULL))
+            pG->Restricted = TRUE;
+        else
+            RegCloseKey(hKey);
+    }
 
-    lvItem.mask = LVIF_PARAM;
-    ListView_GetItem(hListView, &lvItem);
+    FileTypesDlg_InitListView(hwndDlg, hListView);
+    ListView_SetImageList(hListView, pG->himlSmall, LVSIL_SMALL);
+    EnableWindow(GetDlgItem(hwndDlg, IDC_FILETYPES_NEW), !pG->Restricted);
 
-    return (PFILE_TYPE_ENTRY)lvItem.lParam;
+    // Delay loading the items so the propertysheet has time to finalize the UI
+    PostMessage(hListView, WM_KEYDOWN, VK_F5, 0);
+    return pG;
 }
 
 static inline PFILE_TYPE_ENTRY
@@ -1621,69 +1810,56 @@ FileTypesDlg_OnDelete(HWND hwndDlg)
         FileTypesDlg_RemoveExt(hwndDlg);
 
         // Select first item (Win2k3 does it)
-        LV_ITEMW item = { LVIF_STATE };
-        item.stateMask = item.state = LVIS_FOCUSED | LVIS_SELECTED;
-        item.iItem = 0;
-        ListView_SetItem(GetDlgItem(hwndDlg, IDC_FILETYPES_LISTVIEW), &item);
+        HWND hListView = GetDlgItem(hwndDlg, IDC_FILETYPES_LISTVIEW);
+        ListView_SetItemState(hListView, 0, -1, LVIS_FOCUSED | LVIS_SELECTED);
     }
 }
 
 static void
-FileTypesDlg_OnItemChanging(HWND hwndDlg, PFILE_TYPE_ENTRY pEntry)
+FileTypesDlg_OnItemChanging(HWND hwndDlg, PFILE_TYPE_ENTRY pEntry, 
PFILE_TYPE_GLOBALS pG)
 {
-    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);
+    HBITMAP &hbmProgram = pG->hOpenWithImage;
+    LPCWSTR DispAssoc = pEntry->GetAssocForDisplay();
+    LPCWSTR TypeName = GetTypeName(pEntry, pG);
+    CStringW buf;
 
     // 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);
+    FileTypesDlg_SetGroupboxText(hwndDlg, DispAssoc);
+    if (pEntry->IsExtension())
+        buf.Format(IDS_FILE_DETAILSADV, DispAssoc, TypeName, TypeName);
+    else
+        buf = L"";
+    SetDlgItemTextW(hwndDlg, IDC_FILETYPES_DESCRIPTION, buf.GetString());
 
     // delete previous program image
-    if (s_hbmProgram)
+    if (hbmProgram)
     {
-        DeleteObject(s_hbmProgram);
-        s_hbmProgram = NULL;
+        DeleteObject(hbmProgram);
+        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");
+    LPCWSTR appname = GetAppName(pEntry);
+    SetDlgItemTextW(hwndDlg, IDC_FILETYPES_APPNAME, appname);
 
-    // 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);
-}
-
-static VOID
-FileTypesDlg_UpdateAppInfo(HWND hwndDlg, PFILE_TYPE_ENTRY pEntry)
-{
-    pEntry->ProgramPath[0] = pEntry->AppName[0] = UNICODE_NULL;
-
-    DWORD cch = _countof(pEntry->ProgramPath);
-    if (S_OK == AssocQueryStringW(ASSOCF_INIT_IGNOREUNKNOWN, 
ASSOCSTR_EXECUTABLE,
-                                  pEntry->FileExtension, NULL, 
pEntry->ProgramPath, &cch))
+    // set program image
+    HICON hIconSm = NULL;
+    LPCWSTR exe = GetProgramPath(pEntry);
+    if (*exe)
     {
-        QueryFileDescription(pEntry->ProgramPath, pEntry->AppName, 
_countof(pEntry->AppName));
+        ExtractIconExW(exe, 0, NULL, &hIconSm, 1);
     }
+    hbmProgram = BitmapFromIcon(hIconSm, 16, 16);
+    DestroyIcon(hIconSm);
+    SendDlgItemMessageW(hwndDlg, IDC_FILETYPES_ICON, STM_SETIMAGE, 
IMAGE_BITMAP, LPARAM(hbmProgram));
+
+    // Enable/Disable the buttons
+    EnableWindow(GetDlgItem(hwndDlg, IDC_FILETYPES_CHANGE),
+                 !pG->Restricted && pEntry->IsExtension());
+    EnableWindow(GetDlgItem(hwndDlg, IDC_FILETYPES_ADVANCED),
+                 !(pEntry->EditFlags & FTA_NoEdit) && !pG->Restricted);
+    EnableWindow(GetDlgItem(hwndDlg, IDC_FILETYPES_DELETE),
+                 !(pEntry->EditFlags & FTA_NoRemove) && !pG->Restricted && 
pEntry->IsExtension());
 }
 
 // IDD_FOLDER_OPTIONS_FILETYPES
@@ -1694,23 +1870,31 @@ FolderOptionsFileTypesDlg(
     WPARAM wParam,
     LPARAM lParam)
 {
+    PFILE_TYPE_GLOBALS pGlobals = 
(PFILE_TYPE_GLOBALS)GetWindowLongPtrW(hwndDlg, DWLP_USER);
+    if (!pGlobals && uMsg != WM_INITDIALOG)
+        return FALSE;
     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);
+            pGlobals = FileTypesDlg_Initialize(hwndDlg);
+            SetWindowLongPtrW(hwndDlg, DWLP_USER, (LONG_PTR)pGlobals);
             return TRUE;
 
+        case WM_DESTROY:
+            SetWindowLongPtrW(hwndDlg, DWLP_USER, 0);
+            if (pGlobals)
+            {
+                DestroyIcon(pGlobals->hDefExtIconSmall);
+                DeleteObject(pGlobals->hOpenWithImage);
+                SHFree(pGlobals);
+            }
+            break;
+
         case WM_COMMAND:
             switch (LOWORD(wParam))
             {
@@ -1719,7 +1903,7 @@ FolderOptionsFileTypesDlg(
                     if (IDOK == DialogBoxParamW(shell32_hInstance, 
MAKEINTRESOURCEW(IDD_NEWEXTENSION),
                                                 hwndDlg, NewExtDlgProc, 
(LPARAM)&newext))
                     {
-                        FileTypesDlg_AddExt(hwndDlg, newext.szExt, 
newext.szFileType);
+                        FileTypesDlg_AddExt(hwndDlg, newext.szExt, 
newext.szFileType, pGlobals);
                     }
                     break;
 
@@ -1731,26 +1915,24 @@ FolderOptionsFileTypesDlg(
                     pEntry = FileTypesDlg_GetEntry(GetDlgItem(hwndDlg, 
IDC_FILETYPES_LISTVIEW));
                     if (pEntry)
                     {
-                        ZeroMemory(&Info, sizeof(Info));
-                        Info.oaifInFlags = OAIF_FORCE_REGISTRATION | 
OAIF_REGISTER_EXT;
-                        Info.pcszFile = pEntry->FileExtension;
-                        Info.pcszClass = NULL;
-                        if (SHOpenWithDialog(hwndDlg, &Info) == S_OK)
+                        OPENASINFO oai = { pEntry->FileExtension, 0, 
OAIF_ALLOW_REGISTRATION | OAIF_REGISTER_EXT };
+                        if (SUCCEEDED(SHOpenWithDialog(hwndDlg, &oai)))
                         {
-                            FileTypesDlg_UpdateAppInfo(hwndDlg, pEntry);
-                            FileTypesDlg_OnItemChanging(hwndDlg, pEntry);
-                            PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
+                            pEntry->InvalidateDefaultApp();
+                            FileTypesDlg_OnItemChanging(hwndDlg, pEntry, 
pGlobals);
                         }
                     }
                     break;
 
                 case IDC_FILETYPES_ADVANCED:
                     edittype.hwndLV = GetDlgItem(hwndDlg, 
IDC_FILETYPES_LISTVIEW);
+                    edittype.pG = pGlobals;
                     edittype.pEntry = FileTypesDlg_GetEntry(edittype.hwndLV);
-                    if (edittype.pEntry)
+                    if (Normalize(edittype.pEntry))
                     {
                         DialogBoxParamW(shell32_hInstance, 
MAKEINTRESOURCEW(IDD_EDITTYPE),
                                         hwndDlg, EditTypeDlgProc, 
(LPARAM)&edittype);
+                        FileTypesDlg_OnItemChanging(hwndDlg, edittype.pEntry, 
pGlobals);
                     }
                     break;
             }
@@ -1760,24 +1942,38 @@ FolderOptionsFileTypesDlg(
             lppl = (LPNMLISTVIEW) lParam;
             switch (lppl->hdr.code)
             {
+                case LVN_GETDISPINFO:
+                {
+                    LPNMLVDISPINFOW pLVDI = (LPNMLVDISPINFOW)lParam;
+                    PFILE_TYPE_ENTRY entry = 
(PFILE_TYPE_ENTRY)pLVDI->item.lParam;
+                    if (entry && (pLVDI->item.mask & LVIF_TEXT))
+                    {
+                        if (pLVDI->item.iSubItem == 1)
+                        {
+                            pLVDI->item.pszText = GetTypeName(entry, pGlobals);
+                            pLVDI->item.mask |= LVIF_DI_SETITEM;
+                        }
+                    }
+                    break;
+                }
+
                 case LVN_KEYDOWN:
                 {
                     LV_KEYDOWN *pKeyDown = (LV_KEYDOWN *)lParam;
-                    if (pKeyDown->wVKey == VK_DELETE)
+                    switch (pKeyDown->wVKey)
                     {
-                        FileTypesDlg_OnDelete(hwndDlg);
+                        case VK_DELETE:
+                            FileTypesDlg_OnDelete(hwndDlg);
+                            break;
+                        case VK_F5:
+                            FileTypesDlg_Refresh(hwndDlg, 
pKeyDown->hdr.hwndFrom, pGlobals);
+                            break;
                     }
                     break;
                 }
 
                 case NM_DBLCLK:
-                    edittype.hwndLV = GetDlgItem(hwndDlg, 
IDC_FILETYPES_LISTVIEW);
-                    edittype.pEntry = FileTypesDlg_GetEntry(edittype.hwndLV);
-                    if (edittype.pEntry)
-                    {
-                        DialogBoxParamW(shell32_hInstance, 
MAKEINTRESOURCEW(IDD_EDITTYPE),
-                                        hwndDlg, EditTypeDlgProc, 
(LPARAM)&edittype);
-                    }
+                    SendMessage(hwndDlg, WM_COMMAND, IDC_FILETYPES_ADVANCED, 
0);
                     break;
 
                 case LVN_DELETEALLITEMS:
@@ -1787,9 +1983,8 @@ FolderOptionsFileTypesDlg(
                     pEntry = FileTypesDlg_GetEntry(lppl->hdr.hwndFrom, 
lppl->iItem);
                     if (pEntry)
                     {
-                        DestroyIcon(pEntry->hIconLarge);
-                        DestroyIcon(pEntry->hIconSmall);
-                        HeapFree(GetProcessHeap(), 0, pEntry);
+                        pEntry->DestroyIcons();
+                        HeapFree(pGlobals->hHeap, 0, pEntry);
                     }
                     return FALSE;
 
@@ -1802,10 +1997,14 @@ FolderOptionsFileTypesDlg(
 
                     if (!(lppl->uOldState & LVIS_FOCUSED) && (lppl->uNewState 
& LVIS_FOCUSED))
                     {
-                        FileTypesDlg_OnItemChanging(hwndDlg, pEntry);
+                        FileTypesDlg_OnItemChanging(hwndDlg, pEntry, pGlobals);
                     }
                     break;
 
+                case LVN_COLUMNCLICK:
+                    FileTypesDlg_Sort(pGlobals, lppl->hdr.hwndFrom, 
lppl->iSubItem);
+                    break;
+
                 case PSN_SETACTIVE:
                     // On page activation, set the focus to the listview
                     SetFocus(GetDlgItem(hwndDlg, IDC_FILETYPES_LISTVIEW));
diff --git a/dll/win32/shell32/lang/bg-BG.rc b/dll/win32/shell32/lang/bg-BG.rc
index 3f6ca3fdc89..a6f1ec66737 100644
--- a/dll/win32/shell32/lang/bg-BG.rc
+++ b/dll/win32/shell32/lang/bg-BG.rc
@@ -990,10 +990,6 @@ BEGIN
     IDS_FILE_TYPES "File Types"
     IDS_COLUMN_EXTENSION "Extensions"
 
-    /* As in 'INI File' or 'WAV File', fallback string for no-name extensions
-       used in the _File type_ tab of the _Folder Options_ dialog */
-    IDS_FILE_EXT_TYPE "%s File"
-
     IDS_BYTES_FORMAT "bytes"
     IDS_UNKNOWN_APP "Unknown application"
     IDS_EXE_DESCRIPTION "Description:"
diff --git a/dll/win32/shell32/lang/ca-ES.rc b/dll/win32/shell32/lang/ca-ES.rc
index adb698a148d..518dd4329d6 100644
--- a/dll/win32/shell32/lang/ca-ES.rc
+++ b/dll/win32/shell32/lang/ca-ES.rc
@@ -965,7 +965,7 @@ BEGIN
     IDS_SCR_FILE "Screen Saver"
     IDS_SYS_FILE "System File"
     IDS_VXD_FILE "Virtual Device Driver"
-    IDS_ANY_FILE "%s-file"
+    IDS_ANY_FILE "%s File"
 
     IDS_OPEN_VERB "Open"
     IDS_EXPLORE_VERB "Explore"
@@ -990,10 +990,6 @@ BEGIN
     IDS_FILE_TYPES "File Types"
     IDS_COLUMN_EXTENSION "Extensions"
 
-    /* As in 'INI File' or 'WAV File', fallback string for no-name extensions
-       used in the _File type_ tab of the _Folder Options_ dialog */
-    IDS_FILE_EXT_TYPE "%s File"
-
     IDS_BYTES_FORMAT "bytes"
     IDS_UNKNOWN_APP "Unknown application"
     IDS_EXE_DESCRIPTION "Description:"
diff --git a/dll/win32/shell32/lang/cs-CZ.rc b/dll/win32/shell32/lang/cs-CZ.rc
index 95ad5dcc8f7..744d8c727a7 100644
--- a/dll/win32/shell32/lang/cs-CZ.rc
+++ b/dll/win32/shell32/lang/cs-CZ.rc
@@ -998,10 +998,6 @@ BEGIN
     IDS_FILE_TYPES "Typy souborů"
     IDS_COLUMN_EXTENSION "Přípony"
 
-    /* As in 'INI File' or 'WAV File', fallback string for no-name extensions
-       used in the _File type_ tab of the _Folder Options_ dialog */
-    IDS_FILE_EXT_TYPE "Soubor %s"
-
     IDS_BYTES_FORMAT "bajtů"
     IDS_UNKNOWN_APP "Neznámá aplikace"
     IDS_EXE_DESCRIPTION "Popis:"
diff --git a/dll/win32/shell32/lang/da-DK.rc b/dll/win32/shell32/lang/da-DK.rc
index e7b84e57701..7ba29c63939 100644
--- a/dll/win32/shell32/lang/da-DK.rc
+++ b/dll/win32/shell32/lang/da-DK.rc
@@ -972,7 +972,7 @@ BEGIN
     IDS_SCR_FILE "Screen Saver"
     IDS_SYS_FILE "System File"
     IDS_VXD_FILE "Virtual Device Driver"
-    IDS_ANY_FILE "%s-file"
+    IDS_ANY_FILE "%s File"
 
     IDS_OPEN_VERB "Open"
     IDS_EXPLORE_VERB "Explore"
@@ -997,10 +997,6 @@ BEGIN
     IDS_FILE_TYPES "File Types"
     IDS_COLUMN_EXTENSION "Extensions"
 
-    /* As in 'INI File' or 'WAV File', fallback string for no-name extensions
-       used in the _File type_ tab of the _Folder Options_ dialog */
-    IDS_FILE_EXT_TYPE "%s File"
-
     IDS_BYTES_FORMAT "bytes"
     IDS_UNKNOWN_APP "Unknown application"
     IDS_EXE_DESCRIPTION "Description:"
diff --git a/dll/win32/shell32/lang/de-DE.rc b/dll/win32/shell32/lang/de-DE.rc
index 3f558834d2a..ecb87154a4b 100644
--- a/dll/win32/shell32/lang/de-DE.rc
+++ b/dll/win32/shell32/lang/de-DE.rc
@@ -991,10 +991,6 @@ BEGIN
     IDS_FILE_TYPES "Dateitypen"
     IDS_COLUMN_EXTENSION "Erweiterungen"
 
-    /* As in 'INI File' or 'WAV File', fallback string for no-name extensions
-       used in the _File type_ tab of the _Folder Options_ dialog */
-    IDS_FILE_EXT_TYPE "%s-Datei"
-
     IDS_BYTES_FORMAT "Bytes"
     IDS_UNKNOWN_APP "Unbekannte Anwendung"
     IDS_EXE_DESCRIPTION "Beschreibung:"
diff --git a/dll/win32/shell32/lang/el-GR.rc b/dll/win32/shell32/lang/el-GR.rc
index 0fd46399191..e26cab3ff42 100644
--- a/dll/win32/shell32/lang/el-GR.rc
+++ b/dll/win32/shell32/lang/el-GR.rc
@@ -965,7 +965,7 @@ BEGIN
     IDS_SCR_FILE "Screen Saver"
     IDS_SYS_FILE "System File"
     IDS_VXD_FILE "Virtual Device Driver"
-    IDS_ANY_FILE "%s-file"
+    IDS_ANY_FILE "%s File"
 
     IDS_OPEN_VERB "Open"
     IDS_EXPLORE_VERB "Explore"
@@ -990,10 +990,6 @@ BEGIN
     IDS_FILE_TYPES "File Types"
     IDS_COLUMN_EXTENSION "Extensions"
 
-    /* As in 'INI File' or 'WAV File', fallback string for no-name extensions
-       used in the _File type_ tab of the _Folder Options_ dialog */
-    IDS_FILE_EXT_TYPE "%s File"
-
     IDS_BYTES_FORMAT "bytes"
     IDS_UNKNOWN_APP "Unknown application"
     IDS_EXE_DESCRIPTION "Description:"
diff --git a/dll/win32/shell32/lang/en-GB.rc b/dll/win32/shell32/lang/en-GB.rc
index 0a191cbc16b..7d3e5ef59a8 100644
--- a/dll/win32/shell32/lang/en-GB.rc
+++ b/dll/win32/shell32/lang/en-GB.rc
@@ -965,7 +965,7 @@ BEGIN
     IDS_SCR_FILE "Screen Saver"
     IDS_SYS_FILE "System File"
     IDS_VXD_FILE "Virtual Device Driver"
-    IDS_ANY_FILE "%s-file"
+    IDS_ANY_FILE "%s File"
 
     IDS_OPEN_VERB "Open"
     IDS_EXPLORE_VERB "Explore"
@@ -990,10 +990,6 @@ BEGIN
     IDS_FILE_TYPES "File Types"
     IDS_COLUMN_EXTENSION "Extensions"
 
-    /* As in 'INI File' or 'WAV File', fallback string for no-name extensions
-       used in the _File type_ tab of the _Folder Options_ dialog */
-    IDS_FILE_EXT_TYPE "%s File"
-
     IDS_BYTES_FORMAT "bytes"
     IDS_UNKNOWN_APP "Unknown application"
     IDS_EXE_DESCRIPTION "Description:"
diff --git a/dll/win32/shell32/lang/en-US.rc b/dll/win32/shell32/lang/en-US.rc
index 83f1245ea5f..e8195754991 100644
--- a/dll/win32/shell32/lang/en-US.rc
+++ b/dll/win32/shell32/lang/en-US.rc
@@ -965,7 +965,7 @@ BEGIN
     IDS_SCR_FILE "Screen Saver"
     IDS_SYS_FILE "System File"
     IDS_VXD_FILE "Virtual Device Driver"
-    IDS_ANY_FILE "%s-file"
+    IDS_ANY_FILE "%s File"
 
     IDS_OPEN_VERB "Open"
     IDS_EXPLORE_VERB "Explore"
@@ -990,10 +990,6 @@ BEGIN
     IDS_FILE_TYPES "File Types"
     IDS_COLUMN_EXTENSION "Extensions"
 
-    /* As in 'INI File' or 'WAV File', fallback string for no-name extensions
-       used in the _File type_ tab of the _Folder Options_ dialog */
-    IDS_FILE_EXT_TYPE "%s File"
-
     IDS_BYTES_FORMAT "bytes"
     IDS_UNKNOWN_APP "Unknown application"
     IDS_EXE_DESCRIPTION "Description:"
diff --git a/dll/win32/shell32/lang/es-ES.rc b/dll/win32/shell32/lang/es-ES.rc
index ed20a44cdcd..0d4e112eada 100644
--- a/dll/win32/shell32/lang/es-ES.rc
+++ b/dll/win32/shell32/lang/es-ES.rc
@@ -999,10 +999,6 @@ BEGIN
     IDS_FILE_TYPES "Tipos de archivo"
     IDS_COLUMN_EXTENSION "Extensiones"
 
-    /* As in 'INI File' or 'WAV File', fallback string for no-name extensions
-       used in the _File type_ tab of the _Folder Options_ dialog */
-    IDS_FILE_EXT_TYPE "Archivo %s"
-
     IDS_BYTES_FORMAT "bytes"
     IDS_UNKNOWN_APP "Aplicación desconocida"
     IDS_EXE_DESCRIPTION "Descripción:"
diff --git a/dll/win32/shell32/lang/et-EE.rc b/dll/win32/shell32/lang/et-EE.rc
index 056706f257f..67324abb2da 100644
--- a/dll/win32/shell32/lang/et-EE.rc
+++ b/dll/win32/shell32/lang/et-EE.rc
@@ -997,10 +997,6 @@ BEGIN
     IDS_FILE_TYPES "Failitüübid"
     IDS_COLUMN_EXTENSION "Laiendused"
 
-    /* As in 'INI File' or 'WAV File', fallback string for no-name extensions
-       used in the _File type_ tab of the _Folder Options_ dialog */
-    IDS_FILE_EXT_TYPE "%s Fail"
-
     IDS_BYTES_FORMAT "baiti"
     IDS_UNKNOWN_APP "Tundmatu rakendus"
     IDS_EXE_DESCRIPTION "Kirjeldus:"
diff --git a/dll/win32/shell32/lang/eu-ES.rc b/dll/win32/shell32/lang/eu-ES.rc
index a94192b88ca..0eb4c03261c 100644
--- a/dll/win32/shell32/lang/eu-ES.rc
+++ b/dll/win32/shell32/lang/eu-ES.rc
@@ -995,10 +995,6 @@ BEGIN
     IDS_FILE_TYPES "Fitxategi-mota"
     IDS_COLUMN_EXTENSION "Luzapena"
 
-    /* As in 'INI File' or 'WAV File', fallback string for no-name extensions
-       used in the _File type_ tab of the _Folder Options_ dialog */
-    IDS_FILE_EXT_TYPE "%s fitxategi"
-
     IDS_BYTES_FORMAT "bytes"
     IDS_UNKNOWN_APP "Aplikazio ezezaguna"
     IDS_EXE_DESCRIPTION "Deskribapena:"
diff --git a/dll/win32/shell32/lang/fi-FI.rc b/dll/win32/shell32/lang/fi-FI.rc
index cb68d3b4682..6243ce56153 100644
--- a/dll/win32/shell32/lang/fi-FI.rc
+++ b/dll/win32/shell32/lang/fi-FI.rc
@@ -965,7 +965,7 @@ BEGIN
     IDS_SCR_FILE "Screen Saver"
     IDS_SYS_FILE "System File"
     IDS_VXD_FILE "Virtual Device Driver"
-    IDS_ANY_FILE "%s-file"
+    IDS_ANY_FILE "%s File"
 
     IDS_OPEN_VERB "Open"
     IDS_EXPLORE_VERB "Explore"
@@ -990,10 +990,6 @@ BEGIN
     IDS_FILE_TYPES "File Types"
     IDS_COLUMN_EXTENSION "Extensions"
 
-    /* As in 'INI File' or 'WAV File', fallback string for no-name extensions
-       used in the _File type_ tab of the _Folder Options_ dialog */
-    IDS_FILE_EXT_TYPE "%s File"
-
     IDS_BYTES_FORMAT "bytes"
     IDS_UNKNOWN_APP "Unknown application"
     IDS_EXE_DESCRIPTION "Description:"
diff --git a/dll/win32/shell32/lang/fr-FR.rc b/dll/win32/shell32/lang/fr-FR.rc
index 8304728dffa..0bb74655ef3 100644
--- a/dll/win32/shell32/lang/fr-FR.rc
+++ b/dll/win32/shell32/lang/fr-FR.rc
@@ -990,10 +990,6 @@ BEGIN
     IDS_FILE_TYPES "Types de fichiers"
     IDS_COLUMN_EXTENSION "Extensions"
 
-    /* As in 'INI File' or 'WAV File', fallback string for no-name extensions
-       used in the _File type_ tab of the _Folder Options_ dialog */
-    IDS_FILE_EXT_TYPE "Fichier %s"
-
     IDS_BYTES_FORMAT "octets"
     IDS_UNKNOWN_APP "Application inconnue"
     IDS_EXE_DESCRIPTION "Description :"
diff --git a/dll/win32/shell32/lang/he-IL.rc b/dll/win32/shell32/lang/he-IL.rc
index c56e94f7f9d..5f3bd630847 100644
--- a/dll/win32/shell32/lang/he-IL.rc
+++ b/dll/win32/shell32/lang/he-IL.rc
@@ -997,10 +997,6 @@ BEGIN
     IDS_FILE_TYPES "סוגי קבצים"
     IDS_COLUMN_EXTENSION "סיומות"
 
-    /* As in 'INI File' or 'WAV File', fallback string for no-name extensions
-       used in the _File type_ tab of the _Folder Options_ dialog */
-    IDS_FILE_EXT_TYPE "קובץ %s"
-
     IDS_BYTES_FORMAT "בתים"
     IDS_UNKNOWN_APP "יישום לא ידוע"
     IDS_EXE_DESCRIPTION "תיאור:"
diff --git a/dll/win32/shell32/lang/hi-IN.rc b/dll/win32/shell32/lang/hi-IN.rc
index 5029f8f50c4..8a6ed3d42b3 100644
--- a/dll/win32/shell32/lang/hi-IN.rc
+++ b/dll/win32/shell32/lang/hi-IN.rc
@@ -992,10 +992,6 @@ BEGIN
     IDS_FILE_TYPES "फ़ाइल प्रकारों"
     IDS_COLUMN_EXTENSION "एक्सटेंशन"
 
-    /* As in 'INI File' or 'WAV File', fallback string for no-name extensions
-       used in the _File type_ tab of the _Folder Options_ dialog */
-    IDS_FILE_EXT_TYPE "%s फ़ाइल"
-
     IDS_BYTES_FORMAT "बाइट्स"
     IDS_UNKNOWN_APP "अनजान ऐप्लिकेशन"
     IDS_EXE_DESCRIPTION "विवरण:"
diff --git a/dll/win32/shell32/lang/hu-HU.rc b/dll/win32/shell32/lang/hu-HU.rc
index b7e3dd8dc69..dca369f41aa 100644
--- a/dll/win32/shell32/lang/hu-HU.rc
+++ b/dll/win32/shell32/lang/hu-HU.rc
@@ -989,10 +989,6 @@ BEGIN
     IDS_FILE_TYPES "Fájltípusok"
     IDS_COLUMN_EXTENSION "Kiterjesztések"
 
-    /* As in 'INI File' or 'WAV File', fallback string for no-name extensions
-       used in the _File type_ tab of the _Folder Options_ dialog */
-    IDS_FILE_EXT_TYPE "%s fájl"
-
     IDS_BYTES_FORMAT "bájt"
     IDS_UNKNOWN_APP "Ismeretlen alkalmazás"
     IDS_EXE_DESCRIPTION "Leírás:"
diff --git a/dll/win32/shell32/lang/id-ID.rc b/dll/win32/shell32/lang/id-ID.rc
index 0a3ce0c2e23..14851b34ba0 100644
--- a/dll/win32/shell32/lang/id-ID.rc
+++ b/dll/win32/shell32/lang/id-ID.rc
@@ -987,10 +987,6 @@ BEGIN
     IDS_FILE_TYPES "Jenis Berkas"
     IDS_COLUMN_EXTENSION "Ekstensi"
 
-    /* As in 'INI File' or 'WAV File', fallback string for no-name extensions
-       used in the _File type_ tab of the _Folder Options_ dialog */
-    IDS_FILE_EXT_TYPE "Berkas %s"
-
     IDS_BYTES_FORMAT "byte"
     IDS_UNKNOWN_APP "Aplikasi tidak diketahui"
     IDS_EXE_DESCRIPTION "Deskripsi:"
diff --git a/dll/win32/shell32/lang/it-IT.rc b/dll/win32/shell32/lang/it-IT.rc
index 5cc05d35a9a..2f06fb39638 100644
--- a/dll/win32/shell32/lang/it-IT.rc
+++ b/dll/win32/shell32/lang/it-IT.rc
@@ -990,10 +990,6 @@ BEGIN
     IDS_FILE_TYPES "Tipi di file"
     IDS_COLUMN_EXTENSION "Estensioni"
 
-    /* As in 'INI File' or 'WAV File', fallback string for no-name extensions
-       used in the _File type_ tab of the _Folder Options_ dialog */
-    IDS_FILE_EXT_TYPE "%s File"
-
     IDS_BYTES_FORMAT "byte"
     IDS_UNKNOWN_APP "Applicazione sconosciuta"
     IDS_EXE_DESCRIPTION "Descrizione:"
diff --git a/dll/win32/shell32/lang/ja-JP.rc b/dll/win32/shell32/lang/ja-JP.rc
index 5eaa0bac54f..b4002272715 100644
--- a/dll/win32/shell32/lang/ja-JP.rc
+++ b/dll/win32/shell32/lang/ja-JP.rc
@@ -987,10 +987,6 @@ BEGIN
     IDS_FILE_TYPES "ファイルの種類"
     IDS_COLUMN_EXTENSION "拡張子"
 
-    /* As in 'INI File' or 'WAV File', fallback string for no-name extensions
-       used in the _File type_ tab of the _Folder Options_ dialog */
-    IDS_FILE_EXT_TYPE "%s ファイル"
-
     IDS_BYTES_FORMAT "バイト"
     IDS_UNKNOWN_APP "未知のアプリ"
     IDS_EXE_DESCRIPTION "説明:"
diff --git a/dll/win32/shell32/lang/ko-KR.rc b/dll/win32/shell32/lang/ko-KR.rc
index 721a9433616..2e4478491ba 100644
--- a/dll/win32/shell32/lang/ko-KR.rc
+++ b/dll/win32/shell32/lang/ko-KR.rc
@@ -972,7 +972,7 @@ BEGIN
     IDS_SCR_FILE "Screen Saver"
     IDS_SYS_FILE "System File"
     IDS_VXD_FILE "Virtual Device Driver"
-    IDS_ANY_FILE "%s-file"
+    IDS_ANY_FILE "%s File"
 
     IDS_OPEN_VERB "Open"
     IDS_EXPLORE_VERB "Explore"
@@ -997,10 +997,6 @@ BEGIN
     IDS_FILE_TYPES "File Types"
     IDS_COLUMN_EXTENSION "Extensions"
 
-    /* As in 'INI File' or 'WAV File', fallback string for no-name extensions
-       used in the _File type_ tab of the _Folder Options_ dialog */
-    IDS_FILE_EXT_TYPE "%s File"
-
     IDS_BYTES_FORMAT "bytes"
     IDS_UNKNOWN_APP "Unknown application"
     IDS_EXE_DESCRIPTION "Description:"
diff --git a/dll/win32/shell32/lang/nl-NL.rc b/dll/win32/shell32/lang/nl-NL.rc
index 85fe4161723..f3c20c78acc 100644
--- a/dll/win32/shell32/lang/nl-NL.rc
+++ b/dll/win32/shell32/lang/nl-NL.rc
@@ -965,7 +965,7 @@ BEGIN
     IDS_SCR_FILE "Screen Saver"
     IDS_SYS_FILE "System File"
     IDS_VXD_FILE "Virtual Device Driver"
-    IDS_ANY_FILE "%s-file"
+    IDS_ANY_FILE "%s File"
 
     IDS_OPEN_VERB "Open"
     IDS_EXPLORE_VERB "Explore"
@@ -990,10 +990,6 @@ BEGIN
     IDS_FILE_TYPES "File Types"
     IDS_COLUMN_EXTENSION "Extensions"
 
-    /* As in 'INI File' or 'WAV File', fallback string for no-name extensions
-       used in the _File type_ tab of the _Folder Options_ dialog */
-    IDS_FILE_EXT_TYPE "%s File"
-
     IDS_BYTES_FORMAT "bytes"
     IDS_UNKNOWN_APP "Unknown application"
     IDS_EXE_DESCRIPTION "Description:"
diff --git a/dll/win32/shell32/lang/no-NO.rc b/dll/win32/shell32/lang/no-NO.rc
index 85d13ec384e..c0f8bd18da8 100644
--- a/dll/win32/shell32/lang/no-NO.rc
+++ b/dll/win32/shell32/lang/no-NO.rc
@@ -965,7 +965,7 @@ BEGIN
     IDS_SCR_FILE "Screen Saver"
     IDS_SYS_FILE "Systemfil"
     IDS_VXD_FILE "Virtuell enhetdriver"
-    IDS_ANY_FILE "%s-file"
+    IDS_ANY_FILE "%s fil"
 
     IDS_OPEN_VERB "Åpne"
     IDS_EXPLORE_VERB "Explore"
@@ -990,10 +990,6 @@ BEGIN
     IDS_FILE_TYPES "File Types"
     IDS_COLUMN_EXTENSION "Extensions"
 
-    /* As in 'INI File' or 'WAV File', fallback string for no-name extensions
-       used in the _File type_ tab of the _Folder Options_ dialog */
-    IDS_FILE_EXT_TYPE "%s File"
-
     IDS_BYTES_FORMAT "bytes"
     IDS_UNKNOWN_APP "Unknown application"
     IDS_EXE_DESCRIPTION "Description:"
diff --git a/dll/win32/shell32/lang/pl-PL.rc b/dll/win32/shell32/lang/pl-PL.rc
index 1a9f21e4ad8..e495ffef72b 100644
--- a/dll/win32/shell32/lang/pl-PL.rc
+++ b/dll/win32/shell32/lang/pl-PL.rc
@@ -999,10 +999,6 @@ BEGIN
     IDS_FILE_TYPES "Typy plików"
     IDS_COLUMN_EXTENSION "Rozszerzenia"
 
-    /* As in 'INI File' or 'WAV File', fallback string for no-name extensions
-       used in the _File type_ tab of the _Folder Options_ dialog */
-    IDS_FILE_EXT_TYPE "Plik %s"
-
     IDS_BYTES_FORMAT "bajtów"
     IDS_UNKNOWN_APP "Nieznana aplikacja"
     IDS_EXE_DESCRIPTION "Opis:"
diff --git a/dll/win32/shell32/lang/pt-BR.rc b/dll/win32/shell32/lang/pt-BR.rc
index 8aaf2f5b722..16d1422681e 100644
--- a/dll/win32/shell32/lang/pt-BR.rc
+++ b/dll/win32/shell32/lang/pt-BR.rc
@@ -990,10 +990,6 @@ BEGIN
     IDS_FILE_TYPES "File Types"
     IDS_COLUMN_EXTENSION "Extensões"
 
-    /* As in 'INI File' or 'WAV File', fallback string for no-name extensions
-       used in the _File type_ tab of the _Folder Options_ dialog */
-    IDS_FILE_EXT_TYPE "%s File"
-
     IDS_BYTES_FORMAT "bytes"
     IDS_UNKNOWN_APP "Aplicativo desconhecido"
     IDS_EXE_DESCRIPTION "Descrição:"
diff --git a/dll/win32/shell32/lang/pt-PT.rc b/dll/win32/shell32/lang/pt-PT.rc
index 9fe1d302376..2ca5756dc8e 100644
--- a/dll/win32/shell32/lang/pt-PT.rc
+++ b/dll/win32/shell32/lang/pt-PT.rc
@@ -999,10 +999,6 @@ BEGIN
     IDS_FILE_TYPES "Tipos de ficheiro"
     IDS_COLUMN_EXTENSION "Extensões"
 
-    /* As in 'INI File' or 'WAV File', fallback string for no-name extensions
-       used in the _File type_ tab of the _Folder Options_ dialog */
-    IDS_FILE_EXT_TYPE "Ficheiro %s"
-
     IDS_BYTES_FORMAT "bytes"
     IDS_UNKNOWN_APP "Aplicação desconhecida"
     IDS_EXE_DESCRIPTION "Descrição:"
diff --git a/dll/win32/shell32/lang/ro-RO.rc b/dll/win32/shell32/lang/ro-RO.rc
index 02d56b8673d..540d87c9b24 100644
--- a/dll/win32/shell32/lang/ro-RO.rc
+++ b/dll/win32/shell32/lang/ro-RO.rc
@@ -998,12 +998,9 @@ BEGIN
     IDS_FILE_TYPES "Tipuri"
     IDS_COLUMN_EXTENSION "Extensii"
 
-    /* As in 'INI File' or 'WAV File', fallback string for no-name extensions
-       used in the _File type_ tab of the _Folder Options_ dialog */
-    IDS_FILE_EXT_TYPE "Fişier %s"
-
     IDS_BYTES_FORMAT "octeţi"
     IDS_UNKNOWN_APP "Aplicaţie nespecificată"
+
     IDS_EXE_DESCRIPTION "Descriere:"
 
     IDS_MENU_EMPTY "(Gol)"
diff --git a/dll/win32/shell32/lang/ru-RU.rc b/dll/win32/shell32/lang/ru-RU.rc
index 44d9255511c..773dde053f5 100644
--- a/dll/win32/shell32/lang/ru-RU.rc
+++ b/dll/win32/shell32/lang/ru-RU.rc
@@ -999,10 +999,6 @@ BEGIN
     IDS_FILE_TYPES "Типы файлов"
     IDS_COLUMN_EXTENSION "Расширения"
 
-    /* As in 'INI File' or 'WAV File', fallback string for no-name extensions
-       used in the _File type_ tab of the _Folder Options_ dialog */
-    IDS_FILE_EXT_TYPE "Файл %s"
-
     IDS_BYTES_FORMAT "байт"
     IDS_UNKNOWN_APP "Неизвестное приложение"
     IDS_EXE_DESCRIPTION "Описание:"
diff --git a/dll/win32/shell32/lang/sk-SK.rc b/dll/win32/shell32/lang/sk-SK.rc
index b05b408be0e..59bb8bf6097 100644
--- a/dll/win32/shell32/lang/sk-SK.rc
+++ b/dll/win32/shell32/lang/sk-SK.rc
@@ -965,7 +965,7 @@ BEGIN
     IDS_SCR_FILE "Screen Saver"
     IDS_SYS_FILE "Systémový súbor"
     IDS_VXD_FILE "Ovládač virtuálneho zariadenia"
-    IDS_ANY_FILE "%s-file"
+    IDS_ANY_FILE "%s File"
 
     IDS_OPEN_VERB "Otvoriť"
     IDS_EXPLORE_VERB "Explore"
@@ -990,10 +990,6 @@ BEGIN
     IDS_FILE_TYPES "File Types"
     IDS_COLUMN_EXTENSION "Extensions"
 
-    /* As in 'INI File' or 'WAV File', fallback string for no-name extensions
-       used in the _File type_ tab of the _Folder Options_ dialog */
-    IDS_FILE_EXT_TYPE "%s File"
-
     IDS_BYTES_FORMAT "bytes"
     IDS_UNKNOWN_APP "Unknown application"
     IDS_EXE_DESCRIPTION "Description:"
diff --git a/dll/win32/shell32/lang/sl-SI.rc b/dll/win32/shell32/lang/sl-SI.rc
index bc1b6d1c70d..516ea2483f2 100644
--- a/dll/win32/shell32/lang/sl-SI.rc
+++ b/dll/win32/shell32/lang/sl-SI.rc
@@ -965,7 +965,7 @@ BEGIN
     IDS_SCR_FILE "Screen Saver"
     IDS_SYS_FILE "System File"
     IDS_VXD_FILE "Virtual Device Driver"
-    IDS_ANY_FILE "%s-file"
+    IDS_ANY_FILE "%s File"
 
     IDS_OPEN_VERB "Open"
     IDS_EXPLORE_VERB "Explore"
@@ -990,10 +990,6 @@ BEGIN
     IDS_FILE_TYPES "File Types"
     IDS_COLUMN_EXTENSION "Extensions"
 
-    /* As in 'INI File' or 'WAV File', fallback string for no-name extensions
-       used in the _File type_ tab of the _Folder Options_ dialog */
-    IDS_FILE_EXT_TYPE "%s File"
-
     IDS_BYTES_FORMAT "bytes"
     IDS_UNKNOWN_APP "Unknown application"
     IDS_EXE_DESCRIPTION "Description:"
diff --git a/dll/win32/shell32/lang/sq-AL.rc b/dll/win32/shell32/lang/sq-AL.rc
index c1f0973b65d..fcf87e2f734 100644
--- a/dll/win32/shell32/lang/sq-AL.rc
+++ b/dll/win32/shell32/lang/sq-AL.rc
@@ -997,10 +997,6 @@ BEGIN
     IDS_FILE_TYPES "TipiDokumentit"
     IDS_COLUMN_EXTENSION "Prapashtesa"
 
-    /* As in 'INI File' or 'WAV File', fallback string for no-name extensions
-       used in the _File type_ tab of the _Folder Options_ dialog */
-    IDS_FILE_EXT_TYPE "%s File"
-
     IDS_BYTES_FORMAT "bytes"
     IDS_UNKNOWN_APP "Aplikacion panjohur"
     IDS_EXE_DESCRIPTION "Përshkrimi:"
diff --git a/dll/win32/shell32/lang/sv-SE.rc b/dll/win32/shell32/lang/sv-SE.rc
index 929bbd914b7..9d5486e743d 100644
--- a/dll/win32/shell32/lang/sv-SE.rc
+++ b/dll/win32/shell32/lang/sv-SE.rc
@@ -965,7 +965,7 @@ BEGIN
     IDS_SCR_FILE "Skärmsläckare"
     IDS_SYS_FILE "Systemfil"
     IDS_VXD_FILE "Virtuell enhetsdrivruting"
-    IDS_ANY_FILE "%s-file"
+    IDS_ANY_FILE "%s-fil"
 
     IDS_OPEN_VERB "Öppna"
     IDS_EXPLORE_VERB "Utforska"
@@ -990,10 +990,6 @@ BEGIN
     IDS_FILE_TYPES "Filtyper"
     IDS_COLUMN_EXTENSION "Filändelse"
 
-    /* As in 'INI File' or 'WAV File', fallback string for no-name extensions
-       used in the _File type_ tab of the _Folder Options_ dialog */
-    IDS_FILE_EXT_TYPE "%s-fil"
-
     IDS_BYTES_FORMAT "byte"
     IDS_UNKNOWN_APP "Okänt program"
     IDS_EXE_DESCRIPTION "Beskrivning:"
diff --git a/dll/win32/shell32/lang/tr-TR.rc b/dll/win32/shell32/lang/tr-TR.rc
index c8bbcc708a8..2d52e60d51d 100644
--- a/dll/win32/shell32/lang/tr-TR.rc
+++ b/dll/win32/shell32/lang/tr-TR.rc
@@ -999,10 +999,6 @@ BEGIN
     IDS_FILE_TYPES "Dosya Türleri"
     IDS_COLUMN_EXTENSION "Uzantılar"
 
-    /* As in 'INI File' or 'WAV File', fallback string for no-name extensions
-       used in the _File type_ tab of the _Folder Options_ dialog */
-    IDS_FILE_EXT_TYPE "%s Dosyası"
-
     IDS_BYTES_FORMAT "bit"
     IDS_UNKNOWN_APP "Bilinmeyen Uygulama"
     IDS_EXE_DESCRIPTION "Tanım:"
diff --git a/dll/win32/shell32/lang/uk-UA.rc b/dll/win32/shell32/lang/uk-UA.rc
index b382287c6b8..853f4041a02 100644
--- a/dll/win32/shell32/lang/uk-UA.rc
+++ b/dll/win32/shell32/lang/uk-UA.rc
@@ -990,10 +990,6 @@ BEGIN
     IDS_FILE_TYPES "Типи Файлів"
     IDS_COLUMN_EXTENSION "Розширення"
 
-    /* As in 'INI File' or 'WAV File', fallback string for no-name extensions
-       used in the _File type_ tab of the _Folder Options_ dialog */
-    IDS_FILE_EXT_TYPE "Файл %s"
-
     IDS_BYTES_FORMAT "байт"
     IDS_UNKNOWN_APP "Невідома програма"
     IDS_EXE_DESCRIPTION "Опис:"
diff --git a/dll/win32/shell32/lang/zh-CN.rc b/dll/win32/shell32/lang/zh-CN.rc
index 501eda39614..3d58230cc58 100644
--- a/dll/win32/shell32/lang/zh-CN.rc
+++ b/dll/win32/shell32/lang/zh-CN.rc
@@ -1000,10 +1000,6 @@ BEGIN
     IDS_FILE_TYPES "文件类型"
     IDS_COLUMN_EXTENSION "扩展名"
 
-    /* As in 'INI File' or 'WAV File', fallback string for no-name extensions
-       used in the _File type_ tab of the _Folder Options_ dialog */
-    IDS_FILE_EXT_TYPE "%s 文件"
-
     IDS_BYTES_FORMAT "字节"
     IDS_UNKNOWN_APP "未知应用程序"
     IDS_EXE_DESCRIPTION "描述:"
diff --git a/dll/win32/shell32/lang/zh-HK.rc b/dll/win32/shell32/lang/zh-HK.rc
index b67aae92952..e4700b57e72 100644
--- a/dll/win32/shell32/lang/zh-HK.rc
+++ b/dll/win32/shell32/lang/zh-HK.rc
@@ -998,10 +998,6 @@ BEGIN
     IDS_FILE_TYPES "檔案類型"
     IDS_COLUMN_EXTENSION "副檔名"
 
-    /* As in 'INI File' or 'WAV File', fallback string for no-name extensions
-       used in the _File type_ tab of the _Folder Options_ dialog */
-    IDS_FILE_EXT_TYPE "%s 檔案"
-
     IDS_BYTES_FORMAT "位元組"
     IDS_UNKNOWN_APP "不明應用程式"
     IDS_EXE_DESCRIPTION "描述:"
diff --git a/dll/win32/shell32/lang/zh-TW.rc b/dll/win32/shell32/lang/zh-TW.rc
index c4e5ec18405..2bc2ea7d49f 100644
--- a/dll/win32/shell32/lang/zh-TW.rc
+++ b/dll/win32/shell32/lang/zh-TW.rc
@@ -999,10 +999,6 @@ BEGIN
     IDS_FILE_TYPES "檔案類型"
     IDS_COLUMN_EXTENSION "副檔名"
 
-    /* As in 'INI File' or 'WAV File', fallback string for no-name extensions
-       used in the _File type_ tab of the _Folder Options_ dialog */
-    IDS_FILE_EXT_TYPE "%s 檔案"
-
     IDS_BYTES_FORMAT "位元組"
     IDS_UNKNOWN_APP "未知應用程式"
     IDS_EXE_DESCRIPTION "描述:"
diff --git a/dll/win32/shell32/precomp.h b/dll/win32/shell32/precomp.h
index 8389048af63..97fd073ab6d 100644
--- a/dll/win32/shell32/precomp.h
+++ b/dll/win32/shell32/precomp.h
@@ -111,6 +111,7 @@
 #include "CUserNotification.h"
 #include "dialogs/folder_options.h"
 #include "shelldesktop/CChangeNotifyServer.h"
+#include "utils.h"
 
 #include <wine/debug.h>
 #include <wine/unicode.h>
diff --git a/dll/win32/shell32/shresdef.h b/dll/win32/shell32/shresdef.h
index 6721e625e5d..d4c8422d29a 100644
--- a/dll/win32/shell32/shresdef.h
+++ b/dll/win32/shell32/shresdef.h
@@ -188,7 +188,6 @@
 #define IDS_FILE_TYPES            174
 #define IDS_FILE_DETAILS          175
 #define IDS_FILE_DETAILSADV       176
-#define IDS_FILE_EXT_TYPE         999
 #define IDS_BYTES_FORMAT          177
 #define IDS_OPEN_WITH_RECOMMENDED 178
 #define IDS_OPEN_WITH_OTHER       179
diff --git a/dll/win32/shell32/utils.h b/dll/win32/shell32/utils.h
new file mode 100644
index 00000000000..92a96888c5d
--- /dev/null
+++ b/dll/win32/shell32/utils.h
@@ -0,0 +1,47 @@
+/*
+ * PROJECT:     shell32
+ * LICENSE:     LGPL-2.1+ (https://spdx.org/licenses/LGPL-2.1+)
+ * PURPOSE:     Utility functions
+ * COPYRIGHT:   ReactOS Team
+ */
+
+#pragma once
+
+inline BOOL
+RegValueExists(HKEY hKey, LPCWSTR Name)
+{
+    return RegQueryValueExW(hKey, Name, NULL, NULL, NULL, NULL) == 
ERROR_SUCCESS;
+}
+
+inline BOOL
+RegKeyExists(HKEY hKey, LPCWSTR Path)
+{
+    BOOL ret = !RegOpenKeyExW(hKey, Path, 0, MAXIMUM_ALLOWED, &hKey);
+    if (ret)
+        RegCloseKey(hKey);
+    return ret;
+}
+
+inline DWORD
+RegSetOrDelete(HKEY hKey, LPCWSTR Name, DWORD Type, LPCVOID Data, DWORD Size)
+{
+    if (Data)
+        return RegSetValueExW(hKey, Name, 0, Type, LPBYTE(Data), Size);
+    else
+        return RegDeleteValueW(hKey, Name);
+}
+
+inline DWORD
+RegSetString(HKEY hKey, LPCWSTR Name, LPCWSTR Str, DWORD Type = REG_SZ)
+{
+    return RegSetValueExW(hKey, Name, 0, Type, LPBYTE(Str), (lstrlenW(Str) + 
1) * sizeof(WCHAR));
+}
+
+// SHExtractIconsW is a forward, use this function instead inside shell32
+inline HICON
+SHELL32_SHExtractIcon(LPCWSTR File, int Index, int cx, int cy)
+{
+    HICON hIco;
+    int r = PrivateExtractIconsW(File, Index, cx, cy, &hIco, NULL, 1, 0);
+    return r > 0 ? hIco : NULL;
+}
diff --git a/sdk/include/psdk/shlwapi.h b/sdk/include/psdk/shlwapi.h
index 8ca1e7544dc..547cf01ea8a 100644
--- a/sdk/include/psdk/shlwapi.h
+++ b/sdk/include/psdk/shlwapi.h
@@ -644,6 +644,32 @@ typedef enum
     ASSOCENUM_NONE
 } ASSOCENUM;
 
+typedef enum
+{
+    FTA_None                  = 0x00000000,
+    FTA_Exclude               = 0x00000001,
+    FTA_Show                  = 0x00000002,
+    FTA_HasExtension          = 0x00000004,
+    FTA_NoEdit                = 0x00000008,
+    FTA_NoRemove              = 0x00000010,
+    FTA_NoNewVerb             = 0x00000020,
+    FTA_NoEditVerb            = 0x00000040,
+    FTA_NoRemoveVerb          = 0x00000080,
+    FTA_NoEditDesc            = 0x00000100,
+    FTA_NoEditIcon            = 0x00000200,
+    FTA_NoEditDflt            = 0x00000400,
+    FTA_NoEditVerbCmd         = 0x00000800,
+    FTA_NoEditVerbExe         = 0x00001000,
+    FTA_NoDDE                 = 0x00002000,
+    FTA_NoEditMIME            = 0x00008000,
+    FTA_OpenIsSafe            = 0x00010000,
+    FTA_AlwaysUnsafe          = 0x00020000,
+    FTA_NoRecentDocs          = 0x00100000,
+    FTA_SafeForElevation      = 0x00200000, /* Win8+ */
+    FTA_AlwaysUseDirectInvoke = 0x00400000  /* Win8+ */
+} FILETYPEATTRIBUTEFLAGS;
+DEFINE_ENUM_FLAG_OPERATORS(FILETYPEATTRIBUTEFLAGS)
+
 typedef struct IQueryAssociations *LPQUERYASSOCIATIONS;
 
 #define INTERFACE IQueryAssociations

Reply via email to