framewnd.c 36.2 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
 */

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

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

#include "main.h"
31
#include "wine/debug.h"
32
#include "wine/heap.h"
33

34 35
WINE_DEFAULT_DEBUG_CHANNEL(regedit);

36 37 38 39
/********************************************************************************
 * Global and Local Variables:
 */

40
static const 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
static WCHAR expandW[32], collapseW[32];
50
static WCHAR modifyW[32], modify_binaryW[64];
51

52 53 54 55 56 57
/*******************************************************************************
 * Local module support methods
 */

static void resize_frame_rect(HWND hWnd, PRECT prect)
{
58
    if (IsWindowVisible(hStatusBar)) {
59 60
        RECT rt;

61 62 63 64
        SetupStatusBar(hWnd, TRUE);
        GetClientRect(hStatusBar, &rt);
        prect->bottom -= rt.bottom;
    }
65
    MoveWindow(g_pChildWnd->hWnd, prect->left, prect->top, prect->right, prect->bottom, TRUE);
66 67
}

68
static void resize_frame_client(HWND hWnd)
69
{
70
    RECT rect;
71

72 73
    GetClientRect(hWnd, &rect);
    resize_frame_rect(hWnd, &rect);
74 75 76 77 78 79 80
}

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

static void OnEnterMenuLoop(HWND hWnd)
{
    int nParts;
81
    WCHAR empty = 0;
82 83 84

    /* Update the status bar pane sizes */
    nParts = -1;
85
    SendMessageW(hStatusBar, SB_SETPARTS, 1, (LPARAM)&nParts);
86
    bInMenuLoop = TRUE;
87
    SendMessageW(hStatusBar, SB_SETTEXTW, 0, (LPARAM)&empty);
88 89 90 91 92 93
}

static void OnExitMenuLoop(HWND hWnd)
{
    bInMenuLoop = FALSE;
    /* Update the status bar pane sizes*/
94 95
    SetupStatusBar(hWnd, TRUE);
    UpdateStatusBar();
96 97
}

98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
static void update_expand_or_collapse_item(HWND hwndTV, HTREEITEM selection, HMENU hMenu)
{
    TVITEMW item;
    MENUITEMINFOW info;

    item.hItem = selection;
    item.mask = TVIF_CHILDREN | TVIF_HANDLE | TVIF_STATE;
    item.stateMask = TVIS_EXPANDED;
    SendMessageW(hwndTV, TVM_GETITEMW, 0, (LPARAM)&item);

    info.cbSize = sizeof(MENUITEMINFOW);
    info.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_STATE;
    info.fType = MFT_STRING;
    info.fState = MFS_ENABLED;
    info.dwTypeData = expandW;

    if (!item.cChildren)
    {
        info.fState = MFS_GRAYED;
        goto update;
    }

    if (item.state & TVIS_EXPANDED)
        info.dwTypeData = collapseW;

update:
    SetMenuItemInfoW(hMenu, ID_TREE_EXPAND_COLLAPSE, FALSE, &info);
}

127 128 129 130
static void update_modify_items(HMENU hMenu, int index)
{
    unsigned int state = MF_ENABLED;

131
    if (index == -1)
132 133 134
        state = MF_GRAYED;

    EnableMenuItem(hMenu, ID_EDIT_MODIFY, state | MF_BYCOMMAND);
135
    EnableMenuItem(hMenu, ID_EDIT_MODIFY_BIN, state | MF_BYCOMMAND);
136 137 138
}

static void update_delete_and_rename_items(HMENU hMenu, WCHAR *keyName, int index)
139
{
140
    unsigned int state_d = MF_ENABLED, state_r = MF_ENABLED;
141 142 143 144

    if (!g_pChildWnd->nFocusPanel)
    {
        if (!keyName || !*keyName)
145
            state_d = state_r = MF_GRAYED;
146
    }
147
    else if (index < 1)
148
    {
149
        state_r = MF_GRAYED;
150
        if (index == -1) state_d = MF_GRAYED;
151 152
    }

153 154
    EnableMenuItem(hMenu, ID_EDIT_DELETE, state_d | MF_BYCOMMAND);
    EnableMenuItem(hMenu, ID_EDIT_RENAME, state_r | MF_BYCOMMAND);
155 156
}

157
static void update_new_items_and_copy_keyname(HMENU hMenu, WCHAR *keyName)
158
{
159 160 161 162
    unsigned int state = MF_ENABLED, i;
    unsigned int items[] = {ID_EDIT_NEW_KEY, ID_EDIT_NEW_STRINGVALUE, ID_EDIT_NEW_BINARYVALUE,
                            ID_EDIT_NEW_DWORDVALUE, ID_EDIT_NEW_MULTI_STRINGVALUE,
                            ID_EDIT_NEW_EXPANDVALUE, ID_EDIT_COPYKEYNAME};
163

164
    if (!keyName)
165 166
        state = MF_GRAYED;

167
    for (i = 0; i < ARRAY_SIZE(items); i++)
168
        EnableMenuItem(hMenu, items[i], state | MF_BYCOMMAND);
169 170
}

171 172 173
static void UpdateMenuItems(HMENU hMenu) {
    HWND hwndTV = g_pChildWnd->hTreeWnd;
    HKEY hRootKey = NULL;
174
    LPWSTR keyName;
175
    HTREEITEM selection;
176
    int index;
177 178 179

    selection = (HTREEITEM)SendMessageW(hwndTV, TVM_GETNEXTITEM, TVGN_CARET, 0);
    keyName = GetItemPath(hwndTV, selection, &hRootKey);
180
    index = SendMessageW(g_pChildWnd->hListWnd, LVM_GETNEXTITEM, -1,
181
                         MAKELPARAM(LVNI_FOCUSED | LVNI_SELECTED, 0));
182 183

    update_expand_or_collapse_item(hwndTV, selection, hMenu);
184 185
    update_modify_items(hMenu, index);
    update_delete_and_rename_items(hMenu, keyName, index);
186
    update_new_items_and_copy_keyname(hMenu, keyName);
187 188 189
    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);
190

191
    heap_free(keyName);
192 193
}

194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
static void add_remove_modify_menu_items(HMENU hMenu)
{
    if (!g_pChildWnd->nFocusPanel)
    {
        while (GetMenuItemCount(hMenu) > 9)
            DeleteMenu(hMenu, 0, MF_BYPOSITION);
    }
    else if (GetMenuItemCount(hMenu) < 10)
    {
        InsertMenuW(hMenu, 0, MF_BYPOSITION | MF_SEPARATOR, 0, 0);
        InsertMenuW(hMenu, 0, MF_BYPOSITION | MF_STRING, ID_EDIT_MODIFY_BIN, modify_binaryW);
        InsertMenuW(hMenu, 0, MF_BYPOSITION | MF_STRING, ID_EDIT_MODIFY, modifyW);
    }
}

209
static int add_favourite_key_items(HMENU hMenu, HWND hList)
210
{
211 212
    HKEY hkey;
    LONG rc;
213
    DWORD num_values, max_value_len, value_len, type, i = 0;
214 215 216
    WCHAR *value_name;

    rc = RegOpenKeyExW(HKEY_CURRENT_USER, favoritesKey, 0, KEY_READ, &hkey);
217
    if (rc != ERROR_SUCCESS) return 0;
218 219 220 221 222 223 224 225 226 227 228 229

    rc = RegQueryInfoKeyW(hkey, NULL, NULL, NULL, NULL, NULL, NULL, &num_values,
                          &max_value_len, NULL, NULL, NULL);
    if (rc != ERROR_SUCCESS)
    {
        ERR("RegQueryInfoKey failed: %d\n", rc);
        goto exit;
    }

    if (!num_values) goto exit;

    max_value_len++;
230
    value_name = heap_xalloc(max_value_len * sizeof(WCHAR));
231

232
    if (hMenu) AppendMenuW(hMenu, MF_SEPARATOR, 0, 0);
233 234 235 236 237 238

    for (i = 0; i < num_values; i++)
    {
        value_len = max_value_len;
        rc = RegEnumValueW(hkey, i, value_name, &value_len, NULL, &type, NULL, NULL);
        if (rc == ERROR_SUCCESS && type == REG_SZ)
239 240 241 242 243 244
        {
            if (hMenu)
                AppendMenuW(hMenu, MF_ENABLED | MF_STRING, ID_FAVORITE_FIRST + i, value_name);
            else if (hList)
                SendMessageW(hList, LB_ADDSTRING, 0, (LPARAM)value_name);
        }
245 246
    }

247
    heap_free(value_name);
248 249
exit:
    RegCloseKey(hkey);
250
    return i;
251 252 253 254
}

static void OnInitMenuPopup(HWND hWnd, HMENU hMenu)
{
255 256 257
    if (hMenu == GetSubMenu(hMenuFrame, ID_EDIT_MENU))
        add_remove_modify_menu_items(hMenu);
    else if (hMenu == GetSubMenu(hMenuFrame, ID_FAVORITES_MENU))
258 259
    {
        while (GetMenuItemCount(hMenu) > 2)
260
            DeleteMenu(hMenu, 2, MF_BYPOSITION);
261

262
        add_favourite_key_items(hMenu, NULL);
263
    }
264

265 266 267
    UpdateMenuItems(hMenu);
}

268 269
static void OnMenuSelect(HWND hWnd, UINT nItemID, UINT nFlags, HMENU hSysMenu)
{
270
    WCHAR str[100];
271

272
    str[0] = 0;
273 274 275 276 277
    if (nFlags & MF_POPUP) {
        if (hSysMenu != GetMenu(hWnd)) {
            if (nItemID == 2) nItemID = 5;
        }
    }
278
    if (LoadStringW(hInst, nItemID, str, 100)) {
279
        /* load appropriate string*/
280
        LPWSTR lpsz = str;
281
        /* first newline terminates actual string*/
282
        lpsz = wcschr(lpsz, '\n');
283 284 285
        if (lpsz != NULL)
            *lpsz = '\0';
    }
286
    SendMessageW(hStatusBar, SB_SETTEXTW, 0, (LPARAM)str);
287 288 289 290 291 292 293 294
}

void SetupStatusBar(HWND hWnd, BOOL bResize)
{
    RECT  rc;
    int nParts;
    GetClientRect(hWnd, &rc);
    nParts = rc.right;
295 296
    /*    nParts = -1;*/
    if (bResize)
297 298
        SendMessageW(hStatusBar, WM_SIZE, 0, 0);
    SendMessageW(hStatusBar, SB_SETPARTS, 1, (LPARAM)&nParts);
299
    UpdateStatusBar();
300 301 302 303
}

void UpdateStatusBar(void)
{
304
    LPWSTR fullPath = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, TRUE);
305
    SendMessageW(hStatusBar, SB_SETTEXTW, 0, (LPARAM)fullPath);
306
    heap_free(fullPath);
307 308 309 310
}

static void toggle_child(HWND hWnd, UINT cmd, HWND hchild)
{
311 312
    BOOL vis = IsWindowVisible(hchild);
    HMENU hMenuView = GetSubMenu(hMenuFrame, ID_VIEW_MENU);
313

314 315 316
    CheckMenuItem(hMenuView, cmd, vis?MF_BYCOMMAND:MF_BYCOMMAND|MF_CHECKED);
    ShowWindow(hchild, vis?SW_HIDE:SW_SHOW);
    resize_frame_client(hWnd);
317 318 319 320
}

static BOOL CheckCommDlgError(HWND hWnd)
{
321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356
    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;
357 358
}

359
static void ExportRegistryFile_StoreSelection(HWND hdlg, OPENFILENAMEW *pOpenFileName)
360 361 362
{
    if (IsDlgButtonChecked(hdlg, IDC_EXPORT_SELECTED))
    {
363
        INT len = SendDlgItemMessageW(hdlg, IDC_EXPORT_PATH, WM_GETTEXTLENGTH, 0, 0);
364
        pOpenFileName->lCustData = (LPARAM)heap_xalloc((len + 1) * sizeof(WCHAR));
365
        SendDlgItemMessageW(hdlg, IDC_EXPORT_PATH, WM_GETTEXT, len+1, pOpenFileName->lCustData);
366 367
    }
    else
368 369 370 371
    {
        pOpenFileName->lCustData = (LPARAM)heap_xalloc(sizeof(WCHAR));
        *(WCHAR *)pOpenFileName->lCustData = 0;
    }
372 373
}

374
static UINT_PTR CALLBACK ExportRegistryFile_OFNHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
375
{
376 377
    static OPENFILENAMEW* pOpenFileName;
    OFNOTIFYW *pOfNotify;
378 379 380

    switch (uiMsg) {
    case WM_INITDIALOG:
381
        pOpenFileName = (OPENFILENAMEW*)lParam;
382
        break;
383 384 385 386
    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;
387
    case WM_NOTIFY:
388
        pOfNotify = (OFNOTIFYW*)lParam;
389 390 391
        switch (pOfNotify->hdr.code)
        {
            case CDN_INITDONE:
392
            {
393
                BOOL export_branch = FALSE;
394 395
                WCHAR* path = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, FALSE);
                SendDlgItemMessageW(hdlg, IDC_EXPORT_PATH, WM_SETTEXT, 0, (LPARAM)path);
396
                if (path && path[0])
397
                    export_branch = TRUE;
398
                heap_free(path);
399
                CheckRadioButton(hdlg, IDC_EXPORT_ALL, IDC_EXPORT_SELECTED, export_branch ? IDC_EXPORT_SELECTED : IDC_EXPORT_ALL);
400
                break;
401
            }
402 403 404 405
            case CDN_FILEOK:
                ExportRegistryFile_StoreSelection(hdlg, pOpenFileName);
                break;
        }
406 407 408 409 410 411 412 413
        break;
    default:
        break;
    }
    return 0L;
}


414
static BOOL InitOpenFileName(HWND hWnd, OPENFILENAMEW *pofn)
415
{
416 417
    memset(pofn, 0, sizeof(OPENFILENAMEW));
    pofn->lStructSize = sizeof(OPENFILENAMEW);
418 419 420
    pofn->hwndOwner = hWnd;
    pofn->hInstance = hInst;

421
    if (FilterBuffer[0] == 0)
422 423 424 425 426 427 428
    {
        static const WCHAR filterW[] = {'%','s','%','c','*','.','r','e','g','%','c','%','s','%','c','*','.','r','e','g','%','c','%','s','%','c','*','.','*','%','c',0};
        WCHAR filter_reg[MAX_PATH], filter_reg4[MAX_PATH], filter_all[MAX_PATH];

        LoadStringW(hInst, IDS_FILEDIALOG_FILTER_REG, filter_reg, MAX_PATH);
        LoadStringW(hInst, IDS_FILEDIALOG_FILTER_REG4, filter_reg4, MAX_PATH);
        LoadStringW(hInst, IDS_FILEDIALOG_FILTER_ALL, filter_all, MAX_PATH);
429 430
        swprintf( FilterBuffer, ARRAY_SIZE(FilterBuffer), filterW,
                  filter_reg, 0, 0, filter_reg4, 0, 0, filter_all, 0, 0 );
431
    }
432
    pofn->lpstrFilter = FilterBuffer;
433
    pofn->nFilterIndex = 1;
434 435 436 437 438
    pofn->lpstrFile = FileNameBuffer;
    pofn->nMaxFile = _MAX_PATH;
    pofn->lpstrFileTitle = FileTitleBuffer;
    pofn->nMaxFileTitle = _MAX_PATH;
    pofn->Flags = OFN_HIDEREADONLY;
439
    /* some other fields may be set by the caller */
440
    return TRUE;
441 442
}

443
static BOOL import_registry_filename(LPWSTR filename)
444
{
445
    static const WCHAR rb_mode[] = {'r','b',0};
446

447
    BOOL Success;
448
    FILE* reg_file = _wfopen(filename, rb_mode);
449 450 451 452

    if(!reg_file)
        return FALSE;

453 454 455 456 457 458
    Success = import_registry_file(reg_file);

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

    return Success;
459 460
}

461 462
static BOOL ImportRegistryFile(HWND hWnd)
{
463 464
    OPENFILENAMEW ofn;
    WCHAR title[128];
465 466
    HKEY root_key = NULL;
    WCHAR *key_path;
467 468

    InitOpenFileName(hWnd, &ofn);
469
    ofn.Flags |= OFN_ENABLESIZING;
470
    LoadStringW(hInst, IDS_FILEDIALOG_IMPORT_TITLE, title, ARRAY_SIZE(title));
471
    ofn.lpstrTitle = title;
472
    if (GetOpenFileNameW(&ofn)) {
473 474
        if (!import_registry_filename(ofn.lpstrFile)) {
            messagebox(hWnd, MB_OK|MB_ICONERROR, IDS_APP_TITLE, IDS_IMPORT_FAILED, ofn.lpstrFile);
475
            return FALSE;
476 477 478 479
        } else {
            messagebox(hWnd, MB_OK|MB_ICONINFORMATION, IDS_APP_TITLE,
                       IDS_IMPORT_SUCCESSFUL, ofn.lpstrFile);
        }
480 481 482
    } else {
        CheckCommDlgError(hWnd);
    }
483
    RefreshTreeView(g_pChildWnd->hTreeWnd);
484 485 486

    key_path = GetItemPath(g_pChildWnd->hTreeWnd, 0, &root_key);
    RefreshListView(g_pChildWnd->hListWnd, root_key, key_path, NULL);
487
    heap_free(key_path);
488

489
    return TRUE;
490 491 492
}


493
static BOOL ExportRegistryFile(HWND hWnd)
494
{
495 496
    OPENFILENAMEW ofn;
    WCHAR title[128];
497 498

    InitOpenFileName(hWnd, &ofn);
499
    LoadStringW(hInst, IDS_FILEDIALOG_EXPORT_TITLE, title, ARRAY_SIZE(title));
500
    ofn.lpstrTitle = title;
501
    ofn.Flags = OFN_ENABLETEMPLATE | OFN_ENABLEHOOK | OFN_EXPLORER | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
502
    ofn.lpfnHook = ExportRegistryFile_OFNHookProc;
503 504
    ofn.lpTemplateName = MAKEINTRESOURCEW(IDD_EXPORT_TEMPLATE);
    if (GetSaveFileNameW(&ofn)) {
505
        BOOL result;
506
        result = export_registry_key(ofn.lpstrFile, (LPWSTR)ofn.lCustData, ofn.nFilterIndex);
507 508 509 510 511 512 513
        if (!result) {
            /*printf("Can't open file \"%s\"\n", ofn.lpstrFile);*/
            return FALSE;
        }
    } else {
        CheckCommDlgError(hWnd);
    }
514
    return TRUE;
515 516
}

517
static BOOL PrintRegistryHive(HWND hWnd, LPCWSTR path)
518 519
{
#if 1
520
    PRINTDLGW pd;
521

522 523
    ZeroMemory(&pd, sizeof(PRINTDLGW));
    pd.lStructSize = sizeof(PRINTDLGW);
524 525 526 527 528 529 530 531 532
    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;
533
    if (PrintDlgW(&pd)) {
534
        FIXME("printing is not yet implemented.\n");
535 536 537 538 539
        /* GDI calls to render output. */
        DeleteDC(pd.hDC); /* Delete DC when done.*/
    }
#else
    HRESULT hResult;
540
    PRINTDLGEXW pd;
541

542
    hResult = PrintDlgExW(&pd);
543 544 545 546
    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. */
547
            FIXME("printing is not yet implemented.\n");
548 549 550 551 552
            break;
        case PD_RESULT_CANCEL:
            /*The user clicked the Cancel button. The information in the PRINTDLGEX structure is unchanged. */
            break;
        case PD_RESULT_PRINT:
553
            FIXME("printing is not yet implemented.\n");
554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584
            /*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;
}

585
static BOOL CopyKeyName(HWND hWnd, LPCWSTR keyName)
586 587 588 589 590 591 592
{
    BOOL result;

    result = OpenClipboard(hWnd);
    if (result) {
        result = EmptyClipboard();
        if (result) {
593
            int len = (lstrlenW(keyName)+1)*sizeof(WCHAR);
594 595
            HANDLE hClipData = GlobalAlloc(GHND, len);
            LPVOID pLoc = GlobalLock(hClipData);
596
            lstrcpyW(pLoc, keyName);
597
            GlobalUnlock(hClipData);
598
            SetClipboardData(CF_UNICODETEXT, hClipData);
599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617

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

618 619 620 621 622 623 624 625 626 627 628
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);
629 630
            SendMessageW(hwndValue, EM_SETLIMITTEXT, 127, 0);
            SetWindowTextW(hwndValue, searchString);
631 632 633 634 635
            return TRUE;
        case WM_COMMAND:
            switch(LOWORD(wParam)) {
            case IDC_VALUE_NAME:
                if (HIWORD(wParam) == EN_UPDATE) {
636
                    EnableWindow(GetDlgItem(hwndDlg, IDOK),  GetWindowTextLengthW(hwndValue)>0);
637 638 639 640
                    return TRUE;
                }
                break;
            case IDOK:
641
                if (GetWindowTextLengthW(hwndValue)>0) {
642 643 644 645 646 647
                    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;
648
                    GetWindowTextW(hwndValue, searchString, 128);
649 650 651 652 653 654 655 656 657 658 659 660
                    EndDialog(hwndDlg, IDOK);
                }
                return TRUE;
            case IDCANCEL:
                EndDialog(hwndDlg, IDCANCEL);
                return TRUE;
            }
            break;
    }
    return FALSE;
}
                    
661 662 663 664 665 666
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:
667
        {
668 669 670 671 672 673 674 675 676
            HTREEITEM selected;
            TVITEMW item;
            WCHAR buf[128];

            selected = (HTREEITEM)SendMessageW(g_pChildWnd->hTreeWnd, TVM_GETNEXTITEM, TVGN_CARET, 0);

            item.mask = TVIF_HANDLE | TVIF_TEXT;
            item.hItem = selected;
            item.pszText = buf;
677
            item.cchTextMax = ARRAY_SIZE(buf);
678
            SendMessageW(g_pChildWnd->hTreeWnd, TVM_GETITEMW, 0, (LPARAM)&item);
679

680
            EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
681
            SetWindowTextW(hwndValue, buf);
682
            SendMessageW(hwndValue, EM_SETLIMITTEXT, 127, 0);
683
            return TRUE;
684
        }
685 686 687 688
        case WM_COMMAND:
            switch(LOWORD(wParam)) {
            case IDC_VALUE_NAME:
                if (HIWORD(wParam) == EN_UPDATE) {
689
                    EnableWindow(GetDlgItem(hwndDlg, IDOK), GetWindowTextLengthW(hwndValue) > 0);
690 691 692 693
                    return TRUE;
                }
                break;
            case IDOK:
694 695
                if (GetWindowTextLengthW(hwndValue)>0) {
                    GetWindowTextW(hwndValue, favoriteName, 128);
696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712
                    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) {
713 714
        case WM_INITDIALOG:
            if (!add_favourite_key_items(NULL, hwndList))
715
                return FALSE;
716
            SendMessageW(hwndList, LB_SETCURSEL, 0, 0);
717 718 719 720 721 722 723 724 725 726
            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: {
727 728
                int pos = SendMessageW(hwndList, LB_GETCURSEL, 0, 0);
                int len = SendMessageW(hwndList, LB_GETTEXTLEN, pos, 0);
729
                if (len>0) {
730
                    WCHAR *lpName = heap_xalloc((len + 1) * sizeof(WCHAR));
731
                    SendMessageW(hwndList, LB_GETTEXT, pos, (LPARAM)lpName);
732 733
                    if (len>127)
                        lpName[127] = '\0';
734
                    lstrcpyW(favoriteName, lpName);
735
                    EndDialog(hwndDlg, IDOK);
736
                    heap_free(lpName);
737 738 739 740 741 742 743 744 745 746 747 748
                }
                return TRUE;
            }
            case IDCANCEL:
                EndDialog(hwndDlg, IDCANCEL);
                return TRUE;
            }
            break;
    }
    return FALSE;
}
                    
749 750 751 752 753 754 755 756 757
/*******************************************************************************
 *
 *  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)
{
758
    HKEY hKeyRoot = 0;
759
    DWORD valueType;
760

761 762
    if (LOWORD(wParam) >= ID_FAVORITE_FIRST && LOWORD(wParam) <= ID_FAVORITE_LAST) {
        HKEY hKey;
763
        if (RegOpenKeyExW(HKEY_CURRENT_USER, favoritesKey,
764
            0, KEY_READ, &hKey) == ERROR_SUCCESS) {
765
            WCHAR namebuf[KEY_MAX_LEN];
766 767
            BYTE valuebuf[4096];
            DWORD ksize = KEY_MAX_LEN, vsize = sizeof(valuebuf), type = 0;
768
            if (RegEnumValueW(hKey, LOWORD(wParam) - ID_FAVORITE_FIRST, namebuf, &ksize, NULL,
769
                &type, valuebuf, &vsize) == ERROR_SUCCESS) {
770 771
                SendMessageW( g_pChildWnd->hTreeWnd, TVM_SELECTITEM, TVGN_CARET,
                             (LPARAM) FindPathInTree(g_pChildWnd->hTreeWnd, (WCHAR *)valuebuf) );
772 773 774 775 776
            }
            RegCloseKey(hKey);
        }
        return TRUE;
    }
777
    switch (LOWORD(wParam)) {
778 779 780
    case ID_REGISTRY_IMPORTREGISTRYFILE:
        ImportRegistryFile(hWnd);
        break;
781
    case ID_EDIT_EXPORT:
782
    case ID_REGISTRY_EXPORTREGISTRYFILE:
783
        ExportRegistryFile(hWnd);
784 785
        break;
    case ID_REGISTRY_PRINT:
786 787
    {
        const WCHAR empty = 0;
788
        PrintRegistryHive(hWnd, &empty);
789
        break;
790
    }
791
    case ID_EDIT_DELETE:
792 793 794
    {
        HWND hWndDelete = GetFocus();
        if (hWndDelete == g_pChildWnd->hTreeWnd) {
795
	    WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
796
	    if (keyPath == 0 || *keyPath == 0) {
797 798
	        MessageBeep(MB_ICONHAND);
            } else if (DeleteKey(hWnd, hKeyRoot, keyPath)) {
799
		DeleteNode(g_pChildWnd->hTreeWnd, 0);
800
            }
801
            heap_free(keyPath);
802
        } else if (hWndDelete == g_pChildWnd->hListWnd) {
803
            unsigned int num_selected, index, focus_idx;
804 805
            WCHAR *keyPath;

806 807 808
            num_selected = SendMessageW(g_pChildWnd->hListWnd, LVM_GETSELECTEDCOUNT, 0, 0L);

            if (!num_selected)
809
                break;
810 811 812 813
            else if (num_selected == 1)
                index = IDS_DELETE_VALUE_TEXT;
            else
                index = IDS_DELETE_VALUE_TEXT_MULTIPLE;
814

815 816
            if (messagebox(hWnd, MB_YESNO | MB_ICONEXCLAMATION, IDS_DELETE_VALUE_TITLE, index) != IDYES)
                break;
817

818 819
            keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);

820
            focus_idx = SendMessageW(g_pChildWnd->hListWnd, LVM_GETNEXTITEM, -1, MAKELPARAM(LVNI_FOCUSED, 0));
821
            index = SendMessageW(g_pChildWnd->hListWnd, LVM_GETNEXTITEM, -1, MAKELPARAM(LVNI_SELECTED, 0));
822

823
            while (index != -1)
824
            {
825
                WCHAR *valueName = GetItemText(g_pChildWnd->hListWnd, index);
826
                if (!DeleteValue(hWnd, hKeyRoot, keyPath, valueName))
827
                {
828
                    heap_free(valueName);
829 830
                    break;
                }
831
                heap_free(valueName);
832
                SendMessageW(g_pChildWnd->hListWnd, LVM_DELETEITEM, index, 0L);
833 834 835 836 837 838 839 840 841 842 843
                /* the default value item is always visible, so add it back in */
                if (!index)
                {
                    AddEntryToList(g_pChildWnd->hListWnd, NULL, REG_SZ, NULL, 0, 0);
                    if (!focus_idx)
                    {
                        LVITEMW item;
                        item.state = item.stateMask = LVIS_FOCUSED;
                        SendMessageW(g_pChildWnd->hListWnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
                    }
                }
844
                index = SendMessageW(g_pChildWnd->hListWnd, LVM_GETNEXTITEM, -1, MAKELPARAM(LVNI_SELECTED, 0));
845
            }
846
            heap_free(keyPath);
847 848
        } else if (IsChild(g_pChildWnd->hTreeWnd, hWndDelete) ||
                   IsChild(g_pChildWnd->hListWnd, hWndDelete)) {
849
            SendMessageW(hWndDelete, WM_KEYDOWN, VK_DELETE, 0);
850
        }
851
        break;
852
    }
853
    case ID_EDIT_MODIFY:
854
    case ID_EDIT_MODIFY_BIN:
855
    {
856 857
        WCHAR *valueName = GetValueName(g_pChildWnd->hListWnd);
        WCHAR *keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
858
        ModifyValue(hWnd, hKeyRoot, keyPath, valueName);
859
        heap_free(keyPath);
860
        heap_free(valueName);
861
        break;
862
    }
863 864 865 866 867
    case ID_EDIT_FIND:
    case ID_EDIT_FINDNEXT:
    {
        HTREEITEM hItem;
        if (LOWORD(wParam) == ID_EDIT_FIND &&
868
            DialogBoxW(0, MAKEINTRESOURCEW(IDD_FIND), hWnd, find_dlgproc) != IDOK)
869 870 871
            break;
        if (!*searchString)
            break;
872
        hItem = (HTREEITEM)SendMessageW(g_pChildWnd->hTreeWnd, TVM_GETNEXTITEM, TVGN_CARET, 0);
873
        if (hItem) {
874 875
            int row = SendMessageW(g_pChildWnd->hListWnd, LVM_GETNEXTITEM, -1, MAKELPARAM(LVNI_FOCUSED, 0));
            HCURSOR hcursorOld = SetCursor(LoadCursorW(NULL, (LPCWSTR)IDC_WAIT));
876 877 878
            hItem = FindNext(g_pChildWnd->hTreeWnd, hItem, searchString, searchMask, &row);
            SetCursor(hcursorOld);
            if (hItem) {
879
                SendMessageW( g_pChildWnd->hTreeWnd, TVM_SELECTITEM, TVGN_CARET, (LPARAM) hItem );
880 881 882
                InvalidateRect(g_pChildWnd->hTreeWnd, NULL, TRUE);
                UpdateWindow(g_pChildWnd->hTreeWnd);
                if (row != -1) {
883 884 885 886 887 888 889 890 891
                    LVITEMW item;

                    item.state = 0;
                    item.stateMask = LVIS_FOCUSED | LVIS_SELECTED;
                    SendMessageW(g_pChildWnd->hListWnd, LVM_SETITEMSTATE, (UINT)-1, (LPARAM)&item);

                    item.state = LVIS_FOCUSED | LVIS_SELECTED;
                    item.stateMask = LVIS_FOCUSED | LVIS_SELECTED;
                    SendMessageW(g_pChildWnd->hListWnd, LVM_SETITEMSTATE, row, (LPARAM)&item);
892 893 894 895 896
                    SetFocus(g_pChildWnd->hListWnd);
                } else {
                    SetFocus(g_pChildWnd->hTreeWnd);
                }
            } else {
897
                messagebox(hWnd, MB_OK|MB_ICONINFORMATION, IDS_APP_TITLE, IDS_NOTFOUND, searchString);
898 899 900 901
            }
        }
        break;
    }
902
    case ID_EDIT_COPYKEYNAME:
903
    {
904
        LPWSTR fullPath = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, FALSE);
905 906
        if (fullPath) {
            CopyKeyName(hWnd, fullPath);
907
            heap_free(fullPath);
908
        }
909
        break;
910
    }
911
    case ID_EDIT_NEW_KEY:
912 913
    {
        WCHAR newKeyW[MAX_NEW_KEY_LEN];
914
        WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
915
        if (CreateKey(hWnd, hKeyRoot, keyPath, newKeyW)) {
916 917 918
            if (InsertNode(g_pChildWnd->hTreeWnd, 0, newKeyW))
                StartKeyRename(g_pChildWnd->hTreeWnd);
        }
919
        heap_free(keyPath);
920
    }
921
	break;
922 923 924
    case ID_EDIT_NEW_STRINGVALUE:
	valueType = REG_SZ;
	goto create_value;
925 926 927
    case ID_EDIT_NEW_EXPANDVALUE:
	valueType = REG_EXPAND_SZ;
	goto create_value;
928 929 930
    case ID_EDIT_NEW_MULTI_STRINGVALUE:
	valueType = REG_MULTI_SZ;
	goto create_value;
931 932 933 934 935 936 937
    case ID_EDIT_NEW_BINARYVALUE:
	valueType = REG_BINARY;
	goto create_value;
    case ID_EDIT_NEW_DWORDVALUE:
	valueType = REG_DWORD;
	/* fall through */
    create_value:
938
    {
939
        WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
940
        WCHAR newKey[MAX_NEW_KEY_LEN];
941
        if (CreateValue(hWnd, hKeyRoot, keyPath, valueType, newKey))
942
            StartValueRename(g_pChildWnd->hListWnd);
943
        heap_free(keyPath);
944
    }
945
	break;
946
    case ID_EDIT_RENAME:
947
    {
948
        WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
949 950 951 952 953 954 955
        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);
        }
956
        heap_free(keyPath);
957
	break;
958 959 960 961 962 963 964
    }
    case ID_TREE_EXPAND_COLLAPSE:
    {
        HTREEITEM selected = (HTREEITEM)SendMessageW(g_pChildWnd->hTreeWnd, TVM_GETNEXTITEM, TVGN_CARET, 0);
        SendMessageW(g_pChildWnd->hTreeWnd, TVM_EXPAND, TVE_TOGGLE, (LPARAM)selected);
        break;
    }
965 966 967 968 969 970 971 972 973 974 975
    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;
976 977 978
    case ID_FAVORITES_ADDTOFAVORITES:
    {
    	HKEY hKey;
979
	LPWSTR lpKeyPath = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, FALSE);
980
    	if (lpKeyPath) {
981
            if (DialogBoxW(0, MAKEINTRESOURCEW(IDD_ADDFAVORITE), hWnd, addtofavorites_dlgproc) == IDOK) {
982
                if (RegCreateKeyExW(HKEY_CURRENT_USER, favoritesKey,
983 984
                    0, NULL, 0, 
                    KEY_READ|KEY_WRITE, NULL, &hKey, NULL) == ERROR_SUCCESS) {
985
                    RegSetValueExW(hKey, favoriteName, 0, REG_SZ, (BYTE *)lpKeyPath, (lstrlenW(lpKeyPath)+1)*sizeof(WCHAR));
986 987 988
                    RegCloseKey(hKey);
                }
            }
989
            heap_free(lpKeyPath);
990 991 992 993 994
        }
        break;
    }
    case ID_FAVORITES_REMOVEFAVORITE:
    {
995
        if (DialogBoxW(0, MAKEINTRESOURCEW(IDD_DELFAVORITE), hWnd, removefavorite_dlgproc) == IDOK) {
996
            HKEY hKey;
997
            if (RegOpenKeyExW(HKEY_CURRENT_USER, favoritesKey,
998
                0, KEY_READ|KEY_WRITE, &hKey) == ERROR_SUCCESS) {
999
                RegDeleteValueW(hKey, favoriteName);
1000 1001 1002 1003 1004
                RegCloseKey(hKey);
            }
        }
        break;
    }
1005
    case ID_VIEW_REFRESH:
1006
    {
1007
        WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
Crestez Leonard's avatar
Crestez Leonard committed
1008
        RefreshTreeView(g_pChildWnd->hTreeWnd);
1009
        RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, NULL);
1010
        heap_free(keyPath);
1011
    }
1012
        break;
1013 1014 1015
   /*case ID_OPTIONS_TOOLBAR:*/
   /*	toggle_child(hWnd, LOWORD(wParam), hToolBar);*/
   /*    break;*/
1016 1017
    case ID_VIEW_STATUSBAR:
        toggle_child(hWnd, LOWORD(wParam), hStatusBar);
1018 1019
        break;
    case ID_HELP_HELPTOPICS:
1020 1021 1022
    {
        const WCHAR help_regedit[] = {'r','e','g','e','d','i','t',0};
        WinHelpW(hWnd, help_regedit, HELP_FINDER, 0);
1023
        break;
1024
    }
1025 1026 1027
    case ID_HELP_ABOUT:
        ShowAboutBox(hWnd);
        break;
1028 1029 1030 1031 1032 1033 1034 1035 1036
    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);
1037
            SetCursor(LoadCursorW(0, (LPCWSTR)IDC_SIZEWE));
1038
            SendMessageW(g_pChildWnd->hWnd, WM_LBUTTONDOWN, 0, MAKELPARAM(pt.x, pt.y));
1039 1040 1041
        }
        return TRUE;
    }
1042
    default:
1043
        return FALSE;
1044 1045
    }

1046
    return TRUE;
1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061
}

/********************************************************************************
 *
 *  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)
{
1062 1063
    static const WCHAR captionW[] = {'r','e','g','e','d','i','t',' ','c','h','i','l','d',' ','w','i','n','d','o','w',0};

1064
    switch (message) {
1065
    case WM_CREATE:
1066 1067 1068
        CreateWindowExW(0, szChildClass, captionW, WS_CHILD | WS_VISIBLE,
                        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
                        hWnd, NULL, hInst, 0);
1069 1070 1071 1072
        LoadStringW(hInst, IDS_EXPAND, expandW, ARRAY_SIZE(expandW));
        LoadStringW(hInst, IDS_COLLAPSE, collapseW, ARRAY_SIZE(collapseW));
        LoadStringW(hInst, IDS_EDIT_MODIFY, modifyW, ARRAY_SIZE(modifyW));
        LoadStringW(hInst, IDS_EDIT_MODIFY_BIN, modify_binaryW, ARRAY_SIZE(modify_binaryW));
1073 1074
        break;
    case WM_COMMAND:
1075
        if (!_CmdWndProc(hWnd, message, wParam, lParam))
1076
            return DefWindowProcW(hWnd, message, wParam, lParam);
1077
        break;
1078 1079 1080 1081
    case WM_ACTIVATE:
        if (LOWORD(hWnd)) 
            SetFocus(g_pChildWnd->hWnd);
        break;
1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092
    case WM_SIZE:
        resize_frame_client(hWnd);
        break;
    case WM_TIMER:
        break;
    case WM_ENTERMENULOOP:
        OnEnterMenuLoop(hWnd);
        break;
    case WM_EXITMENULOOP:
        OnExitMenuLoop(hWnd);
        break;
1093 1094
    case WM_INITMENUPOPUP:
        if (!HIWORD(lParam))
1095
            OnInitMenuPopup(hWnd, (HMENU)wParam);
1096
        break;
1097 1098 1099 1100
    case WM_MENUSELECT:
        OnMenuSelect(hWnd, LOWORD(wParam), HIWORD(wParam), (HMENU)lParam);
        break;
    case WM_DESTROY:
1101 1102 1103
    {
        const WCHAR help_regedit[] = {'r','e','g','e','d','i','t',0};
        WinHelpW(hWnd, help_regedit, HELP_QUIT, 0);
1104
        PostQuitMessage(0);
1105
    }
1106
    default:
1107
        return DefWindowProcW(hWnd, message, wParam, lParam);
1108 1109
    }
    return 0;
1110
}