1 /*++
2 
3 Copyright (c) Microsoft Corporation
4 
5 ModuleName:
6 
7     MxGeneralKm.h
8 
9 Abstract:
10 
11     Kernel mode implementation for general OS
12     functions defined in MxGeneral.h
13 
14 Author:
15 
16 
17 
18 Revision History:
19 
20 
21 
22 --*/
23 
24 #pragma once
25 
26 #define MAKE_MX_FUNC_NAME(x)    L##x
27 typedef LPCWSTR                 MxFuncName;
28 typedef PKTHREAD                MxThread;
29 typedef PETHREAD                MdEThread;
30 typedef PDEVICE_OBJECT          MdDeviceObject;
31 typedef PDRIVER_OBJECT          MdDriverObject;
32 typedef PFILE_OBJECT            MdFileObject;
33 typedef PIO_REMOVE_LOCK         MdRemoveLock;
34 typedef PCALLBACK_OBJECT        MdCallbackObject;
35 typedef CALLBACK_FUNCTION       MdCallbackFunctionType, *MdCallbackFunction;
36 typedef PKINTERRUPT             MdInterrupt;
37 typedef KSERVICE_ROUTINE        MdInterruptServiceRoutineType, *MdInterruptServiceRoutine;
38 typedef KSYNCHRONIZE_ROUTINE    MdInterruptSynchronizeRoutineType, *MdInterruptSynchronizeRoutine;
39 
40 #include "mxgeneral.h"
41 #include <ntstrsafe.h>
42 
43 __inline
44 BOOLEAN
45 Mx::IsUM(
46     )
47 {
48     return FALSE;
49 }
50 
51 __inline
52 BOOLEAN
53 Mx::IsKM(
54     )
55 {
56     return TRUE;
57 }
58 
59 __inline
60 MxThread
61 Mx::MxGetCurrentThread(
62     )
63 {
64     return KeGetCurrentThread();
65 }
66 
67 __inline
68 MdEThread
69 Mx::GetCurrentEThread(
70     )
71 {
72     return PsGetCurrentThread();
73 }
74 
75 __inline
76 NTSTATUS
77 Mx::MxTerminateCurrentThread(
78     __in NTSTATUS Status
79     )
80 {
81     return PsTerminateSystemThread(Status);
82 }
83 
84 __inline
85 KIRQL
86 Mx::MxGetCurrentIrql(
87     )
88 {
89     return KeGetCurrentIrql();
90 }
91 
92 __drv_maxIRQL(HIGH_LEVEL)
93 __drv_raisesIRQL(NewIrql)
94 __inline
95 VOID
96 Mx::MxRaiseIrql(
97     __in KIRQL                              NewIrql,
98     __out __deref __drv_savesIRQL PKIRQL    OldIrql
99     )
100 {
101     KeRaiseIrql(NewIrql, OldIrql);
102 }
103 
104 __drv_maxIRQL(HIGH_LEVEL)
105 __inline
106 VOID
107 Mx::MxLowerIrql(
108     __in __drv_restoresIRQL __drv_nonConstant KIRQL NewIrql
109     )
110 {
111     KeLowerIrql(NewIrql);
112 }
113 
114 __inline
115 VOID
116 Mx::MxQueryTickCount(
117     __out PLARGE_INTEGER  TickCount
118     )
119 {
120     KeQueryTickCount(TickCount);
121 }
122 
123 __inline
124 ULONG
125 Mx::MxQueryTimeIncrement(
126     )
127 {
128     return KeQueryTimeIncrement();
129 }
130 
131 __inline
132 VOID
133 Mx::MxBugCheckEx(
134     __in ULONG  BugCheckCode,
135     __in ULONG_PTR  BugCheckParameter1,
136     __in ULONG_PTR  BugCheckParameter2,
137     __in ULONG_PTR  BugCheckParameter3,
138     __in ULONG_PTR  BugCheckParameter4
139 )
140 {
141 #ifdef _MSC_VER
142     #pragma prefast(suppress:__WARNING_USE_OTHER_FUNCTION, "KeBugCheckEx is the intent.");
143 #endif
144     KeBugCheckEx(
145         BugCheckCode,
146         BugCheckParameter1,
147         BugCheckParameter2,
148         BugCheckParameter3,
149         BugCheckParameter4
150         );
151 
152     UNREACHABLE;
153 }
154 
155 __inline
156 VOID
157 Mx::MxDbgBreakPoint(
158     )
159 {
160     DbgBreakPoint();
161 }
162 
163 __inline
164 VOID
165 Mx::MxAssert(
166     __in BOOLEAN Condition
167     )
168 {
169     UNREFERENCED_PARAMETER(Condition);
170 
171     ASSERT(Condition); //this get defined as RtlAssert
172 }
173 
174 __inline
175 VOID
176 Mx::MxAssertMsg(
177     __in LPSTR Message,
178     __in BOOLEAN Condition
179     )
180 {
181     UNREFERENCED_PARAMETER(Message);
182     UNREFERENCED_PARAMETER(Condition);
183 
184     ASSERT(Condition);
185 
186     // ASSERTMSG(Message, Condition); TODO: wtf
187 }
188 
189 _Acquires_lock_(_Global_critical_region_)
190 __inline
191 VOID
192 Mx::MxEnterCriticalRegion(
193     )
194 {
195     KeEnterCriticalRegion();
196 }
197 
198 _Releases_lock_(_Global_critical_region_)
199 __inline
200 VOID
201 Mx::MxLeaveCriticalRegion(
202     )
203 {
204     KeLeaveCriticalRegion();
205 }
206 
207 __inline
208 VOID
209 Mx::MxDelayExecutionThread(
210     __in KPROCESSOR_MODE  WaitMode,
211     __in BOOLEAN  Alertable,
212     __in PLARGE_INTEGER  Interval
213     )
214 {
215     ASSERTMSG("Interval must be relative\n", Interval->QuadPart <= 0);
216 
217     KeDelayExecutionThread(
218         WaitMode,
219         Alertable,
220         Interval
221         );
222 }
223 
224 __inline
225 PVOID
226 Mx::MxGetSystemRoutineAddress(
227     __in MxFuncName FuncName
228     )
229 {
230     UNICODE_STRING funcName;
231 
232     RtlInitUnicodeString(&funcName, FuncName);
233     return MmGetSystemRoutineAddress(&funcName);
234 }
235 
236 __inline
237 VOID
238 Mx::MxReferenceObject(
239     __in PVOID Object
240     )
241 {
242     ObReferenceObject(Object);
243 }
244 
245 __inline
246 VOID
247 Mx::MxDereferenceObject(
248     __in PVOID Object
249     )
250 {
251     ObDereferenceObject(Object);
252 }
253 
254 __inline
255 VOID
256 Mx::MxInitializeRemoveLock(
257     __in MdRemoveLock  Lock,
258     __in ULONG  AllocateTag,
259     __in ULONG  MaxLockedMinutes,
260     __in ULONG  HighWatermark
261     )
262 {
263     IoInitializeRemoveLock(Lock, AllocateTag, MaxLockedMinutes, HighWatermark);
264 }
265 
266 __inline
267 NTSTATUS
268 Mx::MxAcquireRemoveLock(
269     __in MdRemoveLock  RemoveLock,
270     __in_opt PVOID  Tag
271     )
272 {
273     return IoAcquireRemoveLock(RemoveLock, Tag);
274 }
275 
276 __inline
277 VOID
278 Mx::MxReleaseRemoveLock(
279     __in MdRemoveLock  RemoveLock,
280     __in PVOID  Tag
281     )
282 {
283     IoReleaseRemoveLock(RemoveLock, Tag);
284 }
285 
286 __inline
287 VOID
288 Mx::MxReleaseRemoveLockAndWait(
289     __in MdRemoveLock  RemoveLock,
290     __in PVOID  Tag
291     )
292 {
293     IoReleaseRemoveLockAndWait(RemoveLock, Tag);
294 }
295 
296 __inline
297 BOOLEAN
298 Mx::MxHasEnoughRemainingThreadStack(
299     VOID
300     )
301 {
302     return (IoGetRemainingStackSize() < KERNEL_STACK_SIZE/2) ? FALSE : TRUE;
303 }
304 
305 _Releases_lock_(_Global_cancel_spin_lock_)
306 __drv_requiresIRQL(DISPATCH_LEVEL)
307 __inline
308 VOID
309 Mx::ReleaseCancelSpinLock(
310     __in __drv_restoresIRQL __drv_useCancelIRQL  KIRQL  Irql
311     )
312 {
313     IoReleaseCancelSpinLock(Irql);
314 }
315 
316 __inline
317 NTSTATUS
318 Mx::CreateCallback(
319     __out PCALLBACK_OBJECT  *CallbackObject,
320     __in POBJECT_ATTRIBUTES  ObjectAttributes,
321     __in BOOLEAN  Create,
322     __in BOOLEAN  AllowMultipleCallbacks
323     )
324 {
325     return ExCreateCallback(
326         CallbackObject,
327         ObjectAttributes,
328         Create,
329         AllowMultipleCallbacks);
330 }
331 
332 __inline
333 PVOID
334 Mx::RegisterCallback(
335     __in PCALLBACK_OBJECT  CallbackObject,
336     __in MdCallbackFunction  CallbackFunction,
337     __in PVOID  CallbackContext
338     )
339 {
340     return ExRegisterCallback(
341         CallbackObject,
342         CallbackFunction,
343         CallbackContext);
344 }
345 
346 __inline
347 VOID
348 Mx::UnregisterCallback(
349     __in PVOID  CbRegistration
350     )
351 {
352     ExUnregisterCallback(CbRegistration);
353 }
354 
355 __inline
356 VOID
357 Mx::MxUnlockPages(
358     __in PMDL Mdl
359     )
360 {
361     MmUnlockPages(Mdl);
362 }
363 
364 __inline
365 PVOID
366 Mx::MxGetSystemAddressForMdlSafe(
367     __inout PMDL Mdl,
368     __in    ULONG Priority
369     )
370 {
371     return MmGetSystemAddressForMdlSafe(Mdl, Priority);
372 }
373 
374 __inline
375 VOID
376 Mx::MxBuildMdlForNonPagedPool(
377     __inout PMDL Mdl
378     )
379 {
380     MmBuildMdlForNonPagedPool(Mdl);
381 }
382 
383 __inline
384 PVOID
385 Mx::MxGetDriverObjectExtension(
386     __in PDRIVER_OBJECT DriverObject,
387     __in PVOID ClientIdentificationAddress
388     )
389 {
390     return IoGetDriverObjectExtension(DriverObject,
391                                         ClientIdentificationAddress);
392 }
393 
394 __inline
395 NTSTATUS
396 Mx::MxAllocateDriverObjectExtension(
397     _In_  MdDriverObject DriverObject,
398     _In_  PVOID ClientIdentificationAddress,
399     _In_  ULONG DriverObjectExtensionSize,
400     // When successful, this always allocates already-aliased memory.
401     _Post_ _At_(*DriverObjectExtension, _When_(return==0,
402     __drv_aliasesMem __drv_allocatesMem(Mem) _Post_notnull_))
403     _When_(return == 0, _Outptr_result_bytebuffer_(DriverObjectExtensionSize))
404     PVOID *DriverObjectExtension
405     )
406 {
407     return IoAllocateDriverObjectExtension(DriverObject,
408                                             ClientIdentificationAddress,
409                                             DriverObjectExtensionSize,
410                                             DriverObjectExtension);
411 }
412 
413 __inline
414 MdDeviceObject
415 Mx::MxGetAttachedDeviceReference(
416     __in PDEVICE_OBJECT DriverObject
417     )
418 {
419     return IoGetAttachedDeviceReference(DriverObject);
420 }
421 
422 __inline
423 VOID
424 Mx::MxDeleteSymbolicLink(
425     __in PUNICODE_STRING Value
426     )
427 {
428     IoDeleteSymbolicLink(Value);
429 }
430 
431 __inline
432 VOID
433 Mx::MxDeleteNPagedLookasideList(
434     _In_ PNPAGED_LOOKASIDE_LIST LookasideList
435     )
436 {
437     ExDeleteNPagedLookasideList(LookasideList);
438 }
439 
440 __inline
441 VOID
442 Mx::MxDeletePagedLookasideList(
443     _In_ PPAGED_LOOKASIDE_LIST LookasideList
444     )
445 {
446     ExDeletePagedLookasideList(LookasideList);
447 }
448 
449 __inline
450 VOID
451 Mx::MxInitializeNPagedLookasideList(
452     _Out_     PNPAGED_LOOKASIDE_LIST Lookaside,
453     _In_opt_  PALLOCATE_FUNCTION Allocate,
454     _In_opt_  PFREE_FUNCTION Free,
455     _In_      ULONG Flags,
456     _In_      SIZE_T Size,
457     _In_      ULONG Tag,
458     _In_      USHORT Depth
459     )
460 {
461     ExInitializeNPagedLookasideList(Lookaside,
462                                         Allocate,
463                                         Free,
464                                         Flags,
465                                         Size,
466                                         Tag,
467                                         Depth);
468 }
469 
470 __inline
471 VOID
472 Mx::MxInitializePagedLookasideList(
473     _Out_     PPAGED_LOOKASIDE_LIST Lookaside,
474     _In_opt_  PALLOCATE_FUNCTION Allocate,
475     _In_opt_  PFREE_FUNCTION Free,
476     _In_      ULONG Flags,
477     _In_      SIZE_T Size,
478     _In_      ULONG Tag,
479     _In_      USHORT Depth
480     )
481 {
482     ExInitializePagedLookasideList(Lookaside,
483                                         Allocate,
484                                         Free,
485                                         Flags,
486                                         Size,
487                                         Tag,
488                                         Depth);
489 }
490 
491 __inline
492 VOID
493 Mx::MxDeleteDevice(
494     _In_ MdDeviceObject Device
495     )
496 {
497     IoDeleteDevice(Device);
498 }
499 
500 __inline
501 VOID
502 Mx::MxDetachDevice(
503     _Inout_ MdDeviceObject Device
504     )
505 {
506     IoDetachDevice(Device);
507 }
508 
509 __inline
510 MdDeviceObject
511 Mx::MxAttachDeviceToDeviceStack(
512     _In_ MdDeviceObject SourceDevice,
513     _In_ MdDeviceObject TargetDevice
514     )
515 {
516     return IoAttachDeviceToDeviceStack(SourceDevice, TargetDevice);
517 }
518 
519 __inline
520 NTSTATUS
521 Mx::MxCreateDeviceSecure(
522       _In_      PDRIVER_OBJECT DriverObject,
523       _In_      ULONG DeviceExtensionSize,
524       _In_opt_  PUNICODE_STRING DeviceName,
525       _In_      DEVICE_TYPE DeviceType,
526       _In_      ULONG DeviceCharacteristics,
527       _In_      BOOLEAN Exclusive,
528       _In_      PCUNICODE_STRING DefaultSDDLString,
529       _In_opt_  LPCGUID DeviceClassGuid,
530       _Out_     MdDeviceObject *DeviceObject
531     )
532 {
533 #ifndef __REACTOS__ // we don't have wdmsec.lib
534     return IoCreateDeviceSecure(DriverObject,
535                 DeviceExtensionSize,
536                 DeviceName,
537                 DeviceType,
538                 DeviceCharacteristics,
539                 Exclusive,
540                 DefaultSDDLString,
541                 DeviceClassGuid,
542                 DeviceObject);
543 #else
544     return IoCreateDevice(
545                 DriverObject,
546                 DeviceExtensionSize,
547                 DeviceName,
548                 DeviceType,
549                 DeviceCharacteristics,
550                 Exclusive,
551                 DeviceObject);
552 #endif
553 }
554 
555 __inline
556 NTSTATUS
557 Mx::MxCreateDevice(
558     _In_      PDRIVER_OBJECT DriverObject,
559     _In_      ULONG DeviceExtensionSize,
560     _In_opt_  PUNICODE_STRING DeviceName,
561     _In_      DEVICE_TYPE DeviceType,
562     _In_      ULONG DeviceCharacteristics,
563     _In_      BOOLEAN Exclusive,
564     _Out_     MdDeviceObject *DeviceObject
565 )
566 {
567     return IoCreateDevice(DriverObject,
568                     DeviceExtensionSize,
569                     DeviceName,
570                     DeviceType,
571                     DeviceCharacteristics,
572                     Exclusive,
573                     DeviceObject);
574 
575 }
576 
577 __inline
578 NTSTATUS
579 Mx::MxCreateSymbolicLink(
580     _In_ PUNICODE_STRING SymbolicLinkName,
581     _In_ PUNICODE_STRING DeviceName
582     )
583 {
584     return IoCreateSymbolicLink(SymbolicLinkName, DeviceName);
585 }
586 
587 __inline
588 VOID
589 Mx::MxFlushQueuedDpcs(
590     )
591 {
592     KeFlushQueuedDpcs();
593 }
594 
595 __inline
596 NTSTATUS
597 Mx::MxOpenKey(
598     _Out_ PHANDLE KeyHandle,
599     _In_ ACCESS_MASK DesiredAccess,
600     _In_ POBJECT_ATTRIBUTES ObjectAttributes
601     )
602 {
603     return ZwOpenKey(KeyHandle, DesiredAccess, ObjectAttributes);
604 }
605 
606 __inline
607 NTSTATUS
608 Mx::MxSetDeviceInterfaceState(
609     _In_ PUNICODE_STRING SymbolicLinkName,
610     _In_ BOOLEAN Enable
611     )
612 {
613     return IoSetDeviceInterfaceState(SymbolicLinkName, Enable);
614 }
615 
616 
617 __inline
618 NTSTATUS
619 Mx::MxRegisterDeviceInterface(
620     _In_      PDEVICE_OBJECT PhysicalDeviceObject,
621     _In_      const GUID *InterfaceClassGuid,
622     _In_opt_  PUNICODE_STRING ReferenceString,
623     _Out_     PUNICODE_STRING SymbolicLinkName
624     )
625 {
626     return IoRegisterDeviceInterface(PhysicalDeviceObject,
627                                      InterfaceClassGuid,
628                                      ReferenceString,
629                                      SymbolicLinkName);
630 }
631 
632 __inline
633 NTSTATUS
634 Mx::MxDeleteKey(
635     _In_ HANDLE KeyHandle
636     )
637 {
638     return ZwDeleteKey(KeyHandle);
639 }
640 
641 __inline
642 VOID
643 Mx::MxInitializeMdl(
644     _In_  PMDL MemoryDescriptorList,
645     _In_  PVOID BaseVa,
646     _In_  SIZE_T Length
647     )
648 {
649     MmInitializeMdl(MemoryDescriptorList, BaseVa, Length);
650 }
651 
652 __inline
653 PVOID
654 Mx::MxGetMdlVirtualAddress(
655     _In_ PMDL Mdl
656     )
657 {
658     return MmGetMdlVirtualAddress(Mdl);
659 }
660 
661 __inline
662 VOID
663 Mx::MxBuildPartialMdl(
664     _In_     PMDL SourceMdl,
665     _Inout_  PMDL TargetMdl,
666     _In_     PVOID VirtualAddress,
667     _In_     ULONG Length
668     )
669 {
670     IoBuildPartialMdl(SourceMdl,
671                         TargetMdl,
672                         VirtualAddress,
673                         Length
674                         );
675 }
676 
677 __inline
678 VOID
679 Mx::MxQuerySystemTime(
680     _Out_ PLARGE_INTEGER CurrentTime
681     )
682 {
683     KeQuerySystemTime(CurrentTime);
684 }
685 
686 __inline
687 NTSTATUS
688 Mx::MxSetValueKey(
689     _In_      HANDLE KeyHandle,
690     _In_      PUNICODE_STRING ValueName,
691     _In_opt_  ULONG TitleIndex,
692     _In_      ULONG Type,
693     _In_opt_  PVOID Data,
694     _In_      ULONG DataSize
695     )
696 {
697     return ZwSetValueKey(KeyHandle,
698                           ValueName,
699                           TitleIndex,
700                           Type,
701                           Data,
702                           DataSize
703                           );
704 }
705 
706 __inline
707 NTSTATUS
708 Mx::MxQueryValueKey(
709     _In_       HANDLE KeyHandle,
710     _In_       PUNICODE_STRING ValueName,
711     _In_       KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
712     _Out_opt_  PVOID KeyValueInformation,
713     _In_       ULONG Length,
714     _Out_      PULONG ResultLength
715 )
716 {
717     return ZwQueryValueKey(KeyHandle,
718                             ValueName,
719                             KeyValueInformationClass,
720                             KeyValueInformation,
721                             Length,
722                             ResultLength
723                             );
724 }
725 
726 __inline
727 NTSTATUS
728 Mx::MxReferenceObjectByHandle(
729     __in HANDLE Handle,
730     __in ACCESS_MASK DesiredAccess,
731     __in_opt POBJECT_TYPE ObjectType,
732     __in KPROCESSOR_MODE AccessMode,
733     __out  PVOID *Object,
734     __out_opt POBJECT_HANDLE_INFORMATION HandleInformation
735     )
736 {
737     return ObReferenceObjectByHandle(
738                 Handle,
739                 DesiredAccess,
740                 ObjectType,
741                 AccessMode,
742                 Object,
743                 HandleInformation);
744 }
745 
746 __inline
747 NTSTATUS
748 Mx::MxUnRegisterPlugPlayNotification(
749     __in __drv_freesMem(Pool) PVOID NotificationEntry
750     )
751 {
752     return IoUnregisterPlugPlayNotification(NotificationEntry);
753 }
754 
755 
756 __inline
757 NTSTATUS
758 Mx::MxClose(
759     __in HANDLE Handle
760     )
761 {
762     return ZwClose(Handle);
763 }
764 
765 __inline
766 KIRQL
767 Mx::MxAcquireInterruptSpinLock(
768     _Inout_ PKINTERRUPT Interrupt
769     )
770 {
771     return KeAcquireInterruptSpinLock(Interrupt);
772 }
773 
774 __inline
775 VOID
776 Mx::MxReleaseInterruptSpinLock(
777     _Inout_ PKINTERRUPT Interrupt,
778     _In_ KIRQL OldIrql
779     )
780 {
781     KeReleaseInterruptSpinLock(Interrupt, OldIrql);
782 }
783 
784 __inline
785 BOOLEAN
786 Mx::MxInsertQueueDpc(
787   __inout   PRKDPC Dpc,
788   __in_opt  PVOID SystemArgument1,
789   __in_opt  PVOID SystemArgument2
790 )
791 {
792     return KeInsertQueueDpc(Dpc, SystemArgument1, SystemArgument2);
793 }
794 
795 
796