~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/programs/regedit/treeview.c

Version: ~ [ wine-1.5.4 ] ~ [ wine-1.5.3 ] ~ [ wine-1.5.2 ] ~ [ wine-1.5.1 ] ~ [ wine-1.5.0 ] ~ [ wine-1.4 ] ~ [ wine-1.4-rc6 ] ~ [ wine-1.4-rc5 ] ~ [ wine-1.4-rc4 ] ~ [ wine-1.4-rc3 ] ~ [ wine-1.4-rc2 ] ~ [ wine-1.4-rc1 ] ~ [ wine-1.3.37 ] ~ [ wine-1.3.36 ] ~ [ wine-1.3.35 ] ~ [ wine-1.3.34 ] ~ [ wine-1.3.33 ] ~ [ wine-1.3.32 ] ~ [ wine-1.3.31 ] ~ [ wine-1.3.30 ] ~ [ wine-1.3.29 ] ~ [ wine-1.3.28 ] ~ [ wine-1.3.27 ] ~ [ wine-1.3.26 ] ~ [ wine-1.3.25 ] ~ [ wine-1.3.24 ] ~ [ wine-1.3.23 ] ~ [ wine-1.3.22 ] ~ [ wine-1.3.21 ] ~ [ wine-1.3.20 ] ~ [ wine-1.3.19 ] ~ [ wine-1.3.18 ] ~ [ wine-1.2.3 ] ~ [ wine-1.3.17 ] ~ [ wine-1.3.16 ] ~ [ wine-1.3.15 ] ~ [ wine-1.3.14 ] ~ [ wine-1.3.13 ] ~ [ wine-1.3.12 ] ~ [ wine-1.3.11 ] ~ [ wine-1.3.10 ] ~ [ wine-1.3.9 ] ~ [ wine-1.2.2 ] ~ [ wine-1.3.8 ] ~ [ wine-1.3.7 ] ~ [ wine-1.3.6 ] ~ [ wine-1.3.5 ] ~ [ wine-1.2.1 ] ~ [ wine-1.3.4 ] ~ [ wine-1.3.3 ] ~ [ wine-1.3.2 ] ~ [ wine-1.3.1 ] ~ [ wine-1.3.0 ] ~ [ wine-1.2 ] ~ [ wine-1.2-rc7 ] ~ [ wine-1.2-rc6 ] ~ [ wine-1.2-rc5 ] ~ [ wine-1.2-rc4 ] ~ [ wine-1.2-rc3 ] ~ [ wine-1.2-rc2 ] ~ [ wine-1.2-rc1 ] ~ [ wine-1.1.44 ] ~ [ wine-1.1.43 ] ~ [ wine-1.1.42 ] ~ [ wine-1.1.41 ] ~ [ wine-1.1.40 ] ~ [ wine-1.1.39 ] ~ [ wine-1.1.38 ] ~ [ wine-1.1.37 ] ~ [ wine-1.1.36 ] ~ [ wine-1.1.35 ] ~ [ wine-1.1.34 ] ~ [ wine-1.1.33 ] ~ [ wine-1.1.32 ] ~ [ wine-1.1.31 ] ~ [ wine-1.1.30 ] ~ [ wine-1.1.29 ] ~ [ wine-1.1.28 ] ~ [ wine-1.1.27 ] ~ [ wine-1.1.26 ] ~ [ wine-1.1.25 ] ~ [ wine-1.1.24 ] ~ [ wine-1.1.23 ] ~ [ wine-1.1.22 ] ~ [ wine-1.1.21 ] ~ [ wine-1.1.20 ] ~ [ wine-1.1.19 ] ~ [ wine-1.1.18 ] ~ [ wine-1.1.17 ] ~ [ wine-1.1.16 ] ~ [ wine-1.1.15 ] ~ [ wine-1.1.14 ] ~ [ wine-1.1.13 ] ~ [ wine-1.1.12 ] ~ [ wine-1.1.11 ] ~ [ wine-1.1.10 ] ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~

  1 /*
  2  * Regedit treeview
  3  *
  4  * Copyright (C) 2002 Robert Dickenson <robd@reactos.org>
  5  * Copyright (C) 2008 Alexander N. Sørnes <alex@thehandofagony.com>
  6  *
  7  * This library is free software; you can redistribute it and/or
  8  * modify it under the terms of the GNU Lesser General Public
  9  * License as published by the Free Software Foundation; either
 10  * version 2.1 of the License, or (at your option) any later version.
 11  *
 12  * This library is distributed in the hope that it will be useful,
 13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 15  * Lesser General Public License for more details.
 16  *
 17  * You should have received a copy of the GNU Lesser General Public
 18  * License along with this library; if not, write to the Free Software
 19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 20  */
 21 
 22 #define WIN32_LEAN_AND_MEAN     /* Exclude rarely-used stuff from Windows headers */
 23 
 24 #define NONAMELESSUNION
 25 #define NONAMELESSSTRUCT
 26 #include <windows.h>
 27 #include <commctrl.h>
 28 #include <stdlib.h>
 29 #include <stdio.h>
 30 #include <wine/debug.h>
 31 #include <shlwapi.h>
 32 
 33 #include "main.h"
 34 #include "regproc.h"
 35 
 36 WINE_DEFAULT_DEBUG_CHANNEL(regedit);
 37 
 38 /* Global variables and constants  */
 39 /* Image_Open, Image_Closed, and Image_Root - integer variables for indexes of the images.  */
 40 /* CX_BITMAP and CY_BITMAP - width and height of an icon.  */
 41 /* NUM_BITMAPS - number of bitmaps to add to the image list.  */
 42 int Image_Open;
 43 int Image_Closed;
 44 int Image_Root;
 45 
 46 #define CX_ICON    16
 47 #define CY_ICON    16
 48 #define NUM_ICONS    3
 49 
 50 static BOOL UpdateExpandingTree(HWND hwndTV, HTREEITEM hItem, int state);
 51 
 52 static BOOL get_item_path(HWND hwndTV, HTREEITEM hItem, HKEY* phKey, LPWSTR* pKeyPath, int* pPathLen, int* pMaxChars)
 53 {
 54     TVITEMW item;
 55     int maxChars, chars;
 56     LPWSTR newStr;
 57     HTREEITEM hParent;
 58 
 59     item.mask = TVIF_PARAM;
 60     item.hItem = hItem;
 61     if (!TreeView_GetItemW(hwndTV, &item)) return FALSE;
 62 
 63     if (item.lParam) {
 64     /* found root key with valid key value */
 65     *phKey = (HKEY)item.lParam;
 66     return TRUE;
 67     }
 68 
 69     hParent = (HTREEITEM)SendMessageW(hwndTV, TVM_GETNEXTITEM, TVGN_PARENT, (LPARAM)hItem);
 70     if(!get_item_path(hwndTV, hParent, phKey, pKeyPath, pPathLen, pMaxChars)) return FALSE;
 71     if (*pPathLen) {
 72         (*pKeyPath)[*pPathLen] = '\\';
 73         ++(*pPathLen);
 74     }
 75 
 76     do {
 77         item.mask = TVIF_TEXT;
 78         item.hItem = hItem;
 79         item.pszText = *pKeyPath + *pPathLen;
 80         item.cchTextMax = maxChars = *pMaxChars - *pPathLen;
 81         if (!TreeView_GetItemW(hwndTV, &item)) return FALSE;
 82         chars = lstrlenW(item.pszText);
 83     if (chars < maxChars - 1) {
 84             *pPathLen += chars;
 85             break;
 86     }
 87     newStr = HeapReAlloc(GetProcessHeap(), 0, *pKeyPath, *pMaxChars * 2);
 88     if (!newStr) return FALSE;
 89     *pKeyPath = newStr;
 90     *pMaxChars *= 2;
 91     } while(TRUE);
 92 
 93     return TRUE;
 94 }
 95 
 96 LPWSTR GetItemPath(HWND hwndTV, HTREEITEM hItem, HKEY* phRootKey)
 97 {
 98     int pathLen = 0, maxLen;
 99     WCHAR *pathBuffer;
100 
101     pathBuffer = HeapAlloc(GetProcessHeap(), 0, 1024*sizeof(WCHAR));
102     if (!pathBuffer) return NULL;
103     *pathBuffer = 0;
104     maxLen = HeapSize(GetProcessHeap(), 0, pathBuffer);
105     if (maxLen == (SIZE_T) - 1) return NULL;
106     maxLen = maxLen / sizeof(WCHAR);
107     if (!hItem) hItem = (HTREEITEM)SendMessageW(hwndTV, TVM_GETNEXTITEM, TVGN_CARET, 0);
108     if (!hItem) return NULL;
109     if (!get_item_path(hwndTV, hItem, phRootKey, &pathBuffer, &pathLen, &maxLen)) return NULL;
110     return pathBuffer;
111 }
112 
113 static LPWSTR get_path_component(LPCWSTR *lplpKeyName) {
114      LPCWSTR lpPos = *lplpKeyName;
115      LPWSTR lpResult = NULL;
116      int len;
117      if (!lpPos)
118          return NULL;
119      while(*lpPos && *lpPos != '\\')
120          lpPos++;
121      if (*lpPos && lpPos == *lplpKeyName)
122          return NULL;
123      len = lpPos+1-(*lplpKeyName);
124      lpResult = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
125      if (!lpResult) /* that would be very odd */
126          return NULL;
127      lstrcpynW(lpResult, *lplpKeyName, len);
128      *lplpKeyName = *lpPos ? lpPos+1 : NULL;
129      return lpResult;
130 }
131 
132 HTREEITEM FindPathInTree(HWND hwndTV, LPCWSTR lpKeyName) {
133     TVITEMEXW tvi;
134     WCHAR buf[261]; /* tree view has 260 character limitation on item name */
135     HTREEITEM hItem, hOldItem;
136 
137     buf[260] = '\0';
138     hItem = (HTREEITEM)SendMessageW(hwndTV, TVM_GETNEXTITEM, TVGN_ROOT, 0);
139     SendMessageW(hwndTV, TVM_EXPAND, TVE_EXPAND, (LPARAM)hItem );
140     hItem = (HTREEITEM)SendMessageW(hwndTV, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hItem);
141     hOldItem = hItem;
142     while(1) {
143         LPWSTR lpItemName = get_path_component(&lpKeyName);
144 
145         if (lpItemName) {
146             while(hItem) {
147                 tvi.mask = TVIF_TEXT | TVIF_HANDLE;
148                 tvi.hItem = hItem;
149                 tvi.pszText = buf;
150                 tvi.cchTextMax = 260;
151                 SendMessageW(hwndTV, TVM_GETITEMW, 0, (LPARAM) &tvi);
152                 if (!lstrcmpiW(tvi.pszText, lpItemName)) {
153                      SendMessageW(hwndTV, TVM_EXPAND, TVE_EXPAND, (LPARAM)hItem );
154                      if (!lpKeyName)
155                      {
156                          HeapFree(GetProcessHeap(), 0, lpItemName);
157                          return hItem;
158                      }
159                      hOldItem = hItem;
160                      hItem = (HTREEITEM)SendMessageW(hwndTV, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hItem);
161                      break;
162                 }
163                 hItem = (HTREEITEM)SendMessageW(hwndTV, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)hItem);
164             }
165             HeapFree(GetProcessHeap(), 0, lpItemName);
166             if (!hItem)
167                 return hOldItem;
168         }
169         else
170             return hItem;
171     }
172 }
173 
174 BOOL DeleteNode(HWND hwndTV, HTREEITEM hItem)
175 {
176     if (!hItem) hItem = (HTREEITEM)SendMessageW(hwndTV, TVM_GETNEXTITEM, TVGN_CARET, 0);
177     if (!hItem) return FALSE;
178     return (BOOL)SendMessageW(hwndTV, TVM_DELETEITEM, 0, (LPARAM)hItem);
179 }
180 
181 /* Add an entry to the tree. Only give hKey for root nodes (HKEY_ constants) */
182 static HTREEITEM AddEntryToTree(HWND hwndTV, HTREEITEM hParent, LPWSTR label, HKEY hKey, DWORD dwChildren)
183 {
184     TVINSERTSTRUCTW tvins;
185 
186     if (hKey) {
187         if (RegQueryInfoKeyW(hKey, 0, 0, 0, &dwChildren, 0, 0, 0, 0, 0, 0, 0) != ERROR_SUCCESS) {
188             dwChildren = 0;
189         }
190     }
191 
192     tvins.u.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_CHILDREN | TVIF_PARAM;
193     tvins.u.item.pszText = label;
194     tvins.u.item.cchTextMax = lstrlenW(label);
195     tvins.u.item.iImage = Image_Closed;
196     tvins.u.item.iSelectedImage = Image_Open;
197     tvins.u.item.cChildren = dwChildren;
198     tvins.u.item.lParam = (LPARAM)hKey;
199     tvins.hInsertAfter = hKey ? TVI_LAST : TVI_SORT;
200     tvins.hParent = hParent;
201 
202     return TreeView_InsertItemW(hwndTV, &tvins);
203 }
204 
205 static BOOL match_string(LPCWSTR sstring1, LPCWSTR sstring2, int mode)
206 {
207     if (mode & SEARCH_WHOLE)
208         return !lstrcmpiW(sstring1, sstring2);
209     else
210         return NULL != StrStrIW(sstring1, sstring2);
211 }
212 
213 static BOOL match_item(HWND hwndTV, HTREEITEM hItem, LPCWSTR sstring, int mode, int *row)
214 {
215     TVITEMW item;
216     WCHAR keyname[KEY_MAX_LEN];
217     item.mask = TVIF_TEXT;
218     item.hItem = hItem;
219     item.pszText = keyname;
220     item.cchTextMax = KEY_MAX_LEN;
221     if (!TreeView_GetItemW(hwndTV, &item)) return FALSE;
222     if ((mode & SEARCH_KEYS) && match_string(keyname, sstring, mode)) {
223         *row = -1;
224         return TRUE;
225     }
226 
227     if (mode & (SEARCH_VALUES | SEARCH_CONTENT)) {
228         int i, adjust;
229         WCHAR valName[KEY_MAX_LEN], *KeyPath;
230         HKEY hKey, hRoot;
231         DWORD lenName;
232         
233         KeyPath = GetItemPath(hwndTV, hItem, &hRoot);
234 
235         if (!KeyPath || !hRoot)
236              return FALSE;
237 
238         if (RegOpenKeyExW(hRoot, KeyPath, 0, KEY_READ, &hKey) != ERROR_SUCCESS) {
239             HeapFree(GetProcessHeap(), 0, KeyPath);
240             return FALSE;
241         }
242 
243         HeapFree(GetProcessHeap(), 0, KeyPath);
244         lenName = KEY_MAX_LEN;
245         adjust = 0;
246         /* RegEnumValue won't return empty default value, so fake it when dealing with *row,
247            which corresponds to list view rows, not value ids */
248         if (ERROR_SUCCESS == RegEnumValueW(hKey, 0, valName, &lenName, NULL, NULL, NULL, NULL) && *valName)
249             adjust = 1;
250         
251         i = (*row)-adjust;
252         if (i < 0) i = 0;
253         while(1) {
254             DWORD lenValue = 0, type = 0;
255             lenName = KEY_MAX_LEN;
256             
257             if (ERROR_SUCCESS != RegEnumValueW(hKey,
258                 i, valName, &lenName, NULL, &type, NULL, &lenValue))
259                 break;
260             
261             if (mode & SEARCH_VALUES) {
262                 if (match_string(valName, sstring, mode)) {
263                     RegCloseKey(hKey);
264                     *row = i+adjust;
265                     return TRUE;
266                 }
267             }
268             
269             if ((mode & SEARCH_CONTENT) && (type == REG_EXPAND_SZ || type == REG_SZ)) {
270                 LPWSTR buffer;
271                 buffer = HeapAlloc(GetProcessHeap(), 0, lenValue);
272                 if (!buffer)
273                     break;
274                 if (ERROR_SUCCESS != RegEnumValueW(hKey, i, NULL, NULL, NULL, &type, (LPBYTE)buffer, &lenValue))
275                     break;
276                 if (match_string(buffer, sstring, mode)) {
277                     HeapFree(GetProcessHeap(), 0, buffer);
278                     RegCloseKey(hKey);
279                     *row = i+adjust;
280                     return TRUE;
281                 }
282                 HeapFree(GetProcessHeap(), 0, buffer);
283             }
284                             
285             i++;
286         }
287         RegCloseKey(hKey);
288     }        
289     return FALSE;
290 }
291 
292 HTREEITEM FindNext(HWND hwndTV, HTREEITEM hItem, LPCWSTR sstring, int mode, int *row)
293 {
294     HTREEITEM hTry, hLast;
295     
296     hLast = hItem;
297     (*row)++;
298     if (match_item(hwndTV, hLast, sstring, mode & ~SEARCH_KEYS, row)) {
299         return hLast;
300     }
301     *row = 0;
302     
303     while(hLast) {
304         /* first look in subtree */
305         /* no children? maybe we haven't loaded them yet? */
306         if (!SendMessageW(hwndTV, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hLast)) {
307             UINT state = (UINT)SendMessageW(hwndTV, TVM_GETITEMSTATE, (WPARAM)hLast, -1);
308             UpdateExpandingTree(hwndTV, hLast, state);
309         }
310         hTry = (HTREEITEM)SendMessageW(hwndTV, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hLast);
311         if (hTry) {
312             if (match_item(hwndTV, hTry, sstring, mode, row))
313                 return hTry;
314             hLast = hTry;
315             continue;
316         }
317         /* no more children, maybe there are any siblings? */
318         hTry = (HTREEITEM)SendMessageW(hwndTV, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)hLast);
319         if (hTry) {
320             if (match_item(hwndTV, hTry, sstring, mode, row))
321                 return hTry;
322             hLast = hTry;
323             continue;
324         }
325         /* no more siblings, look at the next siblings in parent(s) */
326         hLast = (HTREEITEM)SendMessageW(hwndTV, TVM_GETNEXTITEM, TVGN_PARENT, (LPARAM)hLast);
327         if (!hLast)
328             return NULL;
329         while (hLast && (hTry = (HTREEITEM)SendMessageW(hwndTV, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)hLast)) == NULL) {
330             hLast = (HTREEITEM)SendMessageW(hwndTV, TVM_GETNEXTITEM, TVGN_PARENT, (LPARAM)hLast);
331         }
332         if (match_item(hwndTV, hTry, sstring, mode, row))
333             return hTry;
334         hLast = hTry;
335     }
336     return NULL;
337 }
338 
339 static BOOL RefreshTreeItem(HWND hwndTV, HTREEITEM hItem)
340 {
341     HKEY hRoot, hKey, hSubKey;
342     HTREEITEM childItem;
343     LPWSTR KeyPath;
344     DWORD dwCount, dwIndex, dwMaxSubKeyLen;
345     LPWSTR Name;
346     TVITEMW tvItem;
347     
348     hRoot = NULL;
349     KeyPath = GetItemPath(hwndTV, hItem, &hRoot);
350 
351     if (!KeyPath || !hRoot)
352         return FALSE;
353 
354     if (*KeyPath) {
355         if (RegOpenKeyExW(hRoot, KeyPath, 0, KEY_READ, &hKey) != ERROR_SUCCESS) {
356             WINE_TRACE("RegOpenKeyEx failed, %s was probably removed.\n", wine_dbgstr_w(KeyPath));
357             return FALSE;
358         }
359     } else {
360         hKey = hRoot;
361     }
362     HeapFree(GetProcessHeap(), 0, KeyPath);
363 
364     if (RegQueryInfoKeyW(hKey, 0, 0, 0, &dwCount, &dwMaxSubKeyLen, 0, 0, 0, 0, 0, 0) != ERROR_SUCCESS) {
365         return FALSE;
366     }
367 
368     /* Set the number of children again */
369     tvItem.mask = TVIF_CHILDREN;
370     tvItem.hItem = hItem;
371     tvItem.cChildren = dwCount;
372     if (!TreeView_SetItemW(hwndTV, &tvItem)) {
373         return FALSE;
374     }
375 
376     /* We don't have to bother with the rest if it's not expanded. */
377     if (SendMessageW(hwndTV, TVM_GETITEMSTATE, (WPARAM)hItem, TVIS_EXPANDED) == 0) {
378         RegCloseKey(hKey);
379         return TRUE;
380     }
381 
382     dwMaxSubKeyLen++; /* account for the \0 terminator */
383     if (!(Name = HeapAlloc(GetProcessHeap(), 0, dwMaxSubKeyLen * sizeof(WCHAR)))) {
384         return FALSE;
385     }
386     tvItem.cchTextMax = dwMaxSubKeyLen;
387     if (!(tvItem.pszText = HeapAlloc(GetProcessHeap(), 0, dwMaxSubKeyLen * sizeof(WCHAR)))) {
388         HeapFree(GetProcessHeap(), 0, Name);
389         return FALSE;
390     }
391 
392     /* Now go through all the children in the registry, and check if any have to be added. */
393     for (dwIndex = 0; dwIndex < dwCount; dwIndex++) {
394         DWORD cName = dwMaxSubKeyLen, dwSubCount;
395         BOOL found;
396 
397         found = FALSE;
398         if (RegEnumKeyExW(hKey, dwIndex, Name, &cName, 0, 0, 0, NULL) != ERROR_SUCCESS) {
399             continue;
400         }
401 
402         /* Find the number of children of the node. */
403         dwSubCount = 0;
404         if (RegOpenKeyExW(hKey, Name, 0, KEY_QUERY_VALUE, &hSubKey) == ERROR_SUCCESS) {
405             if (RegQueryInfoKeyW(hSubKey, 0, 0, 0, &dwSubCount, 0, 0, 0, 0, 0, 0, 0) != ERROR_SUCCESS) {
406                 dwSubCount = 0;
407             }
408             RegCloseKey(hSubKey);
409         }
410 
411         /* Check if the node is already in there. */
412         for (childItem = (HTREEITEM)SendMessageW(hwndTV, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hItem); childItem;
413                 childItem = (HTREEITEM)SendMessageW(hwndTV, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)childItem)) {
414             tvItem.mask = TVIF_TEXT;
415             tvItem.hItem = childItem;
416             if (!TreeView_GetItemW(hwndTV, &tvItem)) {
417                 HeapFree(GetProcessHeap(), 0, Name);
418                 HeapFree(GetProcessHeap(), 0, tvItem.pszText);
419                 return FALSE;
420             }
421 
422             if (!lstrcmpiW(tvItem.pszText, Name)) {
423                 found = TRUE;
424                 break;
425             }
426         }
427 
428         if (found == FALSE) {
429             WINE_TRACE("New subkey %s\n", wine_dbgstr_w(Name));
430             AddEntryToTree(hwndTV, hItem, Name, NULL, dwSubCount);
431         }
432     }
433     HeapFree(GetProcessHeap(), 0, Name);
434     HeapFree(GetProcessHeap(), 0, tvItem.pszText);
435     RegCloseKey(hKey);
436 
437     /* Now go through all the children in the tree, and check if any have to be removed. */
438     childItem = (HTREEITEM)SendMessageW(hwndTV, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hItem);
439     while (childItem) {
440         HTREEITEM nextItem = (HTREEITEM)SendMessageW(hwndTV, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)childItem);
441         if (RefreshTreeItem(hwndTV, childItem) == FALSE) {
442             SendMessageW(hwndTV, TVM_DELETEITEM, 0, (LPARAM)childItem);
443         }
444         childItem = nextItem;
445     }
446 
447     return TRUE;
448 }
449 
450 BOOL RefreshTreeView(HWND hwndTV)
451 {
452     HTREEITEM hItem;
453     HTREEITEM hSelectedItem;
454     HCURSOR hcursorOld;
455     HTREEITEM hRoot;
456 
457     WINE_TRACE("\n");
458     hSelectedItem = (HTREEITEM)SendMessageW(hwndTV, TVM_GETNEXTITEM, TVGN_CARET, 0);
459     hcursorOld = SetCursor(LoadCursorW(NULL, (LPCWSTR)IDC_WAIT));
460     SendMessageW(hwndTV, WM_SETREDRAW, FALSE, 0);
461 
462     hRoot = (HTREEITEM)SendMessageW(hwndTV, TVM_GETNEXTITEM, TVGN_ROOT, 0);
463     hItem = (HTREEITEM)SendMessageW(hwndTV, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hRoot);
464     while (hItem) {
465         RefreshTreeItem(hwndTV, hItem);
466         hItem = (HTREEITEM)SendMessageW(hwndTV, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)hItem);
467     }
468 
469     SendMessageW(hwndTV, WM_SETREDRAW, TRUE, 0);
470     InvalidateRect(hwndTV, NULL, FALSE);
471     SetCursor(hcursorOld);
472     
473     /* We reselect the currently selected node, this will prompt a refresh of the listview. */
474     SendMessageW(hwndTV, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hSelectedItem);
475     return TRUE;
476 }
477 
478 HTREEITEM InsertNode(HWND hwndTV, HTREEITEM hItem, LPWSTR name)
479 {
480     WCHAR buf[MAX_NEW_KEY_LEN];
481     HTREEITEM hNewItem = 0;
482     TVITEMEXW item;
483 
484     if (!hItem) hItem = (HTREEITEM)SendMessageW(hwndTV, TVM_GETNEXTITEM, TVGN_CARET, 0);
485     if (!hItem) return FALSE;
486     if (SendMessageW(hwndTV, TVM_GETITEMSTATE, (WPARAM)hItem, TVIS_EXPANDEDONCE)) {
487         hNewItem = AddEntryToTree(hwndTV, hItem, name, 0, 0);
488     } else {
489         item.mask = TVIF_CHILDREN | TVIF_HANDLE;
490         item.hItem = hItem;
491         if (!TreeView_GetItemW(hwndTV, &item)) return FALSE;
492         item.cChildren = 1;
493         if (!TreeView_SetItemW(hwndTV, &item)) return FALSE;
494     }
495     SendMessageW(hwndTV, TVM_EXPAND, TVE_EXPAND, (LPARAM)hItem );
496     if (!hNewItem) {
497         for(hNewItem = (HTREEITEM)SendMessageW(hwndTV, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hItem); hNewItem;
498             hNewItem = (HTREEITEM)SendMessageW(hwndTV, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)hNewItem)) {
499             item.mask = TVIF_HANDLE | TVIF_TEXT;
500             item.hItem = hNewItem;
501             item.pszText = buf;
502             item.cchTextMax = COUNT_OF(buf);
503             if (!TreeView_GetItemW(hwndTV, &item)) continue;
504             if (lstrcmpW(name, item.pszText) == 0) break;
505         }
506     }
507     if (hNewItem)
508         SendMessageW(hwndTV, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hNewItem);
509 
510     return hNewItem;
511 }
512 
513 HWND StartKeyRename(HWND hwndTV)
514 {
515     HTREEITEM hItem;
516 
517     if(!(hItem = (HTREEITEM)SendMessageW(hwndTV, TVM_GETNEXTITEM, TVGN_CARET, 0))) return 0;
518     return (HWND)SendMessageW(hwndTV, TVM_EDITLABELW, 0, (LPARAM)hItem);
519 }
520 
521 static BOOL InitTreeViewItems(HWND hwndTV, LPWSTR pHostName)
522 {
523     TVINSERTSTRUCTW tvins;
524     HTREEITEM hRoot;
525     static WCHAR hkcr[] = {'H','K','E','Y','_','C','L','A','S','S','E','S','_','R','O','O','T',0},
526                  hkcu[] = {'H','K','E','Y','_','C','U','R','R','E','N','T','_','U','S','E','R',0},
527                  hklm[] = {'H','K','E','Y','_','L','O','C','A','L','_','M','A','C','H','I','N','E',0},
528                  hku[]  = {'H','K','E','Y','_','U','S','E','R','S',0},
529                  hkcc[] = {'H','K','E','Y','_','C','U','R','R','E','N','T','_','C','O','N','F','I','G',0},
530                  hkdd[] = {'H','K','E','Y','_','D','Y','N','_','D','A','T','A',0};
531 
532     tvins.u.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_CHILDREN | TVIF_PARAM;
533     /* Set the text of the item.  */
534     tvins.u.item.pszText = pHostName;
535     tvins.u.item.cchTextMax = lstrlenW(pHostName);
536     /* Assume the item is not a parent item, so give it an image.  */
537     tvins.u.item.iImage = Image_Root;
538     tvins.u.item.iSelectedImage = Image_Root;
539     tvins.u.item.cChildren = 5;
540     /* Save the heading level in the item's application-defined data area.  */
541     tvins.u.item.lParam = 0;
542     tvins.hInsertAfter = TVI_FIRST;
543     tvins.hParent = TVI_ROOT;
544     /* Add the item to the tree view control.  */
545     if (!(hRoot = TreeView_InsertItemW(hwndTV, &tvins))) return FALSE;
546 
547     if (!AddEntryToTree(hwndTV, hRoot, hkcr, HKEY_CLASSES_ROOT, 1)) return FALSE;
548     if (!AddEntryToTree(hwndTV, hRoot, hkcu, HKEY_CURRENT_USER, 1)) return FALSE;
549     if (!AddEntryToTree(hwndTV, hRoot, hklm, HKEY_LOCAL_MACHINE, 1)) return FALSE;
550     if (!AddEntryToTree(hwndTV, hRoot, hku, HKEY_USERS, 1)) return FALSE;
551     if (!AddEntryToTree(hwndTV, hRoot, hkcc, HKEY_CURRENT_CONFIG, 1)) return FALSE;
552     if (!AddEntryToTree(hwndTV, hRoot, hkdd, HKEY_DYN_DATA, 1)) return FALSE;
553 
554     /* expand and select host name */
555     SendMessageW(hwndTV, TVM_EXPAND, TVE_EXPAND, (LPARAM)hRoot );
556     SendMessageW(hwndTV, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hRoot);
557     return TRUE;
558 }
559 
560 
561 /*
562  * InitTreeViewImageLists - creates an image list, adds three bitmaps
563  * to it, and associates the image list with a tree view control.
564  * Returns TRUE if successful, or FALSE otherwise.
565  * hwndTV - handle to the tree view control.
566  */
567 static BOOL InitTreeViewImageLists(HWND hwndTV)
568 {
569     HIMAGELIST himl;  /* handle to image list  */
570     HICON hico;       /* handle to icon  */
571 
572     /* Create the image list.  */
573     if ((himl = ImageList_Create(CX_ICON, CY_ICON,
574                                  ILC_MASK, 0, NUM_ICONS)) == NULL)
575         return FALSE;
576 
577     /* Add the open file, closed file, and document bitmaps.  */
578     hico = LoadIconW(hInst, MAKEINTRESOURCEW(IDI_OPEN_FILE));
579     Image_Open = ImageList_AddIcon(himl, hico);
580 
581     hico = LoadIconW(hInst, MAKEINTRESOURCEW(IDI_CLOSED_FILE));
582     Image_Closed = ImageList_AddIcon(himl, hico);
583 
584     hico = LoadIconW(hInst, MAKEINTRESOURCEW(IDI_ROOT));
585     Image_Root = ImageList_AddIcon(himl, hico);
586 
587     /* Fail if not all of the images were added.  */
588     if (ImageList_GetImageCount(himl) < NUM_ICONS)
589     {
590       return FALSE;
591     }
592 
593     /* Associate the image list with the tree view control.  */
594     SendMessageW(hwndTV, TVM_SETIMAGELIST, TVSIL_NORMAL, (LPARAM)himl);
595 
596     return TRUE;
597 }
598 
599 BOOL UpdateExpandingTree(HWND hwndTV, HTREEITEM hItem, int state)
600 {
601     DWORD dwCount, dwIndex, dwMaxSubKeyLen;
602     HKEY hRoot, hNewKey, hKey;
603     LPWSTR keyPath;
604     LPWSTR Name;
605     LONG errCode;
606     HCURSOR hcursorOld;
607     TVITEMW item;
608 
609     static int expanding;
610     if (expanding) return FALSE;
611     if (state & TVIS_EXPANDEDONCE ) {
612         return TRUE;
613     }
614     expanding = TRUE;
615     hcursorOld = SetCursor(LoadCursorW(NULL, (LPCWSTR)IDC_WAIT));
616     SendMessageW(hwndTV, WM_SETREDRAW, FALSE, 0);
617 
618     keyPath = GetItemPath(hwndTV, hItem, &hRoot);
619     if (!keyPath) goto done;
620 
621     if (*keyPath) {
622         errCode = RegOpenKeyExW(hRoot, keyPath, 0, KEY_READ, &hNewKey);
623         if (errCode != ERROR_SUCCESS) goto done;
624     } else {
625         hNewKey = hRoot;
626     }
627 
628     errCode = RegQueryInfoKeyW(hNewKey, 0, 0, 0, &dwCount, &dwMaxSubKeyLen, 0, 0, 0, 0, 0, 0);
629     if (errCode != ERROR_SUCCESS) goto done;
630     dwMaxSubKeyLen++; /* account for the \0 terminator */
631     Name = HeapAlloc(GetProcessHeap(), 0, dwMaxSubKeyLen * sizeof(WCHAR));
632     if (!Name) goto done;
633 
634     for (dwIndex = 0; dwIndex < dwCount; dwIndex++) {
635         DWORD cName = dwMaxSubKeyLen, dwSubCount;
636 
637         errCode = RegEnumKeyExW(hNewKey, dwIndex, Name, &cName, 0, 0, 0, 0);
638         if (errCode != ERROR_SUCCESS) continue;
639         errCode = RegOpenKeyExW(hNewKey, Name, 0, KEY_QUERY_VALUE, &hKey);
640         if (errCode == ERROR_SUCCESS) {
641             errCode = RegQueryInfoKeyW(hKey, 0, 0, 0, &dwSubCount, 0, 0, 0, 0, 0, 0, 0);
642             RegCloseKey(hKey);
643         }
644         if (errCode != ERROR_SUCCESS) dwSubCount = 0;
645         AddEntryToTree(hwndTV, hItem, Name, NULL, dwSubCount);
646     }
647     RegCloseKey(hNewKey);
648     HeapFree(GetProcessHeap(), 0, Name);
649 
650 done:
651     item.mask = TVIF_STATE;
652     item.hItem = hItem;
653     item.stateMask = TVIS_EXPANDEDONCE;
654     item.state = TVIS_EXPANDEDONCE;
655     SendMessageW(hwndTV, TVM_SETITEMW, 0, (LPARAM)&item);
656     SendMessageW(hwndTV, WM_SETREDRAW, TRUE, 0);
657     SetCursor(hcursorOld);
658     expanding = FALSE;
659     HeapFree(GetProcessHeap(), 0, keyPath);
660 
661     return TRUE;
662 }
663 
664 BOOL OnTreeExpanding(HWND hwndTV, NMTREEVIEWW* pnmtv)
665 {
666     return UpdateExpandingTree(hwndTV, pnmtv->itemNew.hItem, pnmtv->itemNew.state);
667 }
668 
669 
670 /*
671  * CreateTreeView - creates a tree view control.
672  * Returns the handle to the new control if successful, or NULL otherwise.
673  * hwndParent - handle to the control's parent window.
674  */
675 HWND CreateTreeView(HWND hwndParent, LPWSTR pHostName, UINT id)
676 {
677     RECT rcClient;
678     HWND hwndTV;
679     WCHAR TreeView[] = {'T','r','e','e',' ','V','i','e','w',0};
680 
681     /* Get the dimensions of the parent window's client area, and create the tree view control.  */
682     GetClientRect(hwndParent, &rcClient);
683     hwndTV = CreateWindowExW(WS_EX_CLIENTEDGE, WC_TREEVIEWW, TreeView,
684                             WS_VISIBLE | WS_CHILD | WS_TABSTOP | TVS_HASLINES | TVS_HASBUTTONS | TVS_LINESATROOT,
685                             0, 0, rcClient.right, rcClient.bottom,
686                             hwndParent, ULongToHandle(id), hInst, NULL);
687     SendMessageW(hwndTV, TVM_SETUNICODEFORMAT, TRUE, 0);
688     /* Initialize the image list, and add items to the control.  */
689     if (!InitTreeViewImageLists(hwndTV) || !InitTreeViewItems(hwndTV, pHostName)) {
690         DestroyWindow(hwndTV);
691         return NULL;
692     }
693     return hwndTV;
694 }
695 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.