1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/wdm/audio/backpln/portcls/registry.cpp
5 * PURPOSE: Registry access object
6 * PROGRAMMER: Johannes Anderwald
7 */
8
9 #include "private.hpp"
10
11 #define NDEBUG
12 #include <debug.h>
13
14 class CRegistryKey : public CUnknownImpl<IRegistryKey>
15 {
16 public:
17 STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
18
19 IMP_IRegistryKey;
CRegistryKey(IUnknown * OuterUnknown,HANDLE hKey,BOOL CanDelete)20 CRegistryKey(IUnknown * OuterUnknown, HANDLE hKey, BOOL CanDelete) :
21 m_hKey(hKey),
22 m_Deleted(FALSE),
23 m_CanDelete(CanDelete)
24 {
25 }
26 virtual ~CRegistryKey();
27
28 protected:
29
30 HANDLE m_hKey;
31 BOOL m_Deleted;
32 BOOL m_CanDelete;
33 };
34
~CRegistryKey()35 CRegistryKey::~CRegistryKey()
36 {
37 if (!m_Deleted)
38 {
39 // close key only when has not been deleted yet
40 ZwClose(m_hKey);
41 }
42 }
43
44 NTSTATUS
45 NTAPI
QueryInterface(IN REFIID refiid,OUT PVOID * Output)46 CRegistryKey::QueryInterface(
47 IN REFIID refiid,
48 OUT PVOID* Output)
49 {
50 UNICODE_STRING GuidString;
51
52 DPRINT("CRegistryKey::QueryInterface entered\n");
53 if (IsEqualGUIDAligned(refiid, IID_IRegistryKey) ||
54 IsEqualGUIDAligned(refiid, IID_IUnknown))
55 {
56 *Output = PVOID(PREGISTRYKEY(this));
57 PUNKNOWN(*Output)->AddRef();
58 return STATUS_SUCCESS;
59 }
60
61 if (RtlStringFromGUID(refiid, &GuidString) == STATUS_SUCCESS)
62 {
63 DPRINT1("CRegistryKey::QueryInterface no interface!!! iface %S\n", GuidString.Buffer);
64 RtlFreeUnicodeString(&GuidString);
65 }
66
67 return STATUS_UNSUCCESSFUL;
68 }
69
70 NTSTATUS
71 NTAPI
DeleteKey()72 CRegistryKey::DeleteKey()
73 {
74 NTSTATUS Status;
75 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
76
77 if (m_Deleted)
78 {
79 // key already deleted
80 return STATUS_INVALID_HANDLE;
81 }
82
83 if (!m_CanDelete)
84 {
85 // only general keys can be deleted
86 return STATUS_ACCESS_DENIED;
87 }
88
89 // delete key
90 Status = ZwDeleteKey(m_hKey);
91 if (NT_SUCCESS(Status))
92 {
93 m_Deleted = TRUE;
94 m_hKey = NULL;
95 }
96 return Status;
97 }
98
99 NTSTATUS
100 NTAPI
EnumerateKey(IN ULONG Index,IN KEY_INFORMATION_CLASS KeyInformationClass,OUT PVOID KeyInformation,IN ULONG Length,OUT PULONG ResultLength)101 CRegistryKey::EnumerateKey(
102 IN ULONG Index,
103 IN KEY_INFORMATION_CLASS KeyInformationClass,
104 OUT PVOID KeyInformation,
105 IN ULONG Length,
106 OUT PULONG ResultLength)
107 {
108 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
109
110 if (m_Deleted)
111 {
112 return STATUS_INVALID_HANDLE;
113 }
114
115 return ZwEnumerateKey(m_hKey, Index, KeyInformationClass, KeyInformation, Length, ResultLength);
116 }
117
118 NTSTATUS
119 NTAPI
EnumerateValueKey(IN ULONG Index,IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,OUT PVOID KeyValueInformation,IN ULONG Length,OUT PULONG ResultLength)120 CRegistryKey::EnumerateValueKey(
121 IN ULONG Index,
122 IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
123 OUT PVOID KeyValueInformation,
124 IN ULONG Length,
125 OUT PULONG ResultLength)
126 {
127 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
128
129 if (m_Deleted)
130 {
131 return STATUS_INVALID_HANDLE;
132 }
133
134 return ZwEnumerateValueKey(m_hKey, Index, KeyValueInformationClass, KeyValueInformation, Length, ResultLength);
135 }
136
137 NTSTATUS
138 NTAPI
NewSubKey(OUT PREGISTRYKEY * RegistrySubKey,IN PUNKNOWN OuterUnknown,IN ACCESS_MASK DesiredAccess,IN PUNICODE_STRING SubKeyName,IN ULONG CreateOptions,OUT PULONG Disposition OPTIONAL)139 CRegistryKey::NewSubKey(
140 OUT PREGISTRYKEY *RegistrySubKey,
141 IN PUNKNOWN OuterUnknown,
142 IN ACCESS_MASK DesiredAccess,
143 IN PUNICODE_STRING SubKeyName,
144 IN ULONG CreateOptions,
145 OUT PULONG Disposition OPTIONAL)
146 {
147 OBJECT_ATTRIBUTES Attributes;
148 NTSTATUS Status;
149 HANDLE hKey;
150 CRegistryKey * RegistryKey;
151
152 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
153
154 DPRINT("CRegistryKey::NewSubKey entered %S\n", SubKeyName->Buffer);
155
156 if (m_Deleted)
157 {
158 return STATUS_INVALID_HANDLE;
159 }
160
161 InitializeObjectAttributes(&Attributes, SubKeyName, OBJ_INHERIT | OBJ_CASE_INSENSITIVE | OBJ_OPENIF | OBJ_KERNEL_HANDLE, m_hKey, NULL);
162 Status = ZwCreateKey(&hKey, DesiredAccess, &Attributes, 0, NULL, CreateOptions, Disposition);
163 if (!NT_SUCCESS(Status))
164 {
165 DPRINT("CRegistryKey::NewSubKey failed with %x\n", Status);
166 return Status;
167 }
168
169 RegistryKey = new(NonPagedPool, TAG_PORTCLASS)CRegistryKey(OuterUnknown, hKey, TRUE);
170 if (!RegistryKey)
171 return STATUS_INSUFFICIENT_RESOURCES;
172
173 Status = RegistryKey->QueryInterface(IID_IRegistryKey, (PVOID*)RegistrySubKey);
174
175 if (!NT_SUCCESS(Status))
176 {
177 delete RegistryKey;
178 return Status;
179 }
180
181 DPRINT("CRegistryKey::NewSubKey RESULT %p\n", *RegistrySubKey);
182 return STATUS_SUCCESS;
183 }
184
185 NTSTATUS
186 NTAPI
QueryKey(IN KEY_INFORMATION_CLASS KeyInformationClass,OUT PVOID KeyInformation,IN ULONG Length,OUT PULONG ResultLength)187 CRegistryKey::QueryKey(
188 IN KEY_INFORMATION_CLASS KeyInformationClass,
189 OUT PVOID KeyInformation,
190 IN ULONG Length,
191 OUT PULONG ResultLength)
192 {
193 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
194
195 if (m_Deleted)
196 {
197 return STATUS_INVALID_HANDLE;
198 }
199
200 return ZwQueryKey(m_hKey, KeyInformationClass, KeyInformation, Length, ResultLength);
201 }
202
203 NTSTATUS
204 NTAPI
QueryRegistryValues(IN PRTL_QUERY_REGISTRY_TABLE QueryTable,IN PVOID Context OPTIONAL)205 CRegistryKey::QueryRegistryValues(
206 IN PRTL_QUERY_REGISTRY_TABLE QueryTable,
207 IN PVOID Context OPTIONAL)
208 {
209 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
210
211 if (m_Deleted)
212 {
213 return STATUS_INVALID_HANDLE;
214 }
215
216 return RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, (PCWSTR)m_hKey, QueryTable, Context, NULL);
217 }
218
219 NTSTATUS
220 NTAPI
QueryValueKey(IN PUNICODE_STRING ValueName,IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,OUT PVOID KeyValueInformation,IN ULONG Length,OUT PULONG ResultLength)221 CRegistryKey::QueryValueKey(
222 IN PUNICODE_STRING ValueName,
223 IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
224 OUT PVOID KeyValueInformation,
225 IN ULONG Length,
226 OUT PULONG ResultLength)
227 {
228 NTSTATUS Status;
229
230 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
231
232 if (m_Deleted)
233 {
234 return STATUS_INVALID_HANDLE;
235 }
236
237 Status = ZwQueryValueKey(m_hKey, ValueName, KeyValueInformationClass, KeyValueInformation, Length, ResultLength);
238 DPRINT("CRegistryKey::QueryValueKey entered %p value %wZ Status %x\n", this, ValueName, Status);
239 return Status;
240 }
241
242 NTSTATUS
243 NTAPI
SetValueKey(IN PUNICODE_STRING ValueName OPTIONAL,IN ULONG Type,IN PVOID Data,IN ULONG DataSize)244 CRegistryKey::SetValueKey(
245 IN PUNICODE_STRING ValueName OPTIONAL,
246 IN ULONG Type,
247 IN PVOID Data,
248 IN ULONG DataSize
249 )
250 {
251 DPRINT("CRegistryKey::SetValueKey entered %S\n", ValueName->Buffer);
252 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
253
254 if (m_Deleted)
255 {
256 return STATUS_INVALID_HANDLE;
257 }
258
259 return ZwSetValueKey(m_hKey, ValueName, 0, Type, Data, DataSize);
260 }
261
262 NTSTATUS
263 NTAPI
PcNewRegistryKey(OUT PREGISTRYKEY * OutRegistryKey,IN PUNKNOWN OuterUnknown OPTIONAL,IN ULONG RegistryKeyType,IN ACCESS_MASK DesiredAccess,IN PVOID DeviceObject OPTIONAL,IN PVOID SubDevice OPTIONAL,IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,IN ULONG CreateOptions OPTIONAL,OUT PULONG Disposition OPTIONAL)264 PcNewRegistryKey(
265 OUT PREGISTRYKEY* OutRegistryKey,
266 IN PUNKNOWN OuterUnknown OPTIONAL,
267 IN ULONG RegistryKeyType,
268 IN ACCESS_MASK DesiredAccess,
269 IN PVOID DeviceObject OPTIONAL,
270 IN PVOID SubDevice OPTIONAL,
271 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
272 IN ULONG CreateOptions OPTIONAL,
273 OUT PULONG Disposition OPTIONAL)
274 {
275 HANDLE hHandle;
276 NTSTATUS Status = STATUS_UNSUCCESSFUL;
277 CRegistryKey * RegistryKey;
278 PPCLASS_DEVICE_EXTENSION DeviceExt;
279 PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor;
280 ISubdevice * Device;
281 PSYMBOLICLINK_ENTRY SymEntry;
282 BOOL CanDelete = FALSE;
283
284 DPRINT("PcNewRegistryKey entered\n");
285
286 if (!OutRegistryKey)
287 return STATUS_INVALID_PARAMETER;
288
289 if (RegistryKeyType != GeneralRegistryKey &&
290 RegistryKeyType != DeviceRegistryKey &&
291 RegistryKeyType != DriverRegistryKey &&
292 RegistryKeyType != HwProfileRegistryKey &&
293 RegistryKeyType != DeviceInterfaceRegistryKey)
294 {
295 return STATUS_INVALID_PARAMETER;
296 }
297
298 // check for the key type
299 if (RegistryKeyType == GeneralRegistryKey)
300 {
301 // do we have the required object attributes
302 if (!ObjectAttributes)
303 {
304 // object attributes is mandatory
305 return STATUS_INVALID_PARAMETER;
306 }
307 // try to create the key
308 Status = ZwCreateKey(&hHandle, DesiredAccess, ObjectAttributes, 0, NULL, CreateOptions, Disposition);
309
310 // key can be deleted
311 CanDelete = TRUE;
312 }
313 else if (RegistryKeyType == DeviceRegistryKey ||
314 RegistryKeyType == DriverRegistryKey ||
315 RegistryKeyType == HwProfileRegistryKey)
316 {
317 // check for HwProfileRegistryKey case
318 if (RegistryKeyType == HwProfileRegistryKey)
319 {
320 // IoOpenDeviceRegistryKey used different constant
321 RegistryKeyType = PLUGPLAY_REGKEY_CURRENT_HWPROFILE | PLUGPLAY_REGKEY_DEVICE;
322 }
323
324 // obtain the new device extension
325 DeviceExt = (PPCLASS_DEVICE_EXTENSION) ((PDEVICE_OBJECT)DeviceObject)->DeviceExtension;
326
327 Status = IoOpenDeviceRegistryKey(DeviceExt->PhysicalDeviceObject, RegistryKeyType, DesiredAccess, &hHandle);
328 }
329 else if (RegistryKeyType == DeviceInterfaceRegistryKey)
330 {
331 if (SubDevice == NULL)
332 {
333 // invalid parameter
334 return STATUS_INVALID_PARAMETER;
335 }
336
337 // look up our undocumented interface
338 Status = ((PUNKNOWN)SubDevice)->QueryInterface(IID_ISubdevice, (LPVOID*)&Device);
339
340 if (!NT_SUCCESS(Status))
341 {
342 DPRINT("No ISubdevice interface\n");
343 // invalid parameter
344 return STATUS_INVALID_PARAMETER;
345 }
346
347 // get the subdevice descriptor
348 Status = Device->GetDescriptor(&SubDeviceDescriptor);
349 if (!NT_SUCCESS(Status))
350 {
351 DPRINT("Failed to get subdevice descriptor %x\n", Status);
352 ((PUNKNOWN)SubDevice)->Release();
353 return STATUS_UNSUCCESSFUL;
354 }
355
356 // is there an registered device interface
357 if (IsListEmpty(&SubDeviceDescriptor->SymbolicLinkList))
358 {
359 DPRINT("No device interface registered\n");
360 ((PUNKNOWN)SubDevice)->Release();
361 return STATUS_UNSUCCESSFUL;
362 }
363
364 // get the first symbolic link
365 SymEntry = (PSYMBOLICLINK_ENTRY)CONTAINING_RECORD(SubDeviceDescriptor->SymbolicLinkList.Flink, SYMBOLICLINK_ENTRY, Entry);
366
367 // open device interface
368 Status = IoOpenDeviceInterfaceRegistryKey(&SymEntry->SymbolicLink, DesiredAccess, &hHandle);
369
370 // release subdevice interface
371 ((PUNKNOWN)SubDevice)->Release();
372 }
373
374 // check for success
375 if (!NT_SUCCESS(Status))
376 {
377 DPRINT1("PcNewRegistryKey failed with %lx\n", Status);
378 return Status;
379 }
380
381 // allocate new registry key object
382 RegistryKey = new(NonPagedPool, TAG_PORTCLASS)CRegistryKey(OuterUnknown, hHandle, CanDelete);
383 if (!RegistryKey)
384 {
385 // not enough memory
386 ZwClose(hHandle);
387 return STATUS_INSUFFICIENT_RESOURCES;
388 }
389
390 // query for interface
391 Status = RegistryKey->QueryInterface(IID_IRegistryKey, (PVOID*)OutRegistryKey);
392
393 if (!NT_SUCCESS(Status))
394 {
395 // out of memory
396 delete RegistryKey;
397 }
398
399 DPRINT("PcNewRegistryKey result %p\n", *OutRegistryKey);
400 return STATUS_SUCCESS;
401 }
402