1 /* 2 * Regedit treeview 3 * 4 * Copyright (C) 2002 Robert Dickenson <robd@reactos.org> 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 */ 20 21 #include <regedit.h> 22 23 /* Global variables and constants */ 24 /* Image_Open, Image_Closed, and Image_Root - integer variables for indexes of the images. */ 25 /* CX_ICON and CY_ICON - width and height of an icon. */ 26 /* NUM_ICON - number of icons to add to the image list. */ 27 static int Image_Open = 0; 28 static int Image_Closed = 0; 29 static int Image_Root = 0; 30 31 static LPTSTR pathBuffer; 32 33 #define NUM_ICONS 3 34 35 static BOOL get_item_path(HWND hwndTV, HTREEITEM hItem, HKEY* phKey, LPTSTR* pKeyPath, int* pPathLen, int* pMaxLen) 36 { 37 TVITEM item; 38 size_t maxLen, len; 39 LPTSTR newStr; 40 41 item.mask = TVIF_PARAM; 42 item.hItem = hItem; 43 if (!TreeView_GetItem(hwndTV, &item)) return FALSE; 44 45 if (item.lParam) 46 { 47 /* found root key with valid key value */ 48 *phKey = (HKEY)item.lParam; 49 return TRUE; 50 } 51 52 if(!get_item_path(hwndTV, TreeView_GetParent(hwndTV, hItem), phKey, pKeyPath, pPathLen, pMaxLen)) return FALSE; 53 if (*pPathLen) 54 { 55 (*pKeyPath)[*pPathLen] = _T('\\'); 56 ++(*pPathLen); 57 } 58 59 do 60 { 61 item.mask = TVIF_TEXT; 62 item.hItem = hItem; 63 item.pszText = *pKeyPath + *pPathLen; 64 maxLen = *pMaxLen - *pPathLen; 65 item.cchTextMax = (int) maxLen; 66 if (!TreeView_GetItem(hwndTV, &item)) return FALSE; 67 len = _tcslen(item.pszText); 68 if (len < maxLen - 1) 69 { 70 *pPathLen += (int) len; 71 break; 72 } 73 newStr = HeapReAlloc(GetProcessHeap(), 0, *pKeyPath, *pMaxLen * 2); 74 if (!newStr) return FALSE; 75 *pKeyPath = newStr; 76 *pMaxLen *= 2; 77 } 78 while(TRUE); 79 80 return TRUE; 81 } 82 83 LPCTSTR GetItemPath(HWND hwndTV, HTREEITEM hItem, HKEY* phRootKey) 84 { 85 int pathLen = 0, maxLen; 86 87 *phRootKey = NULL; 88 if (!pathBuffer) pathBuffer = HeapAlloc(GetProcessHeap(), 0, 1024); 89 if (!pathBuffer) return NULL; 90 *pathBuffer = 0; 91 maxLen = (int) HeapSize(GetProcessHeap(), 0, pathBuffer); 92 if (maxLen == -1) return NULL; 93 if (!hItem) hItem = TreeView_GetSelection(hwndTV); 94 if (!hItem) return NULL; 95 if (!get_item_path(hwndTV, hItem, phRootKey, &pathBuffer, &pathLen, &maxLen)) 96 { 97 return NULL; 98 } 99 return pathBuffer; 100 } 101 102 BOOL DeleteNode(HWND hwndTV, HTREEITEM hItem) 103 { 104 if (!hItem) hItem = TreeView_GetSelection(hwndTV); 105 if (!hItem) return FALSE; 106 return TreeView_DeleteItem(hwndTV, hItem); 107 } 108 109 /* Add an entry to the tree. Only give hKey for root nodes (HKEY_ constants) */ 110 static HTREEITEM AddEntryToTree(HWND hwndTV, HTREEITEM hParent, LPTSTR label, HKEY hKey, DWORD dwChildren) 111 { 112 TVITEM tvi; 113 TVINSERTSTRUCT tvins; 114 115 if (hKey) 116 { 117 if (RegQueryInfoKey(hKey, 0, 0, 0, &dwChildren, 0, 0, 0, 0, 0, 0, 0) != ERROR_SUCCESS) 118 { 119 dwChildren = 0; 120 } 121 } 122 123 tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_CHILDREN | TVIF_PARAM; 124 tvi.pszText = label; 125 tvi.cchTextMax = lstrlen(tvi.pszText); 126 tvi.iImage = Image_Closed; 127 tvi.iSelectedImage = Image_Open; 128 tvi.cChildren = dwChildren; 129 tvi.lParam = (LPARAM)hKey; 130 tvins.item = tvi; 131 tvins.hInsertAfter = (HTREEITEM)(hKey ? TVI_LAST : TVI_FIRST); 132 tvins.hParent = hParent; 133 return TreeView_InsertItem(hwndTV, &tvins); 134 } 135 136 BOOL RefreshTreeItem(HWND hwndTV, HTREEITEM hItem) 137 { 138 HKEY hRoot, hKey, hSubKey; 139 HTREEITEM childItem; 140 LPCTSTR KeyPath; 141 DWORD dwCount, dwIndex, dwMaxSubKeyLen; 142 LPTSTR Name = NULL; 143 TVITEM tvItem; 144 LPTSTR pszNodes = NULL; 145 BOOL bSuccess = FALSE; 146 LPTSTR s; 147 BOOL bAddedAny; 148 149 KeyPath = GetItemPath(hwndTV, hItem, &hRoot); 150 151 if (*KeyPath) 152 { 153 if (RegOpenKeyEx(hRoot, KeyPath, 0, KEY_READ, &hKey) != ERROR_SUCCESS) 154 { 155 goto done; 156 } 157 } 158 else 159 { 160 hKey = hRoot; 161 } 162 163 if (RegQueryInfoKey(hKey, 0, 0, 0, &dwCount, &dwMaxSubKeyLen, 0, 0, 0, 0, 0, 0) != ERROR_SUCCESS) 164 { 165 goto done; 166 } 167 168 /* Set the number of children again */ 169 tvItem.mask = TVIF_CHILDREN; 170 tvItem.hItem = hItem; 171 tvItem.cChildren = dwCount; 172 if (!TreeView_SetItem(hwndTV, &tvItem)) 173 { 174 goto done; 175 } 176 177 /* We don't have to bother with the rest if it's not expanded. */ 178 if (TreeView_GetItemState(hwndTV, hItem, TVIS_EXPANDED) == 0) 179 { 180 RegCloseKey(hKey); 181 bSuccess = TRUE; 182 goto done; 183 } 184 185 dwMaxSubKeyLen++; /* account for the \0 terminator */ 186 if (!(Name = HeapAlloc(GetProcessHeap(), 0, dwMaxSubKeyLen * sizeof(TCHAR)))) 187 { 188 goto done; 189 } 190 tvItem.cchTextMax = dwMaxSubKeyLen; 191 /*if (!(tvItem.pszText = HeapAlloc(GetProcessHeap(), 0, dwMaxSubKeyLen * sizeof(TCHAR)))) { 192 goto done; 193 }*/ 194 195 /* Get all of the tree node siblings in one contiguous block of memory */ 196 { 197 DWORD dwPhysicalSize = 0; 198 DWORD dwActualSize = 0; 199 DWORD dwNewPhysicalSize; 200 LPTSTR pszNewNodes; 201 DWORD dwStep = 10000; 202 203 for (childItem = TreeView_GetChild(hwndTV, hItem); childItem; 204 childItem = TreeView_GetNextSibling(hwndTV, childItem)) 205 { 206 207 if (dwActualSize + dwMaxSubKeyLen + 1 > dwPhysicalSize) 208 { 209 dwNewPhysicalSize = dwActualSize + dwMaxSubKeyLen + 1 + dwStep; 210 211 if (pszNodes) 212 pszNewNodes = (LPTSTR) HeapReAlloc(GetProcessHeap(), 0, pszNodes, dwNewPhysicalSize * sizeof(TCHAR)); 213 else 214 pszNewNodes = (LPTSTR) HeapAlloc(GetProcessHeap(), 0, dwNewPhysicalSize * sizeof(TCHAR)); 215 if (!pszNewNodes) 216 goto done; 217 218 dwPhysicalSize = dwNewPhysicalSize; 219 pszNodes = pszNewNodes; 220 } 221 222 tvItem.mask = TVIF_TEXT; 223 tvItem.hItem = childItem; 224 tvItem.pszText = &pszNodes[dwActualSize]; 225 tvItem.cchTextMax = dwPhysicalSize - dwActualSize; 226 if (!TreeView_GetItem(hwndTV, &tvItem)) 227 goto done; 228 229 dwActualSize += (DWORD) _tcslen(&pszNodes[dwActualSize]) + 1; 230 } 231 232 if (pszNodes) 233 pszNodes[dwActualSize] = '\0'; 234 } 235 236 /* Now go through all the children in the tree, and check if any have to be removed. */ 237 childItem = TreeView_GetChild(hwndTV, hItem); 238 while (childItem) 239 { 240 HTREEITEM nextItem = TreeView_GetNextSibling(hwndTV, childItem); 241 if (RefreshTreeItem(hwndTV, childItem) == FALSE) 242 { 243 (void)TreeView_DeleteItem(hwndTV, childItem); 244 } 245 childItem = nextItem; 246 } 247 248 /* Now go through all the children in the registry, and check if any have to be added. */ 249 bAddedAny = FALSE; 250 for (dwIndex = 0; dwIndex < dwCount; dwIndex++) 251 { 252 DWORD cName = dwMaxSubKeyLen, dwSubCount; 253 BOOL found; 254 255 found = FALSE; 256 if (RegEnumKeyEx(hKey, dwIndex, Name, &cName, 0, 0, 0, NULL) != ERROR_SUCCESS) 257 { 258 continue; 259 } 260 261 /* Check if the node is already in there. */ 262 if (pszNodes) 263 { 264 for (s = pszNodes; *s; s += _tcslen(s) + 1) 265 { 266 if (!_tcscmp(s, Name)) 267 { 268 found = TRUE; 269 break; 270 } 271 } 272 } 273 274 if (found == FALSE) 275 { 276 /* Find the number of children of the node. */ 277 dwSubCount = 0; 278 if (RegOpenKeyEx(hKey, Name, 0, KEY_QUERY_VALUE, &hSubKey) == ERROR_SUCCESS) 279 { 280 if (RegQueryInfoKey(hSubKey, 0, 0, 0, &dwSubCount, 0, 0, 0, 0, 0, 0, 0) != ERROR_SUCCESS) 281 { 282 dwSubCount = 0; 283 } 284 RegCloseKey(hSubKey); 285 } 286 287 AddEntryToTree(hwndTV, hItem, Name, NULL, dwSubCount); 288 bAddedAny = TRUE; 289 } 290 } 291 RegCloseKey(hKey); 292 293 if (bAddedAny) 294 SendMessage(hwndTV, TVM_SORTCHILDREN, 0, (LPARAM) hItem); 295 296 bSuccess = TRUE; 297 298 done: 299 if (pszNodes) 300 HeapFree(GetProcessHeap(), 0, pszNodes); 301 if (Name) 302 HeapFree(GetProcessHeap(), 0, Name); 303 return bSuccess; 304 } 305 306 BOOL RefreshTreeView(HWND hwndTV) 307 { 308 HTREEITEM hItem; 309 HTREEITEM hSelectedItem; 310 HCURSOR hcursorOld; 311 312 hSelectedItem = TreeView_GetSelection(hwndTV); 313 hcursorOld = SetCursor(LoadCursor(NULL, IDC_WAIT)); 314 SendMessage(hwndTV, WM_SETREDRAW, FALSE, 0); 315 316 hItem = TreeView_GetChild(hwndTV, TreeView_GetRoot(hwndTV)); 317 while (hItem) 318 { 319 RefreshTreeItem(hwndTV, hItem); 320 hItem = TreeView_GetNextSibling(hwndTV, hItem); 321 } 322 323 SendMessage(hwndTV, WM_SETREDRAW, TRUE, 0); 324 SetCursor(hcursorOld); 325 326 /* We reselect the currently selected node, this will prompt a refresh of the listview. */ 327 (void)TreeView_SelectItem(hwndTV, hSelectedItem); 328 return TRUE; 329 } 330 331 HTREEITEM InsertNode(HWND hwndTV, HTREEITEM hItem, LPTSTR name) 332 { 333 TCHAR buf[MAX_NEW_KEY_LEN]; 334 HTREEITEM hNewItem = 0; 335 TVITEMEX item; 336 337 /* Default to the current selection */ 338 if (!hItem) 339 { 340 hItem = TreeView_GetSelection(hwndTV); 341 if (!hItem) 342 return FALSE; 343 } 344 345 memset(&item, 0, sizeof(item)); 346 item.hItem = hItem; 347 item.mask = TVIF_CHILDREN | TVIF_HANDLE | TVIF_STATE; 348 if (!TreeView_GetItem(hwndTV, &item)) 349 return FALSE; 350 351 if ((item.state & TVIS_EXPANDEDONCE) && (item.cChildren > 0)) 352 { 353 hNewItem = AddEntryToTree(hwndTV, hItem, name, 0, 0); 354 SendMessage(hwndTV, TVM_SORTCHILDREN, 0, (LPARAM) hItem); 355 } 356 else 357 { 358 item.mask = TVIF_CHILDREN | TVIF_HANDLE; 359 item.hItem = hItem; 360 item.cChildren = 1; 361 if (!TreeView_SetItem(hwndTV, &item)) 362 return FALSE; 363 } 364 365 (void)TreeView_Expand(hwndTV, hItem, TVE_EXPAND); 366 if (!hNewItem) 367 { 368 for(hNewItem = TreeView_GetChild(hwndTV, hItem); hNewItem; hNewItem = TreeView_GetNextSibling(hwndTV, hNewItem)) 369 { 370 item.mask = TVIF_HANDLE | TVIF_TEXT; 371 item.hItem = hNewItem; 372 item.pszText = buf; 373 item.cchTextMax = COUNT_OF(buf); 374 if (!TreeView_GetItem(hwndTV, &item)) continue; 375 if (lstrcmp(name, item.pszText) == 0) break; 376 } 377 } 378 if (hNewItem) (void)TreeView_SelectItem(hwndTV, hNewItem); 379 380 return hNewItem; 381 } 382 383 HWND StartKeyRename(HWND hwndTV) 384 { 385 HTREEITEM hItem; 386 387 if(!(hItem = TreeView_GetSelection(hwndTV))) return 0; 388 return TreeView_EditLabel(hwndTV, hItem); 389 } 390 391 static BOOL InitTreeViewItems(HWND hwndTV, LPTSTR pHostName) 392 { 393 TVITEM tvi; 394 TVINSERTSTRUCT tvins; 395 HTREEITEM hRoot; 396 397 tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_CHILDREN | TVIF_PARAM; 398 /* Set the text of the item. */ 399 tvi.pszText = pHostName; 400 tvi.cchTextMax = lstrlen(tvi.pszText); 401 /* Assume the item is not a parent item, so give it an image. */ 402 tvi.iImage = Image_Root; 403 tvi.iSelectedImage = Image_Root; 404 tvi.cChildren = 5; 405 /* Save the heading level in the item's application-defined data area. */ 406 tvi.lParam = (LPARAM)NULL; 407 tvins.item = tvi; 408 tvins.hInsertAfter = (HTREEITEM)TVI_FIRST; 409 tvins.hParent = TVI_ROOT; 410 /* Add the item to the tree view control. */ 411 if (!(hRoot = TreeView_InsertItem(hwndTV, &tvins))) return FALSE; 412 413 if (!AddEntryToTree(hwndTV, hRoot, _T("HKEY_CLASSES_ROOT"), HKEY_CLASSES_ROOT, 1)) return FALSE; 414 if (!AddEntryToTree(hwndTV, hRoot, _T("HKEY_CURRENT_USER"), HKEY_CURRENT_USER, 1)) return FALSE; 415 if (!AddEntryToTree(hwndTV, hRoot, _T("HKEY_LOCAL_MACHINE"), HKEY_LOCAL_MACHINE, 1)) return FALSE; 416 if (!AddEntryToTree(hwndTV, hRoot, _T("HKEY_USERS"), HKEY_USERS, 1)) return FALSE; 417 if (!AddEntryToTree(hwndTV, hRoot, _T("HKEY_CURRENT_CONFIG"), HKEY_CURRENT_CONFIG, 1)) return FALSE; 418 419 if (GetVersion() & 0x80000000) 420 { 421 /* Win9x specific key */ 422 if (!AddEntryToTree(hwndTV, hRoot, _T("HKEY_DYN_DATA"), HKEY_DYN_DATA, 1)) return FALSE; 423 } 424 425 /* expand and select host name */ 426 (void)TreeView_Expand(hwndTV, hRoot, TVE_EXPAND); 427 (void)TreeView_Select(hwndTV, hRoot, TVGN_CARET); 428 return TRUE; 429 } 430 431 432 /* 433 * InitTreeViewImageLists - creates an image list, adds three bitmaps 434 * to it, and associates the image list with a tree view control. 435 * Returns TRUE if successful, or FALSE otherwise. 436 * hwndTV - handle to the tree view control. 437 */ 438 static BOOL InitTreeViewImageLists(HWND hwndTV) 439 { 440 HIMAGELIST himl; /* handle to image list */ 441 HICON hico; /* handle to icon */ 442 443 /* Create the image list. */ 444 if ((himl = ImageList_Create(GetSystemMetrics(SM_CXSMICON), 445 GetSystemMetrics(SM_CYSMICON), 446 ILC_MASK | ILC_COLOR32, 447 0, 448 NUM_ICONS)) == NULL) 449 { 450 return FALSE; 451 } 452 453 /* Add the open file, closed file, and document bitmaps. */ 454 hico = LoadImage(hInst, 455 MAKEINTRESOURCE(IDI_OPEN_FILE), 456 IMAGE_ICON, 457 GetSystemMetrics(SM_CXSMICON), 458 GetSystemMetrics(SM_CYSMICON), 459 0); 460 if (hico) 461 { 462 Image_Open = ImageList_AddIcon(himl, hico); 463 DestroyIcon(hico); 464 } 465 466 hico = LoadImage(hInst, 467 MAKEINTRESOURCE(IDI_CLOSED_FILE), 468 IMAGE_ICON, 469 GetSystemMetrics(SM_CXSMICON), 470 GetSystemMetrics(SM_CYSMICON), 471 0); 472 if (hico) 473 { 474 Image_Closed = ImageList_AddIcon(himl, hico); 475 DestroyIcon(hico); 476 } 477 478 hico = LoadImage(hInst, 479 MAKEINTRESOURCE(IDI_ROOT), 480 IMAGE_ICON, 481 GetSystemMetrics(SM_CXSMICON), 482 GetSystemMetrics(SM_CYSMICON), 483 0); 484 if (hico) 485 { 486 Image_Root = ImageList_AddIcon(himl, hico); 487 DestroyIcon(hico); 488 } 489 490 /* Fail if not all of the images were added. */ 491 if (ImageList_GetImageCount(himl) < NUM_ICONS) 492 { 493 ImageList_Destroy(himl); 494 return FALSE; 495 } 496 497 /* Associate the image list with the tree view control. */ 498 (void)TreeView_SetImageList(hwndTV, himl, TVSIL_NORMAL); 499 500 return TRUE; 501 } 502 503 BOOL OnTreeExpanding(HWND hwndTV, NMTREEVIEW* pnmtv) 504 { 505 DWORD dwCount, dwIndex, dwMaxSubKeyLen; 506 HKEY hRoot, hNewKey, hKey; 507 LPCTSTR keyPath; 508 LPTSTR Name; 509 LONG errCode; 510 HCURSOR hcursorOld; 511 512 static int expanding; 513 if (expanding) return FALSE; 514 if (pnmtv->itemNew.state & TVIS_EXPANDEDONCE ) 515 { 516 return TRUE; 517 } 518 expanding = TRUE; 519 hcursorOld = SetCursor(LoadCursor(NULL, IDC_WAIT)); 520 SendMessage(hwndTV, WM_SETREDRAW, FALSE, 0); 521 522 keyPath = GetItemPath(hwndTV, pnmtv->itemNew.hItem, &hRoot); 523 if (!keyPath) goto done; 524 525 if (*keyPath) 526 { 527 errCode = RegOpenKeyEx(hRoot, keyPath, 0, KEY_READ, &hNewKey); 528 if (errCode != ERROR_SUCCESS) goto done; 529 } 530 else 531 { 532 hNewKey = hRoot; 533 } 534 535 errCode = RegQueryInfoKey(hNewKey, 0, 0, 0, &dwCount, &dwMaxSubKeyLen, 0, 0, 0, 0, 0, 0); 536 if (errCode != ERROR_SUCCESS) goto done; 537 dwMaxSubKeyLen++; /* account for the \0 terminator */ 538 Name = HeapAlloc(GetProcessHeap(), 0, dwMaxSubKeyLen * sizeof(TCHAR)); 539 if (!Name) goto done; 540 541 for (dwIndex = 0; dwIndex < dwCount; dwIndex++) 542 { 543 DWORD cName = dwMaxSubKeyLen, dwSubCount; 544 545 errCode = RegEnumKeyEx(hNewKey, dwIndex, Name, &cName, 0, 0, 0, 0); 546 if (errCode != ERROR_SUCCESS) continue; 547 errCode = RegOpenKeyEx(hNewKey, Name, 0, KEY_QUERY_VALUE, &hKey); 548 if (errCode == ERROR_SUCCESS) 549 { 550 errCode = RegQueryInfoKey(hKey, 0, 0, 0, &dwSubCount, 0, 0, 0, 0, 0, 0, 0); 551 RegCloseKey(hKey); 552 } 553 if (errCode != ERROR_SUCCESS) dwSubCount = 0; 554 AddEntryToTree(hwndTV, pnmtv->itemNew.hItem, Name, NULL, dwSubCount); 555 } 556 557 SendMessage(hwndTV, TVM_SORTCHILDREN, 0, (LPARAM)pnmtv->itemNew.hItem); 558 559 RegCloseKey(hNewKey); 560 HeapFree(GetProcessHeap(), 0, Name); 561 562 done: 563 SendMessage(hwndTV, WM_SETREDRAW, TRUE, 0); 564 SetCursor(hcursorOld); 565 expanding = FALSE; 566 567 return TRUE; 568 } 569 570 571 BOOL CreateNewKey(HWND hwndTV, HTREEITEM hItem) 572 { 573 TCHAR szNewKeyFormat[128]; 574 TCHAR szNewKey[128]; 575 LPCTSTR pszKeyPath; 576 int iIndex = 1; 577 LONG nResult; 578 HKEY hRootKey = NULL, hKey = NULL, hNewKey = NULL; 579 BOOL bSuccess = FALSE; 580 DWORD dwDisposition; 581 HTREEITEM hNewItem; 582 583 pszKeyPath = GetItemPath(hwndTV, hItem, &hRootKey); 584 if (pszKeyPath[0] == TEXT('\0')) 585 hKey = hRootKey; 586 else if (RegOpenKey(hRootKey, pszKeyPath, &hKey) != ERROR_SUCCESS) 587 goto done; 588 589 if (LoadString(hInst, IDS_NEW_KEY, szNewKeyFormat, sizeof(szNewKeyFormat) / sizeof(szNewKeyFormat[0])) <= 0) 590 goto done; 591 592 /* Need to create a new key with a unique name */ 593 do 594 { 595 wsprintf(szNewKey, szNewKeyFormat, iIndex++); 596 nResult = RegCreateKeyEx(hKey, szNewKey, 0, NULL, 0, KEY_WRITE, NULL, &hNewKey, &dwDisposition); 597 if (hNewKey && dwDisposition == REG_OPENED_EXISTING_KEY) 598 { 599 RegCloseKey(hNewKey); 600 hNewKey = NULL; 601 } 602 else if (!hNewKey) 603 { 604 TCHAR sz[256]; 605 wsprintf(sz, TEXT("Cannot create new key!\n\nError Code: %d"), nResult); 606 MessageBox(hFrameWnd, sz, NULL, MB_ICONERROR); 607 goto done; 608 } 609 } 610 while(!hNewKey); 611 612 /* Insert the new key */ 613 hNewItem = InsertNode(hwndTV, hItem, szNewKey); 614 if (!hNewItem) 615 goto done; 616 617 /* The new key's name is probably not appropriate yet */ 618 (void)TreeView_EditLabel(hwndTV, hNewItem); 619 620 bSuccess = TRUE; 621 622 done: 623 if (hKey != hRootKey && hKey) 624 RegCloseKey(hKey); 625 if (hNewKey) 626 RegCloseKey(hNewKey); 627 return bSuccess; 628 } 629 630 631 /* 632 * CreateTreeView - creates a tree view control. 633 * Returns the handle to the new control if successful, or NULL otherwise. 634 * hwndParent - handle to the control's parent window. 635 */ 636 HWND CreateTreeView(HWND hwndParent, LPTSTR pHostName, HMENU id) 637 { 638 RECT rcClient; 639 HWND hwndTV; 640 641 /* Get the dimensions of the parent window's client area, and create the tree view control. */ 642 GetClientRect(hwndParent, &rcClient); 643 hwndTV = CreateWindowEx(WS_EX_CLIENTEDGE, WC_TREEVIEW, NULL, 644 WS_VISIBLE | WS_CHILD | WS_TABSTOP | TVS_HASLINES | TVS_HASBUTTONS | TVS_LINESATROOT | TVS_EDITLABELS, 645 0, 0, rcClient.right, rcClient.bottom, 646 hwndParent, id, hInst, NULL); 647 /* Initialize the image list, and add items to the control. */ 648 if (!InitTreeViewImageLists(hwndTV) || !InitTreeViewItems(hwndTV, pHostName)) 649 { 650 DestroyWindow(hwndTV); 651 return NULL; 652 } 653 return hwndTV; 654 } 655 656 void DestroyTreeView() 657 { 658 if (pathBuffer) 659 HeapFree(GetProcessHeap(), 0, pathBuffer); 660 } 661 662 BOOL SelectNode(HWND hwndTV, LPCTSTR keyPath) 663 { 664 HTREEITEM hRoot, hItem; 665 HTREEITEM hChildItem; 666 TCHAR szPathPart[128]; 667 TCHAR szBuffer[128]; 668 LPCTSTR s; 669 TVITEM tvi; 670 671 /* Total no-good hack */ 672 if (!_tcsnicmp(keyPath, _T("My Computer\\"), 12)) 673 keyPath += 12; 674 675 hRoot = TreeView_GetRoot(hwndTV); 676 hItem = hRoot; 677 678 while(keyPath[0]) 679 { 680 s = _tcschr(keyPath, TEXT('\\')); 681 lstrcpyn(szPathPart, keyPath, s ? s - keyPath + 1 : _tcslen(keyPath) + 1); 682 683 /* Special case for root to expand root key abbreviations */ 684 if (hItem == hRoot) 685 { 686 if (!_tcsicmp(szPathPart, TEXT("HKCR"))) 687 _tcscpy(szPathPart, TEXT("HKEY_CLASSES_ROOT")); 688 else if (!_tcsicmp(szPathPart, TEXT("HKCU"))) 689 _tcscpy(szPathPart, TEXT("HKEY_CURRENT_USER")); 690 else if (!_tcsicmp(szPathPart, TEXT("HKLM"))) 691 _tcscpy(szPathPart, TEXT("HKEY_LOCAL_MACHINE")); 692 else if (!_tcsicmp(szPathPart, TEXT("HKU"))) 693 _tcscpy(szPathPart, TEXT("HKEY_USERS")); 694 else if (!_tcsicmp(szPathPart, TEXT("HKCC"))) 695 _tcscpy(szPathPart, TEXT("HKEY_CURRENT_CONFIG")); 696 else if (!_tcsicmp(szPathPart, TEXT("HKDD"))) 697 _tcscpy(szPathPart, TEXT("HKEY_DYN_DATA")); 698 } 699 700 for (hChildItem = TreeView_GetChild(hwndTV, hItem); hChildItem; 701 hChildItem = TreeView_GetNextSibling(hwndTV, hChildItem)) 702 { 703 memset(&tvi, 0, sizeof(tvi)); 704 tvi.hItem = hChildItem; 705 tvi.mask = TVIF_TEXT | TVIF_CHILDREN; 706 tvi.pszText = szBuffer; 707 tvi.cchTextMax = sizeof(szBuffer) / sizeof(szBuffer[0]); 708 709 (void)TreeView_GetItem(hwndTV, &tvi); 710 711 if (!_tcsicmp(szBuffer, szPathPart)) 712 break; 713 } 714 715 if (!hChildItem) 716 return FALSE; 717 718 if (tvi.cChildren > 0) 719 { 720 if (!TreeView_Expand(hwndTV, hChildItem, TVE_EXPAND)) 721 return FALSE; 722 } 723 724 keyPath = s ? s + 1 : _T(""); 725 hItem = hChildItem; 726 } 727 728 (void)TreeView_SelectItem(hwndTV, hItem); 729 (void)TreeView_EnsureVisible(hwndTV, hItem); 730 731 return TRUE; 732 } 733 734 735