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