Source code of Windows XP (NT5)
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.

265 lines
6.0 KiB

  1. //depot/Lab04_N/Base/screg/winreg/server/regsval.c#3 - edit change 1053 (text)
  2. /*++
  3. Copyright (c) 1991 Microsoft Corporation
  4. Module Name:
  5. Regsval.c
  6. Abstract:
  7. This module contains the server side implementation for the Win32
  8. Registry set value API. That is:
  9. - BaseRegSetValue
  10. Author:
  11. David J. Gilman (davegi) 27-Nov-1991
  12. Notes:
  13. See the Notes in Regkey.c.
  14. --*/
  15. #include <rpc.h>
  16. #include "regrpc.h"
  17. #include "localreg.h"
  18. #ifdef LOCAL
  19. #include "tsappcmp.h"
  20. #include "regclass.h"
  21. #endif
  22. error_status_t
  23. BaseRegSetValue(
  24. HKEY hKey,
  25. PUNICODE_STRING lpValueName,
  26. DWORD dwType,
  27. LPBYTE lpData,
  28. DWORD cbData
  29. )
  30. /*++
  31. Routine Description:
  32. Set the type and value of an open key. Changes are not committed
  33. until the key is flushed. By "committed" we mean written to disk.
  34. Changes will be seen by subsequent queries as soon as this call
  35. returns.
  36. Arguments:
  37. hKey - Supplies a handle to the open key. Any of the predefined
  38. reserved handles or a previously opened key handle may be used for
  39. hKey.
  40. lpValueName - Supplies the name of the value to set. If the ValueName
  41. is not present, it is added to the key.
  42. dwType - Supplies the type of information to be stored: REG_SZ, etc.
  43. lpData - supplies a pointer to a buffer containing the data to set for
  44. the value entry.
  45. cbData - Supplies the length (in bytes) of the information to be stored.
  46. Return Value:
  47. Returns ERROR_SUCCESS (0) for success; error-code for failure.
  48. Notes:
  49. A set may fail due to memory limits - any config entry must fit in
  50. main memory. If successful, RegSetValue will set the type, contents,
  51. and length of the information stored at the specified key.
  52. KEY_SET_VALUE access is required.
  53. --*/
  54. {
  55. NTSTATUS Status;
  56. HKEY hkSet;
  57. #ifdef LOCAL
  58. PVOID PreSetData = NULL;
  59. HKEY hkUserClasses;
  60. HKEY hkMachineClasses;
  61. hkUserClasses = NULL;
  62. hkMachineClasses = NULL;
  63. #endif
  64. hkSet = hKey;
  65. //
  66. // Subtract the NULL from the Length. This was added on the
  67. // client side so that RPC would transmit it.
  68. //
  69. if ( lpValueName->Length > 0 ) {
  70. lpValueName->Length -= sizeof( UNICODE_NULL );
  71. }
  72. if ((hKey == HKEY_PERFORMANCE_DATA) ||
  73. (hKey==HKEY_PERFORMANCE_TEXT) ||
  74. (hKey==HKEY_PERFORMANCE_NLSTEXT)) {
  75. return(PerfRegSetValue(hKey,
  76. lpValueName->Buffer,
  77. 0,
  78. dwType,
  79. lpData,
  80. cbData));
  81. }
  82. #ifdef LOCAL
  83. if (gpfnTermsrvSetValueKey && gpfnTermsrvGetPreSetValue ) {
  84. //
  85. // Find any pre-set values
  86. //
  87. Status = gpfnTermsrvGetPreSetValue( hKey,
  88. lpValueName,
  89. dwType,
  90. &PreSetData
  91. );
  92. //
  93. // Use the pre-set values if they exists
  94. //
  95. if ( NT_SUCCESS(Status) ) {
  96. lpData = (( PKEY_VALUE_PARTIAL_INFORMATION ) PreSetData )->Data;
  97. cbData = (( PKEY_VALUE_PARTIAL_INFORMATION ) PreSetData )->DataLength;
  98. }
  99. else {
  100. PreSetData = NULL;
  101. }
  102. //
  103. // Save the Master Copy
  104. //
  105. gpfnTermsrvSetValueKey(hKey,
  106. lpValueName,
  107. 0,
  108. dwType,
  109. lpData,
  110. cbData);
  111. }
  112. if ( PreSetData ) {
  113. //
  114. // Set the value and free any data
  115. //
  116. Status = NtSetValueKey(
  117. hKey,
  118. lpValueName,
  119. 0,
  120. dwType,
  121. lpData,
  122. cbData
  123. );
  124. RtlFreeHeap( RtlProcessHeap( ), 0, PreSetData );
  125. return (error_status_t)RtlNtStatusToDosError( Status );
  126. }
  127. else
  128. //
  129. // No pre-set values, just do original code
  130. //
  131. #endif
  132. //
  133. // Call the Nt API to set the value, map the NTSTATUS code to a
  134. // Win32 Registry error code and return.
  135. //
  136. #ifdef LOCAL
  137. if (REG_CLASS_IS_SPECIAL_KEY(hKey)) {
  138. Status = BaseRegGetUserAndMachineClass(
  139. NULL,
  140. hkSet,
  141. MAXIMUM_ALLOWED,
  142. &hkMachineClasses,
  143. &hkUserClasses);
  144. if (!NT_SUCCESS(Status)) {
  145. return (error_status_t)RtlNtStatusToDosError(Status);
  146. }
  147. }
  148. if (hkUserClasses && hkMachineClasses) {
  149. hkSet = hkUserClasses;
  150. }
  151. #endif
  152. Status = NtSetValueKey(
  153. hkSet,
  154. lpValueName,
  155. 0,
  156. dwType,
  157. lpData,
  158. cbData
  159. );
  160. #ifdef LOCAL
  161. if (hkUserClasses && hkMachineClasses) {
  162. if (hkUserClasses != hKey) {
  163. NtClose(hkUserClasses);
  164. } else {
  165. NtClose(hkMachineClasses);
  166. }
  167. }
  168. //if it is a HKLM\Software\Classes subkey and we get ACCDENIED try to create the
  169. //key in HKCU\Software\Classes and set value there
  170. if( (gdwRegistryExtensionFlags & TERMSRV_ENABLE_ACCESS_FLAG_MODIFICATION )
  171. && STATUS_ACCESS_DENIED == Status
  172. && hkSet == hkMachineClasses
  173. && REG_CLASS_IS_SPECIAL_KEY(hKey) ) {
  174. Status = CreateMultipartUserClassKey( hKey, &hkSet );
  175. if(!NT_SUCCESS(Status)) {
  176. return ERROR_ACCESS_DENIED;
  177. }
  178. Status = NtSetValueKey(
  179. hkSet,
  180. lpValueName,
  181. 0,
  182. dwType,
  183. lpData,
  184. cbData
  185. );
  186. NtClose(hkSet);
  187. if(!NT_SUCCESS(Status)) {
  188. return ERROR_ACCESS_DENIED;
  189. }
  190. }
  191. #endif // LOCAL
  192. return (error_status_t) RtlNtStatusToDosError(Status);
  193. }