Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

858 lines
20 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1996 - 1999
  3. Module Name:
  4. map.c
  5. Abstract:
  6. This module contains routines for maintaining the SCSI device map in the
  7. registry.
  8. Authors:
  9. Peter Wieland
  10. Environment:
  11. Kernel mode only
  12. Notes:
  13. Revision History:
  14. --*/
  15. #include "port.h"
  16. #define __FILE_ID__ 'map '
  17. HANDLE ScsiDeviceMapKey = (HANDLE) -1;
  18. VOID
  19. SpDeleteLogicalUnitDeviceMapEntry(
  20. PLOGICAL_UNIT_EXTENSION LogicalUnit
  21. );
  22. VOID
  23. SpDeleteAdapterDeviceMap(
  24. PADAPTER_EXTENSION Adapter
  25. );
  26. NTSTATUS
  27. SpBuildAdapterDeviceMap(
  28. IN PADAPTER_EXTENSION Adapter
  29. );
  30. NTSTATUS
  31. SpBuildLogicalUnitDeviceMapEntry(
  32. IN PLOGICAL_UNIT_EXTENSION LogicalUnit
  33. );
  34. NTSTATUS
  35. SpCreateNumericKey(
  36. IN HANDLE Root,
  37. IN ULONG Name,
  38. IN PWSTR Prefix,
  39. IN BOOLEAN Create,
  40. OUT PHANDLE NewKey,
  41. OUT PULONG Disposition
  42. );
  43. #ifdef ALLOC_PRAGMA
  44. #pragma alloc_text(PAGE, SpInitDeviceMap)
  45. #pragma alloc_text(PAGE, SpBuildDeviceMapEntry)
  46. #pragma alloc_text(PAGE, SpBuildAdapterDeviceMap)
  47. #pragma alloc_text(PAGE, SpBuildLogicalUnitDeviceMapEntry)
  48. #pragma alloc_text(PAGE, SpDeleteLogicalUnitDeviceMapEntry)
  49. #pragma alloc_text(PAGE, SpDeleteAdapterDeviceMap)
  50. #pragma alloc_text(PAGE, SpUpdateLogicalUnitDeviceMapEntry)
  51. #pragma alloc_text(PAGE, SpCreateNumericKey)
  52. #endif
  53. NTSTATUS
  54. SpInitDeviceMap(
  55. VOID
  56. )
  57. /*++
  58. Routine Description:
  59. Arguments:
  60. Return Value:
  61. status
  62. --*/
  63. {
  64. UNICODE_STRING name;
  65. OBJECT_ATTRIBUTES objectAttributes;
  66. HANDLE mapKey;
  67. ULONG disposition;
  68. ULONG i;
  69. NTSTATUS status;
  70. PAGED_CODE();
  71. //
  72. // Open the SCSI key in the device map.
  73. //
  74. RtlInitUnicodeString(&name,
  75. L"\\Registry\\Machine\\Hardware\\DeviceMap\\Scsi");
  76. InitializeObjectAttributes(&objectAttributes,
  77. &name,
  78. OBJ_CASE_INSENSITIVE,
  79. NULL,
  80. (PSECURITY_DESCRIPTOR) NULL);
  81. //
  82. // Create or open the key.
  83. //
  84. status = ZwCreateKey(&mapKey,
  85. KEY_READ | KEY_WRITE,
  86. &objectAttributes,
  87. 0,
  88. (PUNICODE_STRING) NULL,
  89. REG_OPTION_VOLATILE,
  90. &disposition);
  91. if(NT_SUCCESS(status)) {
  92. ScsiDeviceMapKey = mapKey;
  93. } else {
  94. ScsiDeviceMapKey = NULL;
  95. }
  96. return status;
  97. }
  98. NTSTATUS
  99. SpBuildDeviceMapEntry(
  100. IN PCOMMON_EXTENSION CommonExtension
  101. )
  102. /*++
  103. Routine Description:
  104. This routine will make an entry for the specified adapter or logical
  105. unit in the SCSI device map in the registry. This table is maintained for
  106. debugging and legacy use.
  107. A handle to the device map key for this device will be stored in the
  108. common device extension. This handle should only be used within the
  109. context of a system thread.
  110. Arguments:
  111. Extension - the object we are adding to the device map.
  112. Return Value:
  113. status
  114. --*/
  115. {
  116. PAGED_CODE();
  117. if(CommonExtension->IsPdo) {
  118. return SpBuildLogicalUnitDeviceMapEntry((PLOGICAL_UNIT_EXTENSION) CommonExtension);
  119. } else {
  120. return SpBuildAdapterDeviceMap((PADAPTER_EXTENSION) CommonExtension);
  121. }
  122. }
  123. NTSTATUS
  124. SpBuildLogicalUnitDeviceMapEntry(
  125. IN PLOGICAL_UNIT_EXTENSION LogicalUnit
  126. )
  127. {
  128. PADAPTER_EXTENSION adapter = LogicalUnit->AdapterExtension;
  129. HANDLE busKey;
  130. PCWSTR typeString;
  131. ANSI_STRING ansiString;
  132. UNICODE_STRING name;
  133. UNICODE_STRING unicodeString;
  134. ULONG disposition;
  135. NTSTATUS status;
  136. PAGED_CODE();
  137. ASSERT(LogicalUnit->IsTemporary == FALSE);
  138. DebugPrint((1, "SpBuildDeviceMapEntry: Building map entry for lun %p\n",
  139. LogicalUnit));
  140. if(adapter->BusDeviceMapKeys == NULL) {
  141. //
  142. // We don't have keys built for the buses yet. Bail out.
  143. //
  144. return STATUS_UNSUCCESSFUL;
  145. }
  146. //
  147. // If we already have a target or LUN key for this device then we're done.
  148. //
  149. if((LogicalUnit->TargetDeviceMapKey != NULL) &&
  150. (LogicalUnit->LunDeviceMapKey != NULL)) {
  151. return STATUS_SUCCESS;
  152. }
  153. busKey = adapter->BusDeviceMapKeys[LogicalUnit->PathId].BusKey;
  154. //
  155. // Create a key for the target
  156. //
  157. status = SpCreateNumericKey(busKey,
  158. LogicalUnit->TargetId,
  159. L"Target Id ",
  160. TRUE,
  161. &(LogicalUnit->TargetDeviceMapKey),
  162. &disposition);
  163. if(!NT_SUCCESS(status)) {
  164. return status;
  165. }
  166. //
  167. // Create the LUN entry
  168. //
  169. status = SpCreateNumericKey(LogicalUnit->TargetDeviceMapKey,
  170. LogicalUnit->Lun,
  171. L"Logical Unit Id ",
  172. TRUE,
  173. &(LogicalUnit->LunDeviceMapKey),
  174. &disposition);
  175. if(!NT_SUCCESS(status)) {
  176. return status;
  177. }
  178. //
  179. // Create the identifier value
  180. //
  181. RtlInitUnicodeString(&name, L"Identifier");
  182. //
  183. // Get the identifier from the inquiry data
  184. //
  185. ansiString.MaximumLength = 28;
  186. ansiString.Length = 28;
  187. ansiString.Buffer = LogicalUnit->InquiryData.VendorId;
  188. status = RtlAnsiStringToUnicodeString(&unicodeString,
  189. &ansiString,
  190. TRUE);
  191. if(NT_SUCCESS(status)) {
  192. status = ZwSetValueKey(LogicalUnit->LunDeviceMapKey,
  193. &name,
  194. 0,
  195. REG_SZ,
  196. unicodeString.Buffer,
  197. unicodeString.Length + sizeof(WCHAR));
  198. RtlFreeUnicodeString(&unicodeString);
  199. }
  200. //
  201. // Determine the peripheral type
  202. //
  203. typeString =
  204. SpGetDeviceTypeInfo(LogicalUnit->InquiryData.DeviceType)->DeviceMapString;
  205. //
  206. // Set type value.
  207. //
  208. RtlInitUnicodeString(&name, L"Type");
  209. status = ZwSetValueKey(LogicalUnit->LunDeviceMapKey,
  210. &name,
  211. 0,
  212. REG_SZ,
  213. (PVOID) typeString,
  214. (wcslen(typeString) + 1) * sizeof(WCHAR));
  215. //
  216. // Write the inquiry data into the device map for debugging purposes
  217. //
  218. RtlInitUnicodeString(&name, L"InquiryData");
  219. status = ZwSetValueKey(LogicalUnit->LunDeviceMapKey,
  220. &name,
  221. 0,
  222. REG_BINARY,
  223. &(LogicalUnit->InquiryData),
  224. INQUIRYDATABUFFERSIZE);
  225. //
  226. // Convert the serial number into unicode and write it out to the
  227. // registry.
  228. //
  229. //
  230. // Get the identifier from the inquiry data
  231. //
  232. if(LogicalUnit->SerialNumber.Length != 0) {
  233. RtlInitUnicodeString(&name, L"SerialNumber");
  234. status = RtlAnsiStringToUnicodeString(
  235. &unicodeString,
  236. &(LogicalUnit->SerialNumber),
  237. TRUE);
  238. if(NT_SUCCESS(status)) {
  239. status = ZwSetValueKey(LogicalUnit->LunDeviceMapKey,
  240. &name,
  241. 0,
  242. REG_SZ,
  243. unicodeString.Buffer,
  244. unicodeString.Length + sizeof(WCHAR));
  245. RtlFreeUnicodeString(&unicodeString);
  246. }
  247. }
  248. //
  249. // If the device identifier page exists then write it out to the registry
  250. //
  251. if(LogicalUnit->DeviceIdentifierPage != NULL) {
  252. RtlInitUnicodeString(&name, L"DeviceIdentifierPage");
  253. status = ZwSetValueKey(LogicalUnit->LunDeviceMapKey,
  254. &name,
  255. 0,
  256. REG_BINARY,
  257. LogicalUnit->DeviceIdentifierPage,
  258. LogicalUnit->DeviceIdentifierPageLength);
  259. }
  260. return STATUS_SUCCESS;
  261. }
  262. NTSTATUS
  263. SpBuildAdapterDeviceMap(
  264. IN PADAPTER_EXTENSION Adapter
  265. )
  266. {
  267. PSCSIPORT_DRIVER_EXTENSION driverExtension;
  268. HANDLE mapKey;
  269. UNICODE_STRING name;
  270. OBJECT_ATTRIBUTES objectAttributes;
  271. ULONG disposition;
  272. ULONG i;
  273. NTSTATUS status;
  274. PUNICODE_STRING servicePath;
  275. ULONG busNumber;
  276. PAGED_CODE();
  277. //
  278. // Grab the handle to the SCSI device map out of the driver extension.
  279. //
  280. driverExtension = IoGetDriverObjectExtension(
  281. Adapter->DeviceObject->DriverObject,
  282. ScsiPortInitialize);
  283. ASSERT(driverExtension != NULL);
  284. mapKey = ScsiDeviceMapKey;
  285. if(mapKey == NULL) {
  286. //
  287. // For some reason we were unable to create the root of the device map
  288. // during scsiport initialization.
  289. //
  290. return STATUS_UNSUCCESSFUL;
  291. }
  292. //
  293. // Create a key beneath this for the port device
  294. //
  295. status = SpCreateNumericKey(mapKey,
  296. Adapter->PortNumber,
  297. L"Scsi Port ",
  298. TRUE,
  299. &(Adapter->PortDeviceMapKey),
  300. &disposition);
  301. if(!NT_SUCCESS(status)) {
  302. return status;
  303. }
  304. //
  305. // Indicate if it's a PCCARD
  306. //
  307. if(RtlEqualMemory(&GUID_BUS_TYPE_PCMCIA,
  308. &(Adapter->BusTypeGuid),
  309. sizeof(GUID))) {
  310. RtlInitUnicodeString(&name, L"PCCARD");
  311. i = 1;
  312. status = ZwSetValueKey(Adapter->PortDeviceMapKey,
  313. &name,
  314. 0,
  315. REG_DWORD,
  316. &i,
  317. sizeof(ULONG));
  318. }
  319. //
  320. // Set the interrupt value
  321. //
  322. if(Adapter->InterruptLevel) {
  323. RtlInitUnicodeString(&name, L"Interrupt");
  324. i = Adapter->InterruptLevel;
  325. status = ZwSetValueKey(Adapter->PortDeviceMapKey,
  326. &name,
  327. 0,
  328. REG_DWORD,
  329. &i,
  330. sizeof(ULONG));
  331. }
  332. //
  333. // Set the base I/O address value
  334. //
  335. if(Adapter->IoAddress) {
  336. RtlInitUnicodeString(&name, L"IOAddress");
  337. i = Adapter->IoAddress;
  338. status = ZwSetValueKey(Adapter->PortDeviceMapKey,
  339. &name,
  340. 0,
  341. REG_DWORD,
  342. &i,
  343. sizeof(ULONG));
  344. }
  345. if(Adapter->Dma64BitAddresses) {
  346. RtlInitUnicodeString(&name, L"Dma64BitAddresses");
  347. i = 0x1;
  348. status = ZwSetValueKey(Adapter->PortDeviceMapKey,
  349. &name,
  350. 0,
  351. REG_DWORD,
  352. &i,
  353. sizeof(ULONG));
  354. }
  355. servicePath = &driverExtension->RegistryPath;
  356. ASSERT(servicePath != NULL);
  357. //
  358. // Add identifier value. This value is equal to the name of the driver
  359. // in the service key. Note the service key name is not NULL terminated
  360. //
  361. {
  362. PWSTR start;
  363. WCHAR buffer[32];
  364. RtlInitUnicodeString(&name, L"Driver");
  365. //
  366. // Get the name of the driver from the service key name.
  367. //
  368. start = (PWSTR) ((PCHAR) servicePath->Buffer + servicePath->Length);
  369. start--;
  370. while(*start != L'\\' && start > servicePath->Buffer) {
  371. start--;
  372. }
  373. if(*start == L'\\') {
  374. start++;
  375. for(i = 0; i < 30; i++) {
  376. buffer[i] = *start++;
  377. if(start >= (servicePath->Buffer +
  378. (servicePath->Length / sizeof(WCHAR)))) {
  379. break;
  380. }
  381. }
  382. i++;
  383. buffer[i] = L'\0';
  384. status = ZwSetValueKey(Adapter->PortDeviceMapKey,
  385. &name,
  386. 0,
  387. REG_SZ,
  388. buffer,
  389. (i + 1) * sizeof(WCHAR));
  390. }
  391. }
  392. //
  393. // Allocate storage for all the bus handles.
  394. //
  395. Adapter->BusDeviceMapKeys = SpAllocatePool(
  396. PagedPool,
  397. (sizeof(DEVICE_MAP_HANDLES) *
  398. Adapter->NumberOfBuses),
  399. SCSIPORT_TAG_DEVICE_MAP,
  400. Adapter->DeviceObject->DriverObject);
  401. if(Adapter->BusDeviceMapKeys == NULL) {
  402. return STATUS_INSUFFICIENT_RESOURCES;
  403. }
  404. RtlZeroMemory(Adapter->BusDeviceMapKeys,
  405. (sizeof(DEVICE_MAP_HANDLES) * Adapter->NumberOfBuses));
  406. //
  407. // Create a key for each bus. In each bus key create an empty key
  408. // the initiator.
  409. //
  410. for(busNumber = 0;
  411. busNumber < Adapter->NumberOfBuses;
  412. busNumber++) {
  413. PDEVICE_MAP_HANDLES busKeys;
  414. HANDLE busKey;
  415. HANDLE targetKey;
  416. busKeys = &(Adapter->BusDeviceMapKeys[busNumber]);
  417. //
  418. // Create a key entry for the bus.
  419. //
  420. status = SpCreateNumericKey(
  421. Adapter->PortDeviceMapKey,
  422. busNumber,
  423. L"Scsi Bus ",
  424. TRUE,
  425. &(busKeys->BusKey),
  426. &disposition);
  427. if(!NT_SUCCESS(status)) {
  428. continue;
  429. }
  430. //
  431. // Now create a key for the initiator.
  432. //
  433. i = Adapter->PortConfig->InitiatorBusId[busNumber];
  434. status = SpCreateNumericKey(busKeys->BusKey,
  435. i,
  436. L"Initiator Id ",
  437. TRUE,
  438. &(busKeys->InitiatorKey),
  439. &disposition);
  440. if(!NT_SUCCESS(status)) {
  441. continue;
  442. }
  443. }
  444. return STATUS_SUCCESS;
  445. }
  446. VOID
  447. SpDeleteDeviceMapEntry(
  448. IN PCOMMON_EXTENSION CommonExtension
  449. )
  450. {
  451. if(CommonExtension->IsPdo) {
  452. SpDeleteLogicalUnitDeviceMapEntry((PLOGICAL_UNIT_EXTENSION) CommonExtension);
  453. } else {
  454. SpDeleteAdapterDeviceMap((PADAPTER_EXTENSION) CommonExtension);
  455. }
  456. return;
  457. }
  458. VOID
  459. SpDeleteLogicalUnitDeviceMapEntry(
  460. PLOGICAL_UNIT_EXTENSION LogicalUnit
  461. )
  462. {
  463. if(LogicalUnit->LunDeviceMapKey != NULL) {
  464. ASSERT(LogicalUnit->IsTemporary == FALSE);
  465. ZwDeleteKey(LogicalUnit->LunDeviceMapKey);
  466. ZwClose(LogicalUnit->LunDeviceMapKey);
  467. LogicalUnit->LunDeviceMapKey = NULL;
  468. }
  469. if(LogicalUnit->TargetDeviceMapKey != NULL) {
  470. ASSERT(LogicalUnit->IsTemporary == FALSE);
  471. ZwDeleteKey(LogicalUnit->TargetDeviceMapKey);
  472. ZwClose(LogicalUnit->TargetDeviceMapKey);
  473. LogicalUnit->TargetDeviceMapKey = NULL;
  474. }
  475. return;
  476. }
  477. VOID
  478. SpDeleteAdapterDeviceMap(
  479. PADAPTER_EXTENSION Adapter
  480. )
  481. {
  482. if(Adapter->BusDeviceMapKeys != NULL) {
  483. ULONG busNumber;
  484. //
  485. // for each bus on the adapter.
  486. //
  487. for(busNumber = 0; busNumber < Adapter->NumberOfBuses; busNumber++) {
  488. PDEVICE_MAP_HANDLES busKeys;
  489. busKeys = &(Adapter->BusDeviceMapKeys[busNumber]);
  490. //
  491. // Attempt to delete the key for the initiator if it was created.
  492. //
  493. if(busKeys->InitiatorKey != NULL) {
  494. ZwDeleteKey(busKeys->InitiatorKey);
  495. ZwClose(busKeys->InitiatorKey);
  496. }
  497. //
  498. // Attempt to delete the key for the bus if it was created.
  499. //
  500. if(busKeys->BusKey != NULL) {
  501. ZwDeleteKey(busKeys->BusKey);
  502. ZwClose(busKeys->BusKey);
  503. }
  504. }
  505. ExFreePool(Adapter->BusDeviceMapKeys);
  506. Adapter->BusDeviceMapKeys = NULL;
  507. }
  508. //
  509. // Attempt to delete the key for the adapter if it was created.
  510. //
  511. if(Adapter->PortDeviceMapKey != NULL) {
  512. ZwDeleteKey(Adapter->PortDeviceMapKey);
  513. ZwClose(Adapter->PortDeviceMapKey);
  514. Adapter->PortDeviceMapKey = NULL;
  515. }
  516. return;
  517. }
  518. NTSTATUS
  519. SpCreateNumericKey(
  520. IN HANDLE Root,
  521. IN ULONG Name,
  522. IN PWSTR Prefix,
  523. IN BOOLEAN Create,
  524. OUT PHANDLE NewKey,
  525. OUT PULONG Disposition
  526. )
  527. /*++
  528. Routine Description:
  529. This function creates a registry key. The name of the key is a string
  530. version of numeric value passed in.
  531. Arguments:
  532. RootKey - Supplies a handle to the key where the new key should be inserted.
  533. Name - Supplies the numeric value to name the key.
  534. Prefix - Supplies a prefix name to add to name.
  535. Create - if TRUE the key will be created if it does not already exist.
  536. NewKey - Returns the handle for the new key.
  537. Disposition - the disposition value set by ZwCreateKey.
  538. Return Value:
  539. Returns the status of the operation.
  540. --*/
  541. {
  542. UNICODE_STRING string;
  543. UNICODE_STRING stringNum;
  544. OBJECT_ATTRIBUTES objectAttributes;
  545. WCHAR bufferNum[16];
  546. WCHAR buffer[64];
  547. NTSTATUS status;
  548. PAGED_CODE();
  549. //
  550. // Copy the Prefix into a string.
  551. //
  552. string.Length = 0;
  553. string.MaximumLength=64;
  554. string.Buffer = buffer;
  555. RtlInitUnicodeString(&stringNum, Prefix);
  556. RtlCopyUnicodeString(&string, &stringNum);
  557. //
  558. // Create a port number key entry.
  559. //
  560. stringNum.Length = 0;
  561. stringNum.MaximumLength = 16;
  562. stringNum.Buffer = bufferNum;
  563. status = RtlIntegerToUnicodeString(Name, 10, &stringNum);
  564. if (!NT_SUCCESS(status)) {
  565. return status;
  566. }
  567. //
  568. // Append the prefix and the numeric name.
  569. //
  570. RtlAppendUnicodeStringToString(&string, &stringNum);
  571. InitializeObjectAttributes( &objectAttributes,
  572. &string,
  573. OBJ_CASE_INSENSITIVE,
  574. Root,
  575. (PSECURITY_DESCRIPTOR) NULL );
  576. if(Create) {
  577. status = ZwCreateKey(NewKey,
  578. KEY_READ | KEY_WRITE,
  579. &objectAttributes,
  580. 0,
  581. (PUNICODE_STRING) NULL,
  582. REG_OPTION_VOLATILE,
  583. Disposition );
  584. } else {
  585. status = ZwOpenKey(NewKey,
  586. KEY_READ | KEY_WRITE,
  587. &objectAttributes);
  588. *Disposition = REG_OPENED_EXISTING_KEY;
  589. }
  590. return(status);
  591. }
  592. NTSTATUS
  593. SpUpdateLogicalUnitDeviceMapEntry(
  594. IN PLOGICAL_UNIT_EXTENSION LogicalUnit
  595. )
  596. {
  597. UNICODE_STRING name;
  598. PAGED_CODE();
  599. if((LogicalUnit->TargetDeviceMapKey == NULL) ||
  600. (LogicalUnit->LunDeviceMapKey == NULL)) {
  601. return STATUS_UNSUCCESSFUL;
  602. }
  603. //
  604. // Write the inquiry data into the device map for debugging purposes
  605. //
  606. RtlInitUnicodeString(&name, L"InquiryData");
  607. ZwSetValueKey(LogicalUnit->LunDeviceMapKey,
  608. &name,
  609. 0,
  610. REG_BINARY,
  611. &(LogicalUnit->InquiryData),
  612. INQUIRYDATABUFFERSIZE);
  613. return STATUS_SUCCESS;
  614. }