mirror of
https://github.com/mirror/processhacker
synced 2026-06-08 16:03:24 +00:00
650349dd46
* added PhSvcApiAddAccountRight git-svn-id: svn://svn.code.sf.net/p/processhacker/code@4238 21ef857c-d57f-4fe0-8362-d861dc6d29cd
361 lines
13 KiB
C
361 lines
13 KiB
C
/*
|
|
* Process Hacker -
|
|
* choice dialog
|
|
*
|
|
* Copyright (C) 2010-2011 wj32
|
|
*
|
|
* This file is part of Process Hacker.
|
|
*
|
|
* Process Hacker is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* Process Hacker 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 General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <phapp.h>
|
|
#include <settings.h>
|
|
#include <windowsx.h>
|
|
|
|
typedef struct _CHOICE_DIALOG_CONTEXT
|
|
{
|
|
PWSTR Title;
|
|
PWSTR Message;
|
|
PWSTR *Choices;
|
|
ULONG NumberOfChoices;
|
|
PWSTR Option;
|
|
ULONG Flags;
|
|
PPH_STRING *SelectedChoice;
|
|
PBOOLEAN SelectedOption;
|
|
PWSTR SavedChoicesSettingName;
|
|
|
|
HWND ComboBoxHandle;
|
|
} CHOICE_DIALOG_CONTEXT, *PCHOICE_DIALOG_CONTEXT;
|
|
|
|
INT_PTR CALLBACK PhpChoiceDlgProc(
|
|
__in HWND hwndDlg,
|
|
__in UINT uMsg,
|
|
__in WPARAM wParam,
|
|
__in LPARAM lParam
|
|
);
|
|
|
|
/**
|
|
* Prompts the user for input.
|
|
*
|
|
* \remarks If \c PH_CHOICE_DIALOG_PASSWORD is specified, the string
|
|
* returned in \a SelectedChoice is NOT auto-dereferenced.
|
|
*/
|
|
BOOLEAN PhaChoiceDialog(
|
|
__in HWND ParentWindowHandle,
|
|
__in PWSTR Title,
|
|
__in PWSTR Message,
|
|
__in_opt PWSTR *Choices,
|
|
__in_opt ULONG NumberOfChoices,
|
|
__in_opt PWSTR Option,
|
|
__in ULONG Flags,
|
|
__inout PPH_STRING *SelectedChoice,
|
|
__inout_opt PBOOLEAN SelectedOption,
|
|
__in_opt PWSTR SavedChoicesSettingName
|
|
)
|
|
{
|
|
CHOICE_DIALOG_CONTEXT context;
|
|
|
|
context.Title = Title;
|
|
context.Message = Message;
|
|
context.Choices = Choices;
|
|
context.NumberOfChoices = NumberOfChoices;
|
|
context.Option = Option;
|
|
context.Flags = Flags;
|
|
context.SelectedChoice = SelectedChoice;
|
|
context.SelectedOption = SelectedOption;
|
|
context.SavedChoicesSettingName = SavedChoicesSettingName;
|
|
|
|
return DialogBoxParam(
|
|
PhInstanceHandle,
|
|
MAKEINTRESOURCE(IDD_CHOOSE),
|
|
ParentWindowHandle,
|
|
PhpChoiceDlgProc,
|
|
(LPARAM)&context
|
|
) == IDOK;
|
|
}
|
|
|
|
INT_PTR CALLBACK PhpChoiceDlgProc(
|
|
__in HWND hwndDlg,
|
|
__in UINT uMsg,
|
|
__in WPARAM wParam,
|
|
__in LPARAM lParam
|
|
)
|
|
{
|
|
switch (uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
{
|
|
PCHOICE_DIALOG_CONTEXT context = (PCHOICE_DIALOG_CONTEXT)lParam;
|
|
ULONG type;
|
|
ULONG i;
|
|
HWND comboBoxHandle;
|
|
HWND checkBoxHandle;
|
|
RECT checkBoxRect;
|
|
RECT rect;
|
|
ULONG diff;
|
|
|
|
SetProp(hwndDlg, PhMakeContextAtom(), (HANDLE)context);
|
|
PhCenterWindow(hwndDlg, GetParent(hwndDlg));
|
|
|
|
SetWindowText(hwndDlg, context->Title);
|
|
SetWindowText(GetDlgItem(hwndDlg, IDC_MESSAGE), context->Message);
|
|
|
|
type = context->Flags & PH_CHOICE_DIALOG_TYPE_MASK;
|
|
|
|
// Select the control to show, depending on the type. This is
|
|
// because it is impossible to change the style of the combo box
|
|
// after it is created.
|
|
switch (type)
|
|
{
|
|
case PH_CHOICE_DIALOG_USER_CHOICE:
|
|
comboBoxHandle = GetDlgItem(hwndDlg, IDC_CHOICEUSER);
|
|
ShowWindow(GetDlgItem(hwndDlg, IDC_CHOICEUSER), SW_SHOW);
|
|
break;
|
|
case PH_CHOICE_DIALOG_PASSWORD:
|
|
comboBoxHandle = GetDlgItem(hwndDlg, IDC_CHOICESIMPLE);
|
|
ShowWindow(GetDlgItem(hwndDlg, IDC_CHOICESIMPLE), SW_SHOW);
|
|
|
|
// Disable combo box features since it isn't a combo box.
|
|
context->SavedChoicesSettingName = NULL;
|
|
break;
|
|
case PH_CHOICE_DIALOG_CHOICE:
|
|
default:
|
|
comboBoxHandle = GetDlgItem(hwndDlg, IDC_CHOICE);
|
|
ShowWindow(GetDlgItem(hwndDlg, IDC_CHOICE), SW_SHOW);
|
|
break;
|
|
}
|
|
|
|
context->ComboBoxHandle = comboBoxHandle;
|
|
|
|
checkBoxHandle = GetDlgItem(hwndDlg, IDC_OPTION);
|
|
|
|
if (type == PH_CHOICE_DIALOG_PASSWORD)
|
|
{
|
|
// Nothing
|
|
}
|
|
else if (type == PH_CHOICE_DIALOG_USER_CHOICE && context->SavedChoicesSettingName)
|
|
{
|
|
PPH_STRING savedChoices = PhGetStringSetting(context->SavedChoicesSettingName);
|
|
ULONG indexOfDelim;
|
|
PPH_STRING savedChoice;
|
|
|
|
i = 0;
|
|
|
|
// Split the saved choices using the delimiter.
|
|
while (i < (ULONG)savedChoices->Length / 2)
|
|
{
|
|
// BUG BUG BUG - what if the user saves "\s"?
|
|
indexOfDelim = PhFindStringInString(savedChoices, i, L"\\s");
|
|
|
|
if (indexOfDelim == -1)
|
|
indexOfDelim = savedChoices->Length / 2;
|
|
|
|
savedChoice = PhSubstring(savedChoices, i, indexOfDelim - i);
|
|
|
|
if (savedChoice->Length != 0)
|
|
{
|
|
PPH_STRING unescaped;
|
|
|
|
unescaped = PhUnescapeStringForDelimiter(savedChoice, '\\');
|
|
ComboBox_InsertString(comboBoxHandle, -1, unescaped->Buffer);
|
|
PhDereferenceObject(unescaped);
|
|
}
|
|
|
|
PhDereferenceObject(savedChoice);
|
|
|
|
i = indexOfDelim + 2;
|
|
}
|
|
|
|
PhDereferenceObject(savedChoices);
|
|
}
|
|
else
|
|
{
|
|
for (i = 0; i < context->NumberOfChoices; i++)
|
|
{
|
|
ComboBox_AddString(comboBoxHandle, context->Choices[i]);
|
|
}
|
|
|
|
context->SavedChoicesSettingName = NULL; // make sure we don't try to save the choices
|
|
}
|
|
|
|
SetFocus(comboBoxHandle);
|
|
|
|
if (type == PH_CHOICE_DIALOG_PASSWORD)
|
|
{
|
|
if (*context->SelectedChoice)
|
|
SetWindowText(comboBoxHandle, (*context->SelectedChoice)->Buffer);
|
|
|
|
Edit_SetSel(comboBoxHandle, 0, -1);
|
|
}
|
|
else if (type == PH_CHOICE_DIALOG_USER_CHOICE || type == PH_CHOICE_DIALOG_CHOICE)
|
|
{
|
|
// If we failed to choose a default choice based on what was specified,
|
|
// select the first one if possible, or set the text directly.
|
|
if (!(*context->SelectedChoice) || ComboBox_SelectString(
|
|
comboBoxHandle, -1, (*context->SelectedChoice)->Buffer) == CB_ERR)
|
|
{
|
|
if (type == PH_CHOICE_DIALOG_USER_CHOICE && *context->SelectedChoice)
|
|
{
|
|
SetWindowText(comboBoxHandle, (*context->SelectedChoice)->Buffer);
|
|
}
|
|
else if (type == PH_CHOICE_DIALOG_CHOICE && context->NumberOfChoices != 0)
|
|
{
|
|
ComboBox_SelectString(comboBoxHandle, -1, context->Choices[0]);
|
|
}
|
|
}
|
|
|
|
if (type == PH_CHOICE_DIALOG_USER_CHOICE)
|
|
ComboBox_SetEditSel(comboBoxHandle, 0, -1);
|
|
}
|
|
|
|
if (context->Option)
|
|
{
|
|
SetWindowText(checkBoxHandle, context->Option);
|
|
|
|
if (context->SelectedOption)
|
|
Button_SetCheck(checkBoxHandle, *context->SelectedOption ? BST_CHECKED : BST_UNCHECKED);
|
|
}
|
|
else
|
|
{
|
|
// Hide the check box and move the buttons up.
|
|
|
|
ShowWindow(checkBoxHandle, SW_HIDE);
|
|
GetWindowRect(checkBoxHandle, &checkBoxRect);
|
|
MapWindowPoints(NULL, hwndDlg, (POINT *)&checkBoxRect, 2);
|
|
GetWindowRect(GetDlgItem(hwndDlg, IDOK), &rect);
|
|
MapWindowPoints(NULL, hwndDlg, (POINT *)&rect, 2);
|
|
diff = rect.top - checkBoxRect.top;
|
|
|
|
// OK
|
|
rect.top -= diff;
|
|
rect.bottom -= diff;
|
|
SetWindowPos(GetDlgItem(hwndDlg, IDOK), NULL, rect.left, rect.top,
|
|
rect.right - rect.left, rect.bottom - rect.top,
|
|
SWP_NOACTIVATE | SWP_NOZORDER);
|
|
|
|
// Cancel
|
|
GetWindowRect(GetDlgItem(hwndDlg, IDCANCEL), &rect);
|
|
MapWindowPoints(NULL, hwndDlg, (POINT *)&rect, 2);
|
|
rect.top -= diff;
|
|
rect.bottom -= diff;
|
|
SetWindowPos(GetDlgItem(hwndDlg, IDCANCEL), NULL, rect.left, rect.top,
|
|
rect.right - rect.left, rect.bottom - rect.top,
|
|
SWP_NOACTIVATE | SWP_NOZORDER);
|
|
|
|
// Window
|
|
GetWindowRect(hwndDlg, &rect);
|
|
rect.bottom -= diff;
|
|
SetWindowPos(hwndDlg, NULL, rect.left, rect.top,
|
|
rect.right - rect.left, rect.bottom - rect.top,
|
|
SWP_NOACTIVATE | SWP_NOZORDER);
|
|
}
|
|
|
|
SetFocus(comboBoxHandle);
|
|
}
|
|
break;
|
|
case WM_DESTROY:
|
|
{
|
|
RemoveProp(hwndDlg, PhMakeContextAtom());
|
|
}
|
|
break;
|
|
case WM_COMMAND:
|
|
{
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case IDCANCEL:
|
|
EndDialog(hwndDlg, IDCANCEL);
|
|
break;
|
|
case IDOK:
|
|
{
|
|
PCHOICE_DIALOG_CONTEXT context = (PCHOICE_DIALOG_CONTEXT)GetProp(hwndDlg, PhMakeContextAtom());
|
|
PPH_STRING selectedChoice;
|
|
|
|
if ((context->Flags & PH_CHOICE_DIALOG_TYPE_MASK) != PH_CHOICE_DIALOG_PASSWORD)
|
|
{
|
|
selectedChoice = PHA_DEREFERENCE(PhGetWindowText(context->ComboBoxHandle));
|
|
*context->SelectedChoice = selectedChoice;
|
|
}
|
|
else
|
|
{
|
|
// Password values are never auto-dereferenced.
|
|
selectedChoice = PhGetWindowText(context->ComboBoxHandle);
|
|
*context->SelectedChoice = selectedChoice;
|
|
}
|
|
|
|
if (context->Option && context->SelectedOption)
|
|
*context->SelectedOption = Button_GetCheck(GetDlgItem(hwndDlg, IDC_OPTION)) == BST_CHECKED;
|
|
|
|
if (context->SavedChoicesSettingName)
|
|
{
|
|
PH_STRING_BUILDER savedChoices;
|
|
ULONG i;
|
|
ULONG choicesToSave = PH_CHOICE_DIALOG_SAVED_CHOICES;
|
|
PPH_STRING choice;
|
|
PPH_STRING escaped;
|
|
|
|
PhInitializeStringBuilder(&savedChoices, 100);
|
|
|
|
// Push the selected choice to the top, then save the others.
|
|
|
|
if (selectedChoice->Length != 0)
|
|
{
|
|
escaped = PhEscapeStringForDelimiter(selectedChoice, '\\');
|
|
PhAppendStringBuilder(&savedChoices, escaped);
|
|
PhDereferenceObject(escaped);
|
|
PhAppendStringBuilder2(&savedChoices, L"\\s");
|
|
}
|
|
|
|
for (i = 1; i < choicesToSave; i++)
|
|
{
|
|
choice = PhGetComboBoxString(context->ComboBoxHandle, i - 1);
|
|
|
|
if (!choice)
|
|
break;
|
|
|
|
// Don't save the choice if it's the same as the one
|
|
// entered by the user (since we already saved it above).
|
|
if (PhEqualString(choice, selectedChoice, FALSE))
|
|
{
|
|
PhDereferenceObject(choice);
|
|
choicesToSave++; // useless for now, but may be needed in the future
|
|
continue;
|
|
}
|
|
|
|
escaped = PhEscapeStringForDelimiter(choice, '\\');
|
|
PhAppendStringBuilder(&savedChoices, escaped);
|
|
PhDereferenceObject(escaped);
|
|
PhDereferenceObject(choice);
|
|
|
|
PhAppendStringBuilder2(&savedChoices, L"\\s");
|
|
}
|
|
|
|
if (PhEndsWithString2(savedChoices.String, L"\\s", FALSE))
|
|
PhRemoveStringBuilder(&savedChoices, savedChoices.String->Length / 2 - 2, 2);
|
|
|
|
PhSetStringSetting2(context->SavedChoicesSettingName, &savedChoices.String->sr);
|
|
PhDeleteStringBuilder(&savedChoices);
|
|
}
|
|
|
|
EndDialog(hwndDlg, IDOK);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|