Skip to main content

ib_shell_item/folder/
compare.rs

1use std::cmp;
2
3use windows::{
4    Win32::{Foundation::LPARAM, UI::Shell::SHCIDS_COLUMNMASK},
5    core::HRESULT,
6};
7
8use crate::folder::CompareIDs;
9
10impl CompareIDs {
11    /**
12    [MAKE_HRESULT macro (dmerror.h)](https://learn.microsoft.com/en-us/windows/win32/api/dmerror/nf-dmerror-make_hresult)
13
14    ```x86asm
15    cmp     dil, 2
16    movsx   eax, dil
17    movzx   ecx, ax
18    mov     eax, -2147483648
19    cmovne  eax, ecx
20    ret
21    ```
22    */
23    pub fn to_result(order: Option<cmp::Ordering>) -> HRESULT {
24        /*
25        ```x86asm
26        new_result:
27        inc     dil
28        movzx   eax, dil
29        lea     rcx, [rip + .Lswitch.table.new_result]
30        mov     eax, dword ptr [rcx + 4*rax]
31        ret
32
33        .Lswitch.table.new_result:
34        .long   65535
35        .long   0
36        .long   1
37        .long   2147483648
38        ```
39        HRESULT(match order {
40            Some(cmp::Ordering::Less) => 0xFFFF,
41            Some(cmp::Ordering::Equal) => 0,
42            Some(cmp::Ordering::Greater) => 1,
43            None => 1 << 31,
44        })
45        */
46        HRESULT(match order {
47            Some(order) => order as i16 as u16 as i32,
48            None => 1 << 31,
49        })
50    }
51}
52
53impl From<LPARAM> for CompareIDs {
54    fn from(val: LPARAM) -> Self {
55        let v = val.0 as u32;
56        CompareIDs {
57            column: (v & SHCIDS_COLUMNMASK as u32) as u16,
58            flags: (v >> 16) as u16,
59        }
60    }
61}
62
63#[cfg(test)]
64mod tests {
65    use super::*;
66
67    #[test]
68    fn to_result() {
69        use cmp::Ordering::*;
70
71        // Test Less (-1)
72        let hres = CompareIDs::to_result(Some(Less));
73        assert_eq!(hres.0, 0xFFFF);
74
75        // Test Equal (0)
76        let hres = CompareIDs::to_result(Some(Equal));
77        assert_eq!(hres.0, 0);
78
79        // Test Greater (1)
80        let hres = CompareIDs::to_result(Some(Greater));
81        assert_eq!(hres.0, 1);
82
83        // Test None (fallback to -1)
84        let hres = CompareIDs::to_result(None);
85        assert_eq!(hres.0 as u32, 0x80000000);
86    }
87}