1 /* 2 * Program Manager 3 * 4 * Copyright 1996 Ulrich Schmid 5 * Copyright 2002 Sylvain Petreolle 6 * Copyright 2002 Andriy Palamarchuk 7 * 8 * This library is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU Lesser General Public 10 * License as published by the Free Software Foundation; either 11 * version 2.1 of the License, or (at your option) any later version. 12 * 13 * This library is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public 19 * License along with this library; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 21 */ 22 23 /* 24 * PROJECT: ReactOS Program Manager 25 * COPYRIGHT: GPL - See COPYING in the top level directory 26 * FILE: base/shell/progman/dialog.c 27 * PURPOSE: ProgMan dialog boxes 28 * PROGRAMMERS: Ulrich Schmid 29 * Sylvain Petreolle 30 * Andriy Palamarchuk 31 * Hermes Belusca-Maito (hermes.belusca@sfr.fr) 32 */ 33 34 #include "progman.h" 35 36 #include <commdlg.h> 37 38 /*********************************************************************** 39 * 40 * DIALOG_AddFilterItem and DIALOG_BrowseXXX 41 */ 42 43 static 44 VOID 45 DIALOG_AddFilterItem(LPWSTR* p, UINT ids, LPCWSTR filter) 46 { 47 LoadStringW(Globals.hInstance, ids, *p, MAX_STRING_LEN); 48 *p += wcslen(*p) + 1; 49 lstrcpyW(*p, filter); 50 *p += wcslen(*p) + 1; 51 **p = '\0'; 52 } 53 54 static 55 BOOL 56 DIALOG_Browse(HWND hWnd, LPCWSTR lpszzFilter, LPWSTR lpstrFile, INT nMaxFile) 57 { 58 OPENFILENAMEW openfilename; 59 WCHAR szDir[MAX_PATH]; 60 61 ZeroMemory(&openfilename, sizeof(openfilename)); 62 63 GetCurrentDirectoryW(ARRAYSIZE(szDir), szDir); 64 65 openfilename.lStructSize = sizeof(openfilename); 66 openfilename.hwndOwner = hWnd; 67 openfilename.hInstance = Globals.hInstance; 68 openfilename.lpstrFilter = lpszzFilter; 69 openfilename.lpstrFile = lpstrFile; 70 openfilename.nMaxFile = nMaxFile; 71 openfilename.lpstrInitialDir = szDir; 72 openfilename.Flags = 0; 73 openfilename.lpstrDefExt = L"exe"; 74 openfilename.lpstrCustomFilter = NULL; 75 openfilename.nMaxCustFilter = 0; 76 openfilename.nFilterIndex = 0; 77 openfilename.lpstrFileTitle = NULL; 78 openfilename.nMaxFileTitle = 0; 79 openfilename.lpstrTitle = NULL; 80 openfilename.nFileOffset = 0; 81 openfilename.nFileExtension = 0; 82 openfilename.lCustData = 0; 83 openfilename.lpfnHook = NULL; 84 openfilename.lpTemplateName = NULL; 85 86 return GetOpenFileNameW(&openfilename); 87 } 88 89 static 90 BOOL 91 DIALOG_BrowsePrograms(HWND hWnd, LPWSTR lpszFile, INT nMaxFile) 92 { 93 WCHAR szzFilter[2 * MAX_STRING_LEN + 100]; 94 LPWSTR p = szzFilter; 95 96 DIALOG_AddFilterItem(&p, IDS_PROGRAMS , L"*.exe;*.pif;*.com;*.bat;*.cmd"); 97 DIALOG_AddFilterItem(&p, IDS_ALL_FILES, L"*.*"); 98 99 return DIALOG_Browse(hWnd, szzFilter, lpszFile, nMaxFile); 100 } 101 102 static 103 BOOL 104 DIALOG_BrowseSymbols(HWND hWnd, LPWSTR lpszFile, INT nMaxFile) 105 { 106 WCHAR szzFilter[5 * MAX_STRING_LEN + 100]; 107 LPWSTR p = szzFilter; 108 109 DIALOG_AddFilterItem(&p, IDS_SYMBOL_FILES, L"*.ico;*.exe;*.dll"); 110 DIALOG_AddFilterItem(&p, IDS_PROGRAMS, L"*.exe"); 111 DIALOG_AddFilterItem(&p, IDS_LIBRARIES_DLL, L"*.dll"); 112 DIALOG_AddFilterItem(&p, IDS_SYMBOLS_ICO, L"*.ico"); 113 DIALOG_AddFilterItem(&p, IDS_ALL_FILES, L"*.*"); 114 115 return DIALOG_Browse(hWnd, szzFilter, lpszFile, nMaxFile); 116 } 117 118 119 120 /*********************************************************************** 121 * 122 * DIALOG_New 123 */ 124 125 LPCWSTR GroupFormatToFormatName(GROUPFORMAT Format) 126 { 127 static const LPCWSTR FormatNames[] = 128 { 129 L"Windows 3.1", 130 L"NT Ansi", 131 L"NT Unicode" 132 }; 133 134 if (Format > NT_Unicode) 135 return NULL; 136 else 137 return FormatNames[Format]; 138 } 139 140 typedef struct _NEW_ITEM_CONTEXT 141 { 142 INT nDefault; 143 INT nResult; 144 } NEW_ITEM_CONTEXT, *PNEW_ITEM_CONTEXT; 145 146 static 147 INT_PTR 148 CALLBACK 149 DIALOG_NEW_DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) 150 { 151 PNEW_ITEM_CONTEXT pNewItem; 152 GROUPFORMAT format; 153 INT iItem; 154 155 pNewItem = (PNEW_ITEM_CONTEXT)GetWindowLongPtrW(hDlg, 8); 156 157 switch (uMsg) 158 { 159 case WM_INITDIALOG: 160 { 161 pNewItem = (PNEW_ITEM_CONTEXT)lParam; 162 SetWindowLongPtrW(hDlg, 8, lParam); 163 164 for (format = Win_311; format <= NT_Unicode; ++format) 165 { 166 iItem = SendDlgItemMessageW(hDlg, PM_FORMAT, CB_INSERTSTRING, 0, (LPARAM)GroupFormatToFormatName(format)); 167 if (iItem != CB_ERR && iItem != CB_ERRSPACE) 168 SendDlgItemMessageW(hDlg, PM_FORMAT, CB_SETITEMDATA, iItem, format); 169 } 170 171 SendDlgItemMessageW(hDlg, PM_FORMAT, CB_SETCURSEL, 0, 0); 172 CheckRadioButton(hDlg, PM_NEW_GROUP, PM_NEW_PROGRAM, pNewItem->nDefault); 173 CheckRadioButton(hDlg, PM_PERSONAL_GROUP, PM_COMMON_GROUP, PM_PERSONAL_GROUP); 174 175 EnableDlgItem(hDlg, PM_NEW_PROGRAM, GROUP_ActiveGroup() != NULL); 176 177 SendMessageW(hDlg, WM_COMMAND, pNewItem->nDefault, 0); 178 break; 179 } 180 181 case WM_COMMAND: 182 switch (LOWORD(wParam)) 183 { 184 case PM_NEW_GROUP: 185 { 186 CheckRadioButton(hDlg, PM_NEW_GROUP, PM_NEW_PROGRAM, wParam); 187 EnableDlgItem(hDlg, PM_COMMON_GROUP , TRUE); 188 EnableDlgItem(hDlg, PM_PERSONAL_GROUP, TRUE); 189 EnableDlgItem(hDlg, PM_FORMAT_TXT, TRUE); 190 EnableDlgItem(hDlg, PM_FORMAT , TRUE); 191 return TRUE; 192 } 193 194 case PM_NEW_PROGRAM: 195 { 196 CheckRadioButton(hDlg, PM_NEW_GROUP, PM_NEW_PROGRAM, wParam); 197 EnableDlgItem(hDlg, PM_COMMON_GROUP , FALSE); 198 EnableDlgItem(hDlg, PM_PERSONAL_GROUP, FALSE); 199 EnableDlgItem(hDlg, PM_FORMAT_TXT, FALSE); 200 EnableDlgItem(hDlg, PM_FORMAT , FALSE); 201 return TRUE; 202 } 203 204 case IDHELP: 205 MAIN_MessageBoxIDS(IDS_NOT_IMPLEMENTED, IDS_ERROR, MB_OK); 206 return TRUE; 207 208 case IDOK: 209 { 210 iItem = SendDlgItemMessageW(hDlg, PM_FORMAT, CB_GETCURSEL, 0, 0); 211 212 format = SendDlgItemMessageW(hDlg, PM_FORMAT, CB_GETITEMDATA, iItem, 0); 213 format = min(max(format, Win_311), NT_Unicode); 214 215 pNewItem->nResult = !!IsDlgButtonChecked(hDlg, PM_NEW_GROUP); 216 pNewItem->nResult |= (!!IsDlgButtonChecked(hDlg, PM_COMMON_GROUP) << 1); 217 pNewItem->nResult |= (format << 2); 218 219 EndDialog(hDlg, IDOK); 220 return TRUE; 221 } 222 223 case IDCANCEL: 224 EndDialog(hDlg, IDCANCEL); 225 return TRUE; 226 } 227 return FALSE; 228 } 229 230 return FALSE; 231 } 232 233 BOOL DIALOG_New(INT nDefault, PINT pnResult) 234 { 235 INT_PTR ret; 236 NEW_ITEM_CONTEXT NewItem; 237 238 *pnResult = 0; 239 240 NewItem.nDefault = nDefault; 241 NewItem.nResult = 0; 242 ret = DialogBoxParamW(Globals.hInstance, MAKEINTRESOURCEW(IDD_NEW), Globals.hMainWnd, DIALOG_NEW_DlgProc, (LPARAM)&NewItem); 243 if (ret == IDOK) 244 *pnResult = NewItem.nResult; 245 246 return (ret == IDOK); 247 } 248 249 250 /*********************************************************************** 251 * 252 * DIALOG_CopyMove 253 */ 254 255 typedef struct _COPY_MOVE_CONTEXT 256 { 257 PROGRAM* Program; 258 PROGGROUP* hToGroup; 259 BOOL bMove; 260 } COPY_MOVE_CONTEXT, *PCOPY_MOVE_CONTEXT; 261 262 static 263 INT_PTR 264 CALLBACK 265 DIALOG_COPY_MOVE_DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) 266 { 267 PROGGROUP* hGrpItem; 268 PROGGROUP* hGroup; 269 270 PCOPY_MOVE_CONTEXT pCopyMove; 271 INT iItem; 272 273 WCHAR text[MAX_STRING_LEN]; 274 275 pCopyMove = (PCOPY_MOVE_CONTEXT)GetWindowLongPtrW(hDlg, 8); 276 277 switch (uMsg) 278 { 279 case WM_INITDIALOG: 280 { 281 pCopyMove = (PCOPY_MOVE_CONTEXT)lParam; 282 SetWindowLongPtrW(hDlg, 8, lParam); 283 284 if (pCopyMove->bMove) 285 { 286 LoadStringW(Globals.hInstance, IDS_MOVE_PROGRAM_1, text, ARRAYSIZE(text)); 287 SetWindowTextW(hDlg, text); 288 LoadStringW(Globals.hInstance, IDS_MOVE_PROGRAM_2, text, ARRAYSIZE(text)); 289 SetDlgItemTextW(hDlg, PM_COPY_MOVE_TXT, text); 290 } 291 292 /* List all the group names but the source group, in case we are doing a move */ 293 for (hGroup = Globals.hGroups; hGroup; hGroup = hGroup->hNext) 294 { 295 if (!pCopyMove->bMove || hGroup != pCopyMove->Program->hGroup) 296 { 297 iItem = SendDlgItemMessageW(hDlg, PM_TO_GROUP, CB_ADDSTRING, 0, (LPARAM)hGroup->hName); 298 if (iItem != CB_ERR && iItem != CB_ERRSPACE) 299 SendDlgItemMessageW(hDlg, PM_TO_GROUP, CB_SETITEMDATA, iItem, (LPARAM)hGroup); 300 } 301 } 302 SendDlgItemMessageW(hDlg, PM_TO_GROUP, CB_SETCURSEL, 0, 0); 303 SetDlgItemTextW(hDlg, PM_PROGRAM , pCopyMove->Program->hName); 304 SetDlgItemTextW(hDlg, PM_FROM_GROUP, pCopyMove->Program->hGroup->hName); 305 break; 306 } 307 308 case WM_COMMAND: 309 switch (LOWORD(wParam)) 310 { 311 case IDHELP: 312 MAIN_MessageBoxIDS(IDS_NOT_IMPLEMENTED, IDS_ERROR, MB_OK); 313 return TRUE; 314 315 case IDOK: 316 { 317 /* Get the selected group */ 318 iItem = SendDlgItemMessageW(hDlg, PM_TO_GROUP, CB_GETCURSEL, 0, 0); 319 hGrpItem = (PROGGROUP *)SendDlgItemMessageW(hDlg, PM_TO_GROUP, CB_GETITEMDATA, iItem, 0); 320 /* Check that it is indeed in the group list */ 321 for (hGroup = Globals.hGroups; hGroup && hGroup != hGrpItem; hGroup = hGroup->hNext) 322 ; 323 if (pCopyMove->bMove) 324 { 325 if (hGrpItem == pCopyMove->Program->hGroup) 326 hGrpItem = NULL; 327 } 328 pCopyMove->hToGroup = hGrpItem; 329 EndDialog(hDlg, IDOK); 330 return TRUE; 331 } 332 333 case IDCANCEL: 334 EndDialog(hDlg, IDCANCEL); 335 return TRUE; 336 } 337 return FALSE; 338 } 339 340 return FALSE; 341 } 342 343 PROGGROUP* DIALOG_CopyMove(PROGRAM* hProgram, BOOL bMove) 344 { 345 COPY_MOVE_CONTEXT CopyMove; 346 INT_PTR ret; 347 348 CopyMove.bMove = bMove; 349 CopyMove.Program = hProgram; 350 CopyMove.hToGroup = NULL; 351 ret = DialogBoxParamW(Globals.hInstance, MAKEINTRESOURCEW(IDD_COPY_MOVE), Globals.hMainWnd, DIALOG_COPY_MOVE_DlgProc, (LPARAM)&CopyMove); 352 353 return (ret == IDOK ? CopyMove.hToGroup : NULL); 354 } 355 356 /*********************************************************************** 357 * 358 * DIALOG_Delete 359 */ 360 361 BOOL DIALOG_Delete(UINT ids_text_s, LPCWSTR lpszName) 362 { 363 return (MAIN_MessageBoxIDS_s(ids_text_s, lpszName, IDS_DELETE, MB_YESNO | MB_DEFBUTTON2) == IDYES); 364 } 365 366 367 /* Adapted from dll/win32/shell32/dialogs/dialogs.cpp!EnableOkButtonFromEditContents */ 368 BOOL ValidateEditContents(HWND hDlg, INT nIDEditItem) 369 { 370 BOOL Enable = FALSE; 371 LPWSTR psz; 372 INT Length, n; 373 HWND Edit; 374 375 Edit = GetDlgItem(hDlg, nIDEditItem); 376 Length = GetWindowTextLengthW(Edit); 377 378 if (Length <= 0) 379 return FALSE; 380 381 psz = Alloc(0, (Length + 1) * sizeof(WCHAR)); 382 if (psz) 383 { 384 GetWindowTextW(Edit, psz, Length + 1); 385 for (n = 0; n < Length && !Enable; ++n) 386 Enable = (psz[n] != ' '); 387 Free(psz); 388 } 389 else 390 { 391 Enable = TRUE; 392 } 393 394 return Enable; 395 } 396 397 398 /*********************************************************************** 399 * 400 * DIALOG_GroupAttributes 401 */ 402 403 typedef struct _GROUP_ATTRIBUTES_CONTEXT 404 { 405 GROUPFORMAT format; 406 LPWSTR lpszTitle; 407 LPWSTR lpszGrpFile; 408 INT nSize; 409 } GROUP_ATTRIBUTES_CONTEXT, *PGROUP_ATTRIBUTES_CONTEXT; 410 411 static 412 INT_PTR 413 CALLBACK 414 DIALOG_GROUP_DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) 415 { 416 PGROUP_ATTRIBUTES_CONTEXT pGroupAttributes; 417 418 pGroupAttributes = (PGROUP_ATTRIBUTES_CONTEXT)GetWindowLongPtrW(hDlg, 8); 419 420 switch (uMsg) 421 { 422 case WM_INITDIALOG: 423 { 424 DWORD evMask; 425 426 pGroupAttributes = (PGROUP_ATTRIBUTES_CONTEXT)lParam; 427 SetWindowLongPtrW(hDlg, 8, lParam); 428 429 /* Configure Richedit control for sending notification changes */ 430 evMask = SendDlgItemMessageW(hDlg, PM_DESCRIPTION, EM_GETEVENTMASK, 0, 0) | ENM_CHANGE; 431 SendDlgItemMessageW(hDlg, PM_DESCRIPTION, EM_SETEVENTMASK, 0, (LPARAM)evMask); 432 433 SetDlgItemTextW(hDlg, PM_DESCRIPTION, pGroupAttributes->lpszTitle); 434 435 if (pGroupAttributes->format != Win_311) 436 { 437 EnableDlgItem(hDlg, PM_FILE, FALSE); 438 } 439 else 440 { 441 EnableDlgItem(hDlg, PM_FILE, TRUE); 442 SetDlgItemTextW(hDlg, PM_FILE, pGroupAttributes->lpszGrpFile); 443 } 444 445 EnableDlgItem(hDlg, IDOK, ValidateEditContents(hDlg, PM_DESCRIPTION)); 446 break; 447 } 448 449 case WM_COMMAND: 450 switch (LOWORD(wParam)) 451 { 452 case IDHELP: 453 MAIN_MessageBoxIDS(IDS_NOT_IMPLEMENTED, IDS_ERROR, MB_OK); 454 return TRUE; 455 456 case PM_DESCRIPTION: 457 { 458 if (HIWORD(wParam) == EN_CHANGE) 459 EnableDlgItem(hDlg, IDOK, ValidateEditContents(hDlg, PM_DESCRIPTION)); 460 return FALSE; 461 } 462 463 case IDOK: 464 { 465 GetDlgItemTextW(hDlg, PM_DESCRIPTION, pGroupAttributes->lpszTitle, pGroupAttributes->nSize); 466 if (pGroupAttributes->format) 467 *pGroupAttributes->lpszGrpFile = '\0'; 468 else 469 GetDlgItemTextW(hDlg, PM_FILE, pGroupAttributes->lpszGrpFile, pGroupAttributes->nSize); 470 EndDialog(hDlg, IDOK); 471 return TRUE; 472 } 473 474 case IDCANCEL: 475 EndDialog(hDlg, IDCANCEL); 476 return TRUE; 477 } 478 return FALSE; 479 } 480 481 return FALSE; 482 } 483 484 BOOL DIALOG_GroupAttributes(GROUPFORMAT format, LPWSTR lpszTitle, LPWSTR lpszGrpFile, INT nSize) 485 { 486 INT_PTR ret; 487 GROUP_ATTRIBUTES_CONTEXT GroupAttributes; 488 489 GroupAttributes.format = format; 490 GroupAttributes.nSize = nSize; 491 GroupAttributes.lpszTitle = lpszTitle; 492 GroupAttributes.lpszGrpFile = lpszGrpFile; 493 494 ret = DialogBoxParamW(Globals.hInstance, MAKEINTRESOURCEW(IDD_GROUP), Globals.hMainWnd, DIALOG_GROUP_DlgProc, (LPARAM)&GroupAttributes); 495 496 return (ret == IDOK); 497 } 498 499 500 /*********************************************************************** 501 * 502 * DIALOG_Symbol 503 */ 504 505 /* Adapted from dll/win32/shell32/dialogs/dialogs.cpp!EnumPickIconResourceProc */ 506 static 507 BOOL 508 CALLBACK 509 EnumPickIconResourceProc(HMODULE hModule, LPCWSTR lpszType, LPWSTR lpszName, LONG_PTR lParam) 510 { 511 HICON hIcon; 512 HWND hDlgCtrl = (HWND)lParam; 513 WCHAR szName[100]; 514 515 if (IS_INTRESOURCE(lpszName)) 516 StringCbPrintfW(szName, sizeof(szName), L"%u", (unsigned)(UINT_PTR)lpszName); 517 else 518 StringCbCopyW(szName, sizeof(szName), lpszName); 519 520 hIcon = (HICON)LoadImageW(hModule, lpszName, IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR); 521 if (hIcon == NULL) 522 return TRUE; 523 524 SendMessageW(hDlgCtrl, LB_ADDSTRING, 0, (LPARAM)hIcon); 525 return TRUE; 526 } 527 528 static 529 VOID 530 DestroyIconList(HWND hDlgCtrl) 531 { 532 HICON hIcon; 533 UINT count; 534 535 count = SendMessageA(hDlgCtrl, LB_GETCOUNT, 0, 0); 536 if (count == LB_ERR || count == 0) 537 return; 538 539 while (count-- > 0) 540 { 541 hIcon = (HICON)SendMessageA(hDlgCtrl, LB_GETITEMDATA, 0, 0); 542 DestroyIcon(hIcon); 543 SendMessageA(hDlgCtrl, LB_DELETESTRING, 0, 0); 544 } 545 } 546 547 typedef struct _PICK_ICON_CONTEXT 548 { 549 HMODULE hLibrary; 550 HWND hDlgCtrl; 551 WCHAR szName[MAX_PATH]; // LPWSTR lpszIconFile; // INT nSize; 552 INT Index; 553 HICON hIcon; 554 } PICK_ICON_CONTEXT, *PPICK_ICON_CONTEXT; 555 556 #if 0 557 558 static struct 559 { 560 LPSTR lpszIconFile; 561 INT nSize; 562 HICON *lphIcon; 563 INT *lpnIconIndex; 564 } Symbol; 565 566 #endif 567 568 static 569 INT_PTR 570 CALLBACK 571 DIALOG_SYMBOL_DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) 572 { 573 WCHAR filename[MAX_PATHNAME_LEN]; 574 PPICK_ICON_CONTEXT pIconContext; 575 576 pIconContext = (PPICK_ICON_CONTEXT)GetWindowLongPtrW(hDlg, 8); 577 578 switch (uMsg) 579 { 580 case WM_INITDIALOG: 581 { 582 pIconContext = (PPICK_ICON_CONTEXT)lParam; 583 SetWindowLongPtrW(hDlg, 8, lParam); 584 585 pIconContext->hDlgCtrl = GetDlgItem(hDlg, PM_SYMBOL_LIST); 586 SetDlgItemTextW(hDlg, PM_ICON_FILE, pIconContext->szName); 587 SendMessageA(pIconContext->hDlgCtrl, LB_SETITEMHEIGHT, 0, 32); 588 589 pIconContext->hLibrary = LoadLibraryExW(pIconContext->szName, NULL, /* NT6+: LOAD_LIBRARY_AS_IMAGE_RESOURCE | */ LOAD_LIBRARY_AS_DATAFILE); 590 if (pIconContext->hLibrary) 591 { 592 EnumResourceNamesW(pIconContext->hLibrary, 593 (LPCWSTR)RT_GROUP_ICON, 594 EnumPickIconResourceProc, 595 (LONG_PTR)pIconContext->hDlgCtrl); 596 FreeLibrary(pIconContext->hLibrary); 597 pIconContext->hLibrary = NULL; 598 } 599 SendMessageA(pIconContext->hDlgCtrl, LB_SETCURSEL, pIconContext->Index, 0); 600 return TRUE; 601 } 602 603 case WM_MEASUREITEM: 604 { 605 PMEASUREITEMSTRUCT measure = (PMEASUREITEMSTRUCT)lParam; 606 measure->itemWidth = 32; 607 measure->itemHeight = 32; 608 return TRUE; 609 } 610 611 case WM_DRAWITEM: 612 { 613 PDRAWITEMSTRUCT dis = (PDRAWITEMSTRUCT)lParam; 614 615 if (dis->itemState & ODS_SELECTED) 616 FillRect(dis->hDC, &dis->rcItem, (HBRUSH)(COLOR_HIGHLIGHT + 1)); 617 else 618 FillRect(dis->hDC, &dis->rcItem, (HBRUSH)(COLOR_WINDOW + 1)); 619 620 DrawIcon(dis->hDC, dis->rcItem.left, dis->rcItem.top, (HICON)dis->itemData); 621 return TRUE; 622 } 623 624 case WM_COMMAND: 625 switch (LOWORD(wParam)) 626 { 627 case PM_BROWSE: 628 { 629 filename[0] = '\0'; 630 if (!DIALOG_BrowseSymbols(hDlg, filename, ARRAYSIZE(filename))) 631 return TRUE; 632 633 if (_wcsnicmp(pIconContext->szName, filename, ARRAYSIZE(pIconContext->szName)) == 0) 634 return TRUE; 635 636 SetDlgItemTextW(hDlg, PM_ICON_FILE, filename); 637 DestroyIconList(pIconContext->hDlgCtrl); 638 pIconContext->hLibrary = LoadLibraryExW(filename, NULL, /* NT6+: LOAD_LIBRARY_AS_IMAGE_RESOURCE | */ LOAD_LIBRARY_AS_DATAFILE); 639 if (pIconContext->hLibrary) 640 { 641 EnumResourceNamesW(pIconContext->hLibrary, 642 (LPCWSTR)RT_GROUP_ICON, 643 EnumPickIconResourceProc, 644 (LONG_PTR)pIconContext->hDlgCtrl); 645 FreeLibrary(pIconContext->hLibrary); 646 pIconContext->hLibrary = NULL; 647 } 648 SendMessageA(pIconContext->hDlgCtrl, LB_SETCURSEL, 0, 0); 649 return TRUE; 650 } 651 652 case IDHELP: 653 MAIN_MessageBoxIDS(IDS_NOT_IMPLEMENTED, IDS_ERROR, MB_OK); 654 return TRUE; 655 656 case IDOK: 657 { 658 INT nCurSel = SendMessageW(pIconContext->hDlgCtrl, LB_GETCURSEL, 0, 0); 659 GetDlgItemTextW(hDlg, PM_ICON_FILE, pIconContext->szName, ARRAYSIZE(pIconContext->szName)); 660 pIconContext->hIcon = (HICON)SendMessageA(pIconContext->hDlgCtrl, LB_GETITEMDATA, nCurSel, 0); 661 pIconContext->hIcon = CopyIcon(pIconContext->hIcon); 662 DestroyIconList(pIconContext->hDlgCtrl); 663 EndDialog(hDlg, IDOK); 664 return TRUE; 665 } 666 667 case IDCANCEL: 668 DestroyIconList(pIconContext->hDlgCtrl); 669 EndDialog(hDlg, IDCANCEL); 670 return TRUE; 671 } 672 return FALSE; 673 } 674 675 return FALSE; 676 } 677 678 static 679 VOID 680 DIALOG_Symbol(HWND hWnd, HICON *lphIcon, LPWSTR lpszIconFile, INT *lpnIconIndex, INT nSize) 681 { 682 PICK_ICON_CONTEXT IconContext; 683 684 IconContext.Index = *lpnIconIndex; 685 StringCchCopyNW(IconContext.szName, ARRAYSIZE(IconContext.szName), lpszIconFile, nSize); 686 687 if (DialogBoxParamW(Globals.hInstance, MAKEINTRESOURCEW(IDD_SYMBOL), hWnd, DIALOG_SYMBOL_DlgProc, (LPARAM)&IconContext) != IDOK) 688 return; 689 690 StringCchCopyNW(lpszIconFile, nSize, IconContext.szName, ARRAYSIZE(IconContext.szName)); 691 *lpnIconIndex = IconContext.Index; 692 *lphIcon = IconContext.hIcon; 693 } 694 695 696 /*********************************************************************** 697 * 698 * DIALOG_ProgramAttributes 699 */ 700 701 typedef struct _PROGRAM_ATTRIBUTES_CONTEXT 702 { 703 LPWSTR lpszTitle; 704 LPWSTR lpszCmdLine; 705 LPWSTR lpszWorkDir; 706 LPWSTR lpszIconFile; 707 LPWSTR lpszTmpIconFile; 708 INT nSize; 709 INT* lpnCmdShow; 710 INT* lpnHotKey; 711 // HWND hSelGroupWnd; 712 BOOL* lpbNewVDM; // unused! 713 HICON* lphIcon; 714 HICON hTmpIcon; 715 INT* lpnIconIndex; 716 INT nTmpIconIndex; 717 BOOL bCheckBinaryType; 718 } PROGRAM_ATTRIBUTES_CONTEXT, *PPROGRAM_ATTRIBUTES_CONTEXT; 719 720 static 721 INT_PTR 722 CALLBACK 723 DIALOG_PROGRAM_DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) 724 { 725 BOOL bEnable; 726 WCHAR filename[MAX_PATHNAME_LEN]; 727 DWORD evMask; 728 DWORD dwBinaryType; 729 PPROGRAM_ATTRIBUTES_CONTEXT pProgramAttributes; 730 731 pProgramAttributes = (PPROGRAM_ATTRIBUTES_CONTEXT)GetWindowLongPtrW(hDlg, 8); 732 733 switch (uMsg) 734 { 735 case WM_INITDIALOG: 736 { 737 pProgramAttributes = (PPROGRAM_ATTRIBUTES_CONTEXT)lParam; 738 SetWindowLongPtrW(hDlg, 8, lParam); 739 740 evMask = SendDlgItemMessageW(hDlg, PM_COMMAND_LINE, EM_GETEVENTMASK, 0, 0) | ENM_CHANGE; 741 SendDlgItemMessageW(hDlg, PM_COMMAND_LINE, EM_SETEVENTMASK, 0, evMask); 742 743 SetDlgItemTextW(hDlg, PM_DESCRIPTION , pProgramAttributes->lpszTitle); 744 SetDlgItemTextW(hDlg, PM_COMMAND_LINE, pProgramAttributes->lpszCmdLine); 745 SetDlgItemTextW(hDlg, PM_DIRECTORY , pProgramAttributes->lpszWorkDir); 746 747 /* 0x0F 0x06 */ 748 SendDlgItemMessageW(hDlg, PM_HOT_KEY, HKM_SETRULES, HKCOMB_C | HKCOMB_A | HKCOMB_S | HKCOMB_NONE, HOTKEYF_CONTROL | HOTKEYF_ALT); 749 SendDlgItemMessageW(hDlg, PM_HOT_KEY, HKM_SETHOTKEY, *pProgramAttributes->lpnHotKey, 0); 750 751 bEnable = ValidateEditContents(hDlg, PM_COMMAND_LINE); 752 EnableWindow(GetDlgItem(hDlg, IDOK), bEnable); 753 EnableWindow(GetDlgItem(hDlg, PM_OTHER_SYMBOL), bEnable); 754 755 CheckDlgButton(hDlg, PM_SYMBOL, *pProgramAttributes->lpnCmdShow == SW_SHOWMINNOACTIVE); 756 757 if (pProgramAttributes->bCheckBinaryType && 758 (!GetBinaryTypeW(pProgramAttributes->lpszCmdLine, &dwBinaryType) || dwBinaryType != SCS_WOW_BINARY) ) 759 { 760 EnableWindow(GetDlgItem(hDlg, PM_NEW_VDM), FALSE); 761 CheckDlgButton(hDlg, PM_NEW_VDM, BST_CHECKED); 762 } 763 else 764 { 765 EnableWindow(GetDlgItem(hDlg, PM_NEW_VDM), TRUE); 766 CheckDlgButton(hDlg, PM_NEW_VDM, *pProgramAttributes->lpbNewVDM); 767 } 768 SendDlgItemMessageW(hDlg, PM_ICON, STM_SETICON, (WPARAM)pProgramAttributes->hTmpIcon, 0); 769 break; 770 } 771 772 case WM_COMMAND: 773 switch (LOWORD(wParam)) 774 { 775 case PM_NEW_VDM: 776 CheckDlgButton(hDlg, PM_NEW_VDM, !IsDlgButtonChecked(hDlg, PM_NEW_VDM)); 777 return TRUE; 778 779 case PM_BROWSE: 780 { 781 filename[0] = '\0'; 782 if (DIALOG_BrowsePrograms(hDlg, filename, ARRAYSIZE(filename))) 783 { 784 SetDlgItemTextW(hDlg, PM_COMMAND_LINE, filename); 785 if (pProgramAttributes->bCheckBinaryType && 786 (!GetBinaryTypeW(filename, &dwBinaryType) || dwBinaryType != SCS_WOW_BINARY)) 787 { 788 EnableWindow(GetDlgItem(hDlg, PM_NEW_VDM), FALSE); 789 CheckDlgButton(hDlg, PM_NEW_VDM, BST_CHECKED); 790 } 791 else 792 { 793 EnableWindow(GetDlgItem(hDlg, PM_NEW_VDM), TRUE); 794 CheckDlgButton(hDlg, PM_NEW_VDM, BST_UNCHECKED); 795 } 796 } 797 return TRUE; 798 } 799 800 case IDHELP: 801 MAIN_MessageBoxIDS(IDS_NOT_IMPLEMENTED, IDS_ERROR, MB_OK); 802 return TRUE; 803 804 case PM_SYMBOL: 805 CheckDlgButton(hDlg, PM_SYMBOL, !IsDlgButtonChecked(hDlg, PM_SYMBOL)); 806 return TRUE; 807 808 case PM_OTHER_SYMBOL: 809 { 810 DIALOG_Symbol(hDlg, 811 &pProgramAttributes->hTmpIcon, 812 pProgramAttributes->lpszTmpIconFile, 813 &pProgramAttributes->nTmpIconIndex, 814 MAX_PATHNAME_LEN); 815 816 SendDlgItemMessageW(hDlg, PM_ICON, STM_SETICON, (WPARAM)pProgramAttributes->hTmpIcon, 0); 817 return TRUE; 818 } 819 820 case PM_COMMAND_LINE: 821 { 822 if (HIWORD(wParam) == EN_CHANGE) 823 { 824 bEnable = ValidateEditContents(hDlg, PM_COMMAND_LINE); 825 EnableWindow(GetDlgItem(hDlg, IDOK), bEnable); 826 EnableWindow(GetDlgItem(hDlg, PM_OTHER_SYMBOL), bEnable); 827 } 828 return FALSE; 829 } 830 831 case IDOK: 832 { 833 GetDlgItemTextW(hDlg, PM_DESCRIPTION , pProgramAttributes->lpszTitle , pProgramAttributes->nSize); 834 GetDlgItemTextW(hDlg, PM_COMMAND_LINE, pProgramAttributes->lpszCmdLine, pProgramAttributes->nSize); 835 GetDlgItemTextW(hDlg, PM_DIRECTORY , pProgramAttributes->lpszWorkDir, pProgramAttributes->nSize); 836 if (pProgramAttributes->hTmpIcon) 837 { 838 #if 0 839 if (*pProgramAttributes->lphIcon) 840 DestroyIcon(*pProgramAttributes->lphIcon); 841 #endif 842 *pProgramAttributes->lphIcon = pProgramAttributes->hTmpIcon; 843 *pProgramAttributes->lpnIconIndex = pProgramAttributes->nTmpIconIndex; 844 lstrcpynW(pProgramAttributes->lpszIconFile, pProgramAttributes->lpszTmpIconFile, pProgramAttributes->nSize); 845 } 846 *pProgramAttributes->lpnHotKey = SendDlgItemMessageW(hDlg, PM_HOT_KEY, HKM_GETHOTKEY, 0, 0); 847 *pProgramAttributes->lpnCmdShow = IsDlgButtonChecked(hDlg, PM_SYMBOL) ? SW_SHOWMINNOACTIVE : SW_SHOWNORMAL; 848 *pProgramAttributes->lpbNewVDM = IsDlgButtonChecked(hDlg, PM_NEW_VDM); 849 EndDialog(hDlg, IDOK); 850 return TRUE; 851 } 852 853 case IDCANCEL: 854 EndDialog(hDlg, IDCANCEL); 855 return TRUE; 856 } 857 return FALSE; 858 } 859 860 return FALSE; 861 } 862 863 BOOL 864 DIALOG_ProgramAttributes(LPWSTR lpszTitle, LPWSTR lpszCmdLine, LPWSTR lpszWorkDir, LPWSTR lpszIconFile, 865 HICON* lphIcon, INT* lpnIconIndex, INT* lpnHotKey, INT* lpnCmdShow, BOOL* lpbNewVDM, INT nSize) 866 { 867 INT_PTR ret; 868 WCHAR szTmpIconFile[MAX_PATHNAME_LEN]; 869 PROGRAM_ATTRIBUTES_CONTEXT ProgramAttributes; 870 DWORD dwSize; 871 DWORD dwType; 872 873 ProgramAttributes.nSize = nSize; 874 ProgramAttributes.lpszTitle = lpszTitle; 875 ProgramAttributes.lpszCmdLine = lpszCmdLine; 876 ProgramAttributes.lpszWorkDir = lpszWorkDir; 877 ProgramAttributes.lpszIconFile = lpszIconFile; 878 ProgramAttributes.lpnCmdShow = lpnCmdShow; 879 ProgramAttributes.lpnHotKey = lpnHotKey; 880 ProgramAttributes.lpbNewVDM = lpbNewVDM; 881 ProgramAttributes.lphIcon = lphIcon; 882 ProgramAttributes.lpnIconIndex = lpnIconIndex; 883 884 dwSize = sizeof(ProgramAttributes.bCheckBinaryType); 885 if (RegQueryValueExW(Globals.hKeyPMSettings, 886 L"CheckBinaryType", 887 0, 888 &dwType, 889 (LPBYTE)&ProgramAttributes.bCheckBinaryType, 890 &dwSize) != ERROR_SUCCESS 891 || dwType != REG_DWORD) 892 { 893 ProgramAttributes.bCheckBinaryType = TRUE; 894 } 895 896 #if 0 897 ProgramAttributes.hTmpIcon = NULL; 898 #else 899 ProgramAttributes.hTmpIcon = *lphIcon; 900 #endif 901 ProgramAttributes.nTmpIconIndex = *lpnIconIndex; 902 ProgramAttributes.lpszTmpIconFile = szTmpIconFile; 903 wcsncpy(szTmpIconFile, lpszIconFile, ARRAYSIZE(szTmpIconFile)); 904 905 ret = DialogBoxParamW(Globals.hInstance, MAKEINTRESOURCEW(IDD_PROGRAM), Globals.hMainWnd, DIALOG_PROGRAM_DlgProc, (LPARAM)&ProgramAttributes); 906 return (ret == IDOK); 907 } 908 909 910 /*********************************************************************** 911 * 912 * DIALOG_Execute 913 */ 914 915 typedef struct _EXECUTE_CONTEXT 916 { 917 HKEY hKeyPMRecentFilesList; 918 DWORD dwMaxFiles; 919 BOOL bCheckBinaryType; 920 } EXECUTE_CONTEXT, *PEXECUTE_CONTEXT; 921 922 static 923 INT_PTR 924 CALLBACK 925 DIALOG_EXECUTE_DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) 926 { 927 WCHAR szFile[MAX_PATHNAME_LEN]; // filename 928 DWORD BinaryType; 929 PEXECUTE_CONTEXT pExecuteContext; 930 931 pExecuteContext = (PEXECUTE_CONTEXT)GetWindowLongPtrW(hDlg, 8); 932 933 switch (uMsg) 934 { 935 case WM_INITDIALOG: 936 { 937 pExecuteContext = (PEXECUTE_CONTEXT)lParam; 938 SetWindowLongPtrW(hDlg, 8, lParam); 939 940 EnableDlgItem(hDlg, IDOK, ValidateEditContents(hDlg, PM_COMMAND)); 941 942 if (pExecuteContext->bCheckBinaryType) 943 { 944 EnableDlgItem(hDlg, PM_NEW_VDM, FALSE); 945 CheckDlgButton(hDlg, PM_NEW_VDM, BST_CHECKED); 946 } 947 else 948 { 949 EnableDlgItem(hDlg, PM_NEW_VDM, TRUE); 950 } 951 952 break; 953 } 954 955 case WM_COMMAND: 956 switch (LOWORD(wParam)) 957 { 958 case PM_SYMBOL: 959 CheckDlgButton(hDlg, PM_SYMBOL, !IsDlgButtonChecked(hDlg, PM_SYMBOL)); 960 return TRUE; 961 962 case PM_NEW_VDM: 963 CheckDlgButton(hDlg, PM_NEW_VDM, !IsDlgButtonChecked(hDlg, PM_NEW_VDM)); 964 return TRUE; 965 966 case PM_BROWSE: 967 { 968 szFile[0] = '\0'; 969 if (DIALOG_BrowsePrograms(hDlg, szFile, ARRAYSIZE(szFile))) 970 { 971 SetWindowTextW(GetDlgItem(hDlg, PM_COMMAND), szFile); 972 SetFocus(GetDlgItem(hDlg, IDOK)); 973 if (pExecuteContext->bCheckBinaryType && 974 (!GetBinaryTypeW(szFile, &BinaryType) || BinaryType != SCS_WOW_BINARY) ) 975 { 976 EnableDlgItem(hDlg, PM_NEW_VDM, FALSE); 977 CheckDlgButton(hDlg, PM_NEW_VDM, BST_CHECKED); 978 } 979 else 980 { 981 EnableDlgItem(hDlg, PM_NEW_VDM, TRUE); 982 CheckDlgButton(hDlg, PM_NEW_VDM, BST_UNCHECKED); 983 } 984 } 985 return TRUE; 986 } 987 988 case PM_COMMAND: 989 { 990 if (HIWORD(wParam) == CBN_EDITCHANGE) 991 { 992 EnableDlgItem(hDlg, IDOK, ValidateEditContents(hDlg, PM_COMMAND)); 993 } 994 return FALSE; 995 } 996 997 case IDHELP: 998 MAIN_MessageBoxIDS(IDS_NOT_IMPLEMENTED, IDS_ERROR, MB_OK); 999 return TRUE; 1000 1001 case IDOK: 1002 { 1003 GetDlgItemTextW(hDlg, PM_COMMAND, szFile, ARRAYSIZE(szFile)); 1004 ShellExecuteW(NULL, NULL, szFile, NULL, NULL, IsDlgButtonChecked(hDlg, PM_SYMBOL) ? SW_SHOWMINNOACTIVE : SW_SHOWNORMAL); 1005 if (Globals.bMinOnRun) 1006 CloseWindow(Globals.hMainWnd); 1007 EndDialog(hDlg, IDOK); 1008 return TRUE; 1009 } 1010 1011 case IDCANCEL: 1012 EndDialog(hDlg, IDCANCEL); 1013 return TRUE; 1014 } 1015 return FALSE; 1016 } 1017 1018 return FALSE; 1019 } 1020 1021 VOID DIALOG_Execute(VOID) 1022 { 1023 EXECUTE_CONTEXT ExecuteContext; 1024 LONG lRet; 1025 DWORD dwSize; 1026 DWORD dwType; 1027 1028 ExecuteContext.hKeyPMRecentFilesList = NULL; 1029 ExecuteContext.bCheckBinaryType = TRUE; 1030 1031 lRet = RegCreateKeyExW(Globals.hKeyProgMan, 1032 L"Recent File List", 1033 0, 1034 NULL, 1035 0, 1036 KEY_READ | KEY_WRITE, 1037 NULL, 1038 &ExecuteContext.hKeyPMRecentFilesList, 1039 NULL); 1040 if (lRet == ERROR_SUCCESS) 1041 { 1042 dwSize = sizeof(ExecuteContext.dwMaxFiles); 1043 lRet = RegQueryValueExW(ExecuteContext.hKeyPMRecentFilesList, 1044 L"Max Files", 1045 NULL, 1046 &dwType, 1047 (LPBYTE)&ExecuteContext.dwMaxFiles, 1048 &dwSize); 1049 if (lRet != ERROR_SUCCESS || dwType != REG_DWORD) 1050 { 1051 ExecuteContext.dwMaxFiles = 4; 1052 dwSize = sizeof(ExecuteContext.dwMaxFiles); 1053 lRet = RegSetValueExW(ExecuteContext.hKeyPMRecentFilesList, 1054 L"Max Files", 1055 0, 1056 REG_DWORD, 1057 (LPBYTE)&ExecuteContext.dwMaxFiles, 1058 sizeof(ExecuteContext.dwMaxFiles)); 1059 } 1060 1061 dwSize = sizeof(ExecuteContext.bCheckBinaryType); 1062 lRet = RegQueryValueExW(Globals.hKeyPMSettings, 1063 L"CheckBinaryType", 1064 NULL, 1065 &dwType, 1066 (LPBYTE)&ExecuteContext.bCheckBinaryType, 1067 &dwSize); 1068 if (lRet != ERROR_SUCCESS || dwType != REG_DWORD) 1069 { 1070 ExecuteContext.bCheckBinaryType = TRUE; 1071 } 1072 } 1073 1074 DialogBoxParamW(Globals.hInstance, MAKEINTRESOURCEW(IDD_EXECUTE), Globals.hMainWnd, DIALOG_EXECUTE_DlgProc, (LPARAM)&ExecuteContext); 1075 1076 if (ExecuteContext.hKeyPMRecentFilesList) 1077 RegCloseKey(ExecuteContext.hKeyPMRecentFilesList); 1078 } 1079