1 /* 2 * PROJECT: ReactOS Storage Stack / SCSIPORT storage port library 3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) 4 * PURPOSE: Registry operations 5 * COPYRIGHT: Eric Kohl (eric.kohl@reactos.org) 6 * Aleksey Bragin (aleksey@reactos.org) 7 * 2020 Victor Perevertkin (victor.perevertkin@reactos.org) 8 */ 9 10 #include "scsiport.h" 11 #include "scsitypes.h" 12 13 #define NDEBUG 14 #include <debug.h> 15 16 17 VOID 18 SpiInitOpenKeys( 19 _Inout_ PCONFIGURATION_INFO ConfigInfo, 20 _In_ PSCSI_PORT_DRIVER_EXTENSION DriverExtension) 21 { 22 OBJECT_ATTRIBUTES ObjectAttributes; 23 UNICODE_STRING KeyName; 24 NTSTATUS Status; 25 HANDLE parametersKey; 26 27 DriverExtension->IsLegacyDriver = TRUE; 28 29 /* Open the service key */ 30 InitializeObjectAttributes(&ObjectAttributes, 31 &DriverExtension->RegistryPath, 32 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 33 NULL, 34 NULL); 35 36 Status = ZwOpenKey(&ConfigInfo->ServiceKey, KEY_READ, &ObjectAttributes); 37 38 if (!NT_SUCCESS(Status)) 39 { 40 DPRINT("Unable to open driver's registry key %wZ, status 0x%08x\n", 41 DriverExtension->RegistryPath, Status); 42 ConfigInfo->ServiceKey = NULL; 43 } 44 45 /* If we could open driver's service key, then proceed to the Parameters key */ 46 if (ConfigInfo->ServiceKey != NULL) 47 { 48 RtlInitUnicodeString(&KeyName, L"Parameters"); 49 InitializeObjectAttributes(&ObjectAttributes, 50 &KeyName, 51 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 52 ConfigInfo->ServiceKey, 53 NULL); 54 55 /* Try to open it */ 56 Status = ZwOpenKey(&ConfigInfo->DeviceKey, KEY_READ, &ObjectAttributes); 57 58 if (NT_SUCCESS(Status)) 59 { 60 /* Yes, Parameters key exist, and it must be used instead of 61 the Service key */ 62 ZwClose(ConfigInfo->ServiceKey); 63 ConfigInfo->ServiceKey = ConfigInfo->DeviceKey; 64 ConfigInfo->DeviceKey = NULL; 65 } 66 } 67 68 if (ConfigInfo->ServiceKey != NULL) 69 { 70 /* Open the Device key */ 71 RtlInitUnicodeString(&KeyName, L"Device"); 72 InitializeObjectAttributes(&ObjectAttributes, 73 &KeyName, 74 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 75 ConfigInfo->ServiceKey, 76 NULL); 77 78 /* We don't check for failure here - not needed */ 79 ZwOpenKey(&ConfigInfo->DeviceKey, KEY_READ, &ObjectAttributes); 80 81 // Detect the driver PnP capabilities via its Parameters\PnpInterface key 82 // for example: HKLM\SYSTEM\CurrentControlSet\Services\UNIATA\Parameters\PnpInterface 83 84 RtlInitUnicodeString(&KeyName, L"PnpInterface"); 85 InitializeObjectAttributes(&ObjectAttributes, 86 &KeyName, 87 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 88 ConfigInfo->ServiceKey, 89 NULL); 90 91 Status = ZwOpenKey(¶metersKey, KEY_READ, &ObjectAttributes); 92 93 if (NT_SUCCESS(Status)) 94 { 95 // if the key exists, it's enough for us for now 96 // (the proper check should iterate over INTERFACE_TYPE values) 97 DriverExtension->IsLegacyDriver = FALSE; 98 ZwClose(parametersKey); 99 } 100 } 101 } 102 103 /********************************************************************** 104 * NAME INTERNAL 105 * SpiBuildDeviceMap 106 * 107 * DESCRIPTION 108 * Builds the registry device map of all device which are attached 109 * to the given SCSI HBA port. The device map is located at: 110 * \Registry\Machine\DeviceMap\Scsi 111 * 112 * RUN LEVEL 113 * PASSIVE_LEVEL 114 * 115 * ARGUMENTS 116 * DeviceExtension 117 * ... 118 * 119 * RegistryPath 120 * Name of registry driver service key. 121 * 122 * RETURNS 123 * NTSTATUS 124 */ 125 126 NTSTATUS 127 RegistryInitAdapterKey( 128 _Inout_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension) 129 { 130 OBJECT_ATTRIBUTES ObjectAttributes; 131 UNICODE_STRING KeyName; 132 UNICODE_STRING ValueName; 133 WCHAR NameBuffer[64]; 134 HANDLE ScsiKey; 135 HANDLE ScsiPortKey = NULL; 136 HANDLE ScsiBusKey = NULL; 137 HANDLE ScsiInitiatorKey = NULL; 138 ULONG BusNumber; 139 ULONG UlongData; 140 NTSTATUS Status; 141 142 DPRINT("SpiBuildDeviceMap() called\n"); 143 144 if (DeviceExtension == NULL) 145 { 146 DPRINT1("Invalid parameter\n"); 147 return STATUS_INVALID_PARAMETER; 148 } 149 150 /* Open or create the 'Scsi' subkey */ 151 RtlInitUnicodeString(&KeyName, 152 L"\\Registry\\Machine\\Hardware\\DeviceMap\\Scsi"); 153 InitializeObjectAttributes(&ObjectAttributes, 154 &KeyName, 155 OBJ_CASE_INSENSITIVE | OBJ_OPENIF | OBJ_KERNEL_HANDLE, 156 0, 157 NULL); 158 Status = ZwCreateKey(&ScsiKey, 159 KEY_ALL_ACCESS, 160 &ObjectAttributes, 161 0, 162 NULL, 163 REG_OPTION_VOLATILE, 164 NULL); 165 if (!NT_SUCCESS(Status)) 166 { 167 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status); 168 return Status; 169 } 170 171 /* Create new 'Scsi Port X' subkey */ 172 DPRINT("Scsi Port %lu\n", DeviceExtension->PortNumber); 173 174 swprintf(NameBuffer, 175 L"Scsi Port %lu", 176 DeviceExtension->PortNumber); 177 RtlInitUnicodeString(&KeyName, NameBuffer); 178 InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_KERNEL_HANDLE, ScsiKey, NULL); 179 Status = ZwCreateKey(&ScsiPortKey, 180 KEY_ALL_ACCESS, 181 &ObjectAttributes, 182 0, 183 NULL, 184 REG_OPTION_VOLATILE, 185 NULL); 186 ZwClose(ScsiKey); 187 if (!NT_SUCCESS(Status)) 188 { 189 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status); 190 return Status; 191 } 192 193 /* 194 * Create port-specific values 195 */ 196 197 /* Set 'DMA Enabled' (REG_DWORD) value */ 198 UlongData = (ULONG)!DeviceExtension->PortCapabilities.AdapterUsesPio; 199 DPRINT(" DMA Enabled = %s\n", UlongData ? "TRUE" : "FALSE"); 200 RtlInitUnicodeString(&ValueName, L"DMA Enabled"); 201 Status = ZwSetValueKey(ScsiPortKey, 202 &ValueName, 203 0, 204 REG_DWORD, 205 &UlongData, 206 sizeof(UlongData)); 207 if (!NT_SUCCESS(Status)) 208 { 209 DPRINT("ZwSetValueKey('DMA Enabled') failed (Status %lx)\n", Status); 210 ZwClose(ScsiPortKey); 211 return Status; 212 } 213 214 /* Set 'Driver' (REG_SZ) value */ 215 PUNICODE_STRING driverNameU = &DeviceExtension->Common.DeviceObject->DriverObject 216 ->DriverExtension->ServiceKeyName; 217 218 PWCHAR driverName = ExAllocatePoolWithTag(PagedPool, 219 driverNameU->Length + sizeof(UNICODE_NULL), 220 TAG_SCSIPORT); 221 if (!driverName) 222 { 223 DPRINT("Failed to allocate driverName!\n"); 224 ZwClose(ScsiPortKey); 225 return STATUS_INSUFFICIENT_RESOURCES; 226 } 227 228 RtlCopyMemory(driverName, driverNameU->Buffer, driverNameU->Length); 229 driverName[driverNameU->Length / sizeof(WCHAR)] = UNICODE_NULL; 230 231 RtlInitUnicodeString(&ValueName, L"Driver"); 232 Status = ZwSetValueKey(ScsiPortKey, 233 &ValueName, 234 0, 235 REG_SZ, 236 driverName, 237 driverNameU->Length + sizeof(UNICODE_NULL)); 238 239 ExFreePoolWithTag(driverName, TAG_SCSIPORT); 240 241 if (!NT_SUCCESS(Status)) 242 { 243 DPRINT("ZwSetValueKey('Driver') failed (Status %lx)\n", Status); 244 ZwClose(ScsiPortKey); 245 return Status; 246 } 247 248 /* Set 'Interrupt' (REG_DWORD) value (NT4 only) */ 249 UlongData = (ULONG)DeviceExtension->PortConfig->BusInterruptLevel; 250 DPRINT(" Interrupt = %lu\n", UlongData); 251 RtlInitUnicodeString(&ValueName, L"Interrupt"); 252 Status = ZwSetValueKey(ScsiPortKey, 253 &ValueName, 254 0, 255 REG_DWORD, 256 &UlongData, 257 sizeof(UlongData)); 258 if (!NT_SUCCESS(Status)) 259 { 260 DPRINT("ZwSetValueKey('Interrupt') failed (Status %lx)\n", Status); 261 ZwClose(ScsiPortKey); 262 return Status; 263 } 264 265 /* Set 'IOAddress' (REG_DWORD) value (NT4 only) */ 266 UlongData = ScsiPortConvertPhysicalAddressToUlong((*DeviceExtension->PortConfig->AccessRanges)[0].RangeStart); 267 DPRINT(" IOAddress = %lx\n", UlongData); 268 RtlInitUnicodeString(&ValueName, L"IOAddress"); 269 Status = ZwSetValueKey(ScsiPortKey, 270 &ValueName, 271 0, 272 REG_DWORD, 273 &UlongData, 274 sizeof(UlongData)); 275 if (!NT_SUCCESS(Status)) 276 { 277 DPRINT("ZwSetValueKey('IOAddress') failed (Status %lx)\n", Status); 278 ZwClose(ScsiPortKey); 279 return Status; 280 } 281 282 /* Enumerate buses */ 283 for (BusNumber = 0; BusNumber < DeviceExtension->NumberOfBuses; BusNumber++) 284 { 285 /* Create 'Scsi Bus X' key */ 286 DPRINT(" Scsi Bus %lu\n", BusNumber); 287 swprintf(NameBuffer, 288 L"Scsi Bus %lu", 289 BusNumber); 290 RtlInitUnicodeString(&KeyName, NameBuffer); 291 InitializeObjectAttributes(&ObjectAttributes, 292 &KeyName, 293 OBJ_KERNEL_HANDLE, 294 ScsiPortKey, 295 NULL); 296 Status = ZwCreateKey(&ScsiBusKey, 297 KEY_ALL_ACCESS, 298 &ObjectAttributes, 299 0, 300 NULL, 301 REG_OPTION_VOLATILE, 302 NULL); 303 if (!NT_SUCCESS(Status)) 304 { 305 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status); 306 goto ByeBye; 307 } 308 309 /* Create 'Initiator Id X' key */ 310 DPRINT(" Initiator Id %lu\n", 311 DeviceExtension->PortConfig->InitiatorBusId[BusNumber]); 312 swprintf(NameBuffer, 313 L"Initiator Id %lu", 314 (ULONG)(UCHAR)DeviceExtension->PortConfig->InitiatorBusId[BusNumber]); 315 RtlInitUnicodeString(&KeyName, NameBuffer); 316 InitializeObjectAttributes(&ObjectAttributes, 317 &KeyName, 318 OBJ_KERNEL_HANDLE, 319 ScsiBusKey, 320 NULL); 321 Status = ZwCreateKey(&ScsiInitiatorKey, 322 KEY_ALL_ACCESS, 323 &ObjectAttributes, 324 0, 325 NULL, 326 REG_OPTION_VOLATILE, 327 NULL); 328 if (!NT_SUCCESS(Status)) 329 { 330 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status); 331 goto ByeBye; 332 } 333 334 /* FIXME: Are there any initiator values (??) */ 335 336 ZwClose(ScsiInitiatorKey); 337 ScsiInitiatorKey = NULL; 338 339 DeviceExtension->Buses[BusNumber].RegistryMapKey = ScsiBusKey; 340 ScsiBusKey = NULL; 341 } 342 343 ByeBye: 344 if (ScsiInitiatorKey != NULL) 345 ZwClose(ScsiInitiatorKey); 346 347 if (ScsiBusKey != NULL) 348 ZwClose(ScsiBusKey); 349 350 if (ScsiPortKey != NULL) 351 ZwClose(ScsiPortKey); 352 353 DPRINT("SpiBuildDeviceMap() done\n"); 354 355 return Status; 356 } 357 358 NTSTATUS 359 RegistryInitLunKey( 360 _Inout_ PSCSI_PORT_LUN_EXTENSION LunExtension) 361 { 362 WCHAR nameBuffer[64]; 363 UNICODE_STRING keyName; 364 UNICODE_STRING valueName; 365 OBJECT_ATTRIBUTES objectAttributes; 366 HANDLE targetKey; 367 NTSTATUS status; 368 369 // get the LUN's bus key 370 PSCSI_PORT_DEVICE_EXTENSION portExt = LunExtension->Common.LowerDevice->DeviceExtension; 371 HANDLE busKey = portExt->Buses[LunExtension->PathId].RegistryMapKey; 372 373 // create/open 'Target Id X' key 374 swprintf(nameBuffer, L"Target Id %lu", LunExtension->TargetId); 375 RtlInitUnicodeString(&keyName, nameBuffer); 376 InitializeObjectAttributes(&objectAttributes, &keyName, OBJ_KERNEL_HANDLE, busKey, NULL); 377 status = ZwCreateKey(&targetKey, 378 KEY_ALL_ACCESS, 379 &objectAttributes, 380 0, 381 NULL, 382 REG_OPTION_VOLATILE, 383 NULL); 384 if (!NT_SUCCESS(status)) 385 { 386 DPRINT("ZwCreateKey() failed (Status %lx)\n", status); 387 return status; 388 } 389 390 // Create 'Logical Unit Id X' key 391 swprintf(nameBuffer, L"Logical Unit Id %lu", LunExtension->Lun); 392 RtlInitUnicodeString(&keyName, nameBuffer); 393 InitializeObjectAttributes(&objectAttributes, &keyName, OBJ_KERNEL_HANDLE, targetKey, NULL); 394 status = ZwCreateKey(&LunExtension->RegistryMapKey, 395 KEY_ALL_ACCESS, 396 &objectAttributes, 397 0, 398 NULL, 399 REG_OPTION_VOLATILE, 400 NULL); 401 if (!NT_SUCCESS(status)) 402 { 403 DPRINT("ZwCreateKey() failed (Status %lx)\n", status); 404 goto ByeBye; 405 } 406 407 // Set 'Identifier' (REG_SZ) value 408 swprintf(nameBuffer, 409 L"%.8S%.16S%.4S", 410 LunExtension->InquiryData.VendorId, 411 LunExtension->InquiryData.ProductId, 412 LunExtension->InquiryData.ProductRevisionLevel); 413 RtlInitUnicodeString(&valueName, L"Identifier"); 414 status = ZwSetValueKey(LunExtension->RegistryMapKey, 415 &valueName, 416 0, 417 REG_SZ, 418 nameBuffer, 419 (wcslen(nameBuffer) + 1) * sizeof(WCHAR)); 420 if (!NT_SUCCESS(status)) 421 { 422 DPRINT("ZwSetValueKey('Identifier') failed (Status %lx)\n", status); 423 goto ByeBye; 424 } 425 426 // Set 'Type' (REG_SZ) value 427 PWCHAR typeName = (PWCHAR)GetPeripheralTypeW(&LunExtension->InquiryData); 428 DPRINT(" Type = '%S'\n", typeName); 429 RtlInitUnicodeString(&valueName, L"Type"); 430 status = ZwSetValueKey(LunExtension->RegistryMapKey, 431 &valueName, 432 0, 433 REG_SZ, 434 typeName, 435 (wcslen(typeName) + 1) * sizeof(WCHAR)); 436 if (!NT_SUCCESS(status)) 437 { 438 DPRINT("ZwSetValueKey('Type') failed (Status %lx)\n", status); 439 goto ByeBye; 440 } 441 442 // Set 'InquiryData' (REG_BINARY) value 443 RtlInitUnicodeString(&valueName, L"InquiryData"); 444 status = ZwSetValueKey(LunExtension->RegistryMapKey, 445 &valueName, 446 0, 447 REG_BINARY, 448 &LunExtension->InquiryData, 449 INQUIRYDATABUFFERSIZE); 450 if (!NT_SUCCESS(status)) 451 { 452 DPRINT("ZwSetValueKey('InquiryData') failed (Status %lx)\n", status); 453 goto ByeBye; 454 } 455 456 ByeBye: 457 ZwClose(targetKey); 458 // TODO: maybe we will need it in future 459 ZwClose(LunExtension->RegistryMapKey); 460 461 return status; 462 } 463