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.

275 lines
6.5 KiB

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