[NTOBJSHEX] Fix sorting elements by different columns (#4947)
authorEgor Ananyin <ananinegor@gmail.com>
Tue, 20 Dec 2022 20:58:30 +0000 (23:58 +0300)
committerGitHub <noreply@github.com>
Tue, 20 Dec 2022 20:58:30 +0000 (23:58 +0300)
- Add ability to sort NT objects by symlinks
- Add ability to sort registry entries by type/value

CORE-18761 CORE-18762

dll/shellext/ntobjshex/ntobjfolder.cpp
dll/shellext/ntobjshex/regfolder.cpp

index 020dcc3..f4aef06 100644 (file)
@@ -463,8 +463,27 @@ HRESULT CNtObjectFolder::CompareIDs(LPARAM lParam, const NtPidlEntry * first, co
             return MAKE_COMPARE_HRESULT(second->objectType - first->objectType);
 
         case NTOBJECT_COLUMN_LINKTARGET:
-            // Can't sort by link target yet
-            return E_INVALIDARG;
+        {
+            if (first->objectType != SYMBOLICLINK_OBJECT && second->objectType != SYMBOLICLINK_OBJECT)
+                return CompareName(lParam, first, second);
+
+            if (first->objectType != SYMBOLICLINK_OBJECT || second->objectType != SYMBOLICLINK_OBJECT)
+                return first->objectType != SYMBOLICLINK_OBJECT ? S_GREATERTHAN : S_LESSTHAN;
+
+            WCHAR wbLink1[MAX_PATH] = { 0 }, wbLink2[MAX_PATH] = { 0 };
+            UNICODE_STRING firstLink, secondLink;
+            RtlInitEmptyUnicodeString(&firstLink, wbLink1, sizeof(wbLink1));
+
+            if (FAILED_UNEXPECTEDLY(GetNTObjectSymbolicLinkTarget(m_NtPath, first->entryName, &firstLink)))
+                return E_INVALIDARG;
+
+            RtlInitEmptyUnicodeString(&secondLink, wbLink2, sizeof(wbLink2));
+
+            if (FAILED_UNEXPECTEDLY(GetNTObjectSymbolicLinkTarget(m_NtPath, second->entryName, &secondLink)))
+                return E_INVALIDARG;
+
+            return MAKE_COMPARE_HRESULT(RtlCompareUnicodeString(&firstLink, &secondLink, TRUE));
+        }
     }
 
     DbgPrint("Unsupported sorting mode.\n");
index 685a40c..e8369f8 100644 (file)
@@ -409,11 +409,40 @@ HRESULT CRegistryFolder::CompareIDs(LPARAM lParam, const RegPidlEntry * first, c
             return CompareName(lParam, first, second);
 
         case REGISTRY_COLUMN_TYPE:
-            return MAKE_COMPARE_HRESULT(second->contentType - first->contentType);
+        {
+            if (first->entryType != second->entryType)
+                return MAKE_COMPARE_HRESULT(second->entryType - first->entryType);
+
+            if (first->entryType == REG_ENTRY_KEY)
+            {
+                if (first->contentsLength == 0 || second->contentsLength == 0)
+                    return (first->contentsLength == 0) ? S_GREATERTHAN : S_LESSTHAN;
+
+                PWSTR firstKey = (PWSTR)(((PBYTE)first) + FIELD_OFFSET(RegPidlEntry, entryName) + first->entryNameLength + sizeof(WCHAR));
+                PWSTR secondKey = (PWSTR)(((PBYTE)second) + FIELD_OFFSET(RegPidlEntry, entryName) + second->entryNameLength + sizeof(WCHAR));
+                return MAKE_COMPARE_HRESULT(lstrcmpW(firstKey, secondKey));
+            }
+
+            return CompareName(lParam, first, second);
+        }
 
         case REGISTRY_COLUMN_VALUE:
-            // Can't sort by link target yet
-            return E_INVALIDARG;
+        {
+            PCWSTR firstContent, secondContent;
+
+            if (FAILED_UNEXPECTEDLY(FormatContentsForDisplay(first, m_hRoot, m_NtPath, &firstContent)))
+                return E_INVALIDARG;
+
+            if (FAILED_UNEXPECTEDLY(FormatContentsForDisplay(second, m_hRoot, m_NtPath, &secondContent)))
+                return E_INVALIDARG;
+
+            hr = MAKE_COMPARE_HRESULT(lstrcmpW(firstContent, secondContent));
+
+            CoTaskMemFree((LPVOID)firstContent);
+            CoTaskMemFree((LPVOID)secondContent);
+
+            return hr;
+        }
     }
 
     DbgPrint("Unsupported sorting mode.\n");