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.

678 lines
19 KiB

  1. /*****************************************************************************
  2. * registry.cpp - registry key object implementation
  3. *****************************************************************************
  4. * Copyright (c) 1997-2000 Microsoft Corporation. All rights reserved.
  5. */
  6. #include "private.h"
  7. /*****************************************************************************
  8. * Factory.
  9. */
  10. #pragma code_seg("PAGE")
  11. /*****************************************************************************
  12. * CreateRegistryKey()
  13. *****************************************************************************
  14. * Creates a registry key object.
  15. */
  16. NTSTATUS
  17. CreateRegistryKey
  18. (
  19. OUT PUNKNOWN * Unknown,
  20. IN REFCLSID,
  21. IN PUNKNOWN UnknownOuter OPTIONAL,
  22. IN POOL_TYPE PoolType
  23. )
  24. {
  25. PAGED_CODE();
  26. ASSERT(Unknown);
  27. _DbgPrintF(DEBUGLVL_LIFETIME,("Creating REGISTRYKEY"));
  28. STD_CREATE_BODY
  29. (
  30. CRegistryKey,
  31. Unknown,
  32. UnknownOuter,
  33. PoolType
  34. );
  35. }
  36. /*****************************************************************************
  37. * PcNewRegistryKey()
  38. *****************************************************************************
  39. * Creates and initializes a registry key object.
  40. */
  41. PORTCLASSAPI
  42. NTSTATUS
  43. NTAPI
  44. PcNewRegistryKey
  45. (
  46. OUT PREGISTRYKEY * OutRegistryKey,
  47. IN PUNKNOWN OuterUnknown OPTIONAL,
  48. IN ULONG RegistryKeyType,
  49. IN ACCESS_MASK DesiredAccess,
  50. IN PVOID DeviceObject OPTIONAL,
  51. IN PVOID SubDevice OPTIONAL,
  52. IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
  53. IN ULONG CreateOptions OPTIONAL,
  54. OUT PULONG Disposition OPTIONAL
  55. )
  56. {
  57. PAGED_CODE();
  58. ASSERT(OutRegistryKey);
  59. //
  60. // Validate Parameters.
  61. //
  62. if (NULL == OutRegistryKey)
  63. {
  64. _DbgPrintF(DEBUGLVL_TERSE, ("PcNewRegistryKey : Invalid Parameter."));
  65. return STATUS_INVALID_PARAMETER;
  66. }
  67. PUNKNOWN unknown;
  68. NTSTATUS ntStatus =
  69. CreateRegistryKey
  70. (
  71. &unknown,
  72. GUID_NULL,
  73. OuterUnknown,
  74. PagedPool
  75. );
  76. if (NT_SUCCESS(ntStatus))
  77. {
  78. PREGISTRYKEYINIT RegistryKey;
  79. ntStatus =
  80. unknown->QueryInterface
  81. (
  82. IID_IRegistryKey,
  83. (PVOID *) &RegistryKey
  84. );
  85. if (NT_SUCCESS(ntStatus))
  86. {
  87. ntStatus = RegistryKey->Init( RegistryKeyType,
  88. DesiredAccess,
  89. PDEVICE_OBJECT(DeviceObject),
  90. PSUBDEVICE(SubDevice),
  91. ObjectAttributes,
  92. CreateOptions,
  93. Disposition );
  94. if (NT_SUCCESS(ntStatus))
  95. {
  96. *OutRegistryKey = RegistryKey;
  97. } else
  98. {
  99. RegistryKey->Release();
  100. }
  101. }
  102. unknown->Release();
  103. }
  104. return ntStatus;
  105. }
  106. /*****************************************************************************
  107. * Member functions.
  108. */
  109. /*****************************************************************************
  110. * CRegistryKey::~CRegistryKey()
  111. *****************************************************************************
  112. * Destructor.
  113. */
  114. CRegistryKey::
  115. ~CRegistryKey
  116. ( void
  117. )
  118. {
  119. PAGED_CODE();
  120. _DbgPrintF(DEBUGLVL_LIFETIME,("Destroying REGISTRYKEY (0x%08x)",this));
  121. if ( FALSE == m_KeyDeleted )
  122. {
  123. ASSERT(m_KeyHandle);
  124. ZwClose(m_KeyHandle);
  125. }
  126. else
  127. {
  128. ASSERT(!m_KeyHandle);
  129. }
  130. }
  131. /*****************************************************************************
  132. * CRegistryKey::NonDelegatingQueryInterface()
  133. *****************************************************************************
  134. * Obtains an interface.
  135. */
  136. STDMETHODIMP_(NTSTATUS)
  137. CRegistryKey::
  138. NonDelegatingQueryInterface
  139. (
  140. REFIID Interface,
  141. PVOID * Object
  142. )
  143. {
  144. PAGED_CODE();
  145. ASSERT(Object);
  146. if (IsEqualGUIDAligned(Interface,IID_IUnknown))
  147. {
  148. *Object = PVOID(PUNKNOWN(this));
  149. }
  150. else
  151. if (IsEqualGUIDAligned(Interface,IID_IRegistryKey))
  152. {
  153. *Object = PVOID(PREGISTRYKEYINIT(this));
  154. }
  155. else
  156. {
  157. *Object = NULL;
  158. }
  159. if (*Object)
  160. {
  161. PUNKNOWN(*Object)->AddRef();
  162. return STATUS_SUCCESS;
  163. }
  164. return STATUS_INVALID_PARAMETER;
  165. }
  166. /*****************************************************************************
  167. * CRegistryKey::Init()
  168. *****************************************************************************
  169. * Initializes a registry key object.
  170. */
  171. STDMETHODIMP_(NTSTATUS)
  172. CRegistryKey::
  173. Init
  174. (
  175. IN ULONG RegistryKeyType,
  176. IN ACCESS_MASK DesiredAccess,
  177. IN PDEVICE_OBJECT DeviceObject OPTIONAL,
  178. IN PSUBDEVICE SubDevice OPTIONAL,
  179. IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
  180. IN ULONG CreateOptions OPTIONAL,
  181. OUT PULONG Disposition OPTIONAL
  182. )
  183. {
  184. PAGED_CODE();
  185. _DbgPrintF(DEBUGLVL_LIFETIME,("Initializing REGISTRYKEY (0x%08x)",this));
  186. NTSTATUS ntStatus;
  187. m_KeyDeleted = TRUE;
  188. m_GeneralKey = FALSE;
  189. m_KeyHandle = NULL;
  190. switch(RegistryKeyType)
  191. {
  192. case GeneralRegistryKey:
  193. ASSERT(ObjectAttributes);
  194. ntStatus = ZwCreateKey( &m_KeyHandle,
  195. DesiredAccess,
  196. ObjectAttributes,
  197. 0,
  198. NULL,
  199. CreateOptions,
  200. Disposition );
  201. if (NT_SUCCESS(ntStatus))
  202. {
  203. ASSERT(m_KeyHandle);
  204. m_GeneralKey = TRUE;
  205. m_KeyDeleted = FALSE;
  206. }
  207. else
  208. {
  209. ASSERT(!m_KeyHandle);
  210. }
  211. break;
  212. case DeviceRegistryKey:
  213. case DriverRegistryKey:
  214. case HwProfileRegistryKey:
  215. {
  216. ASSERT(DeviceObject);
  217. ULONG DevInstKeyType;
  218. if (RegistryKeyType == DeviceRegistryKey)
  219. {
  220. DevInstKeyType = PLUGPLAY_REGKEY_DEVICE;
  221. } else if(RegistryKeyType == DriverRegistryKey)
  222. {
  223. DevInstKeyType = PLUGPLAY_REGKEY_DRIVER;
  224. } else
  225. {
  226. DevInstKeyType = PLUGPLAY_REGKEY_CURRENT_HWPROFILE;
  227. }
  228. PDEVICE_CONTEXT deviceContext =
  229. PDEVICE_CONTEXT(DeviceObject->DeviceExtension);
  230. PDEVICE_OBJECT PhysicalDeviceObject = deviceContext->PhysicalDeviceObject;
  231. ntStatus = IoOpenDeviceRegistryKey( PhysicalDeviceObject,
  232. DevInstKeyType,
  233. DesiredAccess,
  234. &m_KeyHandle );
  235. if (NT_SUCCESS(ntStatus))
  236. {
  237. ASSERT(m_KeyHandle);
  238. m_GeneralKey = FALSE;
  239. m_KeyDeleted = FALSE;
  240. }
  241. else
  242. {
  243. ASSERT(!m_KeyHandle);
  244. }
  245. }
  246. break;
  247. case DeviceInterfaceRegistryKey:
  248. {
  249. ASSERT(DeviceObject);
  250. ASSERT(SubDevice);
  251. ULONG Index = SubdeviceIndex( DeviceObject,
  252. SubDevice );
  253. if(Index != ULONG(-1))
  254. {
  255. PDEVICE_CONTEXT deviceContext =
  256. PDEVICE_CONTEXT(DeviceObject->DeviceExtension);
  257. PUNICODE_STRING SymbolicLinkName = &deviceContext->SymbolicLinkNames[Index];
  258. ntStatus = IoOpenDeviceInterfaceRegistryKey( SymbolicLinkName,
  259. DesiredAccess,
  260. &m_KeyHandle );
  261. if (NT_SUCCESS(ntStatus))
  262. {
  263. ASSERT(m_KeyHandle);
  264. m_GeneralKey = FALSE;
  265. m_KeyDeleted = FALSE;
  266. }
  267. else
  268. {
  269. ASSERT(!m_KeyHandle);
  270. }
  271. } else
  272. {
  273. ntStatus = STATUS_INVALID_PARAMETER;
  274. }
  275. }
  276. default:
  277. ntStatus = STATUS_INVALID_PARAMETER;
  278. break;
  279. }
  280. return ntStatus;
  281. }
  282. /*****************************************************************************
  283. * CRegistryKey::QueryKey()
  284. *****************************************************************************
  285. * Queries a registry key.
  286. */
  287. STDMETHODIMP_(NTSTATUS)
  288. CRegistryKey::
  289. QueryKey
  290. (
  291. IN KEY_INFORMATION_CLASS KeyInformationClass,
  292. OUT PVOID KeyInformation,
  293. IN ULONG Length,
  294. OUT PULONG ResultLength
  295. )
  296. {
  297. PAGED_CODE();
  298. NTSTATUS ntStatus;
  299. if ( m_KeyDeleted )
  300. {
  301. ntStatus = STATUS_INVALID_HANDLE;
  302. ASSERT(!m_KeyHandle);
  303. }
  304. else
  305. {
  306. ASSERT(m_KeyHandle);
  307. ntStatus = ZwQueryKey( m_KeyHandle,
  308. KeyInformationClass,
  309. KeyInformation,
  310. Length,
  311. ResultLength );
  312. }
  313. return ntStatus;
  314. }
  315. /*****************************************************************************
  316. * CRegistryKey::EnumerateKey()
  317. *****************************************************************************
  318. * Enumerates a registry key.
  319. */
  320. STDMETHODIMP_(NTSTATUS)
  321. CRegistryKey::
  322. EnumerateKey
  323. (
  324. IN ULONG Index,
  325. IN KEY_INFORMATION_CLASS KeyInformationClass,
  326. OUT PVOID KeyInformation,
  327. IN ULONG Length,
  328. OUT PULONG ResultLength
  329. )
  330. {
  331. PAGED_CODE();
  332. NTSTATUS ntStatus;
  333. if ( m_KeyDeleted )
  334. {
  335. ntStatus = STATUS_INVALID_HANDLE;
  336. ASSERT(!m_KeyHandle);
  337. }
  338. else
  339. {
  340. ASSERT(m_KeyHandle);
  341. ntStatus = ZwEnumerateKey( m_KeyHandle,
  342. Index,
  343. KeyInformationClass,
  344. KeyInformation,
  345. Length,
  346. ResultLength );
  347. }
  348. return ntStatus;
  349. }
  350. /*****************************************************************************
  351. * CRegistryKey::QueryValueKey()
  352. *****************************************************************************
  353. * Queries a registry value key.
  354. */
  355. STDMETHODIMP_(NTSTATUS)
  356. CRegistryKey::
  357. QueryValueKey
  358. (
  359. IN PUNICODE_STRING ValueName,
  360. IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
  361. OUT PVOID KeyValueInformation,
  362. IN ULONG Length,
  363. OUT PULONG ResultLength
  364. )
  365. {
  366. PAGED_CODE();
  367. NTSTATUS ntStatus;
  368. if ( m_KeyDeleted )
  369. {
  370. ntStatus = STATUS_INVALID_HANDLE;
  371. ASSERT(!m_KeyHandle);
  372. }
  373. else
  374. {
  375. ASSERT(m_KeyHandle);
  376. ntStatus = ZwQueryValueKey( m_KeyHandle,
  377. ValueName,
  378. KeyValueInformationClass,
  379. KeyValueInformation,
  380. Length,
  381. ResultLength );
  382. }
  383. return ntStatus;
  384. }
  385. /*****************************************************************************
  386. * CRegistryKey::EnumerateValueKey()
  387. *****************************************************************************
  388. * Enumerates a registry value key.
  389. */
  390. STDMETHODIMP_(NTSTATUS)
  391. CRegistryKey::
  392. EnumerateValueKey
  393. (
  394. IN ULONG Index,
  395. IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
  396. OUT PVOID KeyValueInformation,
  397. IN ULONG Length,
  398. OUT PULONG ResultLength
  399. )
  400. {
  401. PAGED_CODE();
  402. NTSTATUS ntStatus;
  403. if ( m_KeyDeleted )
  404. {
  405. ntStatus = STATUS_INVALID_HANDLE;
  406. ASSERT(!m_KeyHandle);
  407. }
  408. else
  409. {
  410. ASSERT(m_KeyHandle);
  411. ntStatus = ZwEnumerateValueKey( m_KeyHandle,
  412. Index,
  413. KeyValueInformationClass,
  414. KeyValueInformation,
  415. Length,
  416. ResultLength );
  417. }
  418. return ntStatus;
  419. }
  420. /*****************************************************************************
  421. * CRegistryKey::SetValueKey()
  422. *****************************************************************************
  423. * Sets a registry value key.
  424. */
  425. STDMETHODIMP_(NTSTATUS)
  426. CRegistryKey::
  427. SetValueKey
  428. (
  429. IN PUNICODE_STRING ValueName OPTIONAL,
  430. IN ULONG Type,
  431. IN PVOID Data,
  432. IN ULONG DataSize
  433. )
  434. {
  435. PAGED_CODE();
  436. NTSTATUS ntStatus;
  437. if ( m_KeyDeleted )
  438. {
  439. ntStatus = STATUS_INVALID_HANDLE;
  440. ASSERT(!m_KeyHandle);
  441. }
  442. else
  443. {
  444. ASSERT(m_KeyHandle);
  445. ntStatus = ZwSetValueKey( m_KeyHandle,
  446. ValueName,
  447. 0,
  448. Type,
  449. Data,
  450. DataSize );
  451. }
  452. return ntStatus;
  453. }
  454. /*****************************************************************************
  455. * CRegistryKey::QueryRegistryValues()
  456. *****************************************************************************
  457. * Queries several registry values with a single call.
  458. */
  459. STDMETHODIMP_(NTSTATUS)
  460. CRegistryKey::
  461. QueryRegistryValues
  462. (
  463. IN PRTL_QUERY_REGISTRY_TABLE QueryTable,
  464. IN PVOID Context OPTIONAL
  465. )
  466. {
  467. PAGED_CODE();
  468. ASSERT(QueryTable);
  469. NTSTATUS ntStatus;
  470. if ( m_KeyDeleted )
  471. {
  472. ntStatus = STATUS_INVALID_HANDLE;
  473. ASSERT(!m_KeyHandle);
  474. }
  475. else
  476. {
  477. ASSERT(m_KeyHandle);
  478. ntStatus = RtlQueryRegistryValues( RTL_REGISTRY_HANDLE,
  479. PWSTR(m_KeyHandle),
  480. QueryTable,
  481. Context,
  482. NULL );
  483. }
  484. return ntStatus;
  485. }
  486. /*****************************************************************************
  487. * CRegistryKey::NewSubKey()
  488. *****************************************************************************
  489. * Opens/creates a subkey for an open registry key.
  490. */
  491. STDMETHODIMP_(NTSTATUS)
  492. CRegistryKey::
  493. NewSubKey
  494. (
  495. OUT PREGISTRYKEY * RegistrySubKey,
  496. IN PUNKNOWN OuterUnknown,
  497. IN ACCESS_MASK DesiredAccess,
  498. IN PUNICODE_STRING SubKeyName,
  499. IN ULONG CreateOptions,
  500. OUT PULONG Disposition OPTIONAL
  501. )
  502. {
  503. PAGED_CODE();
  504. ASSERT(RegistrySubKey);
  505. ASSERT(SubKeyName);
  506. OBJECT_ATTRIBUTES ObjectAttributes;
  507. ASSERT(m_KeyHandle);
  508. InitializeObjectAttributes( &ObjectAttributes,
  509. SubKeyName,
  510. OBJ_INHERIT | OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
  511. m_KeyHandle,
  512. NULL );
  513. return PcNewRegistryKey( RegistrySubKey,
  514. OuterUnknown,
  515. GeneralRegistryKey,
  516. DesiredAccess,
  517. NULL,
  518. NULL,
  519. &ObjectAttributes,
  520. CreateOptions,
  521. Disposition );
  522. }
  523. /*****************************************************************************
  524. * CRegistryKey::DeleteKey()
  525. *****************************************************************************
  526. * Deletes a registry key.
  527. */
  528. STDMETHODIMP_(NTSTATUS)
  529. CRegistryKey::
  530. DeleteKey
  531. (
  532. )
  533. {
  534. PAGED_CODE();
  535. NTSTATUS ntStatus;
  536. if ( m_KeyDeleted )
  537. {
  538. ntStatus = STATUS_INVALID_HANDLE;
  539. ASSERT(!m_KeyHandle);
  540. }
  541. else if ( FALSE == m_GeneralKey )
  542. {
  543. ntStatus = STATUS_ACCESS_DENIED;
  544. }
  545. else
  546. {
  547. ASSERT(m_KeyHandle);
  548. ntStatus = ZwDeleteKey( m_KeyHandle );
  549. if(NT_SUCCESS( ntStatus ))
  550. {
  551. m_KeyDeleted = TRUE;
  552. m_KeyHandle = NULL;
  553. }
  554. else
  555. {
  556. _DbgPrintF(DEBUGLVL_TERSE,("ZwDeleteKey failed for %x!!!",m_KeyHandle));
  557. }
  558. }
  559. return ntStatus;
  560. }
  561. /*****************************************************************************
  562. * PcGetDeviceProperty()
  563. *****************************************************************************
  564. * This wraps a call to IoGetDeviceProperty.
  565. */
  566. PORTCLASSAPI
  567. NTSTATUS
  568. NTAPI
  569. PcGetDeviceProperty
  570. (
  571. IN PVOID DeviceObject,
  572. IN DEVICE_REGISTRY_PROPERTY DeviceProperty,
  573. IN ULONG BufferLength,
  574. OUT PVOID PropertyBuffer,
  575. OUT PULONG ResultLength
  576. )
  577. {
  578. PDEVICE_CONTEXT deviceContext =
  579. PDEVICE_CONTEXT(PDEVICE_OBJECT(DeviceObject)->DeviceExtension);
  580. PDEVICE_OBJECT PhysicalDeviceObject = deviceContext->PhysicalDeviceObject;
  581. return IoGetDeviceProperty( PhysicalDeviceObject,
  582. DeviceProperty,
  583. BufferLength,
  584. PropertyBuffer,
  585. ResultLength );
  586. }
  587. #pragma code_seg()