Synchronize with trunk revision 59636 (just before Alex's CreateProcess revamp).
[reactos.git] / base / applications / regedit / framewnd.c
index a6b4144..7510472 100644 (file)
@@ -18,7 +18,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-#include <regedit.h>
+#include "regedit.h"
 
 /********************************************************************************
  * Global and Local Variables:
@@ -26,7 +26,7 @@
 
 #define FAVORITES_MENU_POSITION 3
 
-static TCHAR s_szFavoritesRegKey[] = _T("Software\\Microsoft\\Windows\\CurrentVersion\\Applets\\Regedit\\Favorites");
+static WCHAR s_szFavoritesRegKey[] = L"Software\\Microsoft\\Windows\\CurrentVersion\\Applets\\Regedit\\Favorites";
 
 static BOOL bInMenuLoop = FALSE;        /* Tells us if we are in the menu loop */
 
@@ -39,13 +39,14 @@ static void resize_frame_rect(HWND hWnd, PRECT prect)
     RECT rt;
     /*
        if (IsWindowVisible(hToolBar)) {
-               SendMessage(hToolBar, WM_SIZE, 0, 0);
+               SendMessageW(hToolBar, WM_SIZE, 0, 0);
                GetClientRect(hToolBar, &rt);
                prect->top = rt.bottom+3;
                prect->bottom -= rt.bottom+3;
        }
      */
-    if (IsWindowVisible(hStatusBar)) {
+    if (IsWindowVisible(hStatusBar))
+    {
         SetupStatusBar(hWnd, TRUE);
         GetClientRect(hStatusBar, &rt);
         prect->bottom -= rt.bottom;
@@ -68,7 +69,7 @@ static void OnInitMenu(HWND hWnd)
     LONG lResult;
     HKEY hKey = NULL;
     DWORD dwIndex, cbValueName, cbValueData, dwType;
-    TCHAR szValueName[256];
+    WCHAR szValueName[256];
     BYTE abValueData[256];
     static int s_nFavoriteMenuSubPos = -1;
     HMENU hMenu;
@@ -84,20 +85,19 @@ static void OnInitMenu(HWND hWnd)
     }
     else
     {
-        while(RemoveMenu(hMenu, s_nFavoriteMenuSubPos, MF_BYPOSITION))
-            ;
+        while(RemoveMenu(hMenu, s_nFavoriteMenuSubPos, MF_BYPOSITION)) ;
     }
 
-    lResult = RegOpenKey(HKEY_CURRENT_USER, s_szFavoritesRegKey, &hKey);
+    lResult = RegOpenKeyW(HKEY_CURRENT_USER, s_szFavoritesRegKey, &hKey);
     if (lResult != ERROR_SUCCESS)
         goto done;
 
     dwIndex = 0;
     do
     {
-        cbValueName = sizeof(szValueName) / sizeof(szValueName[0]);
+        cbValueName = COUNT_OF(szValueName);
         cbValueData = sizeof(abValueData);
-        lResult = RegEnumValue(hKey, dwIndex, szValueName, &cbValueName, NULL, &dwType, abValueData, &cbValueData);
+        lResult = RegEnumValueW(hKey, dwIndex, szValueName, &cbValueName, NULL, &dwType, abValueData, &cbValueData);
         if ((lResult == ERROR_SUCCESS) && (dwType == REG_SZ))
         {
             if (!bDisplayedAny)
@@ -123,9 +123,9 @@ static void OnEnterMenuLoop(HWND hWnd)
 
     /* Update the status bar pane sizes */
     nParts = -1;
-    SendMessage(hStatusBar, SB_SETPARTS, 1, (LPARAM)&nParts);
+    SendMessageW(hStatusBar, SB_SETPARTS, 1, (LPARAM)&nParts);
     bInMenuLoop = TRUE;
-    SendMessage(hStatusBar, SB_SETTEXT, (WPARAM)0, (LPARAM)_T(""));
+    SendMessageW(hStatusBar, SB_SETTEXTW, (WPARAM)0, (LPARAM)L"");
 }
 
 static void OnExitMenuLoop(HWND hWnd)
@@ -138,23 +138,26 @@ static void OnExitMenuLoop(HWND hWnd)
 
 static void OnMenuSelect(HWND hWnd, UINT nItemID, UINT nFlags, HMENU hSysMenu)
 {
-    TCHAR str[100];
+    WCHAR str[100];
 
-    _tcscpy(str, _T(""));
-    if (nFlags & MF_POPUP) {
-        if (hSysMenu != GetMenu(hWnd)) {
+    wcscpy(str, L"");
+    if (nFlags & MF_POPUP)
+    {
+        if (hSysMenu != GetMenu(hWnd))
+        {
             if (nItemID == 2) nItemID = 5;
         }
     }
-    if (LoadString(hInst, nItemID, str, 100)) {
+    if (LoadStringW(hInst, nItemID, str, 100))
+    {
         /* load appropriate string*/
-        LPTSTR lpsz = str;
+        LPWSTR lpsz = str;
         /* first newline terminates actual string*/
-        lpsz = _tcschr(lpsz, _T('\n'));
+        lpsz = wcschr(lpsz, L'\n');
         if (lpsz != NULL)
-            *lpsz = '\0';
+            *lpsz = L'\0';
     }
-    SendMessage(hStatusBar, SB_SETTEXT, 0, (LPARAM)str);
+    SendMessageW(hStatusBar, SB_SETTEXTW, 0, (LPARAM)str);
 }
 
 void SetupStatusBar(HWND hWnd, BOOL bResize)
@@ -165,16 +168,16 @@ void SetupStatusBar(HWND hWnd, BOOL bResize)
     nParts = rc.right;
     /*    nParts = -1;*/
     if (bResize)
-        SendMessage(hStatusBar, WM_SIZE, 0, 0);
-    SendMessage(hStatusBar, SB_SETPARTS, 1, (LPARAM)&nParts);
+        SendMessageW(hStatusBar, WM_SIZE, 0, 0);
+    SendMessageW(hStatusBar, SB_SETPARTS, 1, (LPARAM)&nParts);
 }
 
 void UpdateStatusBar(void)
 {
-       NMHDR nmhdr;
-       ZeroMemory(&nmhdr, sizeof(NMHDR));
+    NMHDR nmhdr;
+    ZeroMemory(&nmhdr, sizeof(NMHDR));
     nmhdr.code = TVN_SELCHANGED;
-    SendMessage(g_pChildWnd->hWnd, WM_NOTIFY, (WPARAM)TREE_WINDOW, (LPARAM)&nmhdr);
+    SendMessageW(g_pChildWnd->hWnd, WM_NOTIFY, (WPARAM)TREE_WINDOW, (LPARAM)&nmhdr);
 }
 
 static void toggle_child(HWND hWnd, UINT cmd, HWND hchild)
@@ -191,72 +194,73 @@ static BOOL CheckCommDlgError(HWND hWnd)
 {
     DWORD dwErrorCode = CommDlgExtendedError();
     UNREFERENCED_PARAMETER(hWnd);
-    switch (dwErrorCode) {
-    case CDERR_DIALOGFAILURE:
-        break;
-    case CDERR_FINDRESFAILURE:
-        break;
-    case CDERR_NOHINSTANCE:
-        break;
-    case CDERR_INITIALIZATION:
-        break;
-    case CDERR_NOHOOK:
-        break;
-    case CDERR_LOCKRESFAILURE:
-        break;
-    case CDERR_NOTEMPLATE:
-        break;
-    case CDERR_LOADRESFAILURE:
-        break;
-    case CDERR_STRUCTSIZE:
-        break;
-    case CDERR_LOADSTRFAILURE:
-        break;
-    case FNERR_BUFFERTOOSMALL:
-        break;
-    case CDERR_MEMALLOCFAILURE:
-        break;
-    case FNERR_INVALIDFILENAME:
-        break;
-    case CDERR_MEMLOCKFAILURE:
-        break;
-    case FNERR_SUBCLASSFAILURE:
-        break;
-    default:
-        break;
+    switch (dwErrorCode)
+    {
+        case CDERR_DIALOGFAILURE:
+            break;
+        case CDERR_FINDRESFAILURE:
+            break;
+        case CDERR_NOHINSTANCE:
+            break;
+        case CDERR_INITIALIZATION:
+            break;
+        case CDERR_NOHOOK:
+            break;
+        case CDERR_LOCKRESFAILURE:
+            break;
+        case CDERR_NOTEMPLATE:
+            break;
+        case CDERR_LOADRESFAILURE:
+            break;
+        case CDERR_STRUCTSIZE:
+            break;
+        case CDERR_LOADSTRFAILURE:
+            break;
+        case FNERR_BUFFERTOOSMALL:
+            break;
+        case CDERR_MEMALLOCFAILURE:
+            break;
+        case FNERR_INVALIDFILENAME:
+            break;
+        case CDERR_MEMLOCKFAILURE:
+            break;
+        case FNERR_SUBCLASSFAILURE:
+            break;
+        default:
+            break;
     }
     return TRUE;
 }
 
-TCHAR FileNameBuffer[_MAX_PATH];
-TCHAR FileTitleBuffer[_MAX_PATH];
+WCHAR FileNameBuffer[_MAX_PATH];
+WCHAR FileTitleBuffer[_MAX_PATH];
 
 typedef struct
 {
-  UINT DisplayID;
-  UINT FilterID;
+    UINT DisplayID;
+    UINT FilterID;
 } FILTERPAIR, *PFILTERPAIR;
 
 void
-BuildFilterStrings(TCHAR *Filter, PFILTERPAIR Pairs, int PairCount)
+BuildFilterStrings(WCHAR *Filter, PFILTERPAIR Pairs, int PairCount)
 {
-  int i, c;
-
-  c = 0;
-  for(i = 0; i < PairCount; i++)
-  {
-    c += LoadString(hInst, Pairs[i].DisplayID, &Filter[c], 255 * sizeof(TCHAR));
-    Filter[++c] = '\0';
-    c += LoadString(hInst, Pairs[i].FilterID, &Filter[c], 255 * sizeof(TCHAR));
-    Filter[++c] = '\0';
-  }
-  Filter[++c] = '\0';
+    int i, c;
+
+    c = 0;
+    for(i = 0; i < PairCount; i++)
+    {
+        c += LoadStringW(hInst, Pairs[i].DisplayID, &Filter[c], 255 * sizeof(WCHAR));
+        Filter[++c] = L'\0';
+        c += LoadStringW(hInst, Pairs[i].FilterID, &Filter[c], 255 * sizeof(WCHAR));
+        Filter[++c] = L'\0';
+    }
+    Filter[++c] = L'\0';
 }
 
 static BOOL InitOpenFileName(HWND hWnd, OPENFILENAME* pofn)
 {
-    FILTERPAIR FilterPairs[3];
-    static TCHAR Filter[1024];
+    FILTERPAIR FilterPairs[4];
+    static WCHAR Filter[1024];
 
     memset(pofn, 0, sizeof(OPENFILENAME));
     pofn->lStructSize = sizeof(OPENFILENAME);
@@ -266,11 +270,13 @@ static BOOL InitOpenFileName(HWND hWnd, OPENFILENAME* pofn)
     /* create filter string */
     FilterPairs[0].DisplayID = IDS_FLT_REGFILES;
     FilterPairs[0].FilterID = IDS_FLT_REGFILES_FLT;
-    FilterPairs[1].DisplayID = IDS_FLT_REGEDIT4;
-    FilterPairs[1].FilterID = IDS_FLT_REGEDIT4_FLT;
-    FilterPairs[2].DisplayID = IDS_FLT_ALLFILES;
-    FilterPairs[2].FilterID = IDS_FLT_ALLFILES_FLT;
-    BuildFilterStrings(Filter, FilterPairs, sizeof(FilterPairs) / sizeof(FILTERPAIR));
+    FilterPairs[1].DisplayID = IDS_FLT_HIVFILES;
+    FilterPairs[1].FilterID = IDS_FLT_HIVFILES_FLT;
+    FilterPairs[2].DisplayID = IDS_FLT_REGEDIT4;
+    FilterPairs[2].FilterID = IDS_FLT_REGEDIT4_FLT;
+    FilterPairs[3].DisplayID = IDS_FLT_ALLFILES;
+    FilterPairs[3].FilterID = IDS_FLT_ALLFILES_FLT;
+    BuildFilterStrings(Filter, FilterPairs, COUNT_OF(FilterPairs));
 
     pofn->lpstrFilter = Filter;
     pofn->lpstrFile = FileNameBuffer;
@@ -278,48 +284,246 @@ static BOOL InitOpenFileName(HWND hWnd, OPENFILENAME* pofn)
     pofn->lpstrFileTitle = FileTitleBuffer;
     pofn->nMaxFileTitle = _MAX_PATH;
     pofn->Flags = OFN_HIDEREADONLY;
+    pofn->lpstrDefExt = L"reg";
     return TRUE;
 }
 
-static BOOL ImportRegistryFile(HWND hWnd)
+#define LOADHIVE_KEYNAMELENGTH 128
+
+static INT_PTR CALLBACK LoadHive_KeyNameInHookProc(HWND hWndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
 {
-    OPENFILENAME ofn;
-    TCHAR Caption[128];
+    static LPWSTR sKey = NULL;
+    switch(uMsg)
+    {
+    case WM_INITDIALOG:
+        sKey = (LPWSTR)lParam;
+        break;
+    case WM_COMMAND:
+        switch(LOWORD(wParam))
+        {
+        case IDOK:
+            if(GetDlgItemTextW(hWndDlg, IDC_EDIT_KEY, sKey, LOADHIVE_KEYNAMELENGTH))
+                return EndDialog(hWndDlg, -1);
+            else
+                return EndDialog(hWndDlg, 0);
+        case IDCANCEL:
+            return EndDialog(hWndDlg, 0);
+        }
+        break;
+    }
+    return FALSE;
+}
+
+static BOOL EnablePrivilege(LPCWSTR lpszPrivilegeName, LPCWSTR lpszSystemName, BOOL bEnablePrivilege)
+{
+    BOOL   bRet   = FALSE;
+    HANDLE hToken = NULL;
+
+    if (OpenProcessToken(GetCurrentProcess(),
+                         TOKEN_ADJUST_PRIVILEGES,
+                         &hToken))
+    {
+        TOKEN_PRIVILEGES tp;
+
+        tp.PrivilegeCount = 1;
+        tp.Privileges[0].Attributes = (bEnablePrivilege ? SE_PRIVILEGE_ENABLED : 0);
+
+        if (LookupPrivilegeValueW(lpszSystemName,
+                                  lpszPrivilegeName,
+                                  &tp.Privileges[0].Luid))
+        {
+            bRet = AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL);
+
+            if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
+                bRet = FALSE;
+        }
+
+        CloseHandle(hToken);
+    }
+
+    return bRet;
+}
 
+static BOOL LoadHive(HWND hWnd)
+{
+    OPENFILENAME ofn;
+    WCHAR Caption[128];
+    LPCWSTR pszKeyPath;
+    WCHAR xPath[LOADHIVE_KEYNAMELENGTH];
+    HKEY hRootKey;
+    WCHAR Filter[1024];
+    FILTERPAIR filter;
+    /* get the item key to load the hive in */
+    pszKeyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hRootKey);
+    /* initialize the "open file" dialog */
     InitOpenFileName(hWnd, &ofn);
-    LoadString(hInst, IDS_IMPORT_REG_FILE, Caption, sizeof(Caption)/sizeof(TCHAR));
+    /* build the "All Files" filter up */
+    filter.DisplayID = IDS_FLT_ALLFILES;
+    filter.FilterID = IDS_FLT_ALLFILES_FLT;
+    BuildFilterStrings(Filter, &filter, sizeof(filter));
+    ofn.lpstrFilter = Filter;
+    /* load and set the caption and flags for dialog */
+    LoadStringW(hInst, IDS_LOAD_HIVE, Caption, COUNT_OF(Caption));
     ofn.lpstrTitle = Caption;
+    ofn.Flags |= OFN_ENABLESIZING;
     /*    ofn.lCustData = ;*/
-    if (GetOpenFileName(&ofn)) {
-        /* FIXME - convert to ascii */
-       if (!import_registry_file(ofn.lpstrFile)) {
-            /*printf("Can't open file \"%s\"\n", ofn.lpstrFile);*/
-            return FALSE;
-        }
-#if 0
-        get_file_name(&s, filename, MAX_PATH);
-        if (!filename[0]) {
-            printf("No file name is specified\n%s", usage);
-            return FALSE;
-            /*exit(1);*/
-        }
-        while (filename[0]) {
-            if (!import_registry_file(filename)) {
-                perror("");
-                printf("Can't open file \"%s\"\n", filename);
+    /* now load the hive */
+    if (GetOpenFileName(&ofn))
+    {
+        if (DialogBoxParamW(hInst, MAKEINTRESOURCEW(IDD_LOADHIVE), hWnd,
+                            &LoadHive_KeyNameInHookProc, (LPARAM)xPath))
+        {
+            LONG regLoadResult;
+
+            /* Enable the 'restore' privilege, load the hive, disable the privilege */
+            EnablePrivilege(SE_RESTORE_NAME, NULL, TRUE);
+            regLoadResult = RegLoadKeyW(hRootKey, xPath, ofn.lpstrFile);
+            EnablePrivilege(SE_RESTORE_NAME, NULL, FALSE);
+
+            if(regLoadResult == ERROR_SUCCESS)
+            {
+                /* refresh tree and list views */
+                RefreshTreeView(g_pChildWnd->hTreeWnd);
+                pszKeyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hRootKey);
+                RefreshListView(g_pChildWnd->hListWnd, hRootKey, pszKeyPath);
+            }
+            else
+            {
+                ErrorMessageBox(hWnd, Caption, regLoadResult);
                 return FALSE;
-                /*exit(1);*/
             }
-            get_file_name(&s, filename, MAX_PATH);
         }
-#endif
-
-    } else {
+    }
+    else
+    {
         CheckCommDlgError(hWnd);
     }
     return TRUE;
 }
 
+static BOOL UnloadHive(HWND hWnd)
+{
+    WCHAR Caption[128];
+    LPCWSTR pszKeyPath;
+    HKEY hRootKey;
+    LONG regUnloadResult;
+
+    /* get the item key to unload */
+    pszKeyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hRootKey);
+    /* load and set the caption and flags for dialog */
+    LoadStringW(hInst, IDS_UNLOAD_HIVE, Caption, COUNT_OF(Caption));
+
+    /* Enable the 'restore' privilege, unload the hive, disable the privilege */
+    EnablePrivilege(SE_RESTORE_NAME, NULL, TRUE);
+    regUnloadResult = RegUnLoadKeyW(hRootKey, pszKeyPath);
+    EnablePrivilege(SE_RESTORE_NAME, NULL, FALSE);
+
+    if(regUnloadResult == ERROR_SUCCESS)
+    {
+        /* refresh tree and list views */
+        RefreshTreeView(g_pChildWnd->hTreeWnd);
+        pszKeyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hRootKey);
+        RefreshListView(g_pChildWnd->hListWnd, hRootKey, pszKeyPath);
+    }
+    else
+    {
+        ErrorMessageBox(hWnd, Caption, regUnloadResult);
+        return FALSE;
+    }
+    return TRUE;
+}
+
+static BOOL ImportRegistryFile(HWND hWnd)
+{
+    BOOL bRet = FALSE;
+    OPENFILENAME ofn;
+    WCHAR Caption[128], szTitle[512], szText[512];
+    HKEY hKeyRoot;
+    LPCWSTR pszKeyPath;
+
+    /* Figure out in which key path we are importing */
+    pszKeyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
+
+    InitOpenFileName(hWnd, &ofn);
+    LoadStringW(hInst, IDS_IMPORT_REG_FILE, Caption, COUNT_OF(Caption));
+    ofn.lpstrTitle = Caption;
+    ofn.Flags |= OFN_ENABLESIZING;
+    /*    ofn.lCustData = ;*/
+    if (GetOpenFileName(&ofn))
+    {
+        /* Look at the extension of the file to determine its type */
+        if (ofn.nFileExtension >= 1 &&
+            _wcsicmp(ofn.lpstrFile + ofn.nFileExtension, L"reg") == 0) /* REGEDIT4 or Windows Registry Editor Version 5.00 */
+        {
+            /* Open the file */
+            FILE* fp = _wfopen(ofn.lpstrFile, L"r");
+
+            /* Import it */
+            if (fp == NULL || !import_registry_file(fp))
+            {
+                /* Error opening the file */
+                LoadStringW(hInst, IDS_APP_TITLE, szTitle, COUNT_OF(szTitle));
+                LoadStringW(hInst, IDS_IMPORT_ERROR, szText, COUNT_OF(szText));
+                InfoMessageBox(hWnd, MB_OK | MB_ICONERROR, szTitle, szText, ofn.lpstrFile);
+                bRet = FALSE;
+            }
+            else
+            {
+                /* Show successful import */
+                LoadStringW(hInst, IDS_APP_TITLE, szTitle, COUNT_OF(szTitle));
+                LoadStringW(hInst, IDS_IMPORT_OK, szText, COUNT_OF(szText));
+                InfoMessageBox(hWnd, MB_OK | MB_ICONINFORMATION, szTitle, szText, ofn.lpstrFile);
+                bRet = TRUE;
+            }
+
+            /* Close the file */
+            if (fp) fclose(fp);
+        }
+        else /* Registry Hive Files */
+        {
+            LoadStringW(hInst, IDS_QUERY_IMPORT_HIVE_CAPTION, szTitle, COUNT_OF(szTitle));
+            LoadStringW(hInst, IDS_QUERY_IMPORT_HIVE_MSG, szText, COUNT_OF(szText));
+
+            /* Display a confirmation message */
+            if (MessageBoxW(g_pChildWnd->hWnd, szText, szTitle, MB_ICONWARNING | MB_YESNO) == IDYES)
+            {
+                LONG lResult;
+                HKEY hSubKey;
+
+                /* Open the subkey */
+                lResult = RegOpenKeyExW(hKeyRoot, pszKeyPath, 0, KEY_WRITE, &hSubKey);
+                if (lResult == ERROR_SUCCESS)
+                {
+                    /* Enable the 'restore' privilege, restore the hive then disable the privilege */
+                    EnablePrivilege(SE_RESTORE_NAME, NULL, TRUE);
+                    lResult = RegRestoreKey(hSubKey, ofn.lpstrFile, REG_FORCE_RESTORE);
+                    EnablePrivilege(SE_RESTORE_NAME, NULL, FALSE);
+
+                    /* Flush the subkey and close it */
+                    RegFlushKey(hSubKey);
+                    RegCloseKey(hSubKey);
+                }
+
+                /* Set the return value */
+                bRet = (lResult == ERROR_SUCCESS);
+
+                /* Display error, if any */
+                if (!bRet) ErrorMessageBox(hWnd, Caption, lResult);
+            }
+        }
+    }
+    else
+    {
+        CheckCommDlgError(hWnd);
+    }
+
+    /* refresh tree and list views */
+    RefreshTreeView(g_pChildWnd->hTreeWnd);
+    pszKeyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
+    RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, pszKeyPath);
+
+    return bRet;
+}
 
 static UINT_PTR CALLBACK ExportRegistryFile_OFNHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
 {
@@ -328,47 +532,48 @@ static UINT_PTR CALLBACK ExportRegistryFile_OFNHookProc(HWND hdlg, UINT uiMsg, W
     HWND hwndExportBranchText;
     UINT_PTR iResult = 0;
     OPENFILENAME *pOfn;
-    LPTSTR pszSelectedKey;
+    LPWSTR pszSelectedKey;
     OFNOTIFY *pOfnNotify;
 
     UNREFERENCED_PARAMETER(wParam);
 
-       switch(uiMsg) {
-       case WM_INITDIALOG:
+    switch(uiMsg)
+    {
+    case WM_INITDIALOG:
         pOfn = (OPENFILENAME *) lParam;
-        pszSelectedKey = (LPTSTR) pOfn->lCustData;
+        pszSelectedKey = (LPWSTR) pOfn->lCustData;
 
         hwndExportAll = GetDlgItem(hdlg, IDC_EXPORT_ALL);
         if (hwndExportAll)
-            SendMessage(hwndExportAll, BM_SETCHECK, pszSelectedKey ? BST_UNCHECKED : BST_CHECKED, 0);
+            SendMessageW(hwndExportAll, BM_SETCHECK, pszSelectedKey ? BST_UNCHECKED : BST_CHECKED, 0);
 
         hwndExportBranch = GetDlgItem(hdlg, IDC_EXPORT_BRANCH);
         if (hwndExportBranch)
-            SendMessage(hwndExportBranch, BM_SETCHECK, pszSelectedKey ? BST_CHECKED : BST_UNCHECKED, 0);
+            SendMessageW(hwndExportBranch, BM_SETCHECK, pszSelectedKey ? BST_CHECKED : BST_UNCHECKED, 0);
 
         hwndExportBranchText = GetDlgItem(hdlg, IDC_EXPORT_BRANCH_TEXT);
         if (hwndExportBranchText)
-            SetWindowText(hwndExportBranchText, pszSelectedKey);
+            SetWindowTextW(hwndExportBranchText, pszSelectedKey);
         break;
 
-       case WM_NOTIFY:
+    case WM_NOTIFY:
         if (((NMHDR *) lParam)->code == CDN_FILEOK)
         {
             pOfnNotify = (OFNOTIFY *) lParam;
-            pszSelectedKey = (LPTSTR) pOfnNotify->lpOFN->lCustData;
+            pszSelectedKey = (LPWSTR) pOfnNotify->lpOFN->lCustData;
 
             hwndExportBranch = GetDlgItem(hdlg, IDC_EXPORT_BRANCH);
             hwndExportBranchText = GetDlgItem(hdlg, IDC_EXPORT_BRANCH_TEXT);
             if (hwndExportBranch && hwndExportBranchText
-                && (SendMessage(hwndExportBranch, BM_GETCHECK, 0, 0) == BST_CHECKED))
-                       {
-                           GetWindowText(hwndExportBranchText, pszSelectedKey, _MAX_PATH);
-                       }
-                       else
-                       {
-                           pszSelectedKey[0] = '\0';
-                       }
-               }
+                    && (SendMessageW(hwndExportBranch, BM_GETCHECK, 0, 0) == BST_CHECKED))
+            {
+                GetWindowTextW(hwndExportBranchText, pszSelectedKey, _MAX_PATH);
+            }
+            else
+            {
+                pszSelectedKey[0] = L'\0';
+            }
+        }
         break;
     }
     return iResult;
@@ -376,19 +581,19 @@ static UINT_PTR CALLBACK ExportRegistryFile_OFNHookProc(HWND hdlg, UINT uiMsg, W
 
 BOOL ExportRegistryFile(HWND hWnd)
 {
+    BOOL bRet = FALSE;
     OPENFILENAME ofn;
-    TCHAR ExportKeyPath[_MAX_PATH];
-    TCHAR Caption[128];
+    WCHAR ExportKeyPath[_MAX_PATH];
+    WCHAR Caption[128], szTitle[512], szText[512];
     HKEY hKeyRoot;
-    LPCTSTR pszKeyPath;
+    LPCWSTR pszKeyPath;
 
     /* Figure out which key path we are exporting */
     pszKeyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
-    RegKeyGetName(ExportKeyPath, sizeof(ExportKeyPath) / sizeof(ExportKeyPath[0]),
-        hKeyRoot, pszKeyPath);
+    GetKeyName(ExportKeyPath, COUNT_OF(ExportKeyPath), hKeyRoot, pszKeyPath);
 
     InitOpenFileName(hWnd, &ofn);
-    LoadString(hInst, IDS_EXPORT_REG_FILE, Caption, sizeof(Caption)/sizeof(TCHAR));
+    LoadStringW(hInst, IDS_EXPORT_REG_FILE, Caption, COUNT_OF(Caption));
     ofn.lpstrTitle = Caption;
 
     /* Only set the path if a key (not the root node) is selected */
@@ -396,51 +601,95 @@ BOOL ExportRegistryFile(HWND hWnd)
     {
         ofn.lCustData = (LPARAM) ExportKeyPath;
     }
-    ofn.Flags = OFN_ENABLETEMPLATE | OFN_EXPLORER | OFN_ENABLEHOOK;
+    ofn.Flags = OFN_ENABLETEMPLATE | OFN_EXPLORER | OFN_ENABLEHOOK | OFN_OVERWRITEPROMPT;
     ofn.lpfnHook = ExportRegistryFile_OFNHookProc;
-    ofn.lpTemplateName = MAKEINTRESOURCE(IDD_EXPORTRANGE);
-    if (GetSaveFileName(&ofn)) {
-        BOOL result;
-        LPSTR pszExportKeyPath;
-#ifdef UNICODE
-        CHAR buffer[_MAX_PATH];
-
-        WideCharToMultiByte(CP_ACP, 0, ExportKeyPath, -1, buffer, sizeof(buffer), NULL, NULL);
-        pszExportKeyPath = buffer;
-#else
-        pszExportKeyPath = ExportKeyPath;
-#endif
+    ofn.lpTemplateName = MAKEINTRESOURCEW(IDD_EXPORTRANGE);
+    if (GetSaveFileName(&ofn))
+    {
+        switch (ofn.nFilterIndex)
+        {
+            case 2: /* Registry Hive Files */
+            {
+                LONG lResult;
+                HKEY hSubKey;
 
-        result = export_registry_key(ofn.lpstrFile, pszExportKeyPath);
-        if (!result) {
-            /*printf("Can't open file \"%s\"\n", ofn.lpstrFile);*/
-            return FALSE;
-        }
-#if 0
-        TCHAR filename[MAX_PATH];
-        filename[0] = '\0';
-        get_file_name(&s, filename, MAX_PATH);
-        if (!filename[0]) {
-            printf("No file name is specified\n%s", usage);
-            return FALSE;
-            /*exit(1);*/
-        }
-        if (s[0]) {
-            TCHAR reg_key_name[KEY_MAX_LEN];
-            get_file_name(&s, reg_key_name, KEY_MAX_LEN);
-            export_registry_key((CHAR)filename, reg_key_name);
-        } else {
-            export_registry_key(filename, NULL);
-        }
-#endif
+                /* Open the subkey */
+                lResult = RegOpenKeyExW(hKeyRoot, pszKeyPath, 0, KEY_READ, &hSubKey);
+                if (lResult == ERROR_SUCCESS)
+                {
+                    /* Enable the 'backup' privilege, save the hive then disable the privilege */
+                    EnablePrivilege(SE_BACKUP_NAME, NULL, TRUE);
+                    lResult = RegSaveKeyW(hSubKey, ofn.lpstrFile, NULL);
+                    if (lResult == ERROR_ALREADY_EXISTS)
+                    {
+                        /*
+                         * We are here, that means that we already said "yes" to the confirmation dialog.
+                         * So we absolutely want to replace the hive file.
+                         */
+                        if (DeleteFileW(ofn.lpstrFile))
+                        {
+                            /* Try again */
+                            lResult = RegSaveKeyW(hSubKey, ofn.lpstrFile, NULL);
+                        }
+                    }
+                    EnablePrivilege(SE_BACKUP_NAME, NULL, FALSE);
+
+                    if (lResult != ERROR_SUCCESS)
+                    {
+                        /*
+                         * If we are here, it's because RegSaveKeyW has failed for any reason.
+                         * The problem is that even if it has failed, it has created or
+                         * replaced the exported hive file with a new empty file. We don't
+                         * want to keep this file, so we delete it.
+                         */
+                        DeleteFileW(ofn.lpstrFile);
+                    }
+
+                    /* Close the subkey */
+                    RegCloseKey(hSubKey);
+                }
 
-    } else {
+                /* Set the return value */
+                bRet = (lResult == ERROR_SUCCESS);
+
+                /* Display error, if any */
+                if (!bRet) ErrorMessageBox(hWnd, Caption, lResult);
+
+                break;
+            }
+
+            case 1:  /* Windows Registry Editor Version 5.00 */
+            case 3:  /* REGEDIT4 */
+            default: /* All files ==> use Windows Registry Editor Version 5.00 */
+            {
+                if (!export_registry_key(ofn.lpstrFile, ExportKeyPath,
+                                         (ofn.nFilterIndex == 3 ? REG_FORMAT_4
+                                                                : REG_FORMAT_5)))
+                {
+                    /* Error creating the file */
+                    LoadStringW(hInst, IDS_APP_TITLE, szTitle, COUNT_OF(szTitle));
+                    LoadStringW(hInst, IDS_EXPORT_ERROR, szText, COUNT_OF(szText));
+                    InfoMessageBox(hWnd, MB_OK | MB_ICONERROR, szTitle, szText, ofn.lpstrFile);
+                    bRet = FALSE;
+                }
+                else
+                {
+                    bRet = TRUE;
+                }
+
+                break;
+            }
+        }
+    }
+    else
+    {
         CheckCommDlgError(hWnd);
     }
-    return TRUE;
+
+    return bRet;
 }
 
-BOOL PrintRegistryHive(HWND hWnd, LPTSTR path)
+BOOL PrintRegistryHive(HWND hWnd, LPWSTR path)
 {
 #if 1
     PRINTDLG pd;
@@ -457,7 +706,8 @@ BOOL PrintRegistryHive(HWND hWnd, LPTSTR path)
     pd.nToPage     = 0xFFFF;
     pd.nMinPage    = 1;
     pd.nMaxPage    = 0xFFFF;
-    if (PrintDlg(&pd)) {
+    if (PrintDlg(&pd))
+    {
         /* GDI calls to render output. */
         DeleteDC(pd.hDC); /* Delete DC when done.*/
     }
@@ -466,8 +716,10 @@ BOOL PrintRegistryHive(HWND hWnd, LPTSTR path)
     PRINTDLGEX pd;
 
     hResult = PrintDlgEx(&pd);
-    if (hResult == S_OK) {
-        switch (pd.dwResultAction) {
+    if (hResult == S_OK)
+    {
+        switch (pd.dwResultAction)
+        {
         case PD_RESULT_APPLY:
             /*The user clicked the Apply button and later clicked the Cancel button. This indicates that the user wants to apply the changes made in the property sheet, but does not yet want to print. The PRINTDLGEX structure contains the information specified by the user at the time the Apply button was clicked. */
             break;
@@ -480,8 +732,11 @@ BOOL PrintRegistryHive(HWND hWnd, LPTSTR path)
         default:
             break;
         }
-    } else {
-        switch (hResult) {
+    }
+    else
+    {
+        switch (hResult)
+        {
         case E_OUTOFMEMORY:
             /*Insufficient memory. */
             break;
@@ -506,18 +761,18 @@ BOOL PrintRegistryHive(HWND hWnd, LPTSTR path)
     return TRUE;
 }
 
-static void ChooseFavorite(LPCTSTR pszFavorite)
+static void ChooseFavorite(LPCWSTR pszFavorite)
 {
     HKEY hKey = NULL;
-    TCHAR szFavoritePath[512];
+    WCHAR szFavoritePath[512];
     DWORD cbData, dwType;
 
-    if (RegOpenKeyEx(HKEY_CURRENT_USER, s_szFavoritesRegKey, 0, KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS)
+    if (RegOpenKeyExW(HKEY_CURRENT_USER, s_szFavoritesRegKey, 0, KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS)
         goto done;
 
     cbData = (sizeof(szFavoritePath) / sizeof(szFavoritePath[0])) - 1;
     memset(szFavoritePath, 0, sizeof(szFavoritePath));
-    if (RegQueryValueEx(hKey, pszFavorite, NULL, &dwType, (LPBYTE) szFavoritePath, &cbData) != ERROR_SUCCESS)
+    if (RegQueryValueExW(hKey, pszFavorite, NULL, &dwType, (LPBYTE) szFavoritePath, &cbData) != ERROR_SUCCESS)
         goto done;
 
     if (dwType == REG_SZ)
@@ -528,13 +783,13 @@ done:
         RegCloseKey(hKey);
 }
 
-BOOL CopyKeyName(HWND hWnd, HKEY hRootKey, LPCTSTR keyName)
+BOOL CopyKeyName(HWND hWnd, HKEY hRootKey, LPCWSTR keyName)
 {
     BOOL bClipboardOpened = FALSE;
     BOOL bSuccess = FALSE;
-    TCHAR szBuffer[512];
+    WCHAR szBuffer[512];
     HGLOBAL hGlobal;
-    LPTSTR s;
+    LPWSTR s;
 
     if (!OpenClipboard(hWnd))
         goto done;
@@ -543,22 +798,18 @@ BOOL CopyKeyName(HWND hWnd, HKEY hRootKey, LPCTSTR keyName)
     if (!EmptyClipboard())
         goto done;
 
-    if (!RegKeyGetName(szBuffer, sizeof(szBuffer) / sizeof(szBuffer[0]), hRootKey, keyName))
+    if (!GetKeyName(szBuffer, COUNT_OF(szBuffer), hRootKey, keyName))
         goto done;
 
-    hGlobal = GlobalAlloc(GMEM_MOVEABLE, (_tcslen(szBuffer) + 1) * sizeof(TCHAR));
+    hGlobal = GlobalAlloc(GMEM_MOVEABLE, (wcslen(szBuffer) + 1) * sizeof(WCHAR));
     if (!hGlobal)
         goto done;
 
     s = GlobalLock(hGlobal);
-    _tcscpy(s, szBuffer);
+    wcscpy(s, szBuffer);
     GlobalUnlock(hGlobal);
 
-#ifdef UNICODE
     SetClipboardData(CF_UNICODETEXT, hGlobal);
-#else
-    SetClipboardData(CF_TEXT, hGlobal);
-#endif
     bSuccess = TRUE;
 
 done:
@@ -567,10 +818,10 @@ done:
     return bSuccess;
 }
 
-static BOOL CreateNewValue(HKEY hRootKey, LPCTSTR pszKeyPath, DWORD dwType)
+static BOOL CreateNewValue(HKEY hRootKey, LPCWSTR pszKeyPath, DWORD dwType)
 {
-    TCHAR szNewValueFormat[128];
-    TCHAR szNewValue[128];
+    WCHAR szNewValueFormat[128];
+    WCHAR szNewValue[128];
     int iIndex = 1;
     BYTE data[128];
     DWORD dwExistingType, cbData;
@@ -578,44 +829,55 @@ static BOOL CreateNewValue(HKEY hRootKey, LPCTSTR pszKeyPath, DWORD dwType)
     HKEY hKey;
     LVFINDINFO lvfi;
 
-    if (RegOpenKey(hRootKey, pszKeyPath, &hKey) != ERROR_SUCCESS)
+    if (RegOpenKeyExW(hRootKey, pszKeyPath, 0, KEY_QUERY_VALUE | KEY_SET_VALUE,
+                      &hKey) != ERROR_SUCCESS)
         return FALSE;
 
-    LoadString(hInst, IDS_NEW_VALUE, szNewValueFormat, sizeof(szNewValueFormat)
-        / sizeof(szNewValueFormat[0]));
+    LoadStringW(hInst, IDS_NEW_VALUE, szNewValueFormat, COUNT_OF(szNewValueFormat));
 
     do
     {
-        _sntprintf(szNewValue, sizeof(szNewValue) / sizeof(szNewValue[0]),
-            szNewValueFormat, iIndex++);
-
+        wsprintf(szNewValue, szNewValueFormat, iIndex++);
         cbData = sizeof(data);
-        lResult = RegQueryValueEx(hKey, szNewValue, NULL, &dwExistingType, data, &cbData);
+        lResult = RegQueryValueExW(hKey, szNewValue, NULL, &dwExistingType, data, &cbData);
     }
     while(lResult == ERROR_SUCCESS);
 
-    switch(dwType) {
-    case REG_DWORD:
-        cbData = sizeof(DWORD);
-        break;
-    case REG_SZ:
-    case REG_EXPAND_SZ:
-        cbData = sizeof(TCHAR);
-        break;
-    case REG_MULTI_SZ:
-        cbData = sizeof(TCHAR) * 2;
-        break;
-    case REG_QWORD:
-        cbData = sizeof(DWORD) * 2;
-        break;
-    default:
-        cbData = 0;
-        break;
+    switch(dwType)
+    {
+        case REG_DWORD:
+            cbData = sizeof(DWORD);
+            break;
+        case REG_SZ:
+        case REG_EXPAND_SZ:
+            cbData = sizeof(WCHAR);
+            break;
+        case REG_MULTI_SZ:
+            /*
+             * WARNING: An empty multi-string has only one null char.
+             * Indeed, multi-strings are built in the following form:
+             * str1\0str2\0...strN\0\0
+             * where each strI\0 is a null-terminated string, and it
+             * ends with a terminating empty string.
+             * Therefore an empty multi-string contains only the terminating
+             * empty string, that is, one null char.
+             */
+            cbData = sizeof(WCHAR);
+            break;
+        case REG_QWORD: /* REG_QWORD_LITTLE_ENDIAN */
+            cbData = sizeof(DWORDLONG); // == sizeof(DWORD) * 2;
+            break;
+        default:
+            cbData = 0;
+            break;
     }
     memset(data, 0, cbData);
-    lResult = RegSetValueEx(hKey, szNewValue, 0, dwType, data, cbData);
+    lResult = RegSetValueExW(hKey, szNewValue, 0, dwType, data, cbData);
+    RegCloseKey(hKey);
     if (lResult != ERROR_SUCCESS)
+    {
         return FALSE;
+    }
 
     RefreshListView(g_pChildWnd->hListWnd, hRootKey, pszKeyPath);
 
@@ -650,9 +912,9 @@ InitializeRemoteRegistryPicker(OUT IDsObjectPicker **pDsObjectPicker)
             {
                 sizeof(DSOP_SCOPE_INIT_INFO),
                 DSOP_SCOPE_TYPE_USER_ENTERED_UPLEVEL_SCOPE | DSOP_SCOPE_TYPE_USER_ENTERED_DOWNLEVEL_SCOPE |
-                    DSOP_SCOPE_TYPE_GLOBAL_CATALOG | DSOP_SCOPE_TYPE_EXTERNAL_UPLEVEL_DOMAIN |
-                    DSOP_SCOPE_TYPE_EXTERNAL_DOWNLEVEL_DOMAIN | DSOP_SCOPE_TYPE_WORKGROUP |
-                    DSOP_SCOPE_TYPE_UPLEVEL_JOINED_DOMAIN | DSOP_SCOPE_TYPE_DOWNLEVEL_JOINED_DOMAIN,
+                DSOP_SCOPE_TYPE_GLOBAL_CATALOG | DSOP_SCOPE_TYPE_EXTERNAL_UPLEVEL_DOMAIN |
+                DSOP_SCOPE_TYPE_EXTERNAL_DOWNLEVEL_DOMAIN | DSOP_SCOPE_TYPE_WORKGROUP |
+                DSOP_SCOPE_TYPE_UPLEVEL_JOINED_DOMAIN | DSOP_SCOPE_TYPE_DOWNLEVEL_JOINED_DOMAIN,
                 0,
                 {
                     {
@@ -670,14 +932,14 @@ InitializeRemoteRegistryPicker(OUT IDsObjectPicker **pDsObjectPicker)
 
         InitInfo.cbSize = sizeof(InitInfo);
         InitInfo.pwzTargetComputer = NULL;
-        InitInfo.cDsScopeInfos = sizeof(Scopes) / sizeof(Scopes[0]);
+        InitInfo.cDsScopeInfos = COUNT_OF(Scopes);
         InitInfo.aDsScopeInfos = Scopes;
         InitInfo.flOptions = 0;
         InitInfo.cAttributesToFetch = 0;
         InitInfo.apwzAttributeNames = NULL;
 
         hRet = (*pDsObjectPicker)->lpVtbl->Initialize(*pDsObjectPicker,
-                                                      &InitInfo);
+                &InitInfo);
 
         if (FAILED(hRet))
         {
@@ -692,21 +954,21 @@ InitializeRemoteRegistryPicker(OUT IDsObjectPicker **pDsObjectPicker)
 static HRESULT
 InvokeRemoteRegistryPickerDialog(IN IDsObjectPicker *pDsObjectPicker,
                                  IN HWND hwndParent  OPTIONAL,
-                                 OUT LPTSTR lpBuffer,
+                                 OUT LPWSTR lpBuffer,
                                  IN UINT uSize)
 {
     IDataObject *pdo = NULL;
     HRESULT hRet;
 
     hRet = pDsObjectPicker->lpVtbl->InvokeDialog(pDsObjectPicker,
-                                                 hwndParent,
-                                                 &pdo);
+            hwndParent,
+            &pdo);
     if (hRet == S_OK)
     {
         STGMEDIUM stm;
         FORMATETC fe;
 
-        fe.cfFormat = (CLIPFORMAT) RegisterClipboardFormat(CFSTR_DSOP_DS_SELECTION_LIST);
+        fe.cfFormat = (CLIPFORMAT) RegisterClipboardFormatW(CFSTR_DSOP_DS_SELECTION_LIST);
         fe.ptd = NULL;
         fe.dwAspect = DVASPECT_CONTENT;
         fe.lindex = -1;
@@ -727,20 +989,11 @@ InvokeRemoteRegistryPickerDialog(IN IDsObjectPicker *pDsObjectPicker,
                     {
                         nlen = uSize - 1;
                     }
-#if UNICODE
+
                     memcpy(lpBuffer,
                            SelectionList->aDsSelection[0].pwzName,
                            nlen * sizeof(WCHAR));
-#else
-                    WideCharToMultiByte(CP_ACP,
-                                        0,
-                                        SelectionList->aDsSelection[0].pwzName,
-                                        nlen,
-                                        lpBuffer,
-                                        uSize,
-                                        NULL,
-                                        NULL);
-#endif
+
                     lpBuffer[nlen] = L'\0';
                 }
 
@@ -772,8 +1025,8 @@ FreeObjectPicker(IN IDsObjectPicker *pDsObjectPicker)
 static BOOL _CmdWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
 {
     HKEY hKeyRoot = 0, hKey = 0;
-    LPCTSTR keyPath;
-    LPCTSTR valueName;
+    LPCWSTR keyPath;
+    LPCWSTR valueName;
     BOOL result = TRUE;
     REGSAM regsam = KEY_READ;
     LONG lRet;
@@ -782,7 +1035,14 @@ static BOOL _CmdWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
     UNREFERENCED_PARAMETER(lParam);
     UNREFERENCED_PARAMETER(message);
 
-    switch (LOWORD(wParam)) {
+    switch (LOWORD(wParam))
+    {
+    case ID_REGISTRY_LOADHIVE:
+        LoadHive(hWnd);
+        return TRUE;
+    case ID_REGISTRY_UNLOADHIVE:
+        UnloadHive(hWnd);
+        return TRUE;
     case ID_REGISTRY_IMPORTREGISTRYFILE:
         ImportRegistryFile(hWnd);
         return TRUE;
@@ -792,7 +1052,7 @@ static BOOL _CmdWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
     case ID_REGISTRY_CONNECTNETWORKREGISTRY:
     {
         IDsObjectPicker *ObjectPicker;
-        TCHAR szComputerName[MAX_COMPUTERNAME_LENGTH + 1];
+        WCHAR szComputerName[MAX_COMPUTERNAME_LENGTH + 1];
         HRESULT hRet;
 
         hRet = CoInitialize(NULL);
@@ -804,7 +1064,7 @@ static BOOL _CmdWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
                 hRet = InvokeRemoteRegistryPickerDialog(ObjectPicker,
                                                         hWnd,
                                                         szComputerName,
-                                                        sizeof(szComputerName) / sizeof(szComputerName[0]));
+                                                        COUNT_OF(szComputerName));
                 if (hRet == S_OK)
                 {
                     /* FIXME - connect to the registry */
@@ -821,7 +1081,7 @@ static BOOL _CmdWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
     case ID_REGISTRY_DISCONNECTNETWORKREGISTRY:
         return TRUE;
     case ID_REGISTRY_PRINT:
-        PrintRegistryHive(hWnd, _T(""));
+        PrintRegistryHive(hWnd, L"");
         return TRUE;
     case ID_REGISTRY_EXIT:
         DestroyWindow(hWnd);
@@ -830,7 +1090,7 @@ static BOOL _CmdWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
         toggle_child(hWnd, LOWORD(wParam), hStatusBar);
         return TRUE;
     case ID_HELP_HELPTOPICS:
-        WinHelp(hWnd, _T("regedit"), HELP_FINDER, 0);
+        WinHelpW(hWnd, getAppName(), HELP_FINDER, 0);
         return TRUE;
     case ID_HELP_ABOUT:
         ShowAboutBox(hWnd);
@@ -845,9 +1105,9 @@ static BOOL _CmdWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
         pts = pt;
         if(ClientToScreen(g_pChildWnd->hWnd, &pts))
         {
-          SetCursorPos(pts.x, pts.y);
-          SetCursor(LoadCursor(0, IDC_SIZEWE));
-          SendMessage(g_pChildWnd->hWnd, WM_LBUTTONDOWN, 0, MAKELPARAM(pt.x, pt.y));
+            SetCursorPos(pts.x, pts.y);
+            SetCursor(LoadCursorW(0, IDC_SIZEWE));
+            SendMessageW(g_pChildWnd->hWnd, WM_LBUTTONDOWN, 0, MAKELPARAM(pt.x, pt.y));
         }
         return TRUE;
     }
@@ -861,12 +1121,14 @@ static BOOL _CmdWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
 
     keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
     valueName = GetValueName(g_pChildWnd->hListWnd, -1);
-    if (keyPath) {
-        lRet = RegOpenKeyEx(hKeyRoot, keyPath, 0, regsam, &hKey);
+    if (keyPath)
+    {
+        lRet = RegOpenKeyExW(hKeyRoot, keyPath, 0, regsam, &hKey);
         if (lRet != ERROR_SUCCESS) hKey = 0;
     }
 
-    switch (LOWORD(wParam)) {
+    switch (LOWORD(wParam))
+    {
     case ID_EDIT_MODIFY:
         if (valueName && ModifyValue(hWnd, hKey, valueName, FALSE))
             RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath);
@@ -887,7 +1149,7 @@ static BOOL _CmdWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
                 }
             }
         }
-        if (GetFocus() == g_pChildWnd->hTreeWnd)
+        else if (GetFocus() == g_pChildWnd->hTreeWnd)
         {
             /* Get focused entry of treeview (if any) */
             HTREEITEM hItem = TreeView_GetSelection(g_pChildWnd->hTreeWnd);
@@ -899,51 +1161,52 @@ static BOOL _CmdWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
     {
         if (GetFocus() == g_pChildWnd->hListWnd)
         {
-          UINT nSelected = ListView_GetSelectedCount(g_pChildWnd->hListWnd);
-          if(nSelected >= 1)
-          {
-            TCHAR msg[128], caption[128];
-            LoadString(hInst, IDS_QUERY_DELETE_CONFIRM, caption, sizeof(caption)/sizeof(TCHAR));
-            LoadString(hInst, (nSelected == 1 ? IDS_QUERY_DELETE_ONE : IDS_QUERY_DELETE_MORE), msg, sizeof(msg)/sizeof(TCHAR));
-            if(MessageBox(g_pChildWnd->hWnd, msg, caption, MB_ICONQUESTION | MB_YESNO) == IDYES)
+            UINT nSelected = ListView_GetSelectedCount(g_pChildWnd->hListWnd);
+            if(nSelected >= 1)
             {
-              int ni, errs;
-
-              item = -1;
-              errs = 0;
-              while((ni = ListView_GetNextItem(g_pChildWnd->hListWnd, item, LVNI_SELECTED)) > -1)
-              {
-                valueName = GetValueName(g_pChildWnd->hListWnd, item);
-                if(RegDeleteValue(hKey, valueName) != ERROR_SUCCESS)
+                WCHAR msg[128], caption[128];
+                LoadStringW(hInst, IDS_QUERY_DELETE_CONFIRM, caption, COUNT_OF(caption));
+                LoadStringW(hInst, (nSelected == 1 ? IDS_QUERY_DELETE_ONE : IDS_QUERY_DELETE_MORE), msg, COUNT_OF(msg));
+                if(MessageBoxW(g_pChildWnd->hWnd, msg, caption, MB_ICONQUESTION | MB_YESNO) == IDYES)
                 {
-                  errs++;
+                    int ni, errs;
+
+                    item = -1;
+                    errs = 0;
+                    while((ni = ListView_GetNextItem(g_pChildWnd->hListWnd, item, LVNI_SELECTED)) > -1)
+                    {
+                        valueName = GetValueName(g_pChildWnd->hListWnd, item);
+                        if(RegDeleteValueW(hKey, valueName) != ERROR_SUCCESS)
+                        {
+                            errs++;
+                        }
+                        item = ni;
+                    }
+
+                    RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath);
+                    if(errs > 0)
+                    {
+                        LoadStringW(hInst, IDS_ERR_DELVAL_CAPTION, caption, COUNT_OF(caption));
+                        LoadStringW(hInst, IDS_ERR_DELETEVALUE, msg, COUNT_OF(msg));
+                        MessageBoxW(g_pChildWnd->hWnd, msg, caption, MB_ICONSTOP);
+                    }
                 }
-                item = ni;
-              }
-
-              RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath);
-              if(errs > 0)
-              {
-                LoadString(hInst, IDS_ERR_DELVAL_CAPTION, caption, sizeof(caption)/sizeof(TCHAR));
-                LoadString(hInst, IDS_ERR_DELETEVALUE, msg, sizeof(msg)/sizeof(TCHAR));
-                MessageBox(g_pChildWnd->hWnd, msg, caption, MB_ICONSTOP);
-              }
             }
-          }
-        } else
-        if (GetFocus() == g_pChildWnd->hTreeWnd)
+        }
+        else if (GetFocus() == g_pChildWnd->hTreeWnd)
         {
-          if (keyPath == 0 || *keyPath == 0)
-          {
-             MessageBeep(MB_ICONHAND);
-          } else
-          if (DeleteKey(hWnd, hKeyRoot, keyPath))
-          {
-            DeleteNode(g_pChildWnd->hTreeWnd, 0);
-            RefreshTreeView(g_pChildWnd->hTreeWnd);
-          }
+            if (keyPath == 0 || *keyPath == 0)
+            {
+                MessageBeep(MB_ICONHAND);
+            }
+            else if (DeleteKey(hWnd, hKeyRoot, keyPath))
+            {
+                DeleteNode(g_pChildWnd->hTreeWnd, 0);
+                RefreshTreeView(g_pChildWnd->hTreeWnd);
+            }
         }
-       break;
+        break;
+    }
     case ID_EDIT_NEW_STRINGVALUE:
         CreateNewValue(hKeyRoot, keyPath, REG_SZ);
         break;
@@ -953,14 +1216,12 @@ static BOOL _CmdWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
     case ID_EDIT_NEW_DWORDVALUE:
         CreateNewValue(hKeyRoot, keyPath, REG_DWORD);
         break;
-       case ID_EDIT_NEW_MULTISTRINGVALUE:
+    case ID_EDIT_NEW_MULTISTRINGVALUE:
         CreateNewValue(hKeyRoot, keyPath, REG_MULTI_SZ);
         break;
-       case ID_EDIT_NEW_EXPANDABLESTRINGVALUE:
+    case ID_EDIT_NEW_EXPANDABLESTRINGVALUE:
         CreateNewValue(hKeyRoot, keyPath, REG_EXPAND_SZ);
         break;
-
-    }
     case ID_EDIT_FIND:
         FindDialog(hWnd);
         break;
@@ -984,11 +1245,12 @@ static BOOL _CmdWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
 
     case ID_VIEW_REFRESH:
         RefreshTreeView(g_pChildWnd->hTreeWnd);
-        /*RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, NULL); */
+        keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
+        RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath);
         break;
-   /*case ID_OPTIONS_TOOLBAR:*/
-   /*  toggle_child(hWnd, LOWORD(wParam), hToolBar);*/
-   /*    break;*/
+        /*case ID_OPTIONS_TOOLBAR:*/
+        /*     toggle_child(hWnd, LOWORD(wParam), hToolBar);*/
+        /*    break;*/
     case ID_EDIT_NEW_KEY:
         CreateNewKey(g_pChildWnd->hTreeWnd, TreeView_GetSelection(g_pChildWnd->hTreeWnd));
         break;
@@ -996,8 +1258,8 @@ static BOOL _CmdWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
         if ((LOWORD(wParam) >= ID_FAVORITES_MIN) && (LOWORD(wParam) <= ID_FAVORITES_MAX))
         {
             HMENU hMenu;
-            MENUITEMINFO mii;
-            TCHAR szFavorite[512];
+            MENUITEMINFOW mii;
+            WCHAR szFavorite[512];
 
             hMenu = GetSubMenu(GetMenu(hWnd), FAVORITES_MENU_POSITION);
 
@@ -1006,7 +1268,7 @@ static BOOL _CmdWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
             mii.fMask = MIIM_TYPE;
             mii.fType = MFT_STRING;
             mii.dwTypeData = szFavorite;
-            mii.cch = sizeof(szFavorite) / sizeof(szFavorite[0]);
+            mii.cch = COUNT_OF(szFavorite);
 
             if (GetMenuItemInfo(hMenu, LOWORD(wParam) - ID_FAVORITES_MIN, TRUE, &mii))
             {
@@ -1021,7 +1283,7 @@ static BOOL _CmdWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
     }
 
     if(hKey)
-      RegCloseKey(hKey);
+        RegCloseKey(hKey);
     return result;
 }
 
@@ -1038,15 +1300,16 @@ static BOOL _CmdWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
 
 LRESULT CALLBACK FrameWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
 {
-    switch (message) {
+    switch (message)
+    {
     case WM_CREATE:
-        CreateWindowEx(0, szChildClass, NULL, WS_CHILD | WS_VISIBLE,
+        CreateWindowExW(0, szChildClass, NULL, WS_CHILD | WS_VISIBLE,
                        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
                        hWnd, (HMENU)0, hInst, 0);
         break;
     case WM_COMMAND:
         if (!_CmdWndProc(hWnd, message, wParam, lParam))
-            return DefWindowProc(hWnd, message, wParam, lParam);
+            return DefWindowProcW(hWnd, message, wParam, lParam);
         break;
     case WM_ACTIVATE:
         if (LOWORD(hWnd))
@@ -1069,11 +1332,17 @@ LRESULT CALLBACK FrameWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lPa
     case WM_MENUSELECT:
         OnMenuSelect(hWnd, LOWORD(wParam), HIWORD(wParam), (HMENU)lParam);
         break;
+    case WM_SYSCOLORCHANGE:
+        /* Forward WM_SYSCOLORCHANGE to common controls */
+        SendMessageW(g_pChildWnd->hListWnd, WM_SYSCOLORCHANGE, 0, 0);
+        SendMessageW(g_pChildWnd->hTreeWnd, WM_SYSCOLORCHANGE, 0, 0);
+        break;
     case WM_DESTROY:
-        WinHelp(hWnd, _T("regedit"), HELP_QUIT, 0);
+        WinHelpW(hWnd, getAppName(), HELP_QUIT, 0);
+        SaveSettings();
         PostQuitMessage(0);
     default:
-        return DefWindowProc(hWnd, message, wParam, lParam);
+        return DefWindowProcW(hWnd, message, wParam, lParam);
     }
     return 0;
 }