vmi_os_windows/comps/object/
mod.rs

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