- Get autochk, calc, cmd, devmgr, expand, format, gettype, hostname, lsass, msconfig...
[reactos.git] / reactos / subsys / system / regedit / listview.c
index 1bd4d04..354317c 100644 (file)
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#include <windows.h>
-#include <windowsx.h>
-#include <commctrl.h>
-#include <stdlib.h>
-#include <tchar.h>
-#include <process.h>
-#include <stdio.h>
+#include <regedit.h>
 
-#include "main.h"
 
 #define CX_ICON    16
 #define CY_ICON    16
@@ -55,7 +48,7 @@ static LPTSTR g_valueName;
 static int default_column_widths[MAX_LIST_COLUMNS] = { 200, 175, 400 };
 static int column_alignment[MAX_LIST_COLUMNS] = { LVCFMT_LEFT, LVCFMT_LEFT, LVCFMT_LEFT };
 
-LPCTSTR GetValueName(HWND hwndLV)
+LPCTSTR GetValueName(HWND hwndLV, int iStartAt)
 {
     int item, len, maxLen;
     LPTSTR newStr;
@@ -66,9 +59,9 @@ LPCTSTR GetValueName(HWND hwndLV)
     if (!g_valueName) return NULL;
     *g_valueName = 0;
     maxLen = HeapSize(GetProcessHeap(), 0, g_valueName);
-    if (maxLen == (SIZE_T) - 1) return NULL;
+    if (maxLen == -1) return NULL;
 
-    item = ListView_GetNextItem(hwndLV, -1, LVNI_FOCUSED | LVNI_SELECTED);
+    item = ListView_GetNextItem(hwndLV, iStartAt, LVNI_SELECTED);
     if (item == -1) return NULL;
     LVItem.mask = LVIF_PARAM;
     LVItem.iItem = item;
@@ -100,13 +93,13 @@ BOOL IsDefaultValue(HWND hwndLV, int i)
 {
   PLINE_INFO lineinfo;
   LVITEM Item;
-  
+
   Item.mask = LVIF_PARAM;
   Item.iItem = i;
   if(ListView_GetItem(hwndLV, &Item))
   {
     lineinfo = (PLINE_INFO)Item.lParam;
-    return lineinfo && (!lineinfo->name || !strcmp(lineinfo->name, _T("")));
+    return lineinfo && (!lineinfo->name || !_tcscmp(lineinfo->name, _T("")));
   }
   return FALSE;
 }
@@ -114,7 +107,7 @@ BOOL IsDefaultValue(HWND hwndLV, int i)
 /*******************************************************************************
  * Local module support methods
  */
-static void AddEntryToList(HWND hwndLV, LPTSTR Name, DWORD dwValType, void* ValBuf, DWORD dwCount, int Position)
+static void AddEntryToList(HWND hwndLV, LPTSTR Name, DWORD dwValType, void* ValBuf, DWORD dwCount, int Position, BOOL ValExists)
 {
     LINE_INFO* linfo;
     LVITEM item;
@@ -159,38 +152,86 @@ static void AddEntryToList(HWND hwndLV, LPTSTR Name, DWORD dwValType, void* ValB
 
     index = ListView_InsertItem(hwndLV, &item);
     if (index != -1) {
-        /*        LPTSTR pszText = NULL; */
-        LPTSTR pszText = _T("value");
         switch (dwValType) {
         case REG_SZ:
         case REG_EXPAND_SZ:
-            if(dwCount)
+            if(dwCount > 0)
             {
               ListView_SetItemText(hwndLV, index, 2, ValBuf);
             }
+            else if(!ValExists)
+            {
+              TCHAR buffer[255];
+              /* load (value not set) string */
+              LoadString(hInst, IDS_VALUE_NOT_SET, buffer, sizeof(buffer)/sizeof(TCHAR));
+              ListView_SetItemText(hwndLV, index, 2, buffer);
+            }
+            break;
+        case REG_MULTI_SZ:
+            {
+              LPTSTR src, str;
+              if(dwCount >= 2)
+              {
+                 src = (LPTSTR)ValBuf;
+                 str = HeapAlloc(GetProcessHeap(), 0, dwCount);
+                  if(str != NULL)
+                  {
+                      *str = _T('\0');
+                     /* concatenate all srings */
+                      while(*src != _T('\0'))
+                      {
+                         _tcscat(str, src);
+                         _tcscat(str, _T(" "));
+                         src += _tcslen(src) + 1;
+                      }
+                      ListView_SetItemText(hwndLV, index, 2, str);
+                     HeapFree(GetProcessHeap(), 0, str);
+                  }
+                  else
+                    ListView_SetItemText(hwndLV, index, 2, _T(""));
+              }
+              else
+                ListView_SetItemText(hwndLV, index, 2, _T(""));
+            }
             break;
         case REG_DWORD: {
-                TCHAR buf[64];
-                wsprintf(buf, _T("0x%08X (%d)"), *(DWORD*)ValBuf, *(DWORD*)ValBuf);
+                TCHAR buf[200];
+                if(dwCount == sizeof(DWORD))
+                {
+                  wsprintf(buf, _T("0x%08X (%d)"), *(DWORD*)ValBuf, *(DWORD*)ValBuf);
+                }
+                else
+                {
+                  LoadString(hInst, IDS_INVALID_DWORD, buf, sizeof(buf)/sizeof(TCHAR));
+                }
                 ListView_SetItemText(hwndLV, index, 2, buf);
             }
             /*            lpsRes = convertHexToDWORDStr(lpbData, dwLen); */
             break;
-        case REG_BINARY: {
+        default:
+           {
                 unsigned int i;
                 LPBYTE pData = (LPBYTE)ValBuf;
-                LPTSTR strBinary = HeapAlloc(GetProcessHeap(), 0, dwCount * sizeof(TCHAR) * 3 + 1);
-                for (i = 0; i < dwCount; i++)
-                    wsprintf( strBinary + i*3, _T("%02X "), pData[i] );
-                strBinary[dwCount * 3] = 0;
-                ListView_SetItemText(hwndLV, index, 2, strBinary);
-                HeapFree(GetProcessHeap(), 0, strBinary);
+                LPTSTR strBinary;
+                if(dwCount > 0)
+                {
+                    strBinary = HeapAlloc(GetProcessHeap(), 0, (dwCount * sizeof(TCHAR) * 3) + sizeof(TCHAR));
+                    for (i = 0; i < dwCount; i++)
+                    {
+                        wsprintf( strBinary + i*3, _T("%02X "), pData[i] );
+                    }
+                    strBinary[dwCount * 3] = 0;
+                    ListView_SetItemText(hwndLV, index, 2, strBinary);
+                    HeapFree(GetProcessHeap(), 0, strBinary);
+                }
+                else
+                {
+                    TCHAR szText[128];
+                    LoadString(hInst, IDS_BINARY_EMPTY, szText, sizeof(szText)/sizeof(TCHAR));
+                    ListView_SetItemText(hwndLV, index, 2, szText);
+                }
             }
             break;
-        default:
-            /*            lpsRes = convertHexToHexCSV(lpbData, dwLen); */
-            ListView_SetItemText(hwndLV, index, 2, pszText);
-            break;
         }
     }
 }
@@ -228,10 +269,10 @@ static BOOL InitListViewImageLists(HWND hwndLV)
 
     hico = LoadIcon(hInst, MAKEINTRESOURCE(IDI_BIN));
     Image_Bin = ImageList_AddIcon(himl, hico);
-    
+
     hico = LoadIcon(hInst, MAKEINTRESOURCE(IDI_STRING));
     Image_String = ImageList_AddIcon(himl, hico);
-    
+
 
     /* Fail if not all of the images were added.  */
     if (ImageList_GetImageCount(himl) < NUM_ICONS)
@@ -256,10 +297,14 @@ static void OnGetDispInfo(NMLVDISPINFO* plvdi)
 
     switch (plvdi->item.iSubItem) {
     case 0:
-        plvdi->item.pszText = _T("(Default)");
+        LoadString(hInst, IDS_DEFAULT_VALUE_NAME, buffer, sizeof(buffer)/sizeof(TCHAR));
+       plvdi->item.pszText = buffer;
         break;
     case 1:
         switch (((LINE_INFO*)plvdi->item.lParam)->dwValType) {
+        case REG_NONE:
+            plvdi->item.pszText = _T("REG_NONE");
+            break;
         case REG_SZ:
             plvdi->item.pszText = _T("REG_SZ");
             break;
@@ -269,33 +314,39 @@ static void OnGetDispInfo(NMLVDISPINFO* plvdi)
         case REG_BINARY:
             plvdi->item.pszText = _T("REG_BINARY");
             break;
-        case REG_DWORD:
+        case REG_DWORD: /* REG_DWORD_LITTLE_ENDIAN */
             plvdi->item.pszText = _T("REG_DWORD");
             break;
         case REG_DWORD_BIG_ENDIAN:
             plvdi->item.pszText = _T("REG_DWORD_BIG_ENDIAN");
             break;
-        case REG_MULTI_SZ:
-            plvdi->item.pszText = _T("REG_MULTI_SZ");
-            break;
         case REG_LINK:
             plvdi->item.pszText = _T("REG_LINK");
             break;
+        case REG_MULTI_SZ:
+            plvdi->item.pszText = _T("REG_MULTI_SZ");
+            break;
         case REG_RESOURCE_LIST:
             plvdi->item.pszText = _T("REG_RESOURCE_LIST");
             break;
-        case REG_NONE:
-            plvdi->item.pszText = _T("REG_NONE");
+        case REG_FULL_RESOURCE_DESCRIPTOR:
+            plvdi->item.pszText = _T("REG_FULL_RESOURCE_DESCRIPTOR");
             break;
-        default:
-            wsprintf(buffer, _T("unknown(%d)"), plvdi->item.lParam);
+        case REG_RESOURCE_REQUIREMENTS_LIST:
+            plvdi->item.pszText = _T("REG_RESOURCE_REQUIREMENTS_LIST");
+            break;
+        case REG_QWORD: /* REG_QWORD_LITTLE_ENDIAN */
+            plvdi->item.pszText = _T("REG_QWORD");
+            break;
+        default: {
+            TCHAR buf2[200];
+           LoadString(hInst, IDS_UNKNOWN_TYPE, buf2, sizeof(buf2)/sizeof(TCHAR));
+           wsprintf(buffer, buf2, ((LINE_INFO*)plvdi->item.lParam)->dwValType);
             plvdi->item.pszText = buffer;
             break;
+          }
         }
         break;
-    case 2:
-        plvdi->item.pszText = _T("(value not set)");
-        break;
     case 3:
         plvdi->item.pszText = _T("");
         break;
@@ -307,10 +358,10 @@ static int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSor
     LINE_INFO*l, *r;
     l = (LINE_INFO*)lParam1;
     r = (LINE_INFO*)lParam2;
-        
-    if (g_columnToSort == ~0UL) 
+
+    if (g_columnToSort == ~0UL)
         g_columnToSort = 0;
-    
+
     if (g_columnToSort == 1 && l->dwValType != r->dwValType)
         return g_invertSort ? (int)r->dwValType - (int)l->dwValType : (int)l->dwValType - (int)r->dwValType;
     if (g_columnToSort == 2) {
@@ -319,17 +370,6 @@ static int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSor
     return g_invertSort ? _tcscmp(r->name, l->name) : _tcscmp(l->name, r->name);
 }
 
-static BOOL _CmdWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
-{
-    switch (LOWORD(wParam)) {
-        /*    case ID_FILE_OPEN: */
-        /*        break; */
-    default:
-        return FALSE;
-    }
-    return TRUE;
-}
-
 BOOL ListWndNotifyProc(HWND hWnd, WPARAM wParam, LPARAM lParam, BOOL *Result)
 {
     NMLVDISPINFO* Info;
@@ -339,21 +379,24 @@ BOOL ListWndNotifyProc(HWND hWnd, WPARAM wParam, LPARAM lParam, BOOL *Result)
             OnGetDispInfo((NMLVDISPINFO*)lParam);
             return TRUE;
         case LVN_COLUMNCLICK:
-            if (g_columnToSort == ((LPNMLISTVIEW)lParam)->iSubItem)
+            if (g_columnToSort == (DWORD)((LPNMLISTVIEW)lParam)->iSubItem)
                 g_invertSort = !g_invertSort;
             else {
                 g_columnToSort = ((LPNMLISTVIEW)lParam)->iSubItem;
                 g_invertSort = FALSE;
             }
-                    
+
             ListView_SortItems(hWnd, CompareFunc, (WPARAM)hWnd);
             return TRUE;
-        case NM_DBLCLK: 
+        case NM_DBLCLK:
+        case NM_RETURN:
             {
                 SendMessage(hFrameWnd, WM_COMMAND, MAKEWPARAM(ID_EDIT_MODIFY, 0), 0);
             }
             return TRUE;
-
+        case NM_SETFOCUS:
+            g_pChildWnd->nFocusPanel = 0;
+            break;
         case LVN_BEGINLABELEDIT:
             {
               PLINE_INFO lineinfo;
@@ -361,7 +404,7 @@ BOOL ListWndNotifyProc(HWND hWnd, WPARAM wParam, LPARAM lParam, BOOL *Result)
               if(Info)
               {
                 lineinfo = (PLINE_INFO)Info->item.lParam;
-                if(!lineinfo->name || !strcmp(lineinfo->name, _T("")))
+                if(!lineinfo->name || !_tcscmp(lineinfo->name, _T("")))
                 {
                   *Result = TRUE;
                 }
@@ -374,12 +417,56 @@ BOOL ListWndNotifyProc(HWND hWnd, WPARAM wParam, LPARAM lParam, BOOL *Result)
                 *Result = TRUE;
               return TRUE;
             }
+        case LVN_ENDLABELEDIT:
+            {
+              PLINE_INFO lineinfo;
+              Info = (NMLVDISPINFO*)lParam;
+              if(Info && Info->item.pszText)
+              {
+                lineinfo = (PLINE_INFO)Info->item.lParam;
+                if(!lineinfo->name || !_tcscmp(lineinfo->name, _T("")))
+                {
+                  *Result = FALSE;
+                }
+                else
+                {
+                 //if((ret = RenameValue(lineinfo->name, Info->item.pszText)) != ERROR_SUCCESS)
+                  {
+                   TCHAR msg[128], caption[128];
+
+                   LoadString(hInst, IDS_ERR_RENVAL_CAPTION, caption, sizeof(caption)/sizeof(TCHAR));
+                   if(_tcslen(Info->item.pszText) == 0)
+                   {
+                     LoadString(hInst, IDS_ERR_RENVAL_TOEMPTY, msg, sizeof(msg)/sizeof(TCHAR));
+                     MessageBox(0, msg, NULL, 0);
+                     *Result = TRUE;
+                   }
+                   else
+                       {
+                         HKEY hKeyRoot;
+                         LPCTSTR keyPath;
+                         LONG lResult;
+                         keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
+                         lResult = RegRenameValue(hKeyRoot, keyPath, Info->item.pszText, lineinfo->name);
+                          if (lineinfo->name)
+                            LocalFree(lineinfo->name);
+                          lineinfo->name = _tcsdup(Info->item.pszText);
+                     *Result = TRUE;
+                     return (lResult == ERROR_SUCCESS);
+                       }
+                 }
+                }
+              }
+              else
+                *Result = TRUE;
+              return TRUE;
+            }
     }
     return FALSE;
 }
 
 
-HWND CreateListView(HWND hwndParent, int id)
+HWND CreateListView(HWND hwndParent, HMENU id)
 {
     RECT rcClient;
     HWND hwndLV;
@@ -389,9 +476,9 @@ HWND CreateListView(HWND hwndParent, int id)
     hwndLV = CreateWindowEx(WS_EX_CLIENTEDGE, WC_LISTVIEW, _T("List View"),
                             WS_VISIBLE | WS_CHILD | WS_TABSTOP | LVS_REPORT | LVS_EDITLABELS,
                             0, 0, rcClient.right, rcClient.bottom,
-                            hwndParent, (HMENU)id, hInst, NULL);
+                            hwndParent, id, hInst, NULL);
     if (!hwndLV) return NULL;
-    
+
     /* Initialize the image list, and add items to the control.  */
     if (!CreateListColumns(hwndLV)) goto fail;
     if (!InitListViewImageLists(hwndLV)) goto fail;
@@ -402,6 +489,24 @@ fail:
     return NULL;
 }
 
+void DestroyListView(HWND hwndLV) {
+    INT count, i;
+       LVITEM item;
+
+    if (g_valueName)
+        HeapFree(GetProcessHeap(), 0, g_valueName);
+
+    count = ListView_GetItemCount(hwndLV);
+    for (i = 0; i < count; i++) {
+        item.mask = LVIF_PARAM;
+        item.iItem = i;
+        ListView_GetItem(hwndLV, &item);
+        free(((LINE_INFO*)item.lParam)->name);
+        HeapFree(GetProcessHeap(), 0, (void*)item.lParam);
+    }
+}
+
 BOOL RefreshListView(HWND hwndLV, HKEY hKey, LPCTSTR keyPath)
 {
     DWORD max_sub_key_len;
@@ -415,9 +520,9 @@ BOOL RefreshListView(HWND hwndLV, HKEY hKey, LPCTSTR keyPath)
     BOOL AddedDefault = FALSE;
 
     if (!hwndLV) return FALSE;
-    
+
     ListView_EditLabel(hwndLV, -1);
-    
+
     SendMessage(hwndLV, WM_SETREDRAW, FALSE, 0);
     count = ListView_GetItemCount(hwndLV);
     for (i = 0; i < count; i++) {
@@ -429,22 +534,20 @@ BOOL RefreshListView(HWND hwndLV, HKEY hKey, LPCTSTR keyPath)
     }
     g_columnToSort = ~0UL;
     ListView_DeleteAllItems(hwndLV);
-    
+
     if(!hKey) return FALSE;
 
     errCode = RegOpenKeyEx(hKey, keyPath, 0, KEY_READ, &hNewKey);
     if (errCode != ERROR_SUCCESS) return FALSE;
 
     /* get size information and resize the buffers if necessary */
-    errCode = RegQueryInfoKey(hNewKey, NULL, NULL, NULL, NULL, &max_sub_key_len, NULL, 
+    errCode = RegQueryInfoKey(hNewKey, NULL, NULL, NULL, NULL, &max_sub_key_len, NULL,
                               &val_count, &max_val_name_len, &max_val_size, NULL, NULL);
 
-    #define BUF_HEAD_SPACE 2 /* FIXME: check why this is required with ROS ??? */
-
     if (errCode == ERROR_SUCCESS) {
-        TCHAR* ValName = HeapAlloc(GetProcessHeap(), 0, ++max_val_name_len * sizeof(TCHAR) + BUF_HEAD_SPACE);
+        TCHAR* ValName = HeapAlloc(GetProcessHeap(), 0, ++max_val_name_len * sizeof(TCHAR));
         DWORD dwValNameLen = max_val_name_len;
-        BYTE* ValBuf = HeapAlloc(GetProcessHeap(), 0, ++max_val_size/* + BUF_HEAD_SPACE*/);
+        BYTE* ValBuf = HeapAlloc(GetProcessHeap(), 0, max_val_size + sizeof(TCHAR));
         DWORD dwValSize = max_val_size;
         DWORD dwIndex = 0L;
         DWORD dwValType;
@@ -453,13 +556,14 @@ BOOL RefreshListView(HWND hwndLV, HKEY hKey, LPCTSTR keyPath)
         /*                } */
         /*                dwValSize = max_val_size; */
         while (RegEnumValue(hNewKey, dwIndex, ValName, &dwValNameLen, NULL, &dwValType, ValBuf, &dwValSize) == ERROR_SUCCESS) {
-            ValBuf[dwValSize] = 0;
-            AddEntryToList(hwndLV, ValName, dwValType, ValBuf, dwValSize, -1);
+            /* Add a terminating 0 character. Usually this is only necessary for strings. */
+            ((TCHAR*)ValBuf)[dwValSize/sizeof(TCHAR)] = 0;
+            AddEntryToList(hwndLV, ValName, dwValType, ValBuf, dwValSize, -1, TRUE);
             dwValNameLen = max_val_name_len;
             dwValSize = max_val_size;
             dwValType = 0L;
             ++dwIndex;
-            if(!strcmp(ValName, _T("")))
+            if(!_tcscmp(ValName, _T("")))
             {
               AddedDefault = TRUE;
             }
@@ -469,7 +573,7 @@ BOOL RefreshListView(HWND hwndLV, HKEY hKey, LPCTSTR keyPath)
     }
     if(!AddedDefault)
     {
-      AddEntryToList(hwndLV, _T(""), REG_SZ, NULL, 0, 0);
+      AddEntryToList(hwndLV, _T(""), REG_SZ, NULL, 0, 0, FALSE);
     }
     ListView_SortItems(hwndLV, CompareFunc, (WPARAM)hwndLV);
     RegCloseKey(hNewKey);