1 /*++
2 
3 Copyright (c) Microsoft Corporation
4 
5 Module Name:
6 
7     FxRegKey.cpp
8 
9 Abstract:
10 
11 Author:
12 
13 Environment:
14 
15     user mode only
16 
17 Revision History:
18 
19 --*/
20 
21 #include "FxSupportPch.hpp"
22 
23 //#define UNICODE
24 //#define _UNICODE
25 #include <Winreg.h>
26 
27 extern "C" {
28 #if defined(EVENT_TRACING)
29 #include "FxRegKeyUM.tmh"
30 #endif
31 }
32 
FxRegKey(PFX_DRIVER_GLOBALS FxDriverGlobals)33 FxRegKey::FxRegKey(
34     PFX_DRIVER_GLOBALS FxDriverGlobals
35     ) :
36     FxPagedObject(FX_TYPE_REG_KEY, sizeof(FxRegKey), FxDriverGlobals),
37     m_Key(NULL),
38     m_Globals(FxDriverGlobals),
39     m_CanCloseHandle(TRUE)
40 {
41 }
42 
__drv_maxIRQL(PASSIVE_LEVEL)43 __drv_maxIRQL(PASSIVE_LEVEL)
44 #pragma prefast(suppress:__WARNING_UNMATCHED_DECL_ANNO, "Can't apply kernel mode annotations.");
45 FxRegKey::~FxRegKey()
46 {
47     if (m_Key != NULL) {
48         if (m_CanCloseHandle == TRUE) {
49             RegCloseKey((HKEY)m_Key);
50         }
51         m_Key = NULL;
52     }
53 }
54 
55 NTSTATUS
56 #pragma prefast(suppress:__WARNING_UNMATCHED_DECL_ANNO, "Can't apply kernel mode annotations.");
_Close(__in HANDLE Key)57 FxRegKey::_Close(
58     __in HANDLE Key
59     )
60 {
61     DWORD err = RegCloseKey((HKEY)Key);
62 
63     if (ERROR_SUCCESS == err) {
64         return STATUS_SUCCESS;
65     }
66     else {
67         return WinErrorToNtStatus(err);
68     }
69 }
70 
71 _Must_inspect_result_
72 NTSTATUS
73 #pragma prefast(suppress:__WARNING_UNMATCHED_DECL_ANNO, "Can't apply kernel mode annotations.");
_Create(__in_opt HANDLE ParentKey,__in PCUNICODE_STRING KeyName,__out HANDLE * NewKey,__in ACCESS_MASK DesiredAccess,__in ULONG CreateOptions,__out_opt PULONG CreateDisposition)74 FxRegKey::_Create(
75     __in_opt  HANDLE ParentKey,
76     __in  PCUNICODE_STRING KeyName,
77     __out HANDLE* NewKey,
78     __in  ACCESS_MASK DesiredAccess,
79     __in  ULONG CreateOptions,
80     __out_opt PULONG CreateDisposition
81     )
82 {
83     HKEY parentKey;
84 
85     if (NULL == ParentKey)
86     {
87         parentKey = HKEY_LOCAL_MACHINE;
88     }
89     else
90     {
91         parentKey = (HKEY) ParentKey;
92     }
93 
94     DWORD err = RegCreateKeyEx(parentKey,
95                           KeyName->Buffer,
96                           0,
97                           NULL,
98                           CreateOptions,
99                           DesiredAccess,
100                           NULL,
101                           (PHKEY)NewKey,
102                           CreateDisposition);
103 
104     if (ERROR_SUCCESS == err) {
105         return STATUS_SUCCESS;
106     }
107     else {
108         return WinErrorToNtStatus(err);
109     }
110 }
111 
112 _Must_inspect_result_
113 NTSTATUS
114 #pragma prefast(suppress:__WARNING_UNMATCHED_DECL_ANNO, "Can't apply kernel mode annotations.");
_OpenKey(__in_opt HANDLE ParentKey,__in PCUNICODE_STRING KeyName,__out HANDLE * Key,__in ACCESS_MASK DesiredAccess)115 FxRegKey::_OpenKey(
116     __in_opt  HANDLE ParentKey,
117     __in  PCUNICODE_STRING KeyName,
118     __out HANDLE* Key,
119     __in  ACCESS_MASK DesiredAccess
120     )
121 {
122     HKEY parentKey;
123 
124     if (NULL == ParentKey)
125     {
126         parentKey = HKEY_LOCAL_MACHINE;
127     }
128     else
129     {
130         parentKey = (HKEY) ParentKey;
131     }
132 
133     DWORD err = RegOpenKeyEx(parentKey,
134                              KeyName->Buffer,
135                              0,
136                              DesiredAccess,
137                              (PHKEY)Key);
138 
139     if (ERROR_SUCCESS == err) {
140         return STATUS_SUCCESS;
141     }
142     else {
143         return WinErrorToNtStatus(err);
144     }
145 }
146 
147 _Must_inspect_result_
148 NTSTATUS
149 #pragma prefast(suppress:__WARNING_UNMATCHED_DECL_ANNO, "Can't apply kernel mode annotations.");
_SetValue(_In_ HANDLE Key,_In_ PCUNICODE_STRING ValueName,_In_ ULONG ValueType,_In_reads_bytes_ (ValueLength)PVOID Value,_In_ ULONG ValueLength)150 FxRegKey::_SetValue(
151     _In_ HANDLE Key,
152     _In_ PCUNICODE_STRING ValueName,
153     _In_ ULONG ValueType,
154     _In_reads_bytes_(ValueLength) PVOID Value,
155     _In_ ULONG ValueLength
156     )
157 {
158     DWORD err;
159 
160     err = RegSetValueEx((HKEY)Key,
161                         ValueName->Buffer,
162                         0,
163                         ValueType,
164                         (BYTE*)Value,
165                         ValueLength);
166     if (ERROR_SUCCESS == err) {
167         return STATUS_SUCCESS;
168     }
169     else {
170         return WinErrorToNtStatus(err);
171     }
172 }
173 
174 _Must_inspect_result_
175 NTSTATUS
176 #pragma prefast(suppress:__WARNING_UNMATCHED_DECL_ANNO, "Can't apply kernel mode annotations.");
_QueryValue(__in PFX_DRIVER_GLOBALS FxDriverGlobals,__in HANDLE Key,__in PCUNICODE_STRING ValueName,__in ULONG ValueLength,__out_bcount_opt (ValueLength)PVOID Value,__out_opt PULONG ValueLengthQueried,__out_opt PULONG ValueType)177 FxRegKey::_QueryValue(
178     __in PFX_DRIVER_GLOBALS FxDriverGlobals,
179     __in HANDLE Key,
180     __in PCUNICODE_STRING ValueName,
181     __in ULONG ValueLength,
182     __out_bcount_opt(ValueLength) PVOID Value,
183     __out_opt PULONG ValueLengthQueried,
184     __out_opt PULONG ValueType
185     )
186 {
187     DWORD err;
188     NTSTATUS status;
189     ULONG length;
190 
191     UNREFERENCED_PARAMETER(FxDriverGlobals);
192     ASSERT(Key != HKEY_PERFORMANCE_DATA);
193 
194     length = ValueLength;
195 
196     err = RegQueryValueEx((HKEY)Key,
197                            ValueName->Buffer,
198                            NULL,
199                            ValueType,
200                            (LPBYTE)Value,
201                            &length);
202 
203     if (ValueLengthQueried != NULL) {
204         *ValueLengthQueried = length;
205     }
206 
207     //
208     // Please see the comment in FxRegKeyKm.cpp FxRegKey::_QueryValue about
209     // the call to ZwQueryValueKey.
210     //
211     // If the user supplies a NULL data buffer, RegQueryValueEx will return
212     // ERROR_SUCCESS. However, in order to satisfy UMDF-KMDF DDI parity as well
213     // as internal mode-agnostic code, we must overwrite RegQueryValueEx's
214     // return value of ERROR_SUCCESS (STATUS_SUCCESS) with STATUS_BUFFER_OVERFLOW.
215     //
216     // Other return values are overwritten because WinErrorToNtStatus does not map
217     // all Win32 error codes that RegQueryValueEx returns to the same NTSTATUS
218     // values that ZwQueryValueKey would return in the KM implementation of
219     // FxRegKey::_QueryValue.
220     //
221     if (err == ERROR_SUCCESS) {
222         if (Value != NULL) {
223             status = STATUS_SUCCESS;
224         }
225         else {
226             status = STATUS_BUFFER_OVERFLOW;
227         }
228     }
229     else if (err == ERROR_MORE_DATA) {
230         status = STATUS_BUFFER_OVERFLOW;
231     }
232     else if (err == ERROR_FILE_NOT_FOUND) {
233         status = STATUS_OBJECT_NAME_NOT_FOUND;
234     }
235     else {
236         status = WinErrorToNtStatus(err);
237     }
238 
239     return status;
240 }
241 
242 _Must_inspect_result_
243 NTSTATUS
244 #pragma prefast(suppress:__WARNING_UNMATCHED_DECL_ANNO, "Can't apply kernel mode annotations.");
_QueryULong(__in HANDLE Key,__in PCUNICODE_STRING ValueName,__out PULONG Value)245 FxRegKey::_QueryULong(
246     __in  HANDLE Key,
247     __in  PCUNICODE_STRING ValueName,
248     __out PULONG Value
249     )
250 {
251     DWORD err;
252     NTSTATUS status;
253     ULONG length, type;
254 
255     ASSERT(Key != HKEY_PERFORMANCE_DATA);
256 
257     type = REG_DWORD;
258     length = sizeof(ULONG);
259 
260     err = RegQueryValueEx((HKEY)Key,
261                            ValueName->Buffer,
262                            NULL,
263                            &type,
264                            (LPBYTE)Value,
265                            &length);
266 
267     if ((err == ERROR_SUCCESS || err == ERROR_MORE_DATA) &&
268          type != REG_DWORD) {
269 
270         ASSERT(FALSE);
271 
272         status = STATUS_OBJECT_TYPE_MISMATCH;
273     }
274     else {
275         if (ERROR_SUCCESS == err) {
276             status = STATUS_SUCCESS;
277         }
278         else {
279             status = WinErrorToNtStatus(err);
280         }
281     }
282 
283     return status;
284 }
285 
286 _Must_inspect_result_
287 #pragma prefast(suppress:__WARNING_UNMATCHED_DECL_ANNO, "Can't apply kernel mode annotations.");
288 NTSTATUS
_QueryQuadWord(__in HANDLE Key,__in PCUNICODE_STRING ValueName,__out PLARGE_INTEGER Value)289 FxRegKey::_QueryQuadWord(
290     __in  HANDLE Key,
291     __in  PCUNICODE_STRING ValueName,
292     __out PLARGE_INTEGER Value
293     )
294 {
295     UNREFERENCED_PARAMETER(Key);
296     UNREFERENCED_PARAMETER(ValueName);
297     UNREFERENCED_PARAMETER(Value);
298 
299     return STATUS_UNSUCCESSFUL;
300 }
301 
302 
303