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.

811 lines
20 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation. All rights reserved.
  3. Module Name:
  4. PpRegState.c
  5. Abstract:
  6. This module contains functions for reading and writing PnP registry state
  7. information.
  8. Author:
  9. Adrian J. Oney - April 21, 2002
  10. Revision History:
  11. --*/
  12. #include "WlDef.h"
  13. #include "PiRegstate.h"
  14. #pragma hdrstop
  15. #ifdef ALLOC_PRAGMA
  16. #pragma alloc_text(PAGE, PpRegStateReadCreateClassCreationSettings)
  17. #pragma alloc_text(PAGE, PiRegStateReadStackCreationSettingsFromKey)
  18. #pragma alloc_text(PAGE, PpRegStateInitEmptyCreationSettings)
  19. #pragma alloc_text(PAGE, PiRegStateOpenClassKey)
  20. #pragma alloc_text(PAGE, PpRegStateUpdateStackCreationSettings)
  21. #pragma alloc_text(PAGE, PpRegStateFreeStackCreationSettings)
  22. #pragma alloc_text(PAGE, PpRegStateLoadSecurityDescriptor)
  23. #endif
  24. //
  25. // Since RtlAddAccessAllowedAceEx isn't exported by the kernel, we must
  26. // hardcode this security descriptor. It is used to make PnP keys that are
  27. // purposely hard to tamper with (SYS_ALL, object/container inherit).
  28. //
  29. ULONG PiRegStateSysAllInherittedSecurityDescriptor[0xC] = {
  30. 0x94040001, 0x00000000, 0x00000000, 0x00000000,
  31. 0x00000014, 0x001c0002, 0x00000001, 0x00140300,
  32. 0x10000000, 0x00000101, 0x05000000, 0x00000012
  33. };
  34. PIDESCRIPTOR_STATE PiRegStateDiscriptor = NOT_VALIDATED;
  35. NTSTATUS
  36. PpRegStateReadCreateClassCreationSettings(
  37. IN LPCGUID DeviceClassGuid,
  38. IN PDRIVER_OBJECT DriverObject,
  39. OUT PSTACK_CREATION_SETTINGS StackCreationSettings
  40. )
  41. /*++
  42. Routine Description:
  43. This routine either retrieves or creates a set of stack creation settings
  44. for the given class GUID.
  45. Arguments:
  46. DeviceClassGuid - Guid representing the class.
  47. DriverObject - Driver object of the device being created. This is used to
  48. build a class name in the event the class doesn't yet exist in the
  49. registry.
  50. StackCreationSettings - Receives settings retrieved from the registry (or
  51. new settings if the registry contains no information.)
  52. Return Value:
  53. NTSTATUS (On error, StackCreationSettings is updated to reflect
  54. "no settings").
  55. --*/
  56. {
  57. PUNICODE_STRING serviceName;
  58. HANDLE classPropertyKey;
  59. HANDLE classKey;
  60. ULONG disposition;
  61. NTSTATUS status;
  62. PAGED_CODE();
  63. //
  64. // Preinit for failure
  65. //
  66. classKey = NULL;
  67. classPropertyKey = NULL;
  68. PpRegStateInitEmptyCreationSettings(StackCreationSettings);
  69. //
  70. // Try to find the appropriate security descriptor for the device. First
  71. // look for an override in the registry using the class GUID. We will
  72. // create a section in the registry if one doesn't exist as well. This is
  73. // a clue to the system administrator that there is something to lock down
  74. // in the system.
  75. //
  76. status = PiRegStateOpenClassKey(
  77. DeviceClassGuid,
  78. KEY_ALL_ACCESS,
  79. TRUE, // CreateIfNotPresent
  80. &disposition,
  81. &classKey
  82. );
  83. if (!NT_SUCCESS(status)) {
  84. return status;
  85. }
  86. //
  87. // Check the disposition to see if we created the key for the first time
  88. //
  89. if (disposition == REG_OPENED_EXISTING_KEY) {
  90. //
  91. // The class is valid, but does it have a property key?
  92. //
  93. status = CmRegUtilOpenExistingWstrKey(
  94. classKey,
  95. REGSTR_KEY_DEVICE_PROPERTIES,
  96. KEY_READ,
  97. &classPropertyKey
  98. );
  99. //
  100. // At this point, class key is no longer needed.
  101. //
  102. ZwClose(classKey);
  103. if (NT_SUCCESS(status)) {
  104. //
  105. // The key exists, so try reading the settings from registry.
  106. //
  107. status = PiRegStateReadStackCreationSettingsFromKey(
  108. classPropertyKey,
  109. StackCreationSettings
  110. );
  111. //
  112. // At this point, class property key is no longer needed.
  113. //
  114. ZwClose(classPropertyKey);
  115. } else if (status == STATUS_OBJECT_NAME_NOT_FOUND) {
  116. //
  117. // No property key means no override, stick with defaults...
  118. //
  119. status = STATUS_SUCCESS;
  120. } else {
  121. //
  122. // Some sort of unexpected error, bail.
  123. //
  124. return status;
  125. }
  126. } else {
  127. //
  128. // New class key: populate the class name using the service's name.
  129. //
  130. serviceName = &DriverObject->DriverExtension->ServiceKeyName;
  131. //
  132. // In low memory scenarios, existing kernels (Win2K, etc) may choose
  133. // not to save the service name.
  134. //
  135. if (serviceName == NULL) {
  136. status = STATUS_INSUFFICIENT_RESOURCES;
  137. } else {
  138. //
  139. // Write out the class value
  140. //
  141. status = CmRegUtilWstrValueSetUcString(
  142. classKey,
  143. REGSTR_VAL_CLASS,
  144. serviceName
  145. );
  146. }
  147. //
  148. // At this point, class key is no longer needed.
  149. //
  150. ZwClose(classKey);
  151. }
  152. //
  153. // Return the result.
  154. //
  155. return status;
  156. }
  157. NTSTATUS
  158. PiRegStateReadStackCreationSettingsFromKey(
  159. IN HANDLE ClassOrDeviceKey,
  160. OUT PSTACK_CREATION_SETTINGS StackCreationSettings
  161. )
  162. /*++
  163. Routine Description:
  164. This routine reads stack creation settings from the registry. It assumes
  165. the passed in handle points to either a device-class property key or a
  166. devnode instance key.
  167. Arguments:
  168. ClassOrDeviceKey - Points to either a device-class *property* key, or a
  169. per-devnode instance key.
  170. StackCreationSettings - Receives settings retrieved from the registry.
  171. Return Value:
  172. STATUS_SUCCESS in which case StackCreationSettings may receive any number
  173. of possible overrides (including no overrides at all). On error, all fields
  174. receive default values.
  175. --*/
  176. {
  177. PKEY_VALUE_FULL_INFORMATION keyInfo;
  178. PSECURITY_DESCRIPTOR embeddedSecurityDescriptor;
  179. PSECURITY_DESCRIPTOR newSecurityDescriptor;
  180. SECURITY_INFORMATION securityInformation;
  181. BOOLEAN daclFromDefaultMechanism;
  182. NTSTATUS status;
  183. PAGED_CODE();
  184. //
  185. // Preinit for error
  186. //
  187. keyInfo = NULL;
  188. PpRegStateInitEmptyCreationSettings(StackCreationSettings);
  189. //
  190. // Read in the security descriptor
  191. //
  192. status = CmRegUtilWstrValueGetFullBuffer(
  193. ClassOrDeviceKey,
  194. REGSTR_VAL_DEVICE_SECURITY_DESCRIPTOR,
  195. REG_BINARY,
  196. 0,
  197. &keyInfo
  198. );
  199. //
  200. // Capture/validate the embedded security descriptor if present
  201. //
  202. if (NT_SUCCESS(status)) {
  203. embeddedSecurityDescriptor = (PSECURITY_DESCRIPTOR) KEY_VALUE_DATA(keyInfo);
  204. status = SeCaptureSecurityDescriptor(
  205. embeddedSecurityDescriptor,
  206. KernelMode,
  207. PagedPool,
  208. TRUE,
  209. &newSecurityDescriptor
  210. );
  211. } else if (status == STATUS_OBJECT_NAME_NOT_FOUND) {
  212. //
  213. // Special case a missing security descriptor
  214. //
  215. newSecurityDescriptor = NULL;
  216. status = STATUS_SUCCESS;
  217. }
  218. //
  219. // Cleanup
  220. //
  221. if (keyInfo) {
  222. ExFreePool(keyInfo);
  223. }
  224. if (!NT_SUCCESS(status)) {
  225. goto ErrorExit;
  226. }
  227. //
  228. // Save this information away.
  229. //
  230. if (newSecurityDescriptor) {
  231. //
  232. // Was this DACL set by an admin, or is this just our own DACL written
  233. // out for everyone to see?
  234. //
  235. status = SeUtilSecurityInfoFromSecurityDescriptor(
  236. newSecurityDescriptor,
  237. &daclFromDefaultMechanism,
  238. &securityInformation
  239. );
  240. if (!NT_SUCCESS(status)) {
  241. goto ErrorExit;
  242. }
  243. if (daclFromDefaultMechanism) {
  244. //
  245. // The DACL is our own, possibly from a previous boot or prior
  246. // unload. We will ignore it, as a newer driver might have chosen
  247. // to update the default DACL.
  248. //
  249. ExFreePool(newSecurityDescriptor);
  250. } else {
  251. //
  252. // The admin manually specified an overriding DACL. Honor it.
  253. //
  254. StackCreationSettings->SecurityDescriptor = newSecurityDescriptor;
  255. StackCreationSettings->Flags |= DSIFLAG_SECURITY_DESCRIPTOR;
  256. }
  257. }
  258. //
  259. // Look for a device type
  260. //
  261. status = CmRegUtilWstrValueGetDword(
  262. ClassOrDeviceKey,
  263. REGSTR_VAL_DEVICE_TYPE,
  264. FILE_DEVICE_UNSPECIFIED,
  265. &StackCreationSettings->DeviceType
  266. );
  267. if (NT_SUCCESS(status)) {
  268. StackCreationSettings->Flags |= DSIFLAG_DEVICE_TYPE;
  269. } else if (status != STATUS_OBJECT_NAME_NOT_FOUND) {
  270. goto ErrorExit;
  271. }
  272. //
  273. // Look for characteristics
  274. //
  275. status = CmRegUtilWstrValueGetDword(
  276. ClassOrDeviceKey,
  277. REGSTR_VAL_DEVICE_CHARACTERISTICS,
  278. 0,
  279. &StackCreationSettings->Characteristics
  280. );
  281. if (NT_SUCCESS(status)) {
  282. StackCreationSettings->Flags |= DSIFLAG_CHARACTERISTICS;
  283. } else if (status != STATUS_OBJECT_NAME_NOT_FOUND) {
  284. goto ErrorExit;
  285. }
  286. //
  287. // And finally, look for the exclusivity bit
  288. //
  289. status = CmRegUtilWstrValueGetDword(
  290. ClassOrDeviceKey,
  291. REGSTR_VAL_DEVICE_EXCLUSIVE,
  292. 0,
  293. &StackCreationSettings->Exclusivity
  294. );
  295. if (NT_SUCCESS(status)) {
  296. StackCreationSettings->Flags |= DSIFLAG_EXCLUSIVE;
  297. } else if (status != STATUS_OBJECT_NAME_NOT_FOUND) {
  298. goto ErrorExit;
  299. } else {
  300. status = STATUS_SUCCESS;
  301. }
  302. return status;
  303. ErrorExit:
  304. if (StackCreationSettings->SecurityDescriptor) {
  305. ExFreePool(StackCreationSettings->SecurityDescriptor);
  306. }
  307. PpRegStateInitEmptyCreationSettings(StackCreationSettings);
  308. return status;
  309. }
  310. VOID
  311. PpRegStateInitEmptyCreationSettings(
  312. OUT PSTACK_CREATION_SETTINGS StackCreationSettings
  313. )
  314. /*++
  315. Routine Description:
  316. This routine creates an initially empty set of stack creation settings.
  317. Arguments:
  318. StackCreationSettings - Structure to fill out.
  319. Return Value:
  320. None.
  321. --*/
  322. {
  323. PAGED_CODE();
  324. StackCreationSettings->Flags = 0;
  325. StackCreationSettings->SecurityDescriptor = NULL;
  326. StackCreationSettings->DeviceType = FILE_DEVICE_UNSPECIFIED;
  327. StackCreationSettings->Characteristics = 0;
  328. StackCreationSettings->Exclusivity = 0;
  329. }
  330. NTSTATUS
  331. PiRegStateOpenClassKey(
  332. IN LPCGUID DeviceClassGuid,
  333. IN ACCESS_MASK DesiredAccess,
  334. IN LOGICAL CreateIfNotPresent,
  335. OUT ULONG *Disposition OPTIONAL,
  336. OUT HANDLE *ClassKeyHandle
  337. )
  338. /*++
  339. Routine Description:
  340. This routine reads opens the specified class key, creating it anew as
  341. needed.
  342. Arguments:
  343. DeviceClassGuid - Guid representing the class.
  344. DesiredAccess - Specifies the desired access that the caller needs to
  345. the key (this isn't really used as the access-mode is KernelMode,
  346. but we specify it anyway).
  347. CreateIfNotPresent - If set, the class key is created if it doesn't exist.
  348. Disposition - This optional pointer receives a ULONG indicating whether
  349. the key was newly created (0 on error):
  350. REG_CREATED_NEW_KEY - A new Registry Key was created.
  351. REG_OPENED_EXISTING_KEY - An existing Registry Key was opened.
  352. ClassKeyHandle - Recieves registry key handle upon success, NULL otherwise.
  353. Note that the handle is in the global kernel namespace (and not the
  354. current processes handle take). The handle should be released using
  355. ZwClose.
  356. Return Value:
  357. STATUS_SUCCESS in which case StackCreationSettings may receive any number
  358. of possible overrides (including no overrides at all). On error, all fields
  359. receive default values.
  360. --*/
  361. {
  362. WCHAR classGuidString[39];
  363. HANDLE classBranchKey;
  364. HANDLE classKey;
  365. ULONG createDisposition;
  366. NTSTATUS status;
  367. PAGED_CODE();
  368. //
  369. // Preinit for error.
  370. //
  371. *ClassKeyHandle = NULL;
  372. if (ARGUMENT_PRESENT(Disposition)) {
  373. *Disposition = 0;
  374. }
  375. //
  376. // Open the class key branch.
  377. //
  378. // Note: Inside the kernel this should be a NULL path relative open off of
  379. // &CmRegistryMachineSystemCurrentControlSetControlClass, as that handle
  380. // is cached.
  381. //
  382. status = CmRegUtilOpenExistingWstrKey(
  383. NULL,
  384. CM_REGISTRY_MACHINE(REGSTR_PATH_CLASS_NT),
  385. KEY_READ,
  386. &classBranchKey
  387. );
  388. if (!NT_SUCCESS(status)) {
  389. return status;
  390. }
  391. //
  392. // Convert the binary GUID into it's corresponding unicode string.
  393. // Note: _snwprintf is used in place of RtlStringCchPrintfW, so as not to
  394. // drag in ntstrsafe.lib, which would be required for w2k
  395. // compatibility as _vsnwprintf is not exported by that OS.
  396. //
  397. _snwprintf(
  398. classGuidString,
  399. sizeof(classGuidString)/sizeof(WCHAR),
  400. L"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
  401. DeviceClassGuid->Data1,
  402. DeviceClassGuid->Data2,
  403. DeviceClassGuid->Data3,
  404. DeviceClassGuid->Data4[0],
  405. DeviceClassGuid->Data4[1],
  406. DeviceClassGuid->Data4[2],
  407. DeviceClassGuid->Data4[3],
  408. DeviceClassGuid->Data4[4],
  409. DeviceClassGuid->Data4[5],
  410. DeviceClassGuid->Data4[6],
  411. DeviceClassGuid->Data4[7]
  412. );
  413. classGuidString[38] = L'\0';
  414. if (CreateIfNotPresent) {
  415. //
  416. // Now try to open or create the class key. If newly created, the
  417. // security will be inherited from the parent Class\ key.
  418. //
  419. status = CmRegUtilCreateWstrKey(
  420. classBranchKey,
  421. classGuidString,
  422. DesiredAccess,
  423. REG_OPTION_NON_VOLATILE,
  424. NULL,
  425. &createDisposition,
  426. &classKey
  427. );
  428. } else {
  429. status = CmRegUtilOpenExistingWstrKey(
  430. classBranchKey,
  431. classGuidString,
  432. DesiredAccess,
  433. &classKey
  434. );
  435. //
  436. // Set the disposition appropriately.
  437. //
  438. createDisposition = REG_OPENED_EXISTING_KEY;
  439. }
  440. //
  441. // We don't need this anymore
  442. //
  443. ZwClose(classBranchKey);
  444. if (NT_SUCCESS(status)) {
  445. *ClassKeyHandle = classKey;
  446. if (ARGUMENT_PRESENT(Disposition)) {
  447. *Disposition = createDisposition;
  448. }
  449. }
  450. return status;
  451. }
  452. NTSTATUS
  453. PpRegStateUpdateStackCreationSettings(
  454. IN LPCGUID DeviceClassGuid,
  455. IN PSTACK_CREATION_SETTINGS StackCreationSettings
  456. )
  457. /*++
  458. Routine Description:
  459. This routine updates the class key in the registry to reflect the passed in
  460. stack creation settings. The key is assumed to already exist.
  461. Arguments:
  462. DeviceClassGuid - Guid representing the class.
  463. StackCreationSettings - Information reflecting the settings to apply.
  464. Return Value:
  465. NTSTATUS.
  466. --*/
  467. {
  468. PSECURITY_DESCRIPTOR tempDescriptor;
  469. ULONG sizeOfDescriptor;
  470. HANDLE classPropertyKey;
  471. HANDLE classKey;
  472. NTSTATUS status;
  473. PAGED_CODE();
  474. //
  475. // Currently this code only supports updating the security descriptor
  476. // in the registry.
  477. //
  478. ASSERT(StackCreationSettings->Flags == DSIFLAG_SECURITY_DESCRIPTOR);
  479. //
  480. // Open the class key (it should exist)
  481. //
  482. status = PiRegStateOpenClassKey(
  483. DeviceClassGuid,
  484. KEY_ALL_ACCESS,
  485. FALSE, // CreateIfNotPresent
  486. NULL,
  487. &classKey
  488. );
  489. if (!NT_SUCCESS(status)) {
  490. return status;
  491. }
  492. //
  493. // Double check our hardcoded descriptor...
  494. //
  495. if (PiRegStateDiscriptor == NOT_VALIDATED) {
  496. status = SeCaptureSecurityDescriptor(
  497. (PSECURITY_DESCRIPTOR) PiRegStateSysAllInherittedSecurityDescriptor,
  498. KernelMode,
  499. PagedPool,
  500. TRUE,
  501. &tempDescriptor
  502. );
  503. if (NT_SUCCESS(status)) {
  504. PiRegStateDiscriptor = VALIDATED_SUCCESSFULLY;
  505. ExFreePool(tempDescriptor);
  506. } else {
  507. ASSERT(0);
  508. PiRegStateDiscriptor = VALIDATED_UNSUCCESSFULLY;
  509. }
  510. }
  511. //
  512. // Get the correct descriptor value.
  513. //
  514. if (PiRegStateDiscriptor == VALIDATED_SUCCESSFULLY) {
  515. //
  516. // Use the tamper-resistant descriptor (due to history, the class keys
  517. // themselves can be accessed by admins. However, the class property
  518. // key had tighter security placed on it. We maintain that tradition.)
  519. //
  520. tempDescriptor = (PSECURITY_DESCRIPTOR) PiRegStateSysAllInherittedSecurityDescriptor;
  521. } else {
  522. //
  523. // Second best, we'll inherit an admin all descriptor from the class
  524. // container.
  525. //
  526. tempDescriptor = (PSECURITY_DESCRIPTOR) NULL;
  527. }
  528. //
  529. // Now try to open or create the class property key.
  530. //
  531. status = CmRegUtilCreateWstrKey(
  532. classKey,
  533. REGSTR_KEY_DEVICE_PROPERTIES,
  534. KEY_ALL_ACCESS,
  535. REG_OPTION_NON_VOLATILE,
  536. tempDescriptor,
  537. NULL,
  538. &classPropertyKey
  539. );
  540. //
  541. // No need for the class key anymore.
  542. //
  543. ZwClose(classKey);
  544. if (!NT_SUCCESS(status)) {
  545. return status;
  546. }
  547. //
  548. // Write out the security descriptor to the registry
  549. //
  550. sizeOfDescriptor = RtlLengthSecurityDescriptor(
  551. StackCreationSettings->SecurityDescriptor
  552. );
  553. status = CmRegUtilWstrValueSetFullBuffer(
  554. classPropertyKey,
  555. REGSTR_VAL_DEVICE_SECURITY_DESCRIPTOR,
  556. REG_BINARY,
  557. StackCreationSettings->SecurityDescriptor,
  558. sizeOfDescriptor
  559. );
  560. //
  561. // Close the property key
  562. //
  563. ZwClose(classPropertyKey);
  564. //
  565. // Done.
  566. //
  567. return status;
  568. }
  569. VOID
  570. PpRegStateFreeStackCreationSettings(
  571. IN PSTACK_CREATION_SETTINGS StackCreationSettings
  572. )
  573. /*++
  574. Routine Description:
  575. This routine frees any state allocated against the passed in stack creation
  576. settings.
  577. Arguments:
  578. StackCreationSettings - Information to free.
  579. Return Value:
  580. None.
  581. --*/
  582. {
  583. PAGED_CODE();
  584. //
  585. // Clean up the security descriptor as appropriate.
  586. //
  587. if (StackCreationSettings->Flags & DSIFLAG_SECURITY_DESCRIPTOR) {
  588. ExFreePool(StackCreationSettings->SecurityDescriptor);
  589. }
  590. }
  591. VOID
  592. PpRegStateLoadSecurityDescriptor(
  593. IN PSECURITY_DESCRIPTOR SecurityDescriptor,
  594. IN OUT PSTACK_CREATION_SETTINGS StackCreationSettings
  595. )
  596. /*++
  597. Routine Description:
  598. This routine updates the stack creation settings to reflect the passed in
  599. security descriptor.
  600. Arguments:
  601. SecurityDescriptor - Security descriptor to load into the stack creation
  602. settings.
  603. StackCreationSettings - Stack creation settings to update.
  604. Return Value:
  605. None.
  606. --*/
  607. {
  608. PAGED_CODE();
  609. ASSERT(!(StackCreationSettings->Flags & DSIFLAG_SECURITY_DESCRIPTOR));
  610. StackCreationSettings->Flags = DSIFLAG_SECURITY_DESCRIPTOR;
  611. StackCreationSettings->SecurityDescriptor = SecurityDescriptor;
  612. }