1 /*++
2 
3 Copyright (c) Microsoft Corporation
4 
5 Module Name:
6 
7     FxCallbackMutexLock.hpp
8 
9 Abstract:
10 
11     This is the C++ header for the FxCallbackMutexLock
12 
13     This represents a container for handling locking
14     when we callback into the device driver at thread
15     level.
16 
17 Author:
18 
19 
20 
21 
22 Revision History:
23 
24 
25 --*/
26 
27 #ifndef _FXCALLBACKMUTEXLOCK_H_
28 #define _FXCALLBACKMUTEXLOCK_H_
29 
30 extern "C" {
31 // #include "FxCallbackMutexLock.hpp.tmh"
32 }
33 
34 class FxCallbackMutexLock : public FxCallbackLock {
35 
36 private:
37 
38 
39 
40 
41 
42 
43 
44     MxPagedLock m_Lock;
45 
46 public:
47 
48     FxCallbackMutexLock(
49         PFX_DRIVER_GLOBALS FxDriverGlobals
50         ) :
51         FxCallbackLock(FxDriverGlobals)
52     {
53         m_Lock.Initialize();
54     }
55 
56     virtual
57     ~FxCallbackMutexLock()
58     {
59         if (m_Verifier) {
60             delete m_Verifier;
61         }
62     }
63 
64     virtual
65     void
66     Initialize(
67         FxObject* ParentObject
68         )
69     {
70         PFX_DRIVER_GLOBALS fxDriverGlobals;
71 
72         m_Verifier = NULL;
73         fxDriverGlobals = GetDriverGlobals();
74 
75         if (fxDriverGlobals->FxVerifierLock) {
76 
77             //
78             // VerifierLock CreateAndInitialize failure is not fatal,
79             // we just won't track anything
80             //
81             (void) FxVerifierLock::CreateAndInitialize(&m_Verifier,
82                                                        fxDriverGlobals,
83                                                        ParentObject,
84                                                        TRUE);
85         }
86     }
87 
88     virtual
89     void
90     Lock(
91         __out PKIRQL PreviousIrql
92         )
93     {
94         MxThread cur = Mx::MxGetCurrentThread();
95 
96         if (m_OwnerThread == cur) {
97             PFX_DRIVER_GLOBALS fxDriverGlobals;
98 
99             fxDriverGlobals = GetDriverGlobals();
100             m_RecursionCount++;
101 
102             //
103             // For now we have decided not to allow this.
104             //
105 
106 
107 
108 
109 
110 
111 
112             //
113             DoTraceLevelMessage(fxDriverGlobals, TRACE_LEVEL_FATAL, TRACINGDEVICE,
114                                 "Recursive acquire of callback lock 0x%p", this);
115 
116             FxVerifierBugCheck(fxDriverGlobals,
117                                WDF_RECURSIVE_LOCK,
118                                (ULONG_PTR)this);
119         }
120         else {
121             if (m_Verifier != NULL) {
122                 m_Verifier->Lock(PreviousIrql, FALSE);
123             }
124             else {
125                 Mx::MxEnterCriticalRegion();
126                 m_Lock.AcquireUnsafe();
127             }
128             m_OwnerThread = cur;
129         }
130     }
131 
132     virtual
133     void
134     Unlock(
135         __in KIRQL PreviousIrql
136         )
137     {
138         CheckOwnership();
139 
140         if (m_RecursionCount > 0) {
141             m_RecursionCount--;
142         }
143         else {
144             m_OwnerThread = NULL;
145             if (m_Verifier) {
146                 m_Verifier->Unlock(PreviousIrql, FALSE);
147             }
148             else {
149                 m_Lock.ReleaseUnsafe();
150                 Mx::MxLeaveCriticalRegion();
151             }
152         }
153     }
154 
155     _Must_inspect_result_
156     virtual
157     BOOLEAN
158     IsOwner(
159         VOID
160         )
161     {
162         MxThread cur = Mx::MxGetCurrentThread();
163 
164         if (m_OwnerThread == cur) {
165             return TRUE;
166         }
167         else {
168             return FALSE;
169         }
170     }
171 };
172 
173 #endif // _FXCALLBACKMUTEXLOCK_H_
174