BOOLEAN PhCmLoadSettingsEx( _In_ HWND TreeNewHandle, _In_opt_ PPH_CM_MANAGER Manager, _In_ ULONG Flags, _In_ PPH_STRINGREF Settings, _In_opt_ PPH_STRINGREF SortSettings ) { BOOLEAN result = FALSE; PH_STRINGREF columnPart; PH_STRINGREF remainingColumnPart; PH_STRINGREF valuePart; PH_STRINGREF subPart; ULONG64 integer; ULONG total; BOOLEAN hasFixedColumn; ULONG count; ULONG i; PPH_HASHTABLE columnHashtable; PH_HASHTABLE_ENUM_CONTEXT enumContext; PPH_KEY_VALUE_PAIR pair; LONG orderArray[PH_CM_ORDER_LIMIT]; LONG maxOrder; if (Settings->Length != 0) { columnHashtable = PhCreateSimpleHashtable(20); remainingColumnPart = *Settings; while (remainingColumnPart.Length != 0) { PPH_TREENEW_COLUMN column; ULONG id; ULONG displayIndex; ULONG width; PhSplitStringRefAtChar(&remainingColumnPart, '|', &columnPart, &remainingColumnPart); if (columnPart.Length != 0) { // Id PhSplitStringRefAtChar(&columnPart, ',', &valuePart, &columnPart); if (valuePart.Length == 0) goto CleanupExit; if (valuePart.Buffer[0] == '+') { PH_STRINGREF pluginName; ULONG subId; PPH_CM_COLUMN cmColumn; // This is a plugin-owned column. if (!Manager) continue; if (!PhEmParseCompoundId(&valuePart, &pluginName, &subId)) continue; cmColumn = PhCmFindColumn(Manager, &pluginName, subId); if (!cmColumn) continue; // can't find the column, skip this part id = cmColumn->Id; } else { if (!PhStringToInteger64(&valuePart, 10, &integer)) goto CleanupExit; id = (ULONG)integer; } // Display Index PhSplitStringRefAtChar(&columnPart, ',', &valuePart, &columnPart); if (!(Flags & PH_CM_COLUMN_WIDTHS_ONLY)) { if (valuePart.Length == 0 || !PhStringToInteger64(&valuePart, 10, &integer)) goto CleanupExit; displayIndex = (ULONG)integer; } else { if (valuePart.Length != 0) goto CleanupExit; displayIndex = -1; } // Width if (columnPart.Length == 0 || !PhStringToInteger64(&columnPart, 10, &integer)) goto CleanupExit; width = (ULONG)integer; column = PhAllocate(sizeof(PH_TREENEW_COLUMN)); column->Id = id; column->DisplayIndex = displayIndex; column->Width = width; PhAddItemSimpleHashtable(columnHashtable, (PVOID)column->Id, column); } } TreeNew_SetRedraw(TreeNewHandle, FALSE); // Set visibility and width. i = 0; count = 0; total = TreeNew_GetColumnCount(TreeNewHandle); hasFixedColumn = !!TreeNew_GetFixedColumn(TreeNewHandle); memset(orderArray, 0, sizeof(orderArray)); maxOrder = 0; while (count < total) { PH_TREENEW_COLUMN setColumn; PPH_TREENEW_COLUMN *columnPtr; if (TreeNew_GetColumn(TreeNewHandle, i, &setColumn)) { columnPtr = (PPH_TREENEW_COLUMN *)PhFindItemSimpleHashtable(columnHashtable, (PVOID)i); if (!(Flags & PH_CM_COLUMN_WIDTHS_ONLY)) { if (columnPtr) { setColumn.Visible = TRUE; setColumn.Width = (*columnPtr)->Width; TreeNew_SetColumn(TreeNewHandle, TN_COLUMN_FLAG_VISIBLE | TN_COLUMN_WIDTH, &setColumn); if (!setColumn.Fixed) { // For compatibility reasons, normal columns have their display indicies stored // one higher than usual (so they start from 1, not 0). Fix that here. if (hasFixedColumn && (*columnPtr)->DisplayIndex != 0) (*columnPtr)->DisplayIndex--; if ((*columnPtr)->DisplayIndex < PH_CM_ORDER_LIMIT) { orderArray[(*columnPtr)->DisplayIndex] = i; if ((ULONG)maxOrder < (*columnPtr)->DisplayIndex + 1) maxOrder = (*columnPtr)->DisplayIndex + 1; } } } else if (!setColumn.Fixed) // never hide the fixed column { setColumn.Visible = FALSE; TreeNew_SetColumn(TreeNewHandle, TN_COLUMN_FLAG_VISIBLE, &setColumn); } } else { if (columnPtr) { setColumn.Width = (*columnPtr)->Width; TreeNew_SetColumn(TreeNewHandle, TN_COLUMN_WIDTH, &setColumn); } } count++; } i++; } if (!(Flags & PH_CM_COLUMN_WIDTHS_ONLY)) { // Set the order array. TreeNew_SetColumnOrderArray(TreeNewHandle, maxOrder, orderArray); } TreeNew_SetRedraw(TreeNewHandle, TRUE); result = TRUE; CleanupExit: PhBeginEnumHashtable(columnHashtable, &enumContext); while (pair = PhNextEnumHashtable(&enumContext)) PhFree(pair->Value); PhDereferenceObject(columnHashtable); } // Load sort settings. if (SortSettings && SortSettings->Length != 0) { PhSplitStringRefAtChar(SortSettings, ',', &valuePart, &subPart); if (valuePart.Length != 0 && subPart.Length != 0) { ULONG sortColumn; PH_SORT_ORDER sortOrder; sortColumn = -1; if (valuePart.Buffer[0] == '+') { PH_STRINGREF pluginName; ULONG subId; PPH_CM_COLUMN cmColumn; if ( Manager && PhEmParseCompoundId(&valuePart, &pluginName, &subId) && (cmColumn = PhCmFindColumn(Manager, &pluginName, subId)) ) { sortColumn = cmColumn->Id; } } else { PhStringToInteger64(&valuePart, 10, &integer); sortColumn = (ULONG)integer; } PhStringToInteger64(&subPart, 10, &integer); sortOrder = (PH_SORT_ORDER)integer; if (sortColumn != -1 && sortOrder <= DescendingSortOrder) { TreeNew_SetSort(TreeNewHandle, sortColumn, sortOrder); } } } return result; }
VOID PhpEnsureValidSortColumnTreeNew( __inout HWND TreeNewHandle, __in ULONG DefaultSortColumn, __in PH_SORT_ORDER DefaultSortOrder ) { ULONG sortColumn; PH_SORT_ORDER sortOrder; // Make sure the column we're sorting by is actually visible, and if not, don't sort anymore. TreeNew_GetSort(TreeNewHandle, &sortColumn, &sortOrder); if (sortOrder != NoSortOrder) { PH_TREENEW_COLUMN column; TreeNew_GetColumn(TreeNewHandle, sortColumn, &column); if (!column.Visible) { if (DefaultSortOrder != NoSortOrder) { // Make sure the default sort column is visible. TreeNew_GetColumn(TreeNewHandle, DefaultSortColumn, &column); if (!column.Visible) { ULONG maxId; ULONG id; BOOLEAN found; // Use the first visible column. maxId = TreeNew_GetMaxId(TreeNewHandle); id = 0; found = FALSE; while (id <= maxId) { if (TreeNew_GetColumn(TreeNewHandle, id, &column)) { if (column.Visible) { DefaultSortColumn = id; found = TRUE; break; } } id++; } if (!found) { DefaultSortColumn = 0; DefaultSortOrder = NoSortOrder; } } } TreeNew_SetSort(TreeNewHandle, DefaultSortColumn, DefaultSortOrder); } } }