[REGEDIT]
[reactos.git] / reactos / base / applications / regedit / framewnd.c
index 13c1186..6ff1371 100644 (file)
@@ -45,7 +45,8 @@ static void resize_frame_rect(HWND hWnd, PRECT prect)
                prect->bottom -= rt.bottom+3;
        }
      */
-    if (IsWindowVisible(hStatusBar)) {
+    if (IsWindowVisible(hStatusBar))
+    {
         SetupStatusBar(hWnd, TRUE);
         GetClientRect(hStatusBar, &rt);
         prect->bottom -= rt.bottom;
@@ -95,7 +96,7 @@ static void OnInitMenu(HWND hWnd)
     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);
         if ((lResult == ERROR_SUCCESS) && (dwType == REG_SZ))
@@ -141,12 +142,15 @@ static void OnMenuSelect(HWND hWnd, UINT nItemID, UINT nFlags, HMENU hSysMenu)
     TCHAR str[100];
 
     _tcscpy(str, _T(""));
-    if (nFlags & MF_POPUP) {
-        if (hSysMenu != GetMenu(hWnd)) {
+    if (nFlags & MF_POPUP)
+    {
+        if (hSysMenu != GetMenu(hWnd))
+        {
             if (nItemID == 2) nItemID = 5;
         }
     }
-    if (LoadString(hInst, nItemID, str, 100)) {
+    if (LoadString(hInst, nItemID, str, 100))
+    {
         /* load appropriate string*/
         LPTSTR lpsz = str;
         /* first newline terminates actual string*/
@@ -171,8 +175,8 @@ void SetupStatusBar(HWND hWnd, BOOL bResize)
 
 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);
 }
@@ -191,7 +195,8 @@ static BOOL CheckCommDlgError(HWND hWnd)
 {
     DWORD dwErrorCode = CommDlgExtendedError();
     UNREFERENCED_PARAMETER(hWnd);
-    switch (dwErrorCode) {
+    switch (dwErrorCode)
+    {
     case CDERR_DIALOGFAILURE:
         break;
     case CDERR_FINDRESFAILURE:
@@ -233,29 +238,29 @@ TCHAR FileTitleBuffer[_MAX_PATH];
 
 typedef struct
 {
-  UINT DisplayID;
-  UINT FilterID;
+    UINT DisplayID;
+    UINT FilterID;
 } FILTERPAIR, *PFILTERPAIR;
 
 void
 BuildFilterStrings(TCHAR *Filter, PFILTERPAIR Pairs, int PairCount)
 {
-  int i, c;
+    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));
+    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';
-  }
-  Filter[++c] = '\0';
 }
 
 static BOOL InitOpenFileName(HWND hWnd, OPENFILENAME* pofn)
 {
-    FILTERPAIR FilterPairs[3];
+    FILTERPAIR FilterPairs[4];
     static TCHAR Filter[1024];
 
     memset(pofn, 0, sizeof(OPENFILENAME));
@@ -266,11 +271,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;
@@ -282,40 +289,239 @@ static BOOL InitOpenFileName(HWND hWnd, OPENFILENAME* pofn)
     return TRUE;
 }
 
-static BOOL ImportRegistryFile(HWND hWnd)
+static INT_PTR CALLBACK LoadHive_KeyNameInHookProc(HWND hWndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+    static LPTSTR sKey = NULL;
+    static INT sLength = 0;
+    switch(uMsg)
+    {
+    case WM_INITDIALOG:
+        sKey = (LPTSTR)lParam;
+        sLength = 128; /* FIXME: Ugly hack! */
+    case WM_COMMAND:
+        switch(LOWORD(wParam))
+        {
+        case IDOK:
+            if(GetDlgItemText(hWndDlg, IDC_EDIT_KEY, sKey, sLength))
+                return EndDialog(hWndDlg, -1);
+            else
+                return EndDialog(hWndDlg, 0);
+        case IDCANCEL:
+            return EndDialog(hWndDlg, 0);
+        }
+        break;
+    }
+    return FALSE;
+}
+
+static BOOL EnablePrivilege(LPCTSTR lpszPrivilegeName, LPCTSTR 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 (LookupPrivilegeValue(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;
     TCHAR Caption[128];
     LPCTSTR pszKeyPath;
+    TCHAR xPath[128];
     HKEY hRootKey;
-
+    TCHAR 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, COUNT_OF(Caption));
+    /* 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 */
+    LoadString(hInst, IDS_LOAD_HIVE, Caption, COUNT_OF(Caption));
     ofn.lpstrTitle = Caption;
     ofn.Flags |= OFN_ENABLESIZING;
     /*    ofn.lCustData = ;*/
-    if (GetOpenFileName(&ofn)) {
-        FILE *fp = _wfopen(ofn.lpstrFile, L"r");
-        if (fp == NULL || !import_registry_file(fp)) {
-            LPSTR p = GetMultiByteString(ofn.lpstrFile);
-            fprintf(stderr, "Can't open file \"%s\"\n", p);
-            HeapFree(GetProcessHeap(), 0, p);
-            if (fp != NULL)
-                fclose(fp);
-            return FALSE;
+    /* now load the hive */
+    if (GetOpenFileName(&ofn))
+    {
+        if(DialogBoxParam(hInst, MAKEINTRESOURCE(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 = RegLoadKey(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;
+            }
         }
-        fclose(fp);
-    } else {
+    }
+    else
+    {
         CheckCommDlgError(hWnd);
     }
+    return TRUE;
+}
 
-    RefreshTreeView(g_pChildWnd->hTreeWnd);
+static BOOL UnloadHive(HWND hWnd)
+{
+    TCHAR Caption[128];
+    LPCTSTR pszKeyPath;
+    HKEY hRootKey;
+    LONG regUnloadResult;
+
+    /* get the item key to unload */
     pszKeyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hRootKey);
-    RefreshListView(g_pChildWnd->hListWnd, hRootKey, pszKeyPath);
+    /* load and set the caption and flags for dialog */
+    LoadString(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 = RegUnLoadKey(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;
+    TCHAR Caption[128], szTitle[256], szText[256];
+    HKEY hKeyRoot;
+    LPCTSTR pszKeyPath;
+
+    /* Figure out in which key path we are importing */
+    pszKeyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
+
+    InitOpenFileName(hWnd, &ofn);
+    LoadString(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 &&
+            _tcsicmp(ofn.lpstrFile + ofn.nFileExtension, TEXT("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))
+            {
+                LPSTR p = GetMultiByteString(ofn.lpstrFile);
+                fprintf(stderr, "Can't open file \"%s\"\n", p);
+                HeapFree(GetProcessHeap(), 0, p);
+                bRet = FALSE;
+            }
+            else
+            {
+                /* Show successful import */
+                LoadString(hInst, IDS_APP_TITLE, szTitle, COUNT_OF(szTitle));
+                LoadString(hInst, IDS_IMPORT_OK, szText, COUNT_OF(szText));
+                MessageBox(NULL, szText, szTitle, MB_OK);
+                bRet = TRUE;
+            }
+
+            /* Close the file */
+            if (fp) fclose(fp);
+        }
+        else /* Registry Hive Files */
+        {
+            LoadString(hInst, IDS_QUERY_IMPORT_HIVE_CAPTION, szTitle, COUNT_OF(szTitle));
+            LoadString(hInst, IDS_QUERY_IMPORT_HIVE_MSG, szText, COUNT_OF(szText));
+
+            /* Display a confirmation message */
+            if (MessageBox(g_pChildWnd->hWnd, szText, szTitle, MB_ICONWARNING | MB_YESNO) == IDYES)
+            {
+                LONG lResult;
+                HKEY hSubKey;
+
+                /* Open the subkey */
+                lResult = RegOpenKeyEx(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)
 {
@@ -329,8 +535,9 @@ static UINT_PTR CALLBACK ExportRegistryFile_OFNHookProc(HWND hdlg, UINT uiMsg, W
 
     UNREFERENCED_PARAMETER(wParam);
 
-       switch(uiMsg) {
-       case WM_INITDIALOG:
+    switch(uiMsg)
+    {
+    case WM_INITDIALOG:
         pOfn = (OPENFILENAME *) lParam;
         pszSelectedKey = (LPTSTR) pOfn->lCustData;
 
@@ -347,7 +554,7 @@ static UINT_PTR CALLBACK ExportRegistryFile_OFNHookProc(HWND hdlg, UINT uiMsg, W
             SetWindowText(hwndExportBranchText, pszSelectedKey);
         break;
 
-       case WM_NOTIFY:
+    case WM_NOTIFY:
         if (((NMHDR *) lParam)->code == CDN_FILEOK)
         {
             pOfnNotify = (OFNOTIFY *) lParam;
@@ -356,15 +563,15 @@ static UINT_PTR CALLBACK ExportRegistryFile_OFNHookProc(HWND hdlg, UINT uiMsg, W
             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';
-                       }
-               }
+                    && (SendMessage(hwndExportBranch, BM_GETCHECK, 0, 0) == BST_CHECKED))
+            {
+                GetWindowText(hwndExportBranchText, pszSelectedKey, _MAX_PATH);
+            }
+            else
+            {
+                pszSelectedKey[0] = '\0';
+            }
+        }
         break;
     }
     return iResult;
@@ -372,6 +579,7 @@ 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];
@@ -383,7 +591,7 @@ BOOL ExportRegistryFile(HWND hWnd)
     GetKeyName(ExportKeyPath, COUNT_OF(ExportKeyPath), hKeyRoot, pszKeyPath);
 
     InitOpenFileName(hWnd, &ofn);
-    LoadString(hInst, IDS_EXPORT_REG_FILE, Caption, sizeof(Caption)/sizeof(TCHAR));
+    LoadString(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 */
@@ -394,25 +602,88 @@ BOOL ExportRegistryFile(HWND hWnd)
     ofn.Flags = OFN_ENABLETEMPLATE | OFN_EXPLORER | OFN_ENABLEHOOK | OFN_OVERWRITEPROMPT;
     ofn.lpfnHook = ExportRegistryFile_OFNHookProc;
     ofn.lpTemplateName = MAKEINTRESOURCE(IDD_EXPORTRANGE);
-    if (GetSaveFileName(&ofn)) {
-        BOOL result;
-        DWORD format;
-        if (ofn.nFilterIndex == 1)
-            format = REG_FORMAT_5;
-        else
-            format = REG_FORMAT_4;
-        result = export_registry_key(ofn.lpstrFile, ExportKeyPath, format);
-        if (!result) {
-            LPSTR p = GetMultiByteString(ofn.lpstrFile);
-            fprintf(stderr, "Can't open file \"%s\"\n", p);
-            HeapFree(GetProcessHeap(), 0, p);
-            return FALSE;
+    if (GetSaveFileName(&ofn))
+    {
+        switch (ofn.nFilterIndex)
+        {
+            case 2: /* Registry Hive Files */
+            {
+                LONG lResult;
+                HKEY hSubKey;
+
+                /* Open the subkey */
+                lResult = RegOpenKeyEx(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 = RegSaveKey(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 (DeleteFile(ofn.lpstrFile))
+                        {
+                            /* Try again */
+                            lResult = RegSaveKey(hSubKey, ofn.lpstrFile, NULL);
+                        }
+                    }
+                    EnablePrivilege(SE_BACKUP_NAME, NULL, FALSE);
+
+                    if (lResult != ERROR_SUCCESS)
+                    {
+                        /*
+                         * If we are here, it's because RegSaveKey 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.
+                         */
+                        DeleteFile(ofn.lpstrFile);
+                    }
+
+                    /* Close the subkey */
+                    RegCloseKey(hSubKey);
+                }
+
+                /* 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)))
+                {
+                    LPSTR p = GetMultiByteString(ofn.lpstrFile);
+                    fprintf(stderr, "Can't open file \"%s\"\n", p);
+                    HeapFree(GetProcessHeap(), 0, p);
+                    bRet = FALSE;
+                }
+                else
+                {
+                    bRet = TRUE;
+                }
+
+                break;
+            }
         }
-    } else {
+    }
+    else
+    {
         CheckCommDlgError(hWnd);
     }
-    return TRUE;
+
+    return bRet;
 }
 
 BOOL PrintRegistryHive(HWND hWnd, LPTSTR path)
@@ -432,7 +703,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.*/
     }
@@ -441,8 +713,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;
@@ -455,8 +729,11 @@ BOOL PrintRegistryHive(HWND hWnd, LPTSTR path)
         default:
             break;
         }
-    } else {
-        switch (hResult) {
+    }
+    else
+    {
+        switch (hResult)
+        {
         case E_OUTOFMEMORY:
             /*Insufficient memory. */
             break;
@@ -521,7 +798,7 @@ BOOL CopyKeyName(HWND hWnd, HKEY hRootKey, LPCTSTR keyName)
     if (!GetKeyName(szBuffer, COUNT_OF(szBuffer), hRootKey, keyName))
         goto done;
 
-    hGlobal = GlobalAlloc(GMEM_MOVEABLE, (_tcslen(szBuffer) + 1) * sizeof(TCHAR));
+    hGlobal = GlobalAlloc(GMEM_MOVEABLE, (lstrlen(szBuffer) + 1) * sizeof(TCHAR));
     if (!hGlobal)
         goto done;
 
@@ -553,23 +830,22 @@ static BOOL CreateNewValue(HKEY hRootKey, LPCTSTR pszKeyPath, DWORD dwType)
     HKEY hKey;
     LVFINDINFO lvfi;
 
-    if (RegOpenKey(hRootKey, pszKeyPath, &hKey) != ERROR_SUCCESS)
+    if (RegOpenKeyEx(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]));
+    LoadString(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);
     }
     while(lResult == ERROR_SUCCESS);
 
-    switch(dwType) {
+    switch(dwType)
+    {
     case REG_DWORD:
         cbData = sizeof(DWORD);
         break;
@@ -589,8 +865,11 @@ static BOOL CreateNewValue(HKEY hRootKey, LPCTSTR pszKeyPath, DWORD dwType)
     }
     memset(data, 0, cbData);
     lResult = RegSetValueEx(hKey, szNewValue, 0, dwType, data, cbData);
+    RegCloseKey(hKey);
     if (lResult != ERROR_SUCCESS)
+    {
         return FALSE;
+    }
 
     RefreshListView(g_pChildWnd->hListWnd, hRootKey, pszKeyPath);
 
@@ -625,9 +904,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,
                 {
                     {
@@ -645,14 +924,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))
         {
@@ -674,8 +953,8 @@ InvokeRemoteRegistryPickerDialog(IN IDsObjectPicker *pDsObjectPicker,
     HRESULT hRet;
 
     hRet = pDsObjectPicker->lpVtbl->InvokeDialog(pDsObjectPicker,
-                                                 hwndParent,
-                                                 &pdo);
+            hwndParent,
+            &pdo);
     if (hRet == S_OK)
     {
         STGMEDIUM stm;
@@ -757,7 +1036,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;
@@ -779,7 +1065,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 */
@@ -820,9 +1106,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(LoadCursor(0, IDC_SIZEWE));
+            SendMessage(g_pChildWnd->hWnd, WM_LBUTTONDOWN, 0, MAKELPARAM(pt.x, pt.y));
         }
         return TRUE;
     }
@@ -836,12 +1122,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) {
+    if (keyPath)
+    {
         lRet = RegOpenKeyEx(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);
@@ -862,7 +1150,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);
@@ -874,51 +1162,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)
+                TCHAR msg[128], caption[128];
+                LoadString(hInst, IDS_QUERY_DELETE_CONFIRM, caption, COUNT_OF(caption));
+                LoadString(hInst, (nSelected == 1 ? IDS_QUERY_DELETE_ONE : IDS_QUERY_DELETE_MORE), msg, COUNT_OF(msg));
+                if(MessageBox(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(RegDeleteValue(hKey, valueName) != ERROR_SUCCESS)
+                        {
+                            errs++;
+                        }
+                        item = ni;
+                    }
+
+                    RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath);
+                    if(errs > 0)
+                    {
+                        LoadString(hInst, IDS_ERR_DELVAL_CAPTION, caption, COUNT_OF(caption));
+                        LoadString(hInst, IDS_ERR_DELETEVALUE, msg, COUNT_OF(msg));
+                        MessageBox(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;
@@ -928,14 +1217,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;
@@ -959,11 +1246,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;
@@ -981,7 +1269,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))
             {
@@ -996,7 +1284,7 @@ static BOOL _CmdWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
     }
 
     if(hKey)
-      RegCloseKey(hKey);
+        RegCloseKey(hKey);
     return result;
 }
 
@@ -1013,7 +1301,8 @@ 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,
                        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
@@ -1044,8 +1333,14 @@ 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 */
+        SendMessage(g_pChildWnd->hListWnd, WM_SYSCOLORCHANGE, 0, 0);
+        SendMessage(g_pChildWnd->hTreeWnd, WM_SYSCOLORCHANGE, 0, 0);
+        break;
     case WM_DESTROY:
         WinHelp(hWnd, _T("regedit"), HELP_QUIT, 0);
+        SaveSettings();
         PostQuitMessage(0);
     default:
         return DefWindowProc(hWnd, message, wParam, lParam);