framewnd.c 32 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/*
 * Regedit frame window
 *
 * Copyright (C) 2002 Robert Dickenson <robd@reactos.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
 */

#define WIN32_LEAN_AND_MEAN     /* Exclude rarely-used stuff from Windows headers */

#include <windows.h>
#include <tchar.h>
#include <commctrl.h>
#include <commdlg.h>
#include <cderr.h>
#include <stdlib.h>
#include <stdio.h>
#include <shellapi.h>

#include "main.h"
#include "regproc.h"
34
#include "wine/unicode.h"
35 36 37 38 39

/********************************************************************************
 * Global and Local Variables:
 */

40
static WCHAR favoritesKey[] =  {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\','A','p','p','l','e','t','s','\\','R','e','g','E','d','i','t','\\','F','a','v','o','r','i','t','e','s',0};
41
static BOOL bInMenuLoop = FALSE;        /* Tells us if we are in the menu loop */
42
static WCHAR favoriteName[128];
43
static WCHAR searchString[128];
44
static int searchMask = SEARCH_KEYS | SEARCH_VALUES | SEARCH_CONTENT;
45

46 47 48
static WCHAR FileNameBuffer[_MAX_PATH];
static WCHAR FileTitleBuffer[_MAX_PATH];
static WCHAR FilterBuffer[_MAX_PATH];
49

50 51 52 53 54 55
/*******************************************************************************
 * Local module support methods
 */

static void resize_frame_rect(HWND hWnd, PRECT prect)
{
56 57 58
    RECT rt;
    /*
    	if (IsWindowVisible(hToolBar)) {
59
		SendMessageW(hToolBar, WM_SIZE, 0, 0);
60 61 62 63 64 65 66 67 68 69
    		GetClientRect(hToolBar, &rt);
    		prect->top = rt.bottom+3;
    		prect->bottom -= rt.bottom+3;
    	}
     */
    if (IsWindowVisible(hStatusBar)) {
        SetupStatusBar(hWnd, TRUE);
        GetClientRect(hStatusBar, &rt);
        prect->bottom -= rt.bottom;
    }
70
    MoveWindow(g_pChildWnd->hWnd, prect->left, prect->top, prect->right, prect->bottom, TRUE);
71 72
}

73
static void resize_frame_client(HWND hWnd)
74
{
75
    RECT rect;
76

77 78
    GetClientRect(hWnd, &rect);
    resize_frame_rect(hWnd, &rect);
79 80 81 82 83 84 85
}

/********************************************************************************/

static void OnEnterMenuLoop(HWND hWnd)
{
    int nParts;
86
    WCHAR empty = 0;
87 88 89

    /* Update the status bar pane sizes */
    nParts = -1;
90
    SendMessageW(hStatusBar, SB_SETPARTS, 1, (LPARAM)&nParts);
91
    bInMenuLoop = TRUE;
92
    SendMessageW(hStatusBar, SB_SETTEXTW, 0, (LPARAM)&empty);
93 94 95 96 97 98
}

static void OnExitMenuLoop(HWND hWnd)
{
    bInMenuLoop = FALSE;
    /* Update the status bar pane sizes*/
99 100
    SetupStatusBar(hWnd, TRUE);
    UpdateStatusBar();
101 102
}

103 104
static void UpdateMenuItems(HMENU hMenu) {
    HWND hwndTV = g_pChildWnd->hTreeWnd;
105
    BOOL bAllowEdit = FALSE;
106
    HKEY hRootKey = NULL;
107
    LPWSTR keyName;
108
    keyName = GetItemPath(hwndTV, TreeView_GetSelection(hwndTV), &hRootKey);
109 110
    if (GetFocus() != hwndTV || (keyName && *keyName)) { /* can't modify root keys, but allow for their values */
        bAllowEdit = TRUE;
111
    }
112 113
    EnableMenuItem(hMenu, ID_EDIT_FIND, MF_ENABLED | MF_BYCOMMAND);
    EnableMenuItem(hMenu, ID_EDIT_FINDNEXT, MF_ENABLED | MF_BYCOMMAND);
114 115 116
    EnableMenuItem(hMenu, ID_EDIT_MODIFY, (bAllowEdit ? MF_ENABLED : MF_GRAYED) | MF_BYCOMMAND);
    EnableMenuItem(hMenu, ID_EDIT_DELETE, (bAllowEdit ? MF_ENABLED : MF_GRAYED) | MF_BYCOMMAND);
    EnableMenuItem(hMenu, ID_EDIT_RENAME, (bAllowEdit ? MF_ENABLED : MF_GRAYED) | MF_BYCOMMAND);
117 118 119
    EnableMenuItem(hMenu, ID_FAVORITES_ADDTOFAVORITES, (hRootKey ? MF_ENABLED : MF_GRAYED) | MF_BYCOMMAND);
    EnableMenuItem(hMenu, ID_FAVORITES_REMOVEFAVORITE, 
        (GetMenuItemCount(hMenu)>2 ? MF_ENABLED : MF_GRAYED) | MF_BYCOMMAND);
120 121

    HeapFree(GetProcessHeap(), 0, keyName);
122 123 124 125 126 127 128 129
}

static void OnInitMenuPopup(HWND hWnd, HMENU hMenu, short wItem)
{
    if (wItem == 3) {
        HKEY hKey;
        while(GetMenuItemCount(hMenu)>2)
            DeleteMenu(hMenu, 2, MF_BYPOSITION);
130
        if (RegOpenKeyExW(HKEY_CURRENT_USER, favoritesKey,
131
            0, KEY_READ, &hKey) == ERROR_SUCCESS) {
132
            WCHAR namebuf[KEY_MAX_LEN];
133 134 135 136 137 138 139 140
            BYTE valuebuf[4096];
            int i = 0;
            BOOL sep = FALSE;
            DWORD ksize, vsize, type;
            LONG error;
            do {
                ksize = KEY_MAX_LEN;
                vsize = sizeof(valuebuf);
141
                error = RegEnumValueW(hKey, i, namebuf, &ksize, NULL, &type, valuebuf, &vsize);
142 143 144 145
                if (error != ERROR_SUCCESS)
                    break;
                if (type == REG_SZ) {
                    if (!sep) {
146
                        AppendMenuW(hMenu, MF_SEPARATOR, -1, NULL);
147 148
                        sep = TRUE;
                    }
149
                    AppendMenuW(hMenu, MF_STRING, ID_FAVORITE_FIRST+i, namebuf);
150 151 152 153 154 155 156 157 158
                }
                i++;
            } while(error == ERROR_SUCCESS);
            RegCloseKey(hKey);
        }
    }
    UpdateMenuItems(hMenu);
}

159 160
static void OnMenuSelect(HWND hWnd, UINT nItemID, UINT nFlags, HMENU hSysMenu)
{
161
    WCHAR str[100];
162

163
    str[0] = 0;
164 165 166 167 168
    if (nFlags & MF_POPUP) {
        if (hSysMenu != GetMenu(hWnd)) {
            if (nItemID == 2) nItemID = 5;
        }
    }
169
    if (LoadStringW(hInst, nItemID, str, 100)) {
170
        /* load appropriate string*/
171
        LPWSTR lpsz = str;
172
        /* first newline terminates actual string*/
173
        lpsz = strchrW(lpsz, '\n');
174 175 176
        if (lpsz != NULL)
            *lpsz = '\0';
    }
177
    SendMessageW(hStatusBar, SB_SETTEXTW, 0, (LPARAM)str);
178 179 180 181 182 183 184 185
}

void SetupStatusBar(HWND hWnd, BOOL bResize)
{
    RECT  rc;
    int nParts;
    GetClientRect(hWnd, &rc);
    nParts = rc.right;
186 187
    /*    nParts = -1;*/
    if (bResize)
188 189
        SendMessageW(hStatusBar, WM_SIZE, 0, 0);
    SendMessageW(hStatusBar, SB_SETPARTS, 1, (LPARAM)&nParts);
190
    UpdateStatusBar();
191 192 193 194
}

void UpdateStatusBar(void)
{
195
    LPWSTR fullPath = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, TRUE);
196
    SendMessageW(hStatusBar, SB_SETTEXTW, 0, (LPARAM)fullPath);
197
    HeapFree(GetProcessHeap(), 0, fullPath);
198 199 200 201
}

static void toggle_child(HWND hWnd, UINT cmd, HWND hchild)
{
202 203
    BOOL vis = IsWindowVisible(hchild);
    HMENU hMenuView = GetSubMenu(hMenuFrame, ID_VIEW_MENU);
204

205 206 207
    CheckMenuItem(hMenuView, cmd, vis?MF_BYCOMMAND:MF_BYCOMMAND|MF_CHECKED);
    ShowWindow(hchild, vis?SW_HIDE:SW_SHOW);
    resize_frame_client(hWnd);
208 209 210 211
}

static BOOL CheckCommDlgError(HWND hWnd)
{
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247
    DWORD dwErrorCode = CommDlgExtendedError();
    switch (dwErrorCode) {
    case CDERR_DIALOGFAILURE:
        break;
    case CDERR_FINDRESFAILURE:
        break;
    case CDERR_NOHINSTANCE:
        break;
    case CDERR_INITIALIZATION:
        break;
    case CDERR_NOHOOK:
        break;
    case CDERR_LOCKRESFAILURE:
        break;
    case CDERR_NOTEMPLATE:
        break;
    case CDERR_LOADRESFAILURE:
        break;
    case CDERR_STRUCTSIZE:
        break;
    case CDERR_LOADSTRFAILURE:
        break;
    case FNERR_BUFFERTOOSMALL:
        break;
    case CDERR_MEMALLOCFAILURE:
        break;
    case FNERR_INVALIDFILENAME:
        break;
    case CDERR_MEMLOCKFAILURE:
        break;
    case FNERR_SUBCLASSFAILURE:
        break;
    default:
        break;
    }
    return TRUE;
248 249
}

250
static void ExportRegistryFile_StoreSelection(HWND hdlg, OPENFILENAMEW *pOpenFileName)
251 252 253
{
    if (IsDlgButtonChecked(hdlg, IDC_EXPORT_SELECTED))
    {
254 255 256
        INT len = SendDlgItemMessageW(hdlg, IDC_EXPORT_PATH, WM_GETTEXTLENGTH, 0, 0);
        pOpenFileName->lCustData = (LPARAM)HeapAlloc(GetProcessHeap(), 0, (len+1)*sizeof(WCHAR));
        SendDlgItemMessageW(hdlg, IDC_EXPORT_PATH, WM_GETTEXT, len+1, pOpenFileName->lCustData);
257 258
    }
    else
259
        pOpenFileName->lCustData = (LPARAM)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WCHAR));
260 261
}

262
static UINT_PTR CALLBACK ExportRegistryFile_OFNHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
263
{
264 265
    static OPENFILENAMEW* pOpenFileName;
    OFNOTIFYW *pOfNotify;
266 267 268

    switch (uiMsg) {
    case WM_INITDIALOG:
269
        pOpenFileName = (OPENFILENAMEW*)lParam;
270
        break;
271 272 273 274
    case WM_COMMAND:
        if (LOWORD(wParam) == IDC_EXPORT_PATH && HIWORD(wParam) == EN_UPDATE)
            CheckRadioButton(hdlg, IDC_EXPORT_ALL, IDC_EXPORT_SELECTED, IDC_EXPORT_SELECTED);
        break;
275
    case WM_NOTIFY:
276
        pOfNotify = (OFNOTIFYW*)lParam;
277 278 279
        switch (pOfNotify->hdr.code)
        {
            case CDN_INITDONE:
280
            {
281
                BOOL export_branch = FALSE;
282 283
                WCHAR* path = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, FALSE);
                SendDlgItemMessageW(hdlg, IDC_EXPORT_PATH, WM_SETTEXT, 0, (LPARAM)path);
284 285
                if (path && strlenW(path) > 0)
                    export_branch = TRUE;
286
                HeapFree(GetProcessHeap(), 0, path);
287
                CheckRadioButton(hdlg, IDC_EXPORT_ALL, IDC_EXPORT_SELECTED, export_branch ? IDC_EXPORT_SELECTED : IDC_EXPORT_ALL);
288
                break;
289
            }
290 291 292 293
            case CDN_FILEOK:
                ExportRegistryFile_StoreSelection(hdlg, pOpenFileName);
                break;
        }
294 295 296 297 298 299 300 301
        break;
    default:
        break;
    }
    return 0L;
}


302
static BOOL InitOpenFileName(HWND hWnd, OPENFILENAMEW *pofn)
303
{
304 305
    memset(pofn, 0, sizeof(OPENFILENAMEW));
    pofn->lStructSize = sizeof(OPENFILENAMEW);
306 307 308
    pofn->hwndOwner = hWnd;
    pofn->hInstance = hInst;

309
    if (FilterBuffer[0] == 0)
310
        LoadStringW(hInst, IDS_FILEDIALOG_FILTER, FilterBuffer, _MAX_PATH);
311
    pofn->lpstrFilter = FilterBuffer;
312
    pofn->nFilterIndex = 2;
313 314 315 316 317
    pofn->lpstrFile = FileNameBuffer;
    pofn->nMaxFile = _MAX_PATH;
    pofn->lpstrFileTitle = FileTitleBuffer;
    pofn->nMaxFileTitle = _MAX_PATH;
    pofn->Flags = OFN_HIDEREADONLY;
318
    /* some other fields may be set by the caller */
319
    return TRUE;
320 321
}

322 323
static BOOL import_registry_filename(LPTSTR filename)
{
324
    BOOL Success;
325 326 327 328 329
    FILE* reg_file = fopen(filename, "r");

    if(!reg_file)
        return FALSE;

330 331 332 333 334 335
    Success = import_registry_file(reg_file);

    if(fclose(reg_file) != 0)
        Success = FALSE;

    return Success;
336 337
}

338 339
static BOOL ImportRegistryFile(HWND hWnd)
{
340 341
    OPENFILENAMEW ofn;
    WCHAR title[128];
342 343

    InitOpenFileName(hWnd, &ofn);
344
    ofn.Flags |= OFN_ENABLESIZING;
345
    LoadStringW(hInst, IDS_FILEDIALOG_IMPORT_TITLE, title, COUNT_OF(title));
346
    ofn.lpstrTitle = title;
347 348 349
    if (GetOpenFileNameW(&ofn)) {
        CHAR* fileA = GetMultiByteString(ofn.lpstrFile);
        if (!import_registry_filename(fileA)) {
350
            /*printf("Can't open file \"%s\"\n", ofn.lpstrFile);*/
351
            HeapFree(GetProcessHeap(), 0, fileA);
352 353
            return FALSE;
        }
354
        HeapFree(GetProcessHeap(), 0, fileA);
355 356 357
    } else {
        CheckCommDlgError(hWnd);
    }
358
    RefreshTreeView(g_pChildWnd->hTreeWnd);
359
    return TRUE;
360 361 362
}


363
static BOOL ExportRegistryFile(HWND hWnd)
364
{
365 366 367
    OPENFILENAMEW ofn;
    WCHAR ExportKeyPath[_MAX_PATH];
    WCHAR title[128];
368

369
    ExportKeyPath[0] = 0;
370
    InitOpenFileName(hWnd, &ofn);
371
    LoadStringW(hInst, IDS_FILEDIALOG_EXPORT_TITLE, title, COUNT_OF(title));
372
    ofn.lpstrTitle = title;
373
    ofn.Flags = OFN_ENABLETEMPLATE | OFN_ENABLEHOOK | OFN_EXPLORER | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
374
    ofn.lpfnHook = ExportRegistryFile_OFNHookProc;
375 376
    ofn.lpTemplateName = MAKEINTRESOURCEW(IDD_EXPORT_TEMPLATE);
    if (GetSaveFileNameW(&ofn)) {
377
        BOOL result;
378
        result = export_registry_key(ofn.lpstrFile, (LPWSTR)ofn.lCustData, ofn.nFilterIndex);
379 380 381 382 383 384 385
        if (!result) {
            /*printf("Can't open file \"%s\"\n", ofn.lpstrFile);*/
            return FALSE;
        }
    } else {
        CheckCommDlgError(hWnd);
    }
386
    return TRUE;
387 388
}

389
static BOOL PrintRegistryHive(HWND hWnd, LPCWSTR path)
390 391
{
#if 1
392
    PRINTDLGW pd;
393 394 395 396 397 398 399 400 401 402 403 404

    ZeroMemory(&pd, sizeof(PRINTDLG));
    pd.lStructSize = sizeof(PRINTDLG);
    pd.hwndOwner   = hWnd;
    pd.hDevMode    = NULL;     /* Don't forget to free or store hDevMode*/
    pd.hDevNames   = NULL;     /* Don't forget to free or store hDevNames*/
    pd.Flags       = PD_USEDEVMODECOPIESANDCOLLATE | PD_RETURNDC;
    pd.nCopies     = 1;
    pd.nFromPage   = 0xFFFF;
    pd.nToPage     = 0xFFFF;
    pd.nMinPage    = 1;
    pd.nMaxPage    = 0xFFFF;
405
    if (PrintDlgW(&pd)) {
406 407 408 409 410
        /* GDI calls to render output. */
        DeleteDC(pd.hDC); /* Delete DC when done.*/
    }
#else
    HRESULT hResult;
411
    PRINTDLGEXW pd;
412

413
    hResult = PrintDlgExW(&pd);
414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453
    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;
        case PD_RESULT_CANCEL:
            /*The user clicked the Cancel button. The information in the PRINTDLGEX structure is unchanged. */
            break;
        case PD_RESULT_PRINT:
            /*The user clicked the Print button. The PRINTDLGEX structure contains the information specified by the user. */
            break;
        default:
            break;
        }
    } else {
        switch (hResult) {
        case E_OUTOFMEMORY:
            /*Insufficient memory. */
            break;
        case E_INVALIDARG:
            /* One or more arguments are invalid. */
            break;
        case E_POINTER:
            /*Invalid pointer. */
            break;
        case E_HANDLE:
            /*Invalid handle. */
            break;
        case E_FAIL:
            /*Unspecified error. */
            break;
        default:
            break;
        }
        return FALSE;
    }
#endif
    return TRUE;
}

454
static BOOL CopyKeyName(HWND hWnd, LPCWSTR keyName)
455 456 457 458 459 460 461
{
    BOOL result;

    result = OpenClipboard(hWnd);
    if (result) {
        result = EmptyClipboard();
        if (result) {
462
            int len = (lstrlenW(keyName)+1)*sizeof(WCHAR);
463 464
            HANDLE hClipData = GlobalAlloc(GHND, len);
            LPVOID pLoc = GlobalLock(hClipData);
465
            lstrcpyW(pLoc, keyName);
466
            GlobalUnlock(hClipData);
467
            hClipData = SetClipboardData(CF_UNICODETEXT, hClipData);
468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486

        } else {
            /* error emptying clipboard*/
            /* DWORD dwError = GetLastError(); */
            ;
        }
        if (!CloseClipboard()) {
            /* error closing clipboard*/
            /* DWORD dwError = GetLastError(); */
            ;
        }
    } else {
        /* error opening clipboard*/
        /* DWORD dwError = GetLastError(); */
        ;
    }
    return result;
}

487 488 489 490 491 492 493 494 495 496 497
static INT_PTR CALLBACK find_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    HWND hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_NAME);
            
    switch(uMsg) {
        case WM_INITDIALOG:
            EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
            CheckDlgButton(hwndDlg, IDC_FIND_KEYS, searchMask&SEARCH_KEYS ? BST_CHECKED : BST_UNCHECKED);
            CheckDlgButton(hwndDlg, IDC_FIND_VALUES, searchMask&SEARCH_VALUES ? BST_CHECKED : BST_UNCHECKED);
            CheckDlgButton(hwndDlg, IDC_FIND_CONTENT, searchMask&SEARCH_CONTENT ? BST_CHECKED : BST_UNCHECKED);
            CheckDlgButton(hwndDlg, IDC_FIND_WHOLE, searchMask&SEARCH_WHOLE ? BST_CHECKED : BST_UNCHECKED);
498 499
            SendMessageW(hwndValue, EM_SETLIMITTEXT, 127, 0);
            SetWindowTextW(hwndValue, searchString);
500 501 502 503 504
            return TRUE;
        case WM_COMMAND:
            switch(LOWORD(wParam)) {
            case IDC_VALUE_NAME:
                if (HIWORD(wParam) == EN_UPDATE) {
505
                    EnableWindow(GetDlgItem(hwndDlg, IDOK),  GetWindowTextLengthW(hwndValue)>0);
506 507 508 509
                    return TRUE;
                }
                break;
            case IDOK:
510
                if (GetWindowTextLengthW(hwndValue)>0) {
511 512 513 514 515 516
                    int mask = 0;
                    if (IsDlgButtonChecked(hwndDlg, IDC_FIND_KEYS)) mask |= SEARCH_KEYS;
                    if (IsDlgButtonChecked(hwndDlg, IDC_FIND_VALUES)) mask |= SEARCH_VALUES;
                    if (IsDlgButtonChecked(hwndDlg, IDC_FIND_CONTENT)) mask |= SEARCH_CONTENT;
                    if (IsDlgButtonChecked(hwndDlg, IDC_FIND_WHOLE)) mask |= SEARCH_WHOLE;
                    searchMask = mask;
517
                    GetWindowTextW(hwndValue, searchString, 128);
518 519 520 521 522 523 524 525 526 527 528 529
                    EndDialog(hwndDlg, IDOK);
                }
                return TRUE;
            case IDCANCEL:
                EndDialog(hwndDlg, IDCANCEL);
                return TRUE;
            }
            break;
    }
    return FALSE;
}
                    
530 531 532 533 534 535
static INT_PTR CALLBACK addtofavorites_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    HWND hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_NAME);
            
    switch(uMsg) {
        case WM_INITDIALOG:
536 537
        {
            HKEY hKeyRoot = NULL;
538
            LPWSTR ItemPath = GetItemPath(g_pChildWnd->hTreeWnd, NULL, &hKeyRoot);
539 540

            if(!ItemPath || !*ItemPath)
541
                ItemPath = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, FALSE);
542
            EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
543 544
            SetWindowTextW(hwndValue, ItemPath);
            SendMessageW(hwndValue, EM_SETLIMITTEXT, 127, 0);
545
            HeapFree(GetProcessHeap(), 0, ItemPath);
546
            return TRUE;
547
        }
548 549 550 551 552 553 554 555 556
        case WM_COMMAND:
            switch(LOWORD(wParam)) {
            case IDC_VALUE_NAME:
                if (HIWORD(wParam) == EN_UPDATE) {
                    EnableWindow(GetDlgItem(hwndDlg, IDOK),  GetWindowTextLength(hwndValue)>0);
                    return TRUE;
                }
                break;
            case IDOK:
557 558
                if (GetWindowTextLengthW(hwndValue)>0) {
                    GetWindowTextW(hwndValue, favoriteName, 128);
559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579
                    EndDialog(hwndDlg, IDOK);
                }
                return TRUE;
            case IDCANCEL:
                EndDialog(hwndDlg, IDCANCEL);
                return TRUE;
            }
            break;
    }
    return FALSE;
}
                    
static INT_PTR CALLBACK removefavorite_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    HWND hwndList = GetDlgItem(hwndDlg, IDC_NAME_LIST);
            
    switch(uMsg) {
        case WM_INITDIALOG: {
            HKEY hKey;
            int i = 0;
            EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
580
            if (RegOpenKeyExW(HKEY_CURRENT_USER, favoritesKey,
581
                0, KEY_READ, &hKey) == ERROR_SUCCESS) {
582
                WCHAR namebuf[KEY_MAX_LEN];
583 584 585 586 587 588
                BYTE valuebuf[4096];
                DWORD ksize, vsize, type;
                LONG error;
                do {
                    ksize = KEY_MAX_LEN;
                    vsize = sizeof(valuebuf);
589
                    error = RegEnumValueW(hKey, i, namebuf, &ksize, NULL, &type, valuebuf, &vsize);
590 591 592
                    if (error != ERROR_SUCCESS)
                        break;
                    if (type == REG_SZ) {
593
                        SendMessageW(hwndList, LB_ADDSTRING, 0, (LPARAM)namebuf);
594 595 596 597 598 599 600 601
                    }
                    i++;
                } while(error == ERROR_SUCCESS);
                RegCloseKey(hKey);
            }
            else
                return FALSE;
            EnableWindow(GetDlgItem(hwndDlg, IDOK), i != 0);
602
            SendMessageW(hwndList, LB_SETCURSEL, 0, 0);
603 604 605 606 607 608 609 610 611 612 613
            return TRUE;
        }
        case WM_COMMAND:
            switch(LOWORD(wParam)) {
            case IDC_NAME_LIST:
                if (HIWORD(wParam) == LBN_SELCHANGE) {
                    EnableWindow(GetDlgItem(hwndDlg, IDOK),  lParam != -1);
                    return TRUE;
                }
                break;
            case IDOK: {
614 615
                int pos = SendMessageW(hwndList, LB_GETCURSEL, 0, 0);
                int len = SendMessageW(hwndList, LB_GETTEXTLEN, pos, 0);
616
                if (len>0) {
617 618
                    LPWSTR lpName = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*(len+1));
                    SendMessageW(hwndList, LB_GETTEXT, pos, (LPARAM)lpName);
619 620
                    if (len>127)
                        lpName[127] = '\0';
621
                    lstrcpyW(favoriteName, lpName);
622 623 624 625 626 627 628 629 630 631 632 633 634 635
                    EndDialog(hwndDlg, IDOK);
                    HeapFree(GetProcessHeap(), 0, lpName);
                }
                return TRUE;
            }
            case IDCANCEL:
                EndDialog(hwndDlg, IDCANCEL);
                return TRUE;
            }
            break;
    }
    return FALSE;
}
                    
636 637 638 639 640 641 642 643 644
/*******************************************************************************
 *
 *  FUNCTION: _CmdWndProc(HWND, unsigned, WORD, LONG)
 *
 *  PURPOSE:  Processes WM_COMMAND messages for the main frame window.
 *
 */
static BOOL _CmdWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
645
    HKEY hKeyRoot = 0;
646
    DWORD valueType;
647 648
    int curIndex;
    BOOL firstItem = TRUE;
649

650 651
    if (LOWORD(wParam) >= ID_FAVORITE_FIRST && LOWORD(wParam) <= ID_FAVORITE_LAST) {
        HKEY hKey;
652
        if (RegOpenKeyExW(HKEY_CURRENT_USER, favoritesKey,
653
            0, KEY_READ, &hKey) == ERROR_SUCCESS) {
654
            WCHAR namebuf[KEY_MAX_LEN];
655 656
            BYTE valuebuf[4096];
            DWORD ksize = KEY_MAX_LEN, vsize = sizeof(valuebuf), type = 0;
657
            if (RegEnumValueW(hKey, LOWORD(wParam) - ID_FAVORITE_FIRST, namebuf, &ksize, NULL,
658
                &type, valuebuf, &vsize) == ERROR_SUCCESS) {
659 660
                SendMessageW( g_pChildWnd->hTreeWnd, TVM_SELECTITEM, TVGN_CARET,
                             (LPARAM) FindPathInTree(g_pChildWnd->hTreeWnd, (WCHAR *)valuebuf) );
661 662 663 664 665
            }
            RegCloseKey(hKey);
        }
        return TRUE;
    }
666
    switch (LOWORD(wParam)) {
667 668 669
    case ID_REGISTRY_IMPORTREGISTRYFILE:
        ImportRegistryFile(hWnd);
        break;
670
    case ID_EDIT_EXPORT:
671
    case ID_REGISTRY_EXPORTREGISTRYFILE:
672
        ExportRegistryFile(hWnd);
673 674 675 676 677 678
        break;
    case ID_REGISTRY_CONNECTNETWORKREGISTRY:
        break;
    case ID_REGISTRY_DISCONNECTNETWORKREGISTRY:
        break;
    case ID_REGISTRY_PRINT:
679 680
    {
        const WCHAR empty = 0;
681
        PrintRegistryHive(hWnd, &empty);
682
        break;
683
    }
684
    case ID_EDIT_DELETE:
685 686 687
    {
        HWND hWndDelete = GetFocus();
        if (hWndDelete == g_pChildWnd->hTreeWnd) {
688
	    WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
689
	    if (keyPath == 0 || *keyPath == 0) {
690 691
	        MessageBeep(MB_ICONHAND);
            } else if (DeleteKey(hWnd, hKeyRoot, keyPath)) {
692
		DeleteNode(g_pChildWnd->hTreeWnd, 0);
693
            }
694
            HeapFree(GetProcessHeap(), 0, keyPath);
695
        } else if (hWndDelete == g_pChildWnd->hListWnd) {
696
        WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
697 698
        curIndex = ListView_GetNextItem(g_pChildWnd->hListWnd, -1, LVNI_SELECTED);
        while(curIndex != -1) {
699
            WCHAR* valueName = GetItemText(g_pChildWnd->hListWnd, curIndex);
700

701 702
            curIndex = ListView_GetNextItem(g_pChildWnd->hListWnd, curIndex, LVNI_SELECTED);
            if(curIndex != -1 && firstItem) {
703 704 705
                if (MessageBoxW(hWnd, MAKEINTRESOURCEW(IDS_DELETE_BOX_TEXT_MULTIPLE),
                                MAKEINTRESOURCEW(IDS_DELETE_BOX_TITLE),
                                MB_YESNO | MB_ICONEXCLAMATION) != IDYES)
706 707
                    break;
            }
708 709

            if (!DeleteValue(hWnd, hKeyRoot, keyPath, valueName, curIndex==-1 && firstItem))
710
            {
711
                HeapFree(GetProcessHeap(), 0, valueName);
712
                break;
713
            }
714
            firstItem = FALSE;
715
            HeapFree(GetProcessHeap(), 0, valueName);
716
        }
717 718
        RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, NULL);
        HeapFree(GetProcessHeap(), 0, keyPath);
719 720 721 722
        } else if (IsChild(g_pChildWnd->hTreeWnd, hWndDelete) ||
                   IsChild(g_pChildWnd->hListWnd, hWndDelete)) {
            SendMessage(hWndDelete, WM_KEYDOWN, VK_DELETE, 0);
        }
723
        break;
724
    }
725
    case ID_EDIT_MODIFY:
726
    {
727
        LPCWSTR valueName = GetValueName(g_pChildWnd->hListWnd);
728
        WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
729 730 731
        if (ModifyValue(hWnd, hKeyRoot, keyPath, valueName))
            RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, valueName);
        HeapFree(GetProcessHeap(), 0, keyPath);
732
        break;
733
    }
734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749
    case ID_EDIT_FIND:
    case ID_EDIT_FINDNEXT:
    {
        HTREEITEM hItem;
        if (LOWORD(wParam) == ID_EDIT_FIND &&
            DialogBox(0, MAKEINTRESOURCE(IDD_FIND), hWnd, find_dlgproc) != IDOK)
            break;
        if (!*searchString)
            break;
        hItem = TreeView_GetSelection(g_pChildWnd->hTreeWnd);
        if (hItem) {
            int row = ListView_GetNextItem(g_pChildWnd->hListWnd, -1, LVNI_FOCUSED);
            HCURSOR hcursorOld = SetCursor(LoadCursor(NULL, IDC_WAIT));
            hItem = FindNext(g_pChildWnd->hTreeWnd, hItem, searchString, searchMask, &row);
            SetCursor(hcursorOld);
            if (hItem) {
750
                SendMessageW( g_pChildWnd->hTreeWnd, TVM_SELECTITEM, TVGN_CARET, (LPARAM) hItem );
751 752 753 754 755 756 757 758 759 760
                InvalidateRect(g_pChildWnd->hTreeWnd, NULL, TRUE);
                UpdateWindow(g_pChildWnd->hTreeWnd);
                if (row != -1) {
                    ListView_SetItemState(g_pChildWnd->hListWnd, -1, 0, LVIS_FOCUSED|LVIS_SELECTED);
                    ListView_SetItemState(g_pChildWnd->hListWnd, row, LVIS_FOCUSED|LVIS_SELECTED, LVIS_FOCUSED|LVIS_SELECTED);
                    SetFocus(g_pChildWnd->hListWnd);
                } else {
                    SetFocus(g_pChildWnd->hTreeWnd);
                }
            } else {
761
                error(hWnd, IDS_NOTFOUND, searchString);
762 763 764 765
            }
        }
        break;
    }
766
    case ID_EDIT_COPYKEYNAME:
767
    {
768
        LPWSTR fullPath = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, FALSE);
769 770 771 772
        if (fullPath) {
            CopyKeyName(hWnd, fullPath);
            HeapFree(GetProcessHeap(), 0, fullPath);
        }
773
        break;
774
    }
775
    case ID_EDIT_NEW_KEY:
776 777
    {
        WCHAR newKeyW[MAX_NEW_KEY_LEN];
778
        WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
779
        if (CreateKey(hWnd, hKeyRoot, keyPath, newKeyW)) {
780 781 782
            if (InsertNode(g_pChildWnd->hTreeWnd, 0, newKeyW))
                StartKeyRename(g_pChildWnd->hTreeWnd);
        }
783
        HeapFree(GetProcessHeap(), 0, keyPath);
784
    }
785
	break;
786 787 788
    case ID_EDIT_NEW_STRINGVALUE:
	valueType = REG_SZ;
	goto create_value;
789 790 791
    case ID_EDIT_NEW_MULTI_STRINGVALUE:
	valueType = REG_MULTI_SZ;
	goto create_value;
792 793 794 795 796 797 798
    case ID_EDIT_NEW_BINARYVALUE:
	valueType = REG_BINARY;
	goto create_value;
    case ID_EDIT_NEW_DWORDVALUE:
	valueType = REG_DWORD;
	/* fall through */
    create_value:
799
    {
800
        WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
801 802 803
        WCHAR newKey[MAX_NEW_KEY_LEN];
        if (CreateValue(hWnd, hKeyRoot, keyPath, valueType, newKey)) {
            RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, newKey);
804
            StartValueRename(g_pChildWnd->hListWnd);
805 806 807
        }
        HeapFree(GetProcessHeap(), 0, keyPath);
    }
808
	break;
809
    case ID_EDIT_RENAME:
810
    {
811
        WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
812 813 814 815 816 817 818 819 820
        if (keyPath == 0 || *keyPath == 0) {
            MessageBeep(MB_ICONHAND);
        } else if (GetFocus() == g_pChildWnd->hTreeWnd) {
            StartKeyRename(g_pChildWnd->hTreeWnd);
        } else if (GetFocus() == g_pChildWnd->hListWnd) {
            StartValueRename(g_pChildWnd->hListWnd);
        }
        HeapFree(GetProcessHeap(), 0, keyPath);
    }
821
	break;
822 823 824 825 826 827 828 829 830 831 832
    case ID_REGISTRY_PRINTERSETUP:
        /*PRINTDLG pd;*/
        /*PrintDlg(&pd);*/
        /*PAGESETUPDLG psd;*/
        /*PageSetupDlg(&psd);*/
        break;
    case ID_REGISTRY_OPENLOCAL:
        break;
    case ID_REGISTRY_EXIT:
        DestroyWindow(hWnd);
        break;
833 834 835
    case ID_FAVORITES_ADDTOFAVORITES:
    {
    	HKEY hKey;
836
	LPWSTR lpKeyPath = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, FALSE);
837 838
    	if (lpKeyPath) {
            if (DialogBox(0, MAKEINTRESOURCE(IDD_ADDFAVORITE), hWnd, addtofavorites_dlgproc) == IDOK) {
839
                if (RegCreateKeyExW(HKEY_CURRENT_USER, favoritesKey,
840 841
                    0, NULL, 0, 
                    KEY_READ|KEY_WRITE, NULL, &hKey, NULL) == ERROR_SUCCESS) {
842
                    RegSetValueExW(hKey, favoriteName, 0, REG_SZ, (BYTE *)lpKeyPath, (lstrlenW(lpKeyPath)+1)*sizeof(WCHAR));
843 844 845 846 847 848 849 850 851 852 853
                    RegCloseKey(hKey);
                }
            }
            HeapFree(GetProcessHeap(), 0, lpKeyPath);
        }
        break;
    }
    case ID_FAVORITES_REMOVEFAVORITE:
    {
        if (DialogBox(0, MAKEINTRESOURCE(IDD_DELFAVORITE), hWnd, removefavorite_dlgproc) == IDOK) {
            HKEY hKey;
854
            if (RegOpenKeyExW(HKEY_CURRENT_USER, favoritesKey,
855
                0, KEY_READ|KEY_WRITE, &hKey) == ERROR_SUCCESS) {
856
                RegDeleteValueW(hKey, favoriteName);
857 858 859 860 861
                RegCloseKey(hKey);
            }
        }
        break;
    }
862
    case ID_VIEW_REFRESH:
863
    {
864
        WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
Crestez Leonard's avatar
Crestez Leonard committed
865
        RefreshTreeView(g_pChildWnd->hTreeWnd);
866 867
        RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, NULL);
        HeapFree(GetProcessHeap(), 0, keyPath);
868
    }
869
        break;
870 871 872
   /*case ID_OPTIONS_TOOLBAR:*/
   /*	toggle_child(hWnd, LOWORD(wParam), hToolBar);*/
   /*    break;*/
873 874
    case ID_VIEW_STATUSBAR:
        toggle_child(hWnd, LOWORD(wParam), hStatusBar);
875 876
        break;
    case ID_HELP_HELPTOPICS:
877 878 879
    {
        const WCHAR help_regedit[] = {'r','e','g','e','d','i','t',0};
        WinHelpW(hWnd, help_regedit, HELP_FINDER, 0);
880
        break;
881
    }
882 883 884
    case ID_HELP_ABOUT:
        ShowAboutBox(hWnd);
        break;
885 886 887 888 889 890 891 892 893 894
    case ID_VIEW_SPLIT: {
        RECT rt;
        POINT pt, pts;
        GetClientRect(g_pChildWnd->hWnd, &rt);
        pt.x = rt.left + g_pChildWnd->nSplitPos;
        pt.y = (rt.bottom / 2);
        pts = pt;
        if(ClientToScreen(g_pChildWnd->hWnd, &pts)) {
            SetCursorPos(pts.x, pts.y);
            SetCursor(LoadCursor(0, IDC_SIZEWE));
895
            SendMessageW(g_pChildWnd->hWnd, WM_LBUTTONDOWN, 0, MAKELPARAM(pt.x, pt.y));
896 897 898
        }
        return TRUE;
    }
899
    default:
900
        return FALSE;
901 902
    }

903
    return TRUE;
904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919
}

/********************************************************************************
 *
 *  FUNCTION: FrameWndProc(HWND, unsigned, WORD, LONG)
 *
 *  PURPOSE:  Processes messages for the main frame window.
 *
 *  WM_COMMAND  - process the application menu
 *  WM_DESTROY  - post a quit message and return
 *
 */

LRESULT CALLBACK FrameWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message) {
920 921 922
    case WM_CREATE:
        CreateWindowEx(0, szChildClass, _T("regedit child window"), WS_CHILD | WS_VISIBLE,
                       CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
923
                       hWnd, NULL, hInst, 0);
924 925
        break;
    case WM_COMMAND:
926
        if (!_CmdWndProc(hWnd, message, wParam, lParam))
927 928
            return DefWindowProc(hWnd, message, wParam, lParam);
        break;
929 930 931 932
    case WM_ACTIVATE:
        if (LOWORD(hWnd)) 
            SetFocus(g_pChildWnd->hWnd);
        break;
933 934 935 936 937 938 939 940 941 942 943
    case WM_SIZE:
        resize_frame_client(hWnd);
        break;
    case WM_TIMER:
        break;
    case WM_ENTERMENULOOP:
        OnEnterMenuLoop(hWnd);
        break;
    case WM_EXITMENULOOP:
        OnExitMenuLoop(hWnd);
        break;
944 945 946 947
    case WM_INITMENUPOPUP:
        if (!HIWORD(lParam))
            OnInitMenuPopup(hWnd, (HMENU)wParam, LOWORD(lParam));
        break;
948 949 950 951
    case WM_MENUSELECT:
        OnMenuSelect(hWnd, LOWORD(wParam), HIWORD(wParam), (HMENU)lParam);
        break;
    case WM_DESTROY:
952 953 954
    {
        const WCHAR help_regedit[] = {'r','e','g','e','d','i','t',0};
        WinHelpW(hWnd, help_regedit, HELP_QUIT, 0);
955
        PostQuitMessage(0);
956
    }
957 958
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
959 960
    }
    return 0;
961
}