diff --git a/2.x/trunk/CHANGELOG.txt b/2.x/trunk/CHANGELOG.txt index bfd9f141a..780de2ed4 100644 --- a/2.x/trunk/CHANGELOG.txt +++ b/2.x/trunk/CHANGELOG.txt @@ -3,6 +3,7 @@ Process Hacker 2.37 * HIGHLIGHTS: * Updated for Windows 10 + * Added regex search to "Find Handles or DLLs" * Added process exit codes to log * Fixed crash that occurred under some conditions when processes terminated * OTHER CHANGES: diff --git a/2.x/trunk/ProcessHacker/ProcessHacker.rc b/2.x/trunk/ProcessHacker/ProcessHacker.rc index 6c5d9c2c7..68d0516b5 100644 --- a/2.x/trunk/ProcessHacker/ProcessHacker.rc +++ b/2.x/trunk/ProcessHacker/ProcessHacker.rc @@ -711,9 +711,10 @@ CAPTION "Find Handles or DLLs" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN LTEXT "Filter:",IDC_STATIC,7,9,20,8 - EDITTEXT IDC_FILTER,32,8,263,12,ES_AUTOHSCROLL + EDITTEXT IDC_FILTER,32,8,223,12,ES_AUTOHSCROLL PUSHBUTTON "Find",IDOK,300,7,50,14 CONTROL "",IDC_RESULTS,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,7,26,343,200 + CONTROL "&Regex",IDC_REGEX,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,261,9,36,10 END IDD_OBJTOKEN DIALOGEX 0, 0, 260, 260 @@ -2472,6 +2473,17 @@ IDB_COG BITMAP "resources\\cog.bmp" // IDR_RT_MANIFEST RT_MANIFEST "ProcessHacker.manifest" + +///////////////////////////////////////////////////////////////////////////// +// +// AFX_DIALOG_LAYOUT +// + +IDD_FINDOBJECTS AFX_DIALOG_LAYOUT +BEGIN + 0 +END + #endif // English (Australia) resources ///////////////////////////////////////////////////////////////////////////// diff --git a/2.x/trunk/ProcessHacker/ProcessHacker.vcxproj b/2.x/trunk/ProcessHacker/ProcessHacker.vcxproj index 91d668f6e..b6cad2fb5 100644 --- a/2.x/trunk/ProcessHacker/ProcessHacker.vcxproj +++ b/2.x/trunk/ProcessHacker/ProcessHacker.vcxproj @@ -423,6 +423,7 @@ + diff --git a/2.x/trunk/ProcessHacker/ProcessHacker.vcxproj.filters b/2.x/trunk/ProcessHacker/ProcessHacker.vcxproj.filters index 9a3604d26..8c97c145c 100644 --- a/2.x/trunk/ProcessHacker/ProcessHacker.vcxproj.filters +++ b/2.x/trunk/ProcessHacker/ProcessHacker.vcxproj.filters @@ -658,5 +658,8 @@ Resources + + Resources + \ No newline at end of file diff --git a/2.x/trunk/ProcessHacker/actions.c b/2.x/trunk/ProcessHacker/actions.c index 1a21b1338..53f44eb0f 100644 --- a/2.x/trunk/ProcessHacker/actions.c +++ b/2.x/trunk/ProcessHacker/actions.c @@ -2,7 +2,7 @@ * Process Hacker - * UI actions * - * Copyright (C) 2010-2015 wj32 + * Copyright (C) 2010-2016 wj32 * * This file is part of Process Hacker. * @@ -523,7 +523,7 @@ BOOLEAN PhUiLogoffComputer( if (ExitWindowsEx(EWX_LOGOFF, 0)) return TRUE; else - PhShowStatus(hWnd, L"Unable to logoff the computer", 0, GetLastError()); + PhShowStatus(hWnd, L"Unable to log off the computer", 0, GetLastError()); return FALSE; } diff --git a/2.x/trunk/ProcessHacker/appsup.c b/2.x/trunk/ProcessHacker/appsup.c index 022ccec0f..30339d4a5 100644 --- a/2.x/trunk/ProcessHacker/appsup.c +++ b/2.x/trunk/ProcessHacker/appsup.c @@ -2,7 +2,7 @@ * Process Hacker - * application support functions * - * Copyright (C) 2010-2015 wj32 + * Copyright (C) 2010-2016 wj32 * * This file is part of Process Hacker. * @@ -28,6 +28,7 @@ #include #include #include "mxml/mxml.h" +#include "pcre/pcre2.h" #include #pragma warning(push) @@ -2131,3 +2132,35 @@ CleanupExit: return result; } + +PPH_STRING PhPcre2GetErrorMessage( + _In_ INT ErrorCode + ) +{ + PPH_STRING buffer; + SIZE_T bufferLength; + INT_PTR returnLength; + + bufferLength = 128 * sizeof(WCHAR); + buffer = PhCreateStringEx(NULL, bufferLength); + + while (TRUE) + { + if ((returnLength = pcre2_get_error_message(ErrorCode, buffer->Buffer, bufferLength / sizeof(WCHAR) + 1)) >= 0) + break; + + PhDereferenceObject(buffer); + bufferLength *= 2; + + if (bufferLength > 0x1000 * sizeof(WCHAR)) + break; + + buffer = PhCreateStringEx(NULL, bufferLength); + } + + if (returnLength < 0) + return NULL; + + buffer->Length = returnLength * sizeof(WCHAR); + return buffer; +} diff --git a/2.x/trunk/ProcessHacker/findobj.c b/2.x/trunk/ProcessHacker/findobj.c index 36e1398e4..56f1efccf 100644 --- a/2.x/trunk/ProcessHacker/findobj.c +++ b/2.x/trunk/ProcessHacker/findobj.c @@ -2,7 +2,7 @@ * Process Hacker - * object search * - * Copyright (C) 2010-2015 wj32 + * Copyright (C) 2010-2016 wj32 * * This file is part of Process Hacker. * @@ -23,7 +23,9 @@ #include #include #include +#include #include +#include "pcre/pcre2.h" #include #define WM_PH_SEARCH_UPDATE (WM_APP + 801) @@ -70,6 +72,8 @@ static RECT MinimumSize; static HANDLE SearchThreadHandle = NULL; static BOOLEAN SearchStop; static PPH_STRING SearchString; +static pcre2_code *SearchRegexCompiledExpression; +static pcre2_match_data *SearchRegexMatchData; static PPH_LIST SearchResults = NULL; static ULONG SearchResultsAddIndex; static PH_QUEUED_LOCK SearchResultsLock = PH_QUEUED_LOCK_INIT; @@ -207,6 +211,8 @@ static INT_PTR CALLBACK PhpFindObjectsDlgProc( PhInitializeLayoutManager(&WindowLayoutManager, hwndDlg); PhAddLayoutItem(&WindowLayoutManager, GetDlgItem(hwndDlg, IDC_FILTER), NULL, PH_ANCHOR_LEFT | PH_ANCHOR_TOP | PH_ANCHOR_RIGHT); + PhAddLayoutItem(&WindowLayoutManager, GetDlgItem(hwndDlg, IDC_REGEX), + NULL, PH_ANCHOR_TOP | PH_ANCHOR_RIGHT); PhAddLayoutItem(&WindowLayoutManager, GetDlgItem(hwndDlg, IDOK), NULL, PH_ANCHOR_TOP | PH_ANCHOR_RIGHT); PhAddLayoutItem(&WindowLayoutManager, lvHandle, @@ -236,10 +242,13 @@ static INT_PTR CALLBACK PhpFindObjectsDlgProc( ExtendedListView_SetCompareFunction(lvHandle, 2, PhpObjectNameCompareFunction); ExtendedListView_SetCompareFunction(lvHandle, 3, PhpObjectHandleCompareFunction); PhLoadListViewColumnsFromSetting(L"FindObjListViewColumns", lvHandle); + + Button_SetCheck(GetDlgItem(hwndDlg, IDC_REGEX), PhGetIntegerSetting(L"FindObjRegex") ? BST_CHECKED : BST_UNCHECKED); } break; case WM_DESTROY: { + PhSetIntegerSetting(L"FindObjRegex", Button_GetCheck(GetDlgItem(hwndDlg, IDC_REGEX)) == BST_CHECKED); PhSaveWindowPlacementToSetting(L"FindObjWindowPosition", L"FindObjWindowSize", hwndDlg); PhSaveListViewColumnsToSetting(L"FindObjListViewColumns", PhFindObjectsListViewHandle); } @@ -284,7 +293,47 @@ static INT_PTR CALLBACK PhpFindObjectsDlgProc( { ULONG i; - // Cleanup previous results. + PhMoveReference(&SearchString, PhGetWindowText(GetDlgItem(hwndDlg, IDC_FILTER))); + + if (SearchRegexCompiledExpression) + { + pcre2_code_free(SearchRegexCompiledExpression); + SearchRegexCompiledExpression = NULL; + } + + if (SearchRegexMatchData) + { + pcre2_match_data_free(SearchRegexMatchData); + SearchRegexMatchData = NULL; + } + + if (Button_GetCheck(GetDlgItem(hwndDlg, IDC_REGEX)) == BST_CHECKED) + { + int errorCode; + PCRE2_SIZE errorOffset; + + SearchRegexCompiledExpression = pcre2_compile( + SearchString->Buffer, + PCRE2_ZERO_TERMINATED, + PCRE2_CASELESS | PCRE2_DOTALL, + &errorCode, + &errorOffset, + NULL + ); + + if (!SearchRegexCompiledExpression) + { + PhShowError(hwndDlg, L"Unable to compile the regular expression: \"%s\" at position %zu.", + PhGetStringOrDefault(PhAutoDereferenceObject(PhPcre2GetErrorMessage(errorCode)), L"Unknown error"), + errorOffset + ); + break; + } + + SearchRegexMatchData = pcre2_match_data_create_from_pattern(SearchRegexCompiledExpression, NULL); + } + + // Clean up previous results. ListView_DeleteAllItems(PhFindObjectsListViewHandle); @@ -308,7 +357,6 @@ static INT_PTR CALLBACK PhpFindObjectsDlgProc( // Start the search. - SearchString = PhGetWindowText(GetDlgItem(hwndDlg, IDC_FILTER)); SearchResults = PhCreateList(128); SearchResultsAddIndex = 0; @@ -316,10 +364,7 @@ static INT_PTR CALLBACK PhpFindObjectsDlgProc( if (!SearchThreadHandle) { - PhDereferenceObject(SearchString); - PhDereferenceObject(SearchResults); - SearchString = NULL; - SearchResults = NULL; + PhClearReference(&SearchResults); break; } @@ -640,8 +685,6 @@ static INT_PTR CALLBACK PhpFindObjectsDlgProc( // Add any un-added items. SendMessage(hwndDlg, WM_PH_SEARCH_UPDATE, 0, 0); - PhDereferenceObject(SearchString); - NtWaitForSingleObject(SearchThreadHandle, FALSE, NULL); NtClose(SearchThreadHandle); SearchThreadHandle = NULL; @@ -669,6 +712,28 @@ static INT_PTR CALLBACK PhpFindObjectsDlgProc( return FALSE; } +static BOOLEAN MatchSearchString( + _In_ PPH_STRINGREF Input + ) +{ + if (SearchRegexCompiledExpression && SearchRegexMatchData) + { + return pcre2_match( + SearchRegexCompiledExpression, + Input->Buffer, + Input->Length / sizeof(WCHAR), + 0, + 0, + SearchRegexMatchData, + NULL + ) >= 0; + } + else + { + return PhFindStringInStringRef(Input, &SearchString->sr, TRUE) != -1; + } +} + typedef struct _SEARCH_HANDLE_CONTEXT { BOOLEAN NeedToFree; @@ -699,7 +764,7 @@ static NTSTATUS NTAPI SearchHandleFunction( upperBestObjectName = PhDuplicateString(bestObjectName); PhUpperString(upperBestObjectName); - if (PhFindStringInString(upperBestObjectName, 0, SearchString->Buffer) != -1 || + if (MatchSearchString(&upperBestObjectName->sr) || (UseSearchPointer && context->HandleInfo->Object == (PVOID)SearchPointer)) { PPHP_OBJECT_SEARCH_RESULT searchResult; @@ -748,7 +813,7 @@ static BOOLEAN NTAPI EnumModulesCallback( upperFileName = PhDuplicateString(Module->FileName); PhUpperString(upperFileName); - if (PhFindStringInString(upperFileName, 0, SearchString->Buffer) != -1 || + if (MatchSearchString(&upperFileName->sr) || (UseSearchPointer && Module->BaseAddress == (PVOID)SearchPointer)) { PPHP_OBJECT_SEARCH_RESULT searchResult; diff --git a/2.x/trunk/ProcessHacker/include/phapp.h b/2.x/trunk/ProcessHacker/include/phapp.h index 486450f53..c236db86b 100644 --- a/2.x/trunk/ProcessHacker/include/phapp.h +++ b/2.x/trunk/ProcessHacker/include/phapp.h @@ -583,6 +583,10 @@ BOOLEAN PhShellOpenKey2( _In_ PPH_STRING KeyName ); +PPH_STRING PhPcre2GetErrorMessage( + _In_ INT ErrorCode + ); + #define PH_LOAD_SHARED_IMAGE(Name, Type) LoadImage(PhInstanceHandle, (Name), (Type), 0, 0, LR_SHARED) FORCEINLINE PVOID PhpGenericPropertyPageHeader( diff --git a/2.x/trunk/ProcessHacker/log.c b/2.x/trunk/ProcessHacker/log.c index e68a15a56..431f456a0 100644 --- a/2.x/trunk/ProcessHacker/log.c +++ b/2.x/trunk/ProcessHacker/log.c @@ -2,7 +2,7 @@ * Process Hacker - * logging system * - * Copyright (C) 2010 wj32 + * Copyright (C) 2010-2016 wj32 * * This file is part of Process Hacker. * diff --git a/2.x/trunk/ProcessHacker/logwnd.c b/2.x/trunk/ProcessHacker/logwnd.c index dc2928523..656f3f98f 100644 --- a/2.x/trunk/ProcessHacker/logwnd.c +++ b/2.x/trunk/ProcessHacker/logwnd.c @@ -2,7 +2,7 @@ * Process Hacker - * log window * - * Copyright (C) 2010-2011 wj32 + * Copyright (C) 2010-2016 wj32 * * This file is part of Process Hacker. * diff --git a/2.x/trunk/ProcessHacker/memedit.c b/2.x/trunk/ProcessHacker/memedit.c index 2fd6eae46..adc5004a7 100644 --- a/2.x/trunk/ProcessHacker/memedit.c +++ b/2.x/trunk/ProcessHacker/memedit.c @@ -2,7 +2,7 @@ * Process Hacker - * memory editor window * - * Copyright (C) 2010-2015 wj32 + * Copyright (C) 2010-2016 wj32 * * This file is part of Process Hacker. * diff --git a/2.x/trunk/ProcessHacker/memrslt.c b/2.x/trunk/ProcessHacker/memrslt.c index 99ad782f0..ee3c9d1ad 100644 --- a/2.x/trunk/ProcessHacker/memrslt.c +++ b/2.x/trunk/ProcessHacker/memrslt.c @@ -2,7 +2,7 @@ * Process Hacker - * memory search results * - * Copyright (C) 2010-2011 wj32 + * Copyright (C) 2010-2016 wj32 * * This file is part of Process Hacker. * @@ -115,8 +115,8 @@ static VOID FilterResults( { PPH_STRING selectedChoice = NULL; PPH_LIST results; - pcre2_code *expression; - pcre2_match_data *match_data; + pcre2_code *compiledExpression; + pcre2_match_data *matchData; results = Context->Results; @@ -187,7 +187,7 @@ static VOID FilterResults( int errorCode; PCRE2_SIZE errorOffset; - expression = pcre2_compile( + compiledExpression = pcre2_compile( selectedChoice->Buffer, PCRE2_ZERO_TERMINATED, (Type == FILTER_REGEX_IGNORECASE ? PCRE2_CASELESS : 0) | PCRE2_DOTALL, @@ -196,21 +196,16 @@ static VOID FilterResults( NULL ); - if (!expression) + if (!compiledExpression) { - PCRE2_UCHAR errorString[512] = L""; - - // TODO: This returns a negative error code if the buffer is too small. - pcre2_get_error_message(errorCode, errorString, sizeof(errorString)); - PhShowError(hwndDlg, L"Unable to compile the regular expression: \"%s\" at position %zu.", - errorString, + PhGetStringOrDefault(PhAutoDereferenceObject(PhPcre2GetErrorMessage(errorCode)), L"Unknown error"), errorOffset ); continue; } - match_data = pcre2_match_data_create_from_pattern(expression, NULL); + matchData = pcre2_match_data_create_from_pattern(compiledExpression, NULL); newResults = PhCreateList(1024); @@ -219,12 +214,12 @@ static VOID FilterResults( PPH_MEMORY_RESULT result = results->Items[i]; if (pcre2_match( - expression, + compiledExpression, result->Display.Buffer, result->Display.Length / sizeof(WCHAR), 0, 0, - match_data, + matchData, NULL ) >= 0) { @@ -233,8 +228,8 @@ static VOID FilterResults( } } - pcre2_match_data_free(match_data); - pcre2_code_free(expression); + pcre2_match_data_free(matchData); + pcre2_code_free(compiledExpression); } if (newResults) diff --git a/2.x/trunk/ProcessHacker/resource.h b/2.x/trunk/ProcessHacker/resource.h index 561fdf63f..3a4fe3c89 100644 --- a/2.x/trunk/ProcessHacker/resource.h +++ b/2.x/trunk/ProcessHacker/resource.h @@ -525,6 +525,7 @@ #define IDC_ZPAGINGMAPPEDWRITESDELTA_V 1371 #define IDC_ZLISTMODIFIEDPAGEFILE_V 1373 #define IDC_SECTION 1375 +#define IDC_REGEX 1377 #define ID_MAINWND_PROCESSTL 2001 #define ID_MAINWND_SERVICETL 2002 #define ID_MAINWND_NETWORKTL 2003 @@ -735,7 +736,7 @@ #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 213 #define _APS_NEXT_COMMAND_VALUE 40290 -#define _APS_NEXT_CONTROL_VALUE 1377 +#define _APS_NEXT_CONTROL_VALUE 1378 #define _APS_NEXT_SYMED_VALUE 169 #endif #endif diff --git a/2.x/trunk/ProcessHacker/settings.c b/2.x/trunk/ProcessHacker/settings.c index 5bc26fa42..959202708 100644 --- a/2.x/trunk/ProcessHacker/settings.c +++ b/2.x/trunk/ProcessHacker/settings.c @@ -2,7 +2,7 @@ * Process Hacker - * program settings * - * Copyright (C) 2010-2015 wj32 + * Copyright (C) 2010-2016 wj32 * * This file is part of Process Hacker. * @@ -88,6 +88,7 @@ VOID PhSettingsInitialization( PhpAddIntegerSetting(L"EnableStage2", L"1"); PhpAddIntegerSetting(L"EnableWarnings", L"1"); PhpAddStringSetting(L"EnvironmentListViewColumns", L""); + PhpAddIntegerSetting(L"FindObjRegex", L"0"); PhpAddStringSetting(L"FindObjListViewColumns", L""); PhpAddIntegerPairSetting(L"FindObjWindowPosition", L"350,350"); PhpAddIntegerPairSetting(L"FindObjWindowSize", L"550,420"); diff --git a/2.x/trunk/plugins/ToolStatus/ToolStatus.rc b/2.x/trunk/plugins/ToolStatus/ToolStatus.rc index f77939b69..730441d94 100644 --- a/2.x/trunk/plugins/ToolStatus/ToolStatus.rc +++ b/2.x/trunk/plugins/ToolStatus/ToolStatus.rc @@ -96,10 +96,10 @@ BEGIN CONTROL "Enable status bar",IDC_ENABLE_STATUSBAR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,19,72,10 CONTROL "Resolve ghost windows to hung windows",IDC_RESOLVEGHOSTWINDOWS, "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,32,152,10 - DEFPUSHBUTTON "OK",IDOK,79,60,50,14 - PUSHBUTTON "Cancel",IDCANCEL,133,60,50,14 CONTROL "Auto-hide main menu (Alt or F10 key toggle)",IDC_ENABLE_AUTOHIDE_MENU, "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,44,157,10 + DEFPUSHBUTTON "OK",IDOK,79,60,50,14 + PUSHBUTTON "Cancel",IDCANCEL,133,60,50,14 END IDD_CUSTOMIZE_TB DIALOGEX 0, 0, 369, 191 @@ -107,23 +107,23 @@ STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSM CAPTION "Customize Toolbar" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN - DEFPUSHBUTTON "Close",IDCANCEL,312,170,50,14 - PUSHBUTTON "Reset",IDC_RESET,258,170,50,14 - LISTBOX IDC_AVAILABLE,7,18,122,117,LBS_OWNERDRAWFIXED | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP LTEXT "Available toolbar buttons:",IDC_STATIC,7,7,85,8 + LISTBOX IDC_AVAILABLE,7,18,122,117,LBS_OWNERDRAWFIXED | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP PUSHBUTTON "Add >",IDC_ADD,133,50,50,14 PUSHBUTTON "< Remove",IDC_REMOVE,134,68,50,14 - LISTBOX IDC_CURRENT,187,18,122,117,LBS_OWNERDRAWFIXED | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP LTEXT "Current toolbar buttons:",IDC_STATIC,188,7,81,8 - COMBOBOX IDC_SEARCHOPTIONS,56,155,123,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - COMBOBOX IDC_TEXTOPTIONS,56,139,123,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + LISTBOX IDC_CURRENT,187,18,122,117,LBS_OWNERDRAWFIXED | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP PUSHBUTTON "Move Up",IDC_MOVEUP,312,18,50,14 PUSHBUTTON "Move Down",IDC_MOVEDOWN,312,36,50,14 LTEXT "Text options:",IDC_STATIC,7,142,44,8 + COMBOBOX IDC_TEXTOPTIONS,56,139,123,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP LTEXT "Search box:",IDC_STATIC,7,158,45,8 + COMBOBOX IDC_SEARCHOPTIONS,56,155,123,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP CONTROL "Enable modern icons",IDC_ENABLE_MODERN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,188,141,83,10 CONTROL "Auto-hide main menu (Alt or F10 key toggle)",IDC_ENABLE_AUTOHIDE_MENU, "Button",BS_AUTOCHECKBOX | WS_TABSTOP,188,154,157,10 + PUSHBUTTON "Reset",IDC_RESET,258,170,50,14 + DEFPUSHBUTTON "Close",IDCANCEL,312,170,50,14 END IDD_CUSTOMIZE_SB DIALOGEX 0, 0, 373, 142 @@ -131,16 +131,16 @@ STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSM CAPTION "Customize Status Bar" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN - DEFPUSHBUTTON "Close",IDCANCEL,316,121,50,14 - PUSHBUTTON "Reset",IDC_RESET,316,103,50,14 - LISTBOX IDC_AVAILABLE,7,18,122,117,LBS_OWNERDRAWFIXED | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP LTEXT "Available status bar entries:",-1,7,7,91,8 + LISTBOX IDC_AVAILABLE,7,18,122,117,LBS_OWNERDRAWFIXED | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP PUSHBUTTON "Add >",IDC_ADD,133,50,50,14 PUSHBUTTON "< Remove",IDC_REMOVE,134,68,50,14 - LISTBOX IDC_CURRENT,187,18,122,117,LBS_OWNERDRAWFIXED | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP LTEXT "Current status bar entries:",-1,188,7,87,8 + LISTBOX IDC_CURRENT,187,18,122,117,LBS_OWNERDRAWFIXED | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP PUSHBUTTON "Move Up",IDC_MOVEUP,316,18,50,14 PUSHBUTTON "Move Down",IDC_MOVEDOWN,316,36,50,14 + PUSHBUTTON "Reset",IDC_RESET,316,103,50,14 + DEFPUSHBUTTON "Close",IDCANCEL,316,121,50,14 END