PPH_STRING PhpGetX500Value( __in PPH_STRING String, __in PPH_STRINGREF KeyName ) { WCHAR keyNamePlusEquals[10]; SIZE_T keyNameLength; ULONG_PTR startIndex; ULONG_PTR endIndex; keyNameLength = KeyName->Length / sizeof(WCHAR); assert(!(keyNameLength > sizeof(keyNamePlusEquals) / sizeof(WCHAR) - 2)); memcpy(keyNamePlusEquals, KeyName->Buffer, KeyName->Length); keyNamePlusEquals[keyNameLength] = '='; keyNamePlusEquals[keyNameLength + 1] = 0; // Find "Key=". startIndex = PhFindStringInString(String, 0, keyNamePlusEquals); if (startIndex == -1) return NULL; startIndex += keyNameLength + 1; if (startIndex * sizeof(WCHAR) >= String->Length) return NULL; // Is the value quoted? if (String->Buffer[startIndex] == '"') { startIndex++; if (startIndex * sizeof(WCHAR) >= String->Length) return NULL; endIndex = PhFindCharInString(String, startIndex, '"'); // It's an error if we didn't find the matching quotation mark. if (endIndex == -1) return NULL; } else { endIndex = PhFindCharInString(String, startIndex, ','); // If we didn't find a comma, it means the key/value pair is // the last one in the string. if (endIndex == -1) endIndex = String->Length / sizeof(WCHAR); } return PhSubstring(String, startIndex, endIndex - startIndex); }
NTSTATUS PhSaveSettings( _In_ PWSTR FileName ) { NTSTATUS status; HANDLE fileHandle; mxml_node_t *topNode; PH_HASHTABLE_ENUM_CONTEXT enumContext; PPH_SETTING setting; topNode = mxmlNewElement(MXML_NO_PARENT, "settings"); PhAcquireQueuedLockShared(&PhSettingsLock); PhBeginEnumHashtable(PhSettingsHashtable, &enumContext); while (setting = PhNextEnumHashtable(&enumContext)) { PPH_STRING settingValue; settingValue = PhpSettingToString(setting->Type, setting); PhpCreateSettingElement(topNode, &setting->Name, &settingValue->sr); PhDereferenceObject(settingValue); } // Write the ignored settings. { ULONG i; for (i = 0; i < PhIgnoredSettings->Count; i++) { PPH_STRING settingValue; setting = PhIgnoredSettings->Items[i]; settingValue = setting->u.Pointer; PhpCreateSettingElement(topNode, &setting->Name, &settingValue->sr); } } PhReleaseQueuedLockShared(&PhSettingsLock); // Create the directory if it does not exist. { PPH_STRING fullPath; ULONG indexOfFileName; PPH_STRING directoryName; fullPath = PhGetFullPath(FileName, &indexOfFileName); if (fullPath) { if (indexOfFileName != -1) { directoryName = PhSubstring(fullPath, 0, indexOfFileName); //SHCreateDirectoryEx(NULL, directoryName->Buffer, NULL); PhDereferenceObject(directoryName); } PhDereferenceObject(fullPath); } } status = PhCreateFileWin32( &fileHandle, FileName, FILE_GENERIC_WRITE, 0, FILE_SHARE_READ, FILE_OVERWRITE_IF, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ); if (!NT_SUCCESS(status)) { mxmlDelete(topNode); return status; } mxmlSaveFd(topNode, fileHandle, PhpSettingsSaveCallback); mxmlDelete(topNode); NtClose(fileHandle); return STATUS_SUCCESS; }
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; SIZE_T 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_PTR indexOfDelim; PPH_STRING savedChoice; i = 0; // Split the saved choices using the delimiter. while (i < 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 } 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) || PhSelectComboBoxString( comboBoxHandle, (*context->SelectedChoice)->Buffer, FALSE) == 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_SetCurSel(comboBoxHandle, 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); } SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)comboBoxHandle, TRUE); } 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 = PH_AUTO(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->sr); 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->sr); PhDereferenceObject(escaped); PhDereferenceObject(choice); PhAppendStringBuilder2(&savedChoices, L"\\s"); } if (PhEndsWithString2(savedChoices.String, L"\\s", FALSE)) PhRemoveEndStringBuilder(&savedChoices, 2); PhSetStringSetting2(context->SavedChoicesSettingName, &savedChoices.String->sr); PhDeleteStringBuilder(&savedChoices); } EndDialog(hwndDlg, IDOK); } break; } } break; } return FALSE; }