Skip to main content

vmi_os_windows/comps/object/
mod.rs

1mod directory;
2mod file;
3mod key;
4mod object_type;
5mod process;
6mod section;
7mod thread;
8mod token;
9
10use vmi_core::{
11    Va, VmiError, VmiState, VmiVa,
12    driver::VmiRead,
13    os::{ProcessObject, ThreadObject},
14};
15
16pub use self::{
17    directory::WindowsDirectoryObject,
18    file::WindowsFileObject,
19    key::WindowsKey,
20    object_type::WindowsObjectType,
21    process::WindowsProcess,
22    section::WindowsSectionObject,
23    thread::{WindowsThread, WindowsThreadState, WindowsThreadWaitReason},
24    token::{
25        WindowsImpersonationLevel, WindowsPrivilege, WindowsToken, WindowsTokenFlags,
26        WindowsTokenPrivilege, WindowsTokenSource, WindowsTokenType,
27    },
28};
29use super::WindowsObjectHeaderNameInfo;
30use crate::{WindowsOs, WindowsOsExt, arch::ArchAdapter, offset, symbol};
31
32/// Trait for types that can be converted from a [`WindowsObject`].
33pub trait FromWindowsObject<'a, Driver>: Sized
34where
35    Driver: VmiRead,
36    Driver::Architecture: ArchAdapter<Driver>,
37{
38    /// Attempts to convert a [`WindowsObject`] into a specific object type.
39    fn from_object(object: WindowsObject<'a, Driver>) -> Result<Option<Self>, VmiError>;
40}
41
42/// A Windows object.
43///
44/// A Windows object is a kernel-managed entity that can be referenced
45/// by handles or pointers. It includes processes, threads, files, and other
46/// system resources managed by the Windows Object Manager.
47///
48/// # Implementation Details
49///
50/// Corresponds to `_OBJECT_HEADER.Body`.
51pub struct WindowsObject<'a, Driver>
52where
53    Driver: VmiRead,
54    Driver::Architecture: ArchAdapter<Driver>,
55{
56    /// The VMI state.
57    vmi: VmiState<'a, WindowsOs<Driver>>,
58
59    /// Address of the object.
60    va: Va,
61}
62
63impl<'a, Driver> FromWindowsObject<'a, Driver> for WindowsObject<'a, Driver>
64where
65    Driver: VmiRead,
66    Driver::Architecture: ArchAdapter<Driver>,
67{
68    fn from_object(object: WindowsObject<'a, Driver>) -> Result<Option<Self>, VmiError> {
69        // Any object can be converted to itself.
70        Ok(Some(object))
71    }
72}
73
74impl<Driver> VmiVa for WindowsObject<'_, Driver>
75where
76    Driver: VmiRead,
77    Driver::Architecture: ArchAdapter<Driver>,
78{
79    fn va(&self) -> Va {
80        self.va
81    }
82}
83
84impl<Driver> std::fmt::Debug for WindowsObject<'_, Driver>
85where
86    Driver: VmiRead,
87    Driver::Architecture: ArchAdapter<Driver>,
88{
89    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
90        let name_info = self.name_info();
91        let typ = self.type_kind();
92
93        f.debug_struct("WindowsObject")
94            .field("typ", &typ)
95            .field("name_info", &name_info)
96            .finish()
97    }
98}
99
100impl<'a, Driver> WindowsObject<'a, Driver>
101where
102    Driver: VmiRead,
103    Driver::Architecture: ArchAdapter<Driver>,
104{
105    /// Creates a new Windows object.
106    pub fn new(vmi: VmiState<'a, WindowsOs<Driver>>, va: Va) -> Self {
107        Self { vmi, va }
108    }
109
110    /// Returns the virtual address of the `_OBJECT_HEADER` structure.
111    ///
112    /// # Implementation Details
113    ///
114    /// `_OBJECT_HEADER` is always at the beginning of the object.
115    pub fn header(&self) -> Va {
116        let OBJECT_HEADER = offset!(self.vmi, _OBJECT_HEADER);
117
118        self.va - OBJECT_HEADER.Body.offset()
119    }
120
121    /// Returns the name information of the object.
122    pub fn name_info(&self) -> Result<Option<WindowsObjectHeaderNameInfo<'a, Driver>>, VmiError> {
123        let ObpInfoMaskToOffset = symbol!(self.vmi, ObpInfoMaskToOffset);
124        let OBJECT_HEADER = offset!(self.vmi, _OBJECT_HEADER);
125
126        let info_mask = self
127            .vmi
128            .read_u8(self.header() + OBJECT_HEADER.InfoMask.offset())?;
129
130        bitflags::bitflags! {
131            struct InfoFlags: u8 {
132                const CREATOR_INFO = 0x01;
133                const NAME_INFO = 0x02;
134                const HANDLE_INFO = 0x04;
135                const QUOTA_INFO = 0x08;
136                const PROCESS_INFO = 0x10;
137            }
138        }
139
140        let info_flags = InfoFlags::from_bits_truncate(info_mask);
141        if !info_flags.contains(InfoFlags::NAME_INFO) {
142            return Ok(None);
143        }
144
145        // Offset = ObpInfoMaskToOffset[OBJECT_HEADER->InfoMask & (DesiredHeaderBit | (DesiredHeaderBit-1))]
146
147        let mask = info_mask & (InfoFlags::NAME_INFO.bits() | (InfoFlags::NAME_INFO.bits() - 1));
148        let mask = mask as u64;
149
150        let kernel_image_base = self.vmi.os().kernel_image_base()?;
151        let offset = self
152            .vmi
153            .read_u8(kernel_image_base + ObpInfoMaskToOffset + mask)? as u64;
154
155        Ok(Some(WindowsObjectHeaderNameInfo::new(
156            self.vmi,
157            self.header() - offset,
158        )))
159    }
160
161    /// Returns the directory object associated with the object name.
162    ///
163    /// Shortcut for [`self.name_info()?.directory()`].
164    ///
165    /// [`self.name_info()?.directory()`]: WindowsObjectHeaderNameInfo::directory
166    pub fn directory(&self) -> Result<Option<WindowsObject<'a, Driver>>, VmiError> {
167        let name_info = match self.name_info()? {
168            Some(name_info) => name_info,
169            None => return Ok(None),
170        };
171
172        name_info.directory()
173    }
174
175    /// Returns the name of the object.
176    ///
177    /// Shortcut for [`self.name_info()?.name()`].
178    ///
179    /// [`self.name_info()?.name()`]: WindowsObjectHeaderNameInfo::name
180    pub fn name(&self) -> Result<Option<String>, VmiError> {
181        let name_info = match self.name_info()? {
182            Some(name_info) => name_info,
183            None => return Ok(None),
184        };
185
186        Ok(Some(name_info.name()?))
187    }
188
189    /// Constructs the full path of a named object from its name information.
190    ///
191    /// Shortcut for [`self.name_info()?.full_path()`].
192    ///
193    /// [`self.name_info()?.full_path()`]: WindowsObjectHeaderNameInfo::full_path
194    pub fn full_path(&self) -> Result<Option<String>, VmiError> {
195        match self.kind()? {
196            Some(WindowsObjectKind::File(file)) => Ok(Some(file.full_path()?)),
197            Some(WindowsObjectKind::Key(key)) => Ok(Some(key.full_path()?)),
198            Some(WindowsObjectKind::Section(section)) => section.full_path(),
199            _ => {
200                let name_info = match self.name_info()? {
201                    Some(name_info) => name_info,
202                    None => return Ok(None),
203                };
204
205                Ok(Some(name_info.full_path()?))
206            }
207        }
208    }
209
210    /// Returns the type of a Windows kernel object.
211    ///
212    /// This method analyzes the object header of a kernel object and returns
213    /// its type object (`_OBJECT_TYPE`). It handles the obfuscation introduced
214    /// by the object header cookie, ensuring accurate type identification even
215    /// on systems with this security feature enabled.
216    pub fn object_type(&self) -> Result<WindowsObjectType<'a, Driver>, VmiError> {
217        let ObTypeIndexTable = symbol!(self.vmi, ObTypeIndexTable);
218        let OBJECT_HEADER = offset!(self.vmi, _OBJECT_HEADER);
219
220        let object_header = self.va - OBJECT_HEADER.Body.offset();
221        let type_index = self
222            .vmi
223            .read_u8(object_header + OBJECT_HEADER.TypeIndex.offset())?;
224
225        let index = match self.vmi.os().object_header_cookie()? {
226            Some(cookie) => {
227                //
228                // TypeIndex
229                //     ^ 2nd least significate byte of OBJECT_HEADER address
230                //     ^ nt!ObHeaderCookie
231                // ref: https://medium.com/@ashabdalhalim/a-light-on-windows-10s-object-header-typeindex-value-e8f907e7073a
232                //
233
234                let salt = (object_header.0 >> 8) as u8;
235                type_index ^ salt ^ cookie
236            }
237            None => type_index,
238        };
239
240        let index = index as u64;
241
242        let kernel_image_base = self.vmi.os().kernel_image_base()?;
243        let object_type = self.vmi.read_va_native(
244            kernel_image_base + ObTypeIndexTable + index * 8, // REVIEW: replace 8 with registers.address_width()?
245        )?;
246
247        Ok(WindowsObjectType::new(self.vmi, object_type))
248    }
249
250    /// Returns the object type name.
251    ///
252    /// Shortcut for [`self.object_type()?.name()`].
253    ///
254    /// [`self.object_type()?.name()`]: WindowsObjectType::name
255    pub fn type_name(&self) -> Result<String, VmiError> {
256        self.object_type()?.name()
257    }
258
259    /// Returns the object type kind.
260    ///
261    /// Shortcut for [`self.object_type()?.kind()`].
262    ///
263    /// [`self.object_type()?.kind()`]: WindowsObjectType::kind
264    pub fn type_kind(&self) -> Result<Option<WindowsObjectTypeKind>, VmiError> {
265        self.object_type()?.kind()
266    }
267
268    /// Returns the specific kind of this object.
269    pub fn kind(&self) -> Result<Option<WindowsObjectKind<'a, Driver>>, VmiError> {
270        let result = match self.type_kind()? {
271            Some(WindowsObjectTypeKind::Directory) => {
272                WindowsObjectKind::Directory(WindowsDirectoryObject::new(self.vmi, self.va))
273            }
274            Some(WindowsObjectTypeKind::File) => {
275                WindowsObjectKind::File(WindowsFileObject::new(self.vmi, self.va))
276            }
277            Some(WindowsObjectTypeKind::Key) => {
278                WindowsObjectKind::Key(WindowsKey::new(self.vmi, self.va))
279            }
280            Some(WindowsObjectTypeKind::Process) => {
281                WindowsObjectKind::Process(WindowsProcess::new(self.vmi, ProcessObject(self.va)))
282            }
283            Some(WindowsObjectTypeKind::Section) => {
284                WindowsObjectKind::Section(WindowsSectionObject::new(self.vmi, self.va))
285            }
286            Some(WindowsObjectTypeKind::Thread) => {
287                WindowsObjectKind::Thread(WindowsThread::new(self.vmi, ThreadObject(self.va)))
288            }
289            Some(WindowsObjectTypeKind::Token) => {
290                WindowsObjectKind::Token(WindowsToken::new(self.vmi, self.va))
291            }
292            Some(WindowsObjectTypeKind::Type) => {
293                WindowsObjectKind::Type(WindowsObjectType::new(self.vmi, self.va))
294            }
295            _ => return Ok(None),
296        };
297
298        Ok(Some(result))
299    }
300
301    /// Returns the object as a directory (`_OBJECT_DIRECTORY`).
302    pub fn as_directory(&self) -> Result<Option<WindowsDirectoryObject<'a, Driver>>, VmiError> {
303        match self.kind()? {
304            Some(WindowsObjectKind::Directory(directory)) => Ok(Some(directory)),
305            _ => Ok(None),
306        }
307    }
308
309    /// Returns the object as a file (`_FILE_OBJECT`).
310    pub fn as_file(&self) -> Result<Option<WindowsFileObject<'a, Driver>>, VmiError> {
311        match self.kind()? {
312            Some(WindowsObjectKind::File(file)) => Ok(Some(file)),
313            _ => Ok(None),
314        }
315    }
316
317    /// Returns the object as a key (`_CM_KEY_BODY`).
318    pub fn as_key(&self) -> Result<Option<WindowsKey<'a, Driver>>, VmiError> {
319        match self.kind()? {
320            Some(WindowsObjectKind::Key(key)) => Ok(Some(key)),
321            _ => Ok(None),
322        }
323    }
324
325    /// Returns the object as a process (`_EPROCESS`).
326    pub fn as_process(&self) -> Result<Option<WindowsProcess<'a, Driver>>, VmiError> {
327        match self.kind()? {
328            Some(WindowsObjectKind::Process(process)) => Ok(Some(process)),
329            _ => Ok(None),
330        }
331    }
332
333    /// Returns the object as a section (`_SECTION_OBJECT`).
334    pub fn as_section(&self) -> Result<Option<WindowsSectionObject<'a, Driver>>, VmiError> {
335        match self.kind()? {
336            Some(WindowsObjectKind::Section(section)) => Ok(Some(section)),
337            _ => Ok(None),
338        }
339    }
340
341    /// Returns the object as a thread (`_ETHREAD`).
342    pub fn as_thread(&self) -> Result<Option<WindowsThread<'a, Driver>>, VmiError> {
343        match self.kind()? {
344            Some(WindowsObjectKind::Thread(thread)) => Ok(Some(thread)),
345            _ => Ok(None),
346        }
347    }
348
349    /// Returns the object as a token (`_TOKEN`).
350    pub fn as_token(&self) -> Result<Option<WindowsToken<'a, Driver>>, VmiError> {
351        match self.kind()? {
352            Some(WindowsObjectKind::Token(token)) => Ok(Some(token)),
353            _ => Ok(None),
354        }
355    }
356
357    /// Returns the object as an object type (`_OBJECT_TYPE`).
358    pub fn as_type(&self) -> Result<Option<WindowsObjectType<'a, Driver>>, VmiError> {
359        match self.kind()? {
360            Some(WindowsObjectKind::Type(object_type)) => Ok(Some(object_type)),
361            _ => Ok(None),
362        }
363    }
364}
365
366/// Identifies the type of a Windows kernel object.
367///
368/// Windows uses a object-based kernel architecture where various system
369/// resources (processes, threads, files, etc.) are represented as kernel
370/// objects. This enum identifies the different types of objects that can
371/// be encountered during introspection.
372///
373/// Each variant corresponds to a specific object type string used internally
374/// by the Windows kernel. For example, "Process" for process objects,
375/// "Thread" for thread objects, etc.
376#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
377pub enum WindowsObjectTypeKind {
378    /// Activation object.
379    ///
380    /// Has `ActivationObject` type name.
381    ActivationObject,
382
383    /// Activity reference object.
384    ///
385    /// Has `ActivityReference` type name.
386    ActivityReference,
387
388    /// Adapter object.
389    ///
390    /// Represented by `_ADAPTER_OBJECT` structure.
391    /// Has `Adapter` type name.
392    Adapter,
393
394    /// ALPC Port object.
395    ///
396    /// Represented by `_ALPC_PORT` structure.
397    /// Has `ALPC Port` type name.
398    AlpcPort,
399
400    /// Callback object.
401    ///
402    /// Has `Callback` type name.
403    Callback,
404
405    /// Composition object.
406    ///
407    /// Has `Composition` type name.
408    Composition,
409
410    /// Controller object.
411    ///
412    /// Has `Controller` type name.
413    Controller,
414
415    /// Core messaging object.
416    ///
417    /// Has `CoreMessaging` type name.
418    CoreMessaging,
419
420    /// Coverage sampler object.
421    ///
422    /// Has `CoverageSampler` type name.
423    CoverageSampler,
424
425    /// CPU partition object.
426    ///
427    /// Has `CpuPartition` type name.
428    CpuPartition,
429
430    /// Debug object.
431    ///
432    /// Represented by `_DEBUG_OBJECT` structure.
433    /// Has `DebugObject` type name.
434    DebugObject,
435
436    /// Desktop object.
437    ///
438    /// Has `Desktop` type name.
439    Desktop,
440
441    /// Device object.
442    ///
443    /// Represented by `_DEVICE_OBJECT` structure.
444    /// Has `Device` type name.
445    Device,
446
447    /// Directory object.
448    ///
449    /// Represented by `_OBJECT_DIRECTORY` structure.
450    /// Has `Directory` type name.
451    Directory,
452
453    /// DMA adapter object.
454    ///
455    /// Has `DmaAdapter` type name.
456    DmaAdapter,
457
458    /// Driver object.
459    ///
460    /// Represented by `_DRIVER_OBJECT` structure.
461    /// Has `Driver` type name.
462    Driver,
463
464    /// DX Composition object.
465    ///
466    /// Has `DxgkCompositionObject` type name.
467    DxgkCompositionObject,
468
469    /// DX Display Manager object.
470    ///
471    /// Has `DxgkDisplayManagerObject` type name.
472    DxgkDisplayManagerObject,
473
474    /// DX Shared Bundle object.
475    ///
476    /// Has `DxgkSharedBundleObject` type name.
477    DxgkSharedBundleObject,
478
479    /// DX Shared Keyed Mutex object.
480    ///
481    /// Has `DxgkSharedKeyedMutexObject` type name.
482    DxgkSharedKeyedMutexObject,
483
484    /// DX Shared Protected Session object.
485    ///
486    /// Has `DxgkSharedProtectedSessionObject` type name.
487    DxgkSharedProtectedSessionObject,
488
489    /// DX Shared Resource object.
490    ///
491    /// Has `DxgkSharedResource` type name.
492    DxgkSharedResource,
493
494    /// DX Shared Swap Chain object.
495    ///
496    /// Has `DxgkSharedSwapChainObject` type name.
497    DxgkSharedSwapChainObject,
498
499    /// DX Shared Sync object.
500    ///
501    /// Has `DxgkSharedSyncObject` type name.
502    DxgkSharedSyncObject,
503
504    /// Energy tracker object.
505    ///
506    /// Has `EnergyTracker` type name.
507    EnergyTracker,
508
509    /// ETW consumer object.
510    ///
511    /// Has `EtwConsumer` type name.
512    EtwConsumer,
513
514    /// ETW registration object.
515    ///
516    /// Has `EtwRegistration` type name.
517    EtwRegistration,
518
519    /// ETW session demux entry object.
520    ///
521    /// Has `EtwSessionDemuxEntry` type name.
522    EtwSessionDemuxEntry,
523
524    /// Event object.
525    ///
526    /// Represented by `_KEVENT` structure.
527    /// Has `Event` type name.
528    Event,
529
530    /// File object.
531    ///
532    /// Represented by `_FILE_OBJECT` structure.
533    /// Has `File` type name.
534    File,
535
536    /// Filter communication port object.
537    ///
538    /// Has `FilterCommunicationPort` type name.
539    FilterCommunicationPort,
540
541    /// Filter connection port object.
542    ///
543    /// Has `FilterConnectionPort` type name.
544    FilterConnectionPort,
545
546    /// I/O completion object.
547    ///
548    /// Has `IoCompletion` type name.
549    IoCompletion,
550
551    /// I/O completion reserve object.
552    ///
553    /// Has `IoCompletionReserve` type name.
554    IoCompletionReserve,
555
556    /// I/O ring object.
557    ///
558    /// Has `IoRing` type name.
559    IoRing,
560
561    /// IR timer object.
562    ///
563    /// Has `IRTimer` type name.
564    IRTimer,
565
566    /// Job object.
567    ///
568    /// Represented by `_EJOB` structure.
569    /// Has `Job` type name.
570    Job,
571
572    /// Key object.
573    ///
574    /// Represented by `_CM_KEY_BODY` structure.
575    /// Has `Key` type name.
576    Key,
577
578    /// Keyed event object.
579    ///
580    /// Has `KeyedEvent` type name.
581    KeyedEvent,
582
583    /// Mutant object.
584    ///
585    /// Represented by `_KMUTANT` structure.
586    /// Has `Mutant` type name.
587    Mutant,
588
589    /// NDIS CM state object.
590    ///
591    /// Has `NdisCmState` type name.
592    NdisCmState,
593
594    /// Partition object.
595    ///
596    /// Has `Partition` type name.
597    Partition,
598
599    /// Performance counter object.
600    ///
601    /// Has `PcwObject` type name.
602    PcwObject,
603
604    /// Power request object.
605    ///
606    /// Has `PowerRequest` type name.
607    PowerRequest,
608
609    /// Port object.
610    ///
611    /// Represented by `_PORT_MESSAGE` structure.
612    /// Has `Port` type name.
613    Port,
614
615    /// Process object.
616    ///
617    /// Represented by `_EPROCESS` structure.
618    /// Has `Process` type name.
619    Process,
620
621    /// Process state change object.
622    ///
623    /// Has `ProcessStateChange` type name.
624    ProcessStateChange,
625
626    /// Profile object.
627    ///
628    /// Has `Profile` type name.
629    Profile,
630
631    /// Sile context (non-paged) object.
632    ///
633    /// Has `PsSiloContextNonPaged` type name.
634    PsSiloContextNonPaged,
635
636    /// Sile context (paged) object.
637    ///
638    /// Has `PsSiloContextPaged` type name.
639    PsSiloContextPaged,
640
641    /// Raw input manager object.
642    ///
643    /// Has `RawInputManager` type name.
644    RawInputManager,
645
646    /// Registry transaction object.
647    ///
648    /// Has `RegistryTransaction` type name.
649    RegistryTransaction,
650
651    /// Section object.
652    ///
653    /// Represented by `_SECTION` (or `_SECTION_OBJECT`) structure.
654    /// Has `Section` type name.
655    Section,
656
657    /// Semaphore object.
658    ///
659    /// Represented by `_KSEMAPHORE` structure.
660    /// Has `Semaphore` type name.
661    Semaphore,
662
663    /// Session object.
664    ///
665    /// Has `Session` type name.
666    Session,
667
668    /// Symbolic link object.
669    ///
670    /// Represented by `_OBJECT_SYMBOLIC_LINK` structure.
671    /// Has `SymbolicLink` type name.
672    SymbolicLink,
673
674    /// Thread object.
675    ///
676    /// Represented by `_ETHREAD` structure.
677    /// Has `Thread` type name.
678    Thread,
679
680    /// Thread state change object.
681    ///
682    /// Has `ThreadStateChange` type name.
683    ThreadStateChange,
684
685    /// Timer object.
686    ///
687    /// Represented by `_KTIMER` structure.
688    /// Has `Timer` type name.
689    Timer,
690
691    /// Transaction manager (Enlistment) object.
692    ///
693    /// Has `TmEn` type name.
694    TmEn,
695
696    /// Transaction manager (Resource Manager) object.
697    ///
698    /// Has `TmRm` type name.
699    TmRm,
700
701    /// Transaction manager object.
702    TmTm,
703
704    /// Transaction object.
705    TmTx,
706
707    /// Token object.
708    ///
709    /// Represented by `_TOKEN` structure.
710    /// Has `Token` type name.
711    Token,
712
713    /// Thread pool worker factory object.
714    ///
715    /// Has `TpWorkerFactory` type name.
716    TpWorkerFactory,
717
718    /// Type object.
719    ///
720    /// Represented by `_OBJECT_TYPE` structure.
721    /// Has `Type` type name.
722    Type,
723
724    /// User APC reserve object.
725    ///
726    /// Has `UserApcReserve` type name.
727    UserApcReserve,
728
729    /// Wait completion packet object.
730    ///
731    /// Has `WaitCompletionPacket` type name.
732    WaitCompletionPacket,
733
734    /// Window station object.
735    ///
736    /// Has `WindowStation` type name.
737    WindowStation,
738
739    /// WMI GUID object.
740    ///
741    /// Has `WmiGuid` type name.
742    WmiGuid,
743}
744
745/// Error parsing a Windows object type.
746#[derive(Debug, PartialEq, Eq)]
747pub struct ParseObjectTypeError;
748
749impl std::str::FromStr for WindowsObjectTypeKind {
750    type Err = ParseObjectTypeError;
751
752    fn from_str(s: &str) -> Result<Self, Self::Err> {
753        use WindowsObjectTypeKind::*;
754
755        match s {
756            "ActivationObject" => Ok(ActivationObject),
757            "ActivityReference" => Ok(ActivityReference),
758            "Adapter" => Ok(Adapter),
759            "ALPC Port" => Ok(AlpcPort),
760            "Callback" => Ok(Callback),
761            "Composition" => Ok(Composition),
762            "Controller" => Ok(Controller),
763            "CoreMessaging" => Ok(CoreMessaging),
764            "CoverageSampler" => Ok(CoverageSampler),
765            "CpuPartition" => Ok(CpuPartition),
766            "DebugObject" => Ok(DebugObject),
767            "Desktop" => Ok(Desktop),
768            "Device" => Ok(Device),
769            "Directory" => Ok(Directory),
770            "DmaAdapter" => Ok(DmaAdapter),
771            "Driver" => Ok(Driver),
772            "DxgkCompositionObject" => Ok(DxgkCompositionObject),
773            "DxgkDisplayManagerObject" => Ok(DxgkDisplayManagerObject),
774            "DxgkSharedBundleObject" => Ok(DxgkSharedBundleObject),
775            "DxgkSharedKeyedMutexObject" => Ok(DxgkSharedKeyedMutexObject),
776            "DxgkSharedProtectedSessionObject" => Ok(DxgkSharedProtectedSessionObject),
777            "DxgkSharedResource" => Ok(DxgkSharedResource),
778            "DxgkSharedSwapChainObject" => Ok(DxgkSharedSwapChainObject),
779            "DxgkSharedSyncObject" => Ok(DxgkSharedSyncObject),
780            "EnergyTracker" => Ok(EnergyTracker),
781            "EtwConsumer" => Ok(EtwConsumer),
782            "EtwRegistration" => Ok(EtwRegistration),
783            "EtwSessionDemuxEntry" => Ok(EtwSessionDemuxEntry),
784            "Event" => Ok(Event),
785            "File" => Ok(File),
786            "FilterCommunicationPort" => Ok(FilterCommunicationPort),
787            "FilterConnectionPort" => Ok(FilterConnectionPort),
788            "IoCompletion" => Ok(IoCompletion),
789            "IoCompletionReserve" => Ok(IoCompletionReserve),
790            "IoRing" => Ok(IoRing),
791            "IRTimer" => Ok(IRTimer),
792            "Job" => Ok(Job),
793            "Key" => Ok(Key),
794            "KeyedEvent" => Ok(KeyedEvent),
795            "Mutant" => Ok(Mutant),
796            "NdisCmState" => Ok(NdisCmState),
797            "Partition" => Ok(Partition),
798            "PcwObject" => Ok(PcwObject),
799            "PowerRequest" => Ok(PowerRequest),
800            "Port" => Ok(Port),
801            "Process" => Ok(Process),
802            "ProcessStateChange" => Ok(ProcessStateChange),
803            "Profile" => Ok(Profile),
804            "PsSiloContextNonPaged" => Ok(PsSiloContextNonPaged),
805            "PsSiloContextPaged" => Ok(PsSiloContextPaged),
806            "RawInputManager" => Ok(RawInputManager),
807            "RegistryTransaction" => Ok(RegistryTransaction),
808            "Section" => Ok(Section),
809            "Semaphore" => Ok(Semaphore),
810            "Session" => Ok(Session),
811            "SymbolicLink" => Ok(SymbolicLink),
812            "Thread" => Ok(Thread),
813            "ThreadStateChange" => Ok(ThreadStateChange),
814            "Timer" => Ok(Timer),
815            "TmEn" => Ok(TmEn),
816            "TmRm" => Ok(TmRm),
817            "TmTm" => Ok(TmTm),
818            "TmTx" => Ok(TmTx),
819            "Token" => Ok(Token),
820            "TpWorkerFactory" => Ok(TpWorkerFactory),
821            "Type" => Ok(Type),
822            "UserApcReserve" => Ok(UserApcReserve),
823            "WaitCompletionPacket" => Ok(WaitCompletionPacket),
824            "WindowStation" => Ok(WindowStation),
825            "WmiGuid" => Ok(WmiGuid),
826            _ => Err(ParseObjectTypeError),
827        }
828    }
829}
830
831/// Represents a specific kind of Windows object.
832pub enum WindowsObjectKind<'a, Driver>
833where
834    Driver: VmiRead,
835    Driver::Architecture: ArchAdapter<Driver>,
836{
837    /// A directory object (`_OBJECT_DIRECTORY`).
838    Directory(WindowsDirectoryObject<'a, Driver>),
839
840    /// A file object (`_FILE_OBJECT`).
841    File(WindowsFileObject<'a, Driver>),
842
843    /// A registry key object (`_CM_KEY_BODY`).
844    Key(WindowsKey<'a, Driver>),
845
846    /// A process object (`_EPROCESS`).
847    Process(WindowsProcess<'a, Driver>),
848
849    /// A section object (`_SECTION_OBJECT`).
850    Section(WindowsSectionObject<'a, Driver>),
851
852    /// A thread object (`_ETHREAD`).
853    Thread(WindowsThread<'a, Driver>),
854
855    /// A token object (`_TOKEN`).
856    Token(WindowsToken<'a, Driver>),
857
858    /// An object type object (`_OBJECT_TYPE`).
859    Type(WindowsObjectType<'a, Driver>),
860}