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