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.

2294 lines
52 KiB

  1. #include "precomp.h"
  2. #include "utils.h"
  3. #define PORT_TAG_MINIPORT_PARAM ('pMlP')
  4. #define PORT_REG_BUFFER_SIZE 512
  5. #define DISK_SERVICE_KEY L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Disk"
  6. HANDLE
  7. PortpOpenParametersKey(
  8. IN PUNICODE_STRING RegistryPath
  9. );
  10. BOOLEAN
  11. PortpReadDriverParameterEntry(
  12. IN HANDLE Key,
  13. OUT PVOID * DriverParameters
  14. );
  15. BOOLEAN
  16. PortpReadLinkTimeoutValue(
  17. IN HANDLE Key,
  18. OUT PULONG LinkTimeout
  19. );
  20. HANDLE
  21. PortOpenDeviceKey(
  22. IN PUNICODE_STRING RegistryPath,
  23. IN ULONG DeviceNumber
  24. );
  25. VOID
  26. PortFreeDriverParameters(
  27. PVOID DriverParameters
  28. );
  29. VOID
  30. PortGetDriverParameters(
  31. IN PUNICODE_STRING RegistryPath,
  32. IN ULONG DeviceNumber,
  33. OUT PVOID * DriverParameters
  34. );
  35. BOOLEAN
  36. PortpReadMaximumLogicalUnitEntry(
  37. IN HANDLE Key,
  38. IN PUCHAR Buffer,
  39. OUT PPORT_ADAPTER_REGISTRY_VALUES Context
  40. );
  41. BOOLEAN
  42. PortpReadInitiatorTargetIdEntry(
  43. IN HANDLE Key,
  44. IN PUCHAR Buffer,
  45. OUT PPORT_ADAPTER_REGISTRY_VALUES Context
  46. );
  47. BOOLEAN
  48. PortpReadDebugEntry(
  49. IN HANDLE Key,
  50. IN PUCHAR Buffer,
  51. OUT PPORT_ADAPTER_REGISTRY_VALUES Context
  52. );
  53. BOOLEAN
  54. PortpReadBreakPointEntry(
  55. IN HANDLE Key,
  56. IN PUCHAR Buffer,
  57. OUT PPORT_ADAPTER_REGISTRY_VALUES Context
  58. );
  59. BOOLEAN
  60. PortpReadDisableSynchronousTransfersEntry(
  61. IN HANDLE Key,
  62. IN PUCHAR Buffer,
  63. OUT PPORT_ADAPTER_REGISTRY_VALUES Context
  64. );
  65. BOOLEAN
  66. PortpReadDisableDisconnectsEntry(
  67. IN HANDLE Key,
  68. IN PUCHAR Buffer,
  69. OUT PPORT_ADAPTER_REGISTRY_VALUES Context
  70. );
  71. BOOLEAN
  72. PortpReadDisableTaggedQueuingEntry(
  73. IN HANDLE Key,
  74. IN PUCHAR Buffer,
  75. OUT PPORT_ADAPTER_REGISTRY_VALUES Context
  76. );
  77. BOOLEAN
  78. PortpReadDisableMultipleRequestsEntry(
  79. IN HANDLE Key,
  80. IN PUCHAR Buffer,
  81. OUT PPORT_ADAPTER_REGISTRY_VALUES Context
  82. );
  83. BOOLEAN
  84. PortpReadMinimumUCXAddressEntry(
  85. IN HANDLE Key,
  86. IN PUCHAR Buffer,
  87. OUT PPORT_ADAPTER_REGISTRY_VALUES Context
  88. );
  89. BOOLEAN
  90. PortpReadMaximumUCXAddressEntry(
  91. IN HANDLE Key,
  92. IN PUCHAR Buffer,
  93. OUT PPORT_ADAPTER_REGISTRY_VALUES Context
  94. );
  95. BOOLEAN
  96. PortpReadMaximumSGListEntry(
  97. IN HANDLE Key,
  98. IN PUCHAR Buffer,
  99. OUT PPORT_ADAPTER_REGISTRY_VALUES Context
  100. );
  101. BOOLEAN
  102. PortpReadNumberOfRequestsEntry(
  103. IN HANDLE Key,
  104. IN PUCHAR Buffer,
  105. OUT PPORT_ADAPTER_REGISTRY_VALUES Context
  106. );
  107. BOOLEAN
  108. PortpReadResourceListEntry(
  109. IN HANDLE Key,
  110. IN PUCHAR Buffer,
  111. OUT PPORT_ADAPTER_REGISTRY_VALUES Context
  112. );
  113. BOOLEAN
  114. PortpReadUncachedExtAlignmentEntry(
  115. IN HANDLE Key,
  116. IN PUCHAR Buffer,
  117. OUT PPORT_ADAPTER_REGISTRY_VALUES Context
  118. );
  119. BOOLEAN
  120. PortpReadInquiryTimeoutEntry(
  121. IN HANDLE Key,
  122. IN PUCHAR Buffer,
  123. OUT PPORT_ADAPTER_REGISTRY_VALUES Context
  124. );
  125. BOOLEAN
  126. PortpReadResetHoldTimeEntry(
  127. IN HANDLE Key,
  128. IN PUCHAR Buffer,
  129. OUT PPORT_ADAPTER_REGISTRY_VALUES Context
  130. );
  131. BOOLEAN
  132. PortpReadCreateInitiatorLUEntry(
  133. IN HANDLE Key,
  134. IN PUCHAR Buffer,
  135. OUT PPORT_ADAPTER_REGISTRY_VALUES Context
  136. );
  137. #if 0
  138. VOID
  139. PortReadRegistrySettings(
  140. IN HANDLE Key,
  141. IN PPORT_ADAPTER_REGISTRY_VALUES Context,
  142. IN ULONG Fields
  143. );
  144. VOID
  145. PortGetRegistrySettings(
  146. IN PUNICODE_STRING RegistryPath,
  147. IN ULONG DeviceNumber,
  148. IN PPORT_ADAPTER_REGISTRY_VALUES Context,
  149. IN ULONG Fields
  150. );
  151. #endif
  152. #ifdef ALLOC_PRAGMA
  153. #pragma alloc_text(PAGE, PortpOpenParametersKey)
  154. #pragma alloc_text(PAGE, PortOpenDeviceKey)
  155. #pragma alloc_text(PAGE, PortpReadDriverParameterEntry)
  156. #pragma alloc_text(PAGE, PortFreeDriverParameters)
  157. #pragma alloc_text(PAGE, PortGetDriverParameters)
  158. #pragma alloc_text(PAGE, PortpReadLinkTimeoutValue)
  159. #pragma alloc_text(PAGE, PortpReadMaximumLogicalUnitEntry)
  160. #pragma alloc_text(PAGE, PortpReadInitiatorTargetIdEntry)
  161. #pragma alloc_text(PAGE, PortpReadDebugEntry)
  162. #pragma alloc_text(PAGE, PortpReadBreakPointEntry)
  163. #pragma alloc_text(PAGE, PortpReadDisableSynchronousTransfersEntry)
  164. #pragma alloc_text(PAGE, PortpReadDisableDisconnectsEntry)
  165. #pragma alloc_text(PAGE, PortpReadDisableTaggedQueuingEntry)
  166. #pragma alloc_text(PAGE, PortpReadDisableMultipleRequestsEntry)
  167. #pragma alloc_text(PAGE, PortpReadMinimumUCXAddressEntry)
  168. #pragma alloc_text(PAGE, PortpReadMaximumUCXAddressEntry)
  169. #pragma alloc_text(PAGE, PortpReadMaximumSGListEntry)
  170. #pragma alloc_text(PAGE, PortpReadNumberOfRequestsEntry)
  171. #pragma alloc_text(PAGE, PortpReadResourceListEntry)
  172. #pragma alloc_text(PAGE, PortpReadUncachedExtAlignmentEntry)
  173. #pragma alloc_text(PAGE, PortpReadInquiryTimeoutEntry)
  174. #pragma alloc_text(PAGE, PortpReadResetHoldTimeEntry)
  175. #pragma alloc_text(PAGE, PortpReadCreateInitiatorLUEntry)
  176. #pragma alloc_text(PAGE, PortReadRegistrySettings)
  177. #pragma alloc_text(PAGE, PortGetRegistrySettings)
  178. #pragma alloc_text(PAGE, PortCreateKeyEx)
  179. #pragma alloc_text(PAGE, PortSetValueKey)
  180. #pragma alloc_text(PAGE, PortGetDiskTimeoutValue)
  181. #endif
  182. HANDLE
  183. PortpOpenParametersKey(
  184. IN PUNICODE_STRING RegistryPath
  185. )
  186. /*++
  187. Routine Description:
  188. This routine will open the services keys for the miniport and put handles
  189. to them into the configuration context structure.
  190. Arguments:
  191. RegistryPath - a pointer to the service key name for this miniport
  192. Return Value:
  193. status
  194. --*/
  195. {
  196. OBJECT_ATTRIBUTES objectAttributes;
  197. UNICODE_STRING unicodeString;
  198. HANDLE serviceKey;
  199. NTSTATUS status;
  200. HANDLE parametersKey;
  201. PAGED_CODE();
  202. //
  203. // Open the service node.
  204. //
  205. InitializeObjectAttributes(&objectAttributes,
  206. RegistryPath,
  207. OBJ_CASE_INSENSITIVE,
  208. NULL,
  209. (PSECURITY_DESCRIPTOR) NULL);
  210. status = ZwOpenKey(&serviceKey, KEY_READ, &objectAttributes);
  211. //
  212. // Try to open the parameters key. If it exists then replace the service
  213. // key with the new key. This allows the device nodes to be placed
  214. // under DriverName\Parameters\Device or DriverName\Device.
  215. //
  216. if (NT_SUCCESS(status)) {
  217. ASSERT(serviceKey != NULL);
  218. //
  219. // Check for a device node. The device node applies to every device.
  220. //
  221. RtlInitUnicodeString(&unicodeString, L"Parameters");
  222. InitializeObjectAttributes(&objectAttributes,
  223. &unicodeString,
  224. OBJ_CASE_INSENSITIVE,
  225. serviceKey,
  226. (PSECURITY_DESCRIPTOR) NULL);
  227. //
  228. // Attempt to open the parameters key.
  229. //
  230. status = ZwOpenKey(&parametersKey,
  231. KEY_READ,
  232. &objectAttributes);
  233. if (NT_SUCCESS(status)) {
  234. //
  235. // There is a Parameters key. Use that instead of the service
  236. // node key. Close the service node and set the new value.
  237. //
  238. ZwClose(serviceKey);
  239. serviceKey = parametersKey;
  240. }
  241. }
  242. return serviceKey;
  243. }
  244. HANDLE
  245. PortOpenDeviceKey(
  246. IN PUNICODE_STRING RegistryPath,
  247. IN ULONG DeviceNumber
  248. )
  249. /*++
  250. Routine Description:
  251. This routine will open the services keys for the miniport and put handles
  252. to them into the configuration context structure.
  253. Arguments:
  254. RegistryPath - a pointer to the service key name for this miniport
  255. DeviceNumber - which device too search for under the service key. -1
  256. indicates that the default device key should be opened.
  257. Return Value:
  258. status
  259. --*/
  260. {
  261. OBJECT_ATTRIBUTES objectAttributes;
  262. WCHAR buffer[64];
  263. UNICODE_STRING unicodeString;
  264. HANDLE serviceKey;
  265. HANDLE deviceKey;
  266. NTSTATUS status;
  267. PAGED_CODE();
  268. deviceKey = NULL;
  269. //
  270. // Open the service's parameters key.
  271. //
  272. serviceKey = PortpOpenParametersKey(RegistryPath);
  273. if (serviceKey != NULL) {
  274. //
  275. // Check for a Device Node. The device node applies to every device.
  276. //
  277. if(DeviceNumber == (ULONG) -1) {
  278. swprintf(buffer, L"Device");
  279. } else {
  280. swprintf(buffer, L"Device%d", DeviceNumber);
  281. }
  282. //
  283. // Initialize an object attributes structure in preparation for opening
  284. // the DeviceN key.
  285. //
  286. RtlInitUnicodeString(&unicodeString, buffer);
  287. InitializeObjectAttributes(&objectAttributes,
  288. &unicodeString,
  289. OBJ_CASE_INSENSITIVE,
  290. serviceKey,
  291. (PSECURITY_DESCRIPTOR) NULL);
  292. //
  293. // It doesn't matter if this call fails or not. If it fails, then there
  294. // is no default device node. If it works then the handle will be set.
  295. //
  296. ZwOpenKey(&deviceKey, KEY_READ, &objectAttributes);
  297. //
  298. // Close the service's parameters key.
  299. //
  300. ZwClose(serviceKey);
  301. }
  302. return deviceKey;
  303. }
  304. BOOLEAN
  305. PortpReadDriverParameterEntry(
  306. IN HANDLE Key,
  307. OUT PVOID * DriverParameters
  308. )
  309. {
  310. NTSTATUS status;
  311. UCHAR buffer[PORT_REG_BUFFER_SIZE];
  312. ULONG length;
  313. UNICODE_STRING valueName;
  314. PKEY_VALUE_FULL_INFORMATION keyValueInformation;
  315. UNICODE_STRING unicodeString;
  316. ANSI_STRING ansiString;
  317. ULONG result;
  318. PAGED_CODE();
  319. keyValueInformation = (PKEY_VALUE_FULL_INFORMATION) buffer;
  320. //
  321. // Try to find a DriverParameter value under the current key.
  322. //
  323. RtlInitUnicodeString(&valueName, L"DriverParameter");
  324. status = ZwQueryValueKey(Key,
  325. &valueName,
  326. KeyValueFullInformation,
  327. buffer,
  328. PORT_REG_BUFFER_SIZE,
  329. &length);
  330. if (!NT_SUCCESS(status)) {
  331. return FALSE;
  332. }
  333. //
  334. // Check that the length is reasonable.
  335. //
  336. if ((keyValueInformation->Type == REG_DWORD) &&
  337. (keyValueInformation->DataLength != sizeof(ULONG))) {
  338. return FALSE;
  339. }
  340. //
  341. // Verify that the name is what we expect.
  342. //
  343. result = _wcsnicmp(keyValueInformation->Name,
  344. L"DriverParameter",
  345. keyValueInformation->NameLength / 2);
  346. if (result != 0) {
  347. return FALSE;
  348. }
  349. //
  350. // If the data length is invalid, abort.
  351. //
  352. if (keyValueInformation->DataLength == 0) {
  353. return FALSE;
  354. }
  355. //
  356. // If we already have a non-NULL driver parameter entry, delete it
  357. // and replace it with the one we've found.
  358. //
  359. if (*DriverParameters != NULL) {
  360. ExFreePool(*DriverParameters);
  361. }
  362. //
  363. // Allocate non-paged pool to hold the data.
  364. //
  365. *DriverParameters =
  366. ExAllocatePoolWithTag(
  367. NonPagedPool,
  368. keyValueInformation->DataLength,
  369. PORT_TAG_MINIPORT_PARAM);
  370. //
  371. // If we failed to allocate the necessary pool, abort.
  372. //
  373. if (*DriverParameters == NULL) {
  374. return FALSE;
  375. }
  376. if (keyValueInformation->Type != REG_SZ) {
  377. //
  378. // The data is not a unicode string, so just copy the bytes into the
  379. // buffer we allocated.
  380. //
  381. RtlCopyMemory(*DriverParameters,
  382. (PCCHAR) keyValueInformation +
  383. keyValueInformation->DataOffset,
  384. keyValueInformation->DataLength);
  385. } else {
  386. //
  387. // This is a unicode string. Convert it to a ANSI string.
  388. //
  389. unicodeString.Buffer =
  390. (PWSTR) ((PCCHAR) keyValueInformation +
  391. keyValueInformation->DataOffset);
  392. unicodeString.Length =
  393. (USHORT) keyValueInformation->DataLength;
  394. unicodeString.MaximumLength =
  395. (USHORT) keyValueInformation->DataLength;
  396. ansiString.Buffer = (PCHAR) *DriverParameters;
  397. ansiString.Length = 0;
  398. ansiString.MaximumLength =
  399. (USHORT) keyValueInformation->DataLength;
  400. status = RtlUnicodeStringToAnsiString(&ansiString,
  401. &unicodeString,
  402. FALSE);
  403. if (!NT_SUCCESS(status)) {
  404. //
  405. // We could not convert the unicode string to ansi. Free the
  406. // buffer we allocated and abort.
  407. //
  408. ExFreePool(*DriverParameters);
  409. *DriverParameters = NULL;
  410. }
  411. }
  412. return TRUE;
  413. }
  414. BOOLEAN
  415. PortpReadLinkTimeoutValue(
  416. IN HANDLE Key,
  417. OUT PULONG LinkTimeout
  418. )
  419. {
  420. NTSTATUS status;
  421. UCHAR buffer[PORT_REG_BUFFER_SIZE];
  422. ULONG length;
  423. UNICODE_STRING valueName;
  424. PKEY_VALUE_FULL_INFORMATION keyValueInformation;
  425. UNICODE_STRING unicodeString;
  426. ULONG result;
  427. PAGED_CODE();
  428. keyValueInformation = (PKEY_VALUE_FULL_INFORMATION) buffer;
  429. //
  430. // Try to find a DriverParameter value under the current key.
  431. //
  432. RtlInitUnicodeString(&valueName, L"LinkTimeout");
  433. status = ZwQueryValueKey(Key,
  434. &valueName,
  435. KeyValueFullInformation,
  436. buffer,
  437. PORT_REG_BUFFER_SIZE,
  438. &length);
  439. if (!NT_SUCCESS(status)) {
  440. return FALSE;
  441. }
  442. //
  443. // Check that the length is reasonable.
  444. //
  445. if ((keyValueInformation->Type == REG_DWORD) &&
  446. (keyValueInformation->DataLength != sizeof(ULONG))) {
  447. return FALSE;
  448. }
  449. //
  450. // Verify that the name is what we expect.
  451. //
  452. result = _wcsnicmp(keyValueInformation->Name,
  453. L"LinkTimeout",
  454. keyValueInformation->NameLength / 2);
  455. if (result != 0) {
  456. return FALSE;
  457. }
  458. //
  459. // If the data length is invalid, abort.
  460. //
  461. if (keyValueInformation->DataLength == 0) {
  462. return FALSE;
  463. }
  464. //
  465. // Data type must be REG_DWORD.
  466. //
  467. if (keyValueInformation->Type != REG_DWORD) {
  468. return FALSE;
  469. }
  470. //
  471. // Extract the value.
  472. //
  473. *LinkTimeout = *((PULONG)(buffer + keyValueInformation->DataOffset));
  474. //
  475. // Check that the value is sane.
  476. //
  477. if (*LinkTimeout > 600) {
  478. *LinkTimeout = 600;
  479. }
  480. return TRUE;
  481. }
  482. VOID
  483. PortFreeDriverParameters(
  484. PVOID DriverParameters
  485. )
  486. {
  487. PAGED_CODE();
  488. ExFreePool(DriverParameters);
  489. }
  490. VOID
  491. PortGetDriverParameters(
  492. IN PUNICODE_STRING RegistryPath,
  493. IN ULONG DeviceNumber,
  494. OUT PVOID * DriverParameters
  495. )
  496. {
  497. HANDLE key;
  498. PAGED_CODE();
  499. key = PortOpenDeviceKey(RegistryPath, -1);
  500. if (key != NULL) {
  501. PortpReadDriverParameterEntry(key, DriverParameters);
  502. ZwClose(key);
  503. }
  504. key = PortOpenDeviceKey(RegistryPath, DeviceNumber);
  505. if (key != NULL) {
  506. PortpReadDriverParameterEntry(key, DriverParameters);
  507. ZwClose(key);
  508. }
  509. }
  510. VOID
  511. PortGetLinkTimeoutValue(
  512. IN PUNICODE_STRING RegistryPath,
  513. IN ULONG DeviceNumber,
  514. OUT PULONG LinkTimeoutValue
  515. )
  516. {
  517. HANDLE key;
  518. PAGED_CODE();
  519. key = PortOpenDeviceKey(RegistryPath, -1);
  520. if (key != NULL) {
  521. PortpReadLinkTimeoutValue(key, LinkTimeoutValue);
  522. ZwClose(key);
  523. }
  524. key = PortOpenDeviceKey(RegistryPath, DeviceNumber);
  525. if (key != NULL) {
  526. PortpReadLinkTimeoutValue(key, LinkTimeoutValue);
  527. ZwClose(key);
  528. }
  529. }
  530. BOOLEAN
  531. PortpReadMaximumLogicalUnitEntry(
  532. IN HANDLE Key,
  533. IN PUCHAR Buffer,
  534. OUT PPORT_ADAPTER_REGISTRY_VALUES Context
  535. )
  536. {
  537. NTSTATUS status;
  538. ULONG length;
  539. UNICODE_STRING valueName;
  540. PKEY_VALUE_FULL_INFORMATION keyValueInformation;
  541. PAGED_CODE();
  542. keyValueInformation = (PKEY_VALUE_FULL_INFORMATION) Buffer;
  543. RtlInitUnicodeString(&valueName, L"MaximumLogicalUnit");
  544. status = ZwQueryValueKey(Key,
  545. &valueName,
  546. KeyValueFullInformation,
  547. Buffer,
  548. PORT_REG_BUFFER_SIZE,
  549. &length);
  550. if (!NT_SUCCESS(status)) {
  551. return FALSE;
  552. }
  553. if (keyValueInformation->Type != REG_DWORD) {
  554. return FALSE;
  555. }
  556. if (keyValueInformation->DataLength != sizeof(ULONG)) {
  557. return FALSE;
  558. }
  559. Context->MaxLuCount = *((PUCHAR)
  560. (Buffer + keyValueInformation->DataOffset));
  561. //
  562. // If the value is out of bounds, then reset it.
  563. //
  564. if (Context->MaxLuCount > PORT_MAXIMUM_LOGICAL_UNITS) {
  565. Context->MaxLuCount = PORT_MAXIMUM_LOGICAL_UNITS;
  566. }
  567. return TRUE;
  568. }
  569. BOOLEAN
  570. PortpReadInitiatorTargetIdEntry(
  571. IN HANDLE Key,
  572. IN PUCHAR Buffer,
  573. OUT PPORT_ADAPTER_REGISTRY_VALUES Context
  574. )
  575. {
  576. NTSTATUS status;
  577. ULONG length;
  578. UNICODE_STRING valueName;
  579. PKEY_VALUE_FULL_INFORMATION keyValueInformation;
  580. PAGED_CODE();
  581. keyValueInformation = (PKEY_VALUE_FULL_INFORMATION) Buffer;
  582. RtlInitUnicodeString(&valueName, L"InitiatorTargetId");
  583. status = ZwQueryValueKey(Key,
  584. &valueName,
  585. KeyValueFullInformation,
  586. Buffer,
  587. PORT_REG_BUFFER_SIZE,
  588. &length);
  589. if (!NT_SUCCESS(status)) {
  590. return FALSE;
  591. }
  592. if (keyValueInformation->Type != REG_DWORD) {
  593. return FALSE;
  594. }
  595. if (keyValueInformation->DataLength != sizeof(ULONG)) {
  596. return FALSE;
  597. }
  598. Context->PortConfig.InitiatorBusId[0] = *((PUCHAR)(Buffer + keyValueInformation->DataOffset));
  599. //
  600. // IF the value is out of bounds, then reset it.
  601. //
  602. if (Context->PortConfig.InitiatorBusId[0] >
  603. Context->PortConfig.MaximumNumberOfTargets - 1) {
  604. Context->PortConfig.InitiatorBusId[0] = (UCHAR)PORT_UNINITIALIZED_VALUE;
  605. }
  606. return TRUE;
  607. }
  608. BOOLEAN
  609. PortpReadDebugEntry(
  610. IN HANDLE Key,
  611. IN PUCHAR Buffer,
  612. OUT PPORT_ADAPTER_REGISTRY_VALUES Context
  613. )
  614. {
  615. NTSTATUS status;
  616. ULONG length;
  617. UNICODE_STRING valueName;
  618. PKEY_VALUE_FULL_INFORMATION keyValueInformation;
  619. PAGED_CODE();
  620. keyValueInformation = (PKEY_VALUE_FULL_INFORMATION) Buffer;
  621. RtlInitUnicodeString(&valueName, L"ScsiDebug");
  622. status = ZwQueryValueKey(Key,
  623. &valueName,
  624. KeyValueFullInformation,
  625. Buffer,
  626. PORT_REG_BUFFER_SIZE,
  627. &length);
  628. if (!NT_SUCCESS(status)) {
  629. return FALSE;
  630. }
  631. if (keyValueInformation->Type != REG_DWORD) {
  632. return FALSE;
  633. }
  634. if (keyValueInformation->DataLength != sizeof(ULONG)) {
  635. return FALSE;
  636. }
  637. Context->EnableDebugging = *((PULONG)(Buffer + keyValueInformation->DataOffset));
  638. return TRUE;
  639. }
  640. BOOLEAN
  641. PortpReadBreakPointEntry(
  642. IN HANDLE Key,
  643. IN PUCHAR Buffer,
  644. OUT PPORT_ADAPTER_REGISTRY_VALUES Context
  645. )
  646. {
  647. NTSTATUS status;
  648. ULONG length;
  649. ULONG value;
  650. UNICODE_STRING valueName;
  651. PKEY_VALUE_FULL_INFORMATION keyValueInformation;
  652. PAGED_CODE();
  653. keyValueInformation = (PKEY_VALUE_FULL_INFORMATION) Buffer;
  654. RtlInitUnicodeString(&valueName, L"BreakPointOnEntry");
  655. status = ZwQueryValueKey(Key,
  656. &valueName,
  657. KeyValueFullInformation,
  658. Buffer,
  659. PORT_REG_BUFFER_SIZE,
  660. &length);
  661. if (!NT_SUCCESS(status)) {
  662. return FALSE;
  663. }
  664. if (keyValueInformation->Type == REG_DWORD &&
  665. keyValueInformation->DataLength != sizeof(ULONG)) {
  666. return FALSE;
  667. }
  668. value = *((PULONG)(Buffer + keyValueInformation->DataOffset));
  669. if (value > 0) {
  670. DbgBreakPoint();
  671. }
  672. return TRUE;
  673. }
  674. BOOLEAN
  675. PortpReadDisableSynchronousTransfersEntry(
  676. IN HANDLE Key,
  677. IN PUCHAR Buffer,
  678. OUT PPORT_ADAPTER_REGISTRY_VALUES Context
  679. )
  680. {
  681. NTSTATUS status;
  682. ULONG length;
  683. ULONG value;
  684. UNICODE_STRING valueName;
  685. PKEY_VALUE_FULL_INFORMATION keyValueInformation;
  686. PAGED_CODE();
  687. keyValueInformation = (PKEY_VALUE_FULL_INFORMATION) Buffer;
  688. RtlInitUnicodeString(&valueName, L"DisableSynchronousTransfers");
  689. status = ZwQueryValueKey(Key,
  690. &valueName,
  691. KeyValueFullInformation,
  692. Buffer,
  693. PORT_REG_BUFFER_SIZE,
  694. &length);
  695. if (!NT_SUCCESS(status)) {
  696. return FALSE;
  697. }
  698. if (keyValueInformation->Type == REG_DWORD &&
  699. keyValueInformation->DataLength != sizeof(ULONG)) {
  700. return FALSE;
  701. }
  702. value = *((PULONG)(Buffer + keyValueInformation->DataOffset));
  703. if (value > 0) {
  704. Context->SrbFlags |= SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
  705. }
  706. return TRUE;
  707. }
  708. BOOLEAN
  709. PortpReadDisableDisconnectsEntry(
  710. IN HANDLE Key,
  711. IN PUCHAR Buffer,
  712. OUT PPORT_ADAPTER_REGISTRY_VALUES Context
  713. )
  714. {
  715. NTSTATUS status;
  716. ULONG length;
  717. ULONG value;
  718. UNICODE_STRING valueName;
  719. PKEY_VALUE_FULL_INFORMATION keyValueInformation;
  720. PAGED_CODE();
  721. keyValueInformation = (PKEY_VALUE_FULL_INFORMATION) Buffer;
  722. RtlInitUnicodeString(&valueName, L"DisableDisconnects");
  723. status = ZwQueryValueKey(Key,
  724. &valueName,
  725. KeyValueFullInformation,
  726. Buffer,
  727. PORT_REG_BUFFER_SIZE,
  728. &length);
  729. if (!NT_SUCCESS(status)) {
  730. return FALSE;
  731. }
  732. if (keyValueInformation->Type == REG_DWORD &&
  733. keyValueInformation->DataLength != sizeof(ULONG)) {
  734. return FALSE;
  735. }
  736. value = *((PULONG)(Buffer + keyValueInformation->DataOffset));
  737. if (value > 0) {
  738. Context->SrbFlags |= SRB_FLAGS_DISABLE_DISCONNECT;
  739. }
  740. return TRUE;
  741. }
  742. BOOLEAN
  743. PortpReadDisableTaggedQueuingEntry(
  744. IN HANDLE Key,
  745. IN PUCHAR Buffer,
  746. OUT PPORT_ADAPTER_REGISTRY_VALUES Context
  747. )
  748. {
  749. NTSTATUS status;
  750. ULONG length;
  751. ULONG value;
  752. UNICODE_STRING valueName;
  753. PKEY_VALUE_FULL_INFORMATION keyValueInformation;
  754. PAGED_CODE();
  755. keyValueInformation = (PKEY_VALUE_FULL_INFORMATION) Buffer;
  756. RtlInitUnicodeString(&valueName, L"DisableTaggedQueuing");
  757. status = ZwQueryValueKey(Key,
  758. &valueName,
  759. KeyValueFullInformation,
  760. Buffer,
  761. PORT_REG_BUFFER_SIZE,
  762. &length);
  763. if (!NT_SUCCESS(status)) {
  764. return FALSE;
  765. }
  766. if (keyValueInformation->Type == REG_DWORD &&
  767. keyValueInformation->DataLength != sizeof(ULONG)) {
  768. return FALSE;
  769. }
  770. value = *((PULONG)(Buffer + keyValueInformation->DataOffset));
  771. if (value > 0) {
  772. Context->DisableTaggedQueueing = TRUE;
  773. }
  774. return TRUE;
  775. }
  776. BOOLEAN
  777. PortpReadDisableMultipleRequestsEntry(
  778. IN HANDLE Key,
  779. IN PUCHAR Buffer,
  780. OUT PPORT_ADAPTER_REGISTRY_VALUES Context
  781. )
  782. {
  783. NTSTATUS status;
  784. ULONG length;
  785. ULONG value;
  786. UNICODE_STRING valueName;
  787. PKEY_VALUE_FULL_INFORMATION keyValueInformation;
  788. PAGED_CODE();
  789. keyValueInformation = (PKEY_VALUE_FULL_INFORMATION) Buffer;
  790. RtlInitUnicodeString(&valueName, L"DisableMultipleRequests");
  791. status = ZwQueryValueKey(Key,
  792. &valueName,
  793. KeyValueFullInformation,
  794. Buffer,
  795. PORT_REG_BUFFER_SIZE,
  796. &length);
  797. if (!NT_SUCCESS(status)) {
  798. return FALSE;
  799. }
  800. if (keyValueInformation->Type == REG_DWORD &&
  801. keyValueInformation->DataLength != sizeof(ULONG)) {
  802. return FALSE;
  803. }
  804. value = *((PULONG)(Buffer + keyValueInformation->DataOffset));
  805. if (value > 0) {
  806. Context->DisableMultipleLu = TRUE;
  807. }
  808. return TRUE;
  809. }
  810. BOOLEAN
  811. PortpReadMinimumUCXAddressEntry(
  812. IN HANDLE Key,
  813. IN PUCHAR Buffer,
  814. OUT PPORT_ADAPTER_REGISTRY_VALUES Context
  815. )
  816. {
  817. NTSTATUS status;
  818. ULONG length;
  819. UNICODE_STRING valueName;
  820. PKEY_VALUE_FULL_INFORMATION keyValueInformation;
  821. PAGED_CODE();
  822. keyValueInformation = (PKEY_VALUE_FULL_INFORMATION) Buffer;
  823. RtlInitUnicodeString(&valueName, L"MinimumUCXAddress");
  824. status = ZwQueryValueKey(Key,
  825. &valueName,
  826. KeyValueFullInformation,
  827. Buffer,
  828. PORT_REG_BUFFER_SIZE,
  829. &length);
  830. if (!NT_SUCCESS(status)) {
  831. return FALSE;
  832. }
  833. /*
  834. if (keyValueInformation->Type == REG_DWORD &&
  835. keyValueInformation->DataLength != sizeof(ULONG)) {
  836. return FALSE;
  837. }
  838. */
  839. if (keyValueInformation->Type != REG_BINARY) {
  840. return FALSE;
  841. }
  842. if (keyValueInformation->DataLength != sizeof(ULONGLONG)) {
  843. return FALSE;
  844. }
  845. Context->MinimumCommonBufferBase.QuadPart =
  846. *((PULONGLONG)(Buffer + keyValueInformation->DataOffset));
  847. //
  848. // Ensure that the minimum and maximum parameters are valid.
  849. // If there's not at least one valid page between them then reset
  850. // minimum to zero.
  851. //
  852. if (Context->MinimumCommonBufferBase.QuadPart >=
  853. (Context->MaximumCommonBufferBase.QuadPart - PAGE_SIZE)) {
  854. Context->MinimumCommonBufferBase.QuadPart = 0;
  855. }
  856. return TRUE;
  857. }
  858. BOOLEAN
  859. PortpReadMaximumUCXAddressEntry(
  860. IN HANDLE Key,
  861. IN PUCHAR Buffer,
  862. OUT PPORT_ADAPTER_REGISTRY_VALUES Context
  863. )
  864. {
  865. NTSTATUS status;
  866. ULONG length;
  867. UNICODE_STRING valueName;
  868. PKEY_VALUE_FULL_INFORMATION keyValueInformation;
  869. PAGED_CODE();
  870. keyValueInformation = (PKEY_VALUE_FULL_INFORMATION) Buffer;
  871. RtlInitUnicodeString(&valueName, L"MaximumUCXAddress");
  872. status = ZwQueryValueKey(Key,
  873. &valueName,
  874. KeyValueFullInformation,
  875. Buffer,
  876. PORT_REG_BUFFER_SIZE,
  877. &length);
  878. if (!NT_SUCCESS(status)) {
  879. return FALSE;
  880. }
  881. /*
  882. if (keyValueInformation->Type == REG_DWORD &&
  883. keyValueInformation->DataLength != sizeof(ULONG)) {
  884. return FALSE;
  885. }
  886. */
  887. if (keyValueInformation->Type != REG_BINARY) {
  888. return FALSE;
  889. }
  890. if (keyValueInformation->DataLength != sizeof(ULONGLONG)) {
  891. return FALSE;
  892. }
  893. Context->MaximumCommonBufferBase.QuadPart =
  894. *((PULONGLONG)(Buffer + keyValueInformation->DataOffset));
  895. if (Context->MaximumCommonBufferBase.QuadPart == 0) {
  896. Context->MaximumCommonBufferBase.LowPart = 0xffffffff;
  897. Context->MaximumCommonBufferBase.HighPart = 0x0;
  898. }
  899. return TRUE;
  900. }
  901. BOOLEAN
  902. PortpReadMaximumSGListEntry(
  903. IN HANDLE Key,
  904. IN PUCHAR Buffer,
  905. OUT PPORT_ADAPTER_REGISTRY_VALUES Context
  906. )
  907. {
  908. NTSTATUS status;
  909. ULONG length;
  910. UNICODE_STRING valueName;
  911. ULONG maxBreaks, minBreaks;
  912. PKEY_VALUE_FULL_INFORMATION keyValueInformation;
  913. PAGED_CODE();
  914. keyValueInformation = (PKEY_VALUE_FULL_INFORMATION) Buffer;
  915. RtlInitUnicodeString(&valueName, L"MaximumSGList");
  916. status = ZwQueryValueKey(Key,
  917. &valueName,
  918. KeyValueFullInformation,
  919. Buffer,
  920. PORT_REG_BUFFER_SIZE,
  921. &length);
  922. if (!NT_SUCCESS(status)) {
  923. return FALSE;
  924. }
  925. if (keyValueInformation->Type != REG_DWORD) {
  926. return FALSE;
  927. }
  928. if (keyValueInformation->DataLength != sizeof(ULONG)) {
  929. return FALSE;
  930. }
  931. Context->PortConfig.NumberOfPhysicalBreaks =
  932. *((PUCHAR)(Buffer + keyValueInformation->DataOffset));
  933. //
  934. // If the value is out of bounds, then reset it.
  935. //
  936. if ((Context->PortConfig.MapBuffers) && (!Context->PortConfig.Master)) {
  937. maxBreaks = PORT_UNINITIALIZED_VALUE;
  938. minBreaks = PORT_MINIMUM_PHYSICAL_BREAKS;
  939. } else {
  940. maxBreaks = PORT_MAXIMUM_PHYSICAL_BREAKS;
  941. minBreaks = PORT_MINIMUM_PHYSICAL_BREAKS;
  942. }
  943. if (Context->PortConfig.NumberOfPhysicalBreaks > maxBreaks) {
  944. Context->PortConfig.NumberOfPhysicalBreaks = maxBreaks;
  945. } else if (Context->PortConfig.NumberOfPhysicalBreaks < minBreaks) {
  946. Context->PortConfig.NumberOfPhysicalBreaks = minBreaks;
  947. }
  948. return TRUE;
  949. }
  950. BOOLEAN
  951. PortpReadNumberOfRequestsEntry(
  952. IN HANDLE Key,
  953. IN PUCHAR Buffer,
  954. OUT PPORT_ADAPTER_REGISTRY_VALUES Context
  955. )
  956. {
  957. NTSTATUS status;
  958. ULONG length;
  959. UNICODE_STRING valueName;
  960. ULONG value;
  961. PKEY_VALUE_FULL_INFORMATION keyValueInformation;
  962. PAGED_CODE();
  963. keyValueInformation = (PKEY_VALUE_FULL_INFORMATION) Buffer;
  964. RtlInitUnicodeString(&valueName, L"NumberOfRequests");
  965. status = ZwQueryValueKey(Key,
  966. &valueName,
  967. KeyValueFullInformation,
  968. Buffer,
  969. PORT_REG_BUFFER_SIZE,
  970. &length);
  971. if (!NT_SUCCESS(status)) {
  972. return FALSE;
  973. }
  974. if (keyValueInformation->Type != REG_DWORD) {
  975. return FALSE;
  976. }
  977. if (keyValueInformation->DataLength != sizeof(ULONG)) {
  978. return FALSE;
  979. }
  980. value = *((PULONG)(Buffer + keyValueInformation->DataOffset));
  981. //
  982. // If the value is out of bounds, then reset it.
  983. //
  984. if (value < MINIMUM_EXTENSIONS) {
  985. Context->NumberOfRequests = MINIMUM_EXTENSIONS;
  986. } else if (value > MAXIMUM_EXTENSIONS) {
  987. Context->NumberOfRequests = MAXIMUM_EXTENSIONS;
  988. } else {
  989. Context->NumberOfRequests = value;
  990. }
  991. return TRUE;
  992. }
  993. BOOLEAN
  994. PortpReadResourceListEntry(
  995. IN HANDLE Key,
  996. IN PUCHAR Buffer,
  997. OUT PPORT_ADAPTER_REGISTRY_VALUES Context
  998. )
  999. {
  1000. NTSTATUS status;
  1001. ULONG length;
  1002. UNICODE_STRING valueName;
  1003. ULONG value;
  1004. ULONG count;
  1005. ULONG rangeCount;
  1006. PCM_SCSI_DEVICE_DATA scsiData;
  1007. PCM_FULL_RESOURCE_DESCRIPTOR resource;
  1008. PCM_PARTIAL_RESOURCE_DESCRIPTOR descriptor;
  1009. PKEY_VALUE_FULL_INFORMATION keyValueInformation;
  1010. PAGED_CODE();
  1011. rangeCount = 0;
  1012. keyValueInformation = (PKEY_VALUE_FULL_INFORMATION) Buffer;
  1013. RtlInitUnicodeString(&valueName, L"ResourceList");
  1014. status = ZwQueryValueKey(Key,
  1015. &valueName,
  1016. KeyValueFullInformation,
  1017. Buffer,
  1018. PORT_REG_BUFFER_SIZE,
  1019. &length);
  1020. if (!NT_SUCCESS(status)) {
  1021. RtlInitUnicodeString(&valueName, L"Configuration Data");
  1022. status = ZwQueryValueKey(Key,
  1023. &valueName,
  1024. KeyValueFullInformation,
  1025. Buffer,
  1026. PORT_REG_BUFFER_SIZE,
  1027. &length);
  1028. if (!NT_SUCCESS(status)) {
  1029. return FALSE;
  1030. }
  1031. }
  1032. if (keyValueInformation->Type != REG_FULL_RESOURCE_DESCRIPTOR ||
  1033. keyValueInformation->DataLength < sizeof(CM_FULL_RESOURCE_DESCRIPTOR)) {
  1034. return FALSE;
  1035. }
  1036. resource = (PCM_FULL_RESOURCE_DESCRIPTOR)
  1037. (Buffer + keyValueInformation->DataOffset);
  1038. //
  1039. // Set the bus number equal to the bus number for the
  1040. // resouce. Note the context value is also set to the
  1041. // new bus number.
  1042. //
  1043. Context->BusNumber = resource->BusNumber;
  1044. Context->PortConfig.SystemIoBusNumber = resource->BusNumber;
  1045. //
  1046. // Walk the resource list and update the configuration.
  1047. //
  1048. for (count = 0; count < resource->PartialResourceList.Count; count++) {
  1049. descriptor = &resource->PartialResourceList.PartialDescriptors[count];
  1050. //
  1051. // Verify size is ok.
  1052. //
  1053. if ((ULONG)((PCHAR) (descriptor + 1) - (PCHAR) resource) >
  1054. keyValueInformation->DataLength) {
  1055. //
  1056. //Resource data too small.
  1057. //
  1058. return FALSE;
  1059. }
  1060. //
  1061. // Switch on descriptor type;
  1062. //
  1063. switch (descriptor->Type) {
  1064. case CmResourceTypePort:
  1065. if (rangeCount >= Context->PortConfig.NumberOfAccessRanges) {
  1066. //
  1067. //Too many access ranges.
  1068. //
  1069. continue;
  1070. }
  1071. Context->AccessRanges[rangeCount].RangeStart =
  1072. descriptor->u.Port.Start;
  1073. Context->AccessRanges[rangeCount].RangeLength =
  1074. descriptor->u.Port.Length;
  1075. Context->AccessRanges[rangeCount].RangeInMemory = FALSE;
  1076. rangeCount++;
  1077. break;
  1078. case CmResourceTypeMemory:
  1079. if (rangeCount >= Context->PortConfig.NumberOfAccessRanges) {
  1080. //
  1081. //Too many access ranges.
  1082. //
  1083. continue;
  1084. }
  1085. Context->AccessRanges[rangeCount].RangeStart =
  1086. descriptor->u.Memory.Start;
  1087. Context->AccessRanges[rangeCount].RangeLength =
  1088. descriptor->u.Memory.Length;
  1089. Context->AccessRanges[rangeCount].RangeInMemory = TRUE;
  1090. rangeCount++;
  1091. break;
  1092. case CmResourceTypeInterrupt:
  1093. Context->PortConfig.BusInterruptVector =
  1094. descriptor->u.Interrupt.Vector;
  1095. Context->PortConfig.BusInterruptLevel =
  1096. descriptor->u.Interrupt.Level;
  1097. break;
  1098. case CmResourceTypeDma:
  1099. Context->PortConfig.DmaChannel = descriptor->u.Dma.Channel;
  1100. Context->PortConfig.DmaPort = descriptor->u.Dma.Port;
  1101. break;
  1102. case CmResourceTypeDeviceSpecific:
  1103. if (descriptor->u.DeviceSpecificData.DataSize < sizeof(CM_SCSI_DEVICE_DATA) ||
  1104. (PCHAR) (descriptor + 1) -
  1105. (PCHAR) resource + descriptor->u.DeviceSpecificData.DataSize >
  1106. keyValueInformation->DataLength) {
  1107. //
  1108. //Device specific resource data too small.
  1109. //
  1110. break;
  1111. }
  1112. scsiData = (PCM_SCSI_DEVICE_DATA) (descriptor+1);
  1113. Context->PortConfig.InitiatorBusId[0] = scsiData->HostIdentifier;
  1114. break;
  1115. }
  1116. }
  1117. return TRUE;
  1118. }
  1119. BOOLEAN
  1120. PortpReadUncachedExtAlignmentEntry(
  1121. IN HANDLE Key,
  1122. IN PUCHAR Buffer,
  1123. OUT PPORT_ADAPTER_REGISTRY_VALUES Context
  1124. )
  1125. {
  1126. NTSTATUS status;
  1127. ULONG length;
  1128. ULONG value;
  1129. UNICODE_STRING valueName;
  1130. PKEY_VALUE_FULL_INFORMATION keyValueInformation;
  1131. PAGED_CODE();
  1132. keyValueInformation = (PKEY_VALUE_FULL_INFORMATION) Buffer;
  1133. RtlInitUnicodeString(&valueName, L"UncachedExtAlignment");
  1134. status = ZwQueryValueKey(Key,
  1135. &valueName,
  1136. KeyValueFullInformation,
  1137. Buffer,
  1138. PORT_REG_BUFFER_SIZE,
  1139. &length);
  1140. if (!NT_SUCCESS(status)) {
  1141. return FALSE;
  1142. }
  1143. if (keyValueInformation->Type != REG_DWORD) {
  1144. return FALSE;
  1145. }
  1146. if (keyValueInformation->DataLength != sizeof(ULONG)) {
  1147. return FALSE;
  1148. }
  1149. value = *((PULONG)(Buffer + keyValueInformation->DataOffset));
  1150. //
  1151. // Specified alignment must be 3 to 16, which equates to 8-byte and
  1152. // 64k-byte alignment, respectively.
  1153. //
  1154. if (value > MAX_UNCACHED_EXT_ALIGNMENT) {
  1155. value = MAX_UNCACHED_EXT_ALIGNMENT;
  1156. } else if (value < MIN_UNCACHED_EXT_ALIGNMENT) {
  1157. value = MIN_UNCACHED_EXT_ALIGNMENT;
  1158. }
  1159. Context->UncachedExtAlignment = 1 << value;
  1160. return TRUE;
  1161. }
  1162. BOOLEAN
  1163. PortpReadInquiryTimeoutEntry(
  1164. IN HANDLE Key,
  1165. IN PUCHAR Buffer,
  1166. OUT PPORT_ADAPTER_REGISTRY_VALUES Context
  1167. )
  1168. {
  1169. NTSTATUS status;
  1170. ULONG length;
  1171. ULONG value;
  1172. UNICODE_STRING valueName;
  1173. PKEY_VALUE_FULL_INFORMATION keyValueInformation;
  1174. PAGED_CODE();
  1175. keyValueInformation = (PKEY_VALUE_FULL_INFORMATION) Buffer;
  1176. RtlInitUnicodeString(&valueName, L"InquiryTimeout");
  1177. status = ZwQueryValueKey(Key,
  1178. &valueName,
  1179. KeyValueFullInformation,
  1180. Buffer,
  1181. PORT_REG_BUFFER_SIZE,
  1182. &length);
  1183. if (!NT_SUCCESS(status)) {
  1184. return FALSE;
  1185. }
  1186. if (keyValueInformation->Type != REG_DWORD) {
  1187. return FALSE;
  1188. }
  1189. if (keyValueInformation->DataLength != sizeof(ULONG)) {
  1190. return FALSE;
  1191. }
  1192. value = *((PULONG)(Buffer + keyValueInformation->DataOffset));
  1193. Context->InquiryTimeout = (value <= MAX_TIMEOUT_VALUE) ? value : MAX_TIMEOUT_VALUE;
  1194. return TRUE;
  1195. }
  1196. BOOLEAN
  1197. PortpReadResetHoldTimeEntry(
  1198. IN HANDLE Key,
  1199. IN PUCHAR Buffer,
  1200. OUT PPORT_ADAPTER_REGISTRY_VALUES Context
  1201. )
  1202. {
  1203. NTSTATUS status;
  1204. ULONG length;
  1205. ULONG value;
  1206. UNICODE_STRING valueName;
  1207. PKEY_VALUE_FULL_INFORMATION keyValueInformation;
  1208. PAGED_CODE();
  1209. keyValueInformation = (PKEY_VALUE_FULL_INFORMATION) Buffer;
  1210. RtlInitUnicodeString(&valueName, L"ResetHoldTime");
  1211. status = ZwQueryValueKey(Key,
  1212. &valueName,
  1213. KeyValueFullInformation,
  1214. Buffer,
  1215. PORT_REG_BUFFER_SIZE,
  1216. &length);
  1217. if (!NT_SUCCESS(status)) {
  1218. return FALSE;
  1219. }
  1220. if (keyValueInformation->Type != REG_DWORD) {
  1221. return FALSE;
  1222. }
  1223. if (keyValueInformation->DataLength != sizeof(ULONG)) {
  1224. return FALSE;
  1225. }
  1226. value = *((PULONG)(Buffer + keyValueInformation->DataOffset));
  1227. Context->ResetHoldTime = (value <= MAX_RESET_HOLD_TIME) ? value : MAX_RESET_HOLD_TIME;
  1228. return TRUE;
  1229. }
  1230. BOOLEAN
  1231. PortpReadCreateInitiatorLUEntry(
  1232. IN HANDLE Key,
  1233. IN PUCHAR Buffer,
  1234. OUT PPORT_ADAPTER_REGISTRY_VALUES Context
  1235. )
  1236. {
  1237. NTSTATUS status;
  1238. ULONG length;
  1239. ULONG value;
  1240. UNICODE_STRING valueName;
  1241. PKEY_VALUE_FULL_INFORMATION keyValueInformation;
  1242. PAGED_CODE();
  1243. keyValueInformation = (PKEY_VALUE_FULL_INFORMATION) Buffer;
  1244. RtlInitUnicodeString(&valueName, L"CreateInitiatorLU");
  1245. status = ZwQueryValueKey(Key,
  1246. &valueName,
  1247. KeyValueFullInformation,
  1248. Buffer,
  1249. PORT_REG_BUFFER_SIZE,
  1250. &length);
  1251. if (!NT_SUCCESS(status)) {
  1252. return FALSE;
  1253. }
  1254. if (keyValueInformation->Type != REG_DWORD) {
  1255. return FALSE;
  1256. }
  1257. if (keyValueInformation->DataLength != sizeof(ULONG)) {
  1258. return FALSE;
  1259. }
  1260. value = *((PULONG)(Buffer + keyValueInformation->DataOffset));
  1261. Context->CreateInitiatorLU = (value == 0) ? FALSE : TRUE;
  1262. return TRUE;
  1263. }
  1264. VOID
  1265. PortReadRegistrySettings(
  1266. IN HANDLE Key,
  1267. IN PPORT_ADAPTER_REGISTRY_VALUES Context,
  1268. IN ULONG Fields
  1269. )
  1270. /*++
  1271. Routine Description:
  1272. This routine parses a device key node and updates the configuration
  1273. information.
  1274. Arguments:
  1275. Key - an open key to the device node.
  1276. Context - a pointer to the configuration context structure.
  1277. Fields - a bit-field indicating which registry parameters to fetch.
  1278. Return Value:
  1279. None
  1280. --*/
  1281. {
  1282. UCHAR buffer[PORT_REG_BUFFER_SIZE];
  1283. PAGED_CODE();
  1284. if (Fields & MAXIMUM_LOGICAL_UNIT) {
  1285. PortpReadMaximumLogicalUnitEntry(Key, buffer, Context);
  1286. }
  1287. if (Fields & INITIATOR_TARGET_ID) {
  1288. PortpReadInitiatorTargetIdEntry(Key, buffer, Context);
  1289. }
  1290. if (Fields & SCSI_DEBUG) {
  1291. PortpReadDebugEntry(Key, buffer, Context);
  1292. }
  1293. if (Fields & BREAK_POINT_ON_ENTRY) {
  1294. PortpReadBreakPointEntry(Key, buffer, Context);
  1295. }
  1296. if (Fields & DISABLE_SYNCHRONOUS_TRANSFERS) {
  1297. PortpReadDisableSynchronousTransfersEntry(Key, buffer, Context);
  1298. }
  1299. if (Fields & DISABLE_DISCONNECTS) {
  1300. PortpReadDisableDisconnectsEntry(Key, buffer, Context);
  1301. }
  1302. if (Fields & DISABLE_TAGGED_QUEUING) {
  1303. PortpReadDisableTaggedQueuingEntry(Key, buffer, Context);
  1304. }
  1305. if (Fields & DISABLE_MULTIPLE_REQUESTS) {
  1306. PortpReadDisableMultipleRequestsEntry(Key, buffer, Context);
  1307. }
  1308. if (Fields & MAXIMUM_UCX_ADDRESS) {
  1309. PortpReadMaximumUCXAddressEntry(Key, buffer, Context);
  1310. }
  1311. if (Fields & MINIMUM_UCX_ADDRESS) {
  1312. PortpReadMinimumUCXAddressEntry(Key, buffer, Context);
  1313. }
  1314. if (Fields & DRIVER_PARAMETERS) {
  1315. PortpReadDriverParameterEntry(Key, &(Context->Parameter));
  1316. }
  1317. if (Fields & MAXIMUM_SG_LIST) {
  1318. PortpReadMaximumSGListEntry(Key, buffer, Context);
  1319. }
  1320. if (Fields & NUMBER_OF_REQUESTS) {
  1321. PortpReadNumberOfRequestsEntry(Key, buffer, Context);
  1322. }
  1323. if (Fields & RESOURCE_LIST) {
  1324. PortpReadResourceListEntry(Key, buffer, Context);
  1325. }
  1326. if (Fields & CONFIGURATION_DATA) {
  1327. PortpReadResourceListEntry(Key, buffer, Context);
  1328. }
  1329. if (Fields & UNCACHED_EXT_ALIGNMENT) {
  1330. PortpReadUncachedExtAlignmentEntry(Key, buffer, Context);
  1331. }
  1332. if (Fields & INQUIRY_TIMEOUT) {
  1333. PortpReadInquiryTimeoutEntry(Key, buffer, Context);
  1334. }
  1335. if (Fields & RESET_HOLD_TIME) {
  1336. PortpReadResetHoldTimeEntry(Key, buffer, Context);
  1337. }
  1338. if (Fields & CREATE_INITIATOR_LU) {
  1339. PortpReadCreateInitiatorLUEntry(Key, buffer, Context);
  1340. }
  1341. }
  1342. VOID
  1343. PortGetRegistrySettings(
  1344. IN PUNICODE_STRING RegistryPath,
  1345. IN ULONG DeviceNumber,
  1346. IN PPORT_ADAPTER_REGISTRY_VALUES Context,
  1347. IN ULONG Fields
  1348. )
  1349. {
  1350. HANDLE key;
  1351. PUNICODE_STRING value;
  1352. PAGED_CODE();
  1353. //DbgPrint("\nRegistryPath: %ws\n", RegistryPath->Buffer);
  1354. key = PortOpenDeviceKey(RegistryPath, -1);
  1355. if (key != NULL) {
  1356. PortReadRegistrySettings(key, Context, Fields);
  1357. ZwClose(key);
  1358. }
  1359. key = PortOpenDeviceKey(RegistryPath, DeviceNumber);
  1360. if (key != NULL) {
  1361. PortReadRegistrySettings(key, Context, Fields);
  1362. ZwClose(key);
  1363. }
  1364. }
  1365. NTSTATUS
  1366. PortCreateKeyEx(
  1367. IN HANDLE Key,
  1368. IN ULONG CreateOptions,
  1369. OUT PHANDLE NewKeyBuffer, OPTIONAL
  1370. IN PCWSTR Format,
  1371. ...
  1372. )
  1373. /*++
  1374. Routine Description:
  1375. Create a key using a printf style string.
  1376. Arguments:
  1377. Key - Supplies the root key under which this key will be created. The
  1378. key is always created with a DesiredAccess of KEY_ALL_ACCESS.
  1379. CreateOptions - Supplies the CreateOptions parameter to ZwCreateKey.
  1380. NewKeyBuffer - Optional buffer to return the created key.
  1381. Format - Format specifier for the key name.
  1382. ... - Variable arguments necessary for the specific format.
  1383. Return Value:
  1384. NTSTATUS code - STATUS_OBJECT_NAME_EXISTS if the key already existed
  1385. before opening.
  1386. --*/
  1387. {
  1388. NTSTATUS Status;
  1389. HANDLE NewKey;
  1390. ULONG Disposition;
  1391. UNICODE_STRING String;
  1392. WCHAR Buffer[64];
  1393. va_list arglist;
  1394. OBJECT_ATTRIBUTES ObjectAttributes;
  1395. PAGED_CODE();
  1396. va_start (arglist, Format);
  1397. _vsnwprintf (Buffer, ARRAY_COUNT (Buffer) - 1, Format, arglist);
  1398. //
  1399. // If we overflow the buffer, there will not be a terminating NULL.
  1400. // Fix this problem.
  1401. //
  1402. Buffer [ARRAY_COUNT (Buffer) - 1] = UNICODE_NULL;
  1403. RtlInitUnicodeString (&String, Buffer);
  1404. InitializeObjectAttributes (&ObjectAttributes,
  1405. &String,
  1406. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
  1407. Key,
  1408. NULL);
  1409. Status = ZwCreateKey (&NewKey,
  1410. KEY_ALL_ACCESS,
  1411. &ObjectAttributes,
  1412. 0,
  1413. NULL,
  1414. CreateOptions,
  1415. &Disposition);
  1416. //
  1417. // If the key already existed, return STATUS_OBJECT_NAME_EXISTS.
  1418. //
  1419. if (NT_SUCCESS (Status) && Disposition == REG_OPENED_EXISTING_KEY) {
  1420. Status = STATUS_OBJECT_NAME_EXISTS;
  1421. }
  1422. //
  1423. // Pass back the new key value if desired, otherwise close it.
  1424. //
  1425. if (NT_SUCCESS (Status)) {
  1426. if (NewKeyBuffer) {
  1427. *NewKeyBuffer = NewKey;
  1428. } else {
  1429. ZwClose (NewKey);
  1430. }
  1431. }
  1432. va_end (arglist);
  1433. return Status;
  1434. }
  1435. NTSTATUS
  1436. PortSetValueKey(
  1437. IN HANDLE KeyHandle,
  1438. IN PCWSTR ValueName,
  1439. IN ULONG Type,
  1440. IN PVOID Data,
  1441. IN ULONG DataSize
  1442. )
  1443. /*++
  1444. Routine Description:
  1445. Simple wrapper around ZwSetValueKey that includes support for NULL-
  1446. terminated ValueName parameter and ANSI string type.
  1447. Arguments:
  1448. KeyHandle - Supplies the key to set the value for.
  1449. ValueName - Supplies a NULL terminated unicode string representing the
  1450. value. This may be NULL to pass in NULL to ZwSetValueKey.
  1451. Type - Specifies the type of data to be written for ValueName. See
  1452. ZwSetValueKey for more information.
  1453. In addition to the value types specified in the DDK for ZwSetValueKey,
  1454. Type may also be PORT_REG_ANSI_STRING if the data is an ANSI string.
  1455. If the type is ANSI string, the data will be converted to a unicode
  1456. string before being written to the registry. The ansi string does
  1457. not need to be NULL terminated. Instead, the size of the ansi string
  1458. must be specified in the DataSize field below.
  1459. Data - Supplies the data to be written for the key specified in ValueName.
  1460. DataSize - Supplies the size of the data to be written. If the data type
  1461. is PORT_REG_ANSI_STRING, DataSize need not include the terminating
  1462. NULL character for the ansi string (but it may). The converted
  1463. Unicode string will be NULL terminated whether or not the ANSI
  1464. string was NULL terminated.
  1465. Return Value:
  1466. NTSTATUS code.
  1467. --*/
  1468. {
  1469. NTSTATUS Status;
  1470. ANSI_STRING AnsiString;
  1471. UNICODE_STRING UncValueNameBuffer;
  1472. UNICODE_STRING UncDataString;
  1473. PUNICODE_STRING UncValueName;
  1474. PAGED_CODE();
  1475. //
  1476. // If ValueName == NULL, need to pass NULL down to ZwSetValueKey.
  1477. //
  1478. if (ValueName) {
  1479. RtlInitUnicodeString (&UncValueNameBuffer, ValueName);
  1480. UncValueName = &UncValueNameBuffer;
  1481. } else {
  1482. UncValueName = NULL;
  1483. }
  1484. //
  1485. // If this is our special, extended port type, then convert the ANSI
  1486. // string to unicode.
  1487. //
  1488. if (Type == PORT_REG_ANSI_STRING) {
  1489. //
  1490. // We use the DataSize as the length.
  1491. //
  1492. ASSERT (DataSize <= MAXUSHORT);
  1493. AnsiString.Length = (USHORT)DataSize;
  1494. AnsiString.MaximumLength = (USHORT)DataSize;
  1495. AnsiString.Buffer = Data;
  1496. //
  1497. // NB: RtlAnsiStringToUnicodeString always returns a NULL terminated
  1498. // Unicode string, whether or not the ANSI version of the string
  1499. // is NULL terminated.
  1500. //
  1501. Status = RtlAnsiStringToUnicodeString (&UncDataString,
  1502. &AnsiString,
  1503. TRUE);
  1504. if (!NT_SUCCESS (Status)) {
  1505. return Status;
  1506. }
  1507. Data = UncDataString.Buffer;
  1508. DataSize = UncDataString.Length + sizeof (WCHAR);
  1509. Type = REG_SZ;
  1510. }
  1511. Status = ZwSetValueKey (KeyHandle,
  1512. UncValueName,
  1513. 0,
  1514. Type,
  1515. Data,
  1516. DataSize);
  1517. if (Type == PORT_REG_ANSI_STRING) {
  1518. RtlFreeUnicodeString (&UncDataString);
  1519. }
  1520. return Status;
  1521. }
  1522. VOID
  1523. PortGetDiskTimeoutValue(
  1524. OUT PULONG DiskTimeout
  1525. )
  1526. /*++
  1527. Routine Description:
  1528. This routine will open the disk services key, and read the TimeOutValue
  1529. field, which should be used as the timeoutvalue for all srb's(like
  1530. inquiry, report-luns) created by the Port driver.
  1531. Arguments:
  1532. DiskTimeout - Will be unchanged if we could not read the registry, or the
  1533. timeout value(in the registry) was 0. Else the registry value is returned.
  1534. --*/
  1535. {
  1536. NTSTATUS status;
  1537. UCHAR buffer[PORT_REG_BUFFER_SIZE];
  1538. ULONG length;
  1539. UNICODE_STRING valueName;
  1540. PKEY_VALUE_FULL_INFORMATION keyValueInformation;
  1541. OBJECT_ATTRIBUTES objectAttributes;
  1542. UNICODE_STRING unicodeString;
  1543. ULONG result;
  1544. IN HANDLE Key;
  1545. ULONG TimeoutValue;
  1546. PAGED_CODE();
  1547. RtlInitUnicodeString(&unicodeString, DISK_SERVICE_KEY);
  1548. InitializeObjectAttributes(&objectAttributes,
  1549. &unicodeString,
  1550. OBJ_CASE_INSENSITIVE,
  1551. NULL,
  1552. NULL);
  1553. status = ZwOpenKey(&Key,
  1554. KEY_READ,
  1555. &objectAttributes);
  1556. if(!NT_SUCCESS(status)) {
  1557. return;
  1558. }
  1559. keyValueInformation = (PKEY_VALUE_FULL_INFORMATION) buffer;
  1560. //
  1561. // Try to find the Timeout value under disk services key.
  1562. //
  1563. RtlInitUnicodeString(&valueName, L"TimeoutValue");
  1564. status = ZwQueryValueKey(Key,
  1565. &valueName,
  1566. KeyValueFullInformation,
  1567. buffer,
  1568. PORT_REG_BUFFER_SIZE,
  1569. &length);
  1570. if (!NT_SUCCESS(status)) {
  1571. return;
  1572. }
  1573. //
  1574. // Check that the length is reasonable.
  1575. //
  1576. if ((keyValueInformation->Type == REG_DWORD) &&
  1577. (keyValueInformation->DataLength != sizeof(ULONG))) {
  1578. return;
  1579. }
  1580. //
  1581. // Verify that the name is what we expect.
  1582. //
  1583. result = _wcsnicmp(keyValueInformation->Name,
  1584. L"TimeoutValue",
  1585. keyValueInformation->NameLength / 2);
  1586. if (result != 0) {
  1587. return;
  1588. }
  1589. //
  1590. // If the data length is invalid, abort.
  1591. //
  1592. if (keyValueInformation->DataLength == 0) {
  1593. return;
  1594. }
  1595. //
  1596. // Data type must be REG_DWORD.
  1597. //
  1598. if (keyValueInformation->Type != REG_DWORD) {
  1599. return;
  1600. }
  1601. //
  1602. // Extract the value.
  1603. //
  1604. TimeoutValue = *((PULONG)(buffer + keyValueInformation->DataOffset));
  1605. if(!TimeoutValue){
  1606. return;
  1607. }
  1608. *DiskTimeout = TimeoutValue;
  1609. return;
  1610. }