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.

651 lines
16 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. Regsval.c
  5. Abstract:
  6. This module contains the client side wrappers for the Win32 Registry
  7. set value APIs. That is:
  8. - RegSetValueA
  9. - RegSetValueW
  10. - RegSetValueExA
  11. - RegSetValueExW
  12. Author:
  13. David J. Gilman (davegi) 18-Mar-1992
  14. Notes:
  15. See the notes in server\regsval.c.
  16. --*/
  17. #include <rpc.h>
  18. #include "regrpc.h"
  19. #include "client.h"
  20. #include <string.h>
  21. #include <wow64reg.h>
  22. LONG
  23. RegSetValueA (
  24. HKEY hKey,
  25. LPCSTR lpSubKey,
  26. DWORD dwType,
  27. LPCSTR lpData,
  28. DWORD cbData
  29. )
  30. /*++
  31. Routine Description:
  32. Win 3.1 ANSI RPC wrapper for setting a value.
  33. --*/
  34. {
  35. HKEY ChildKey;
  36. LONG Error;
  37. HKEY TempHandle = NULL;
  38. #if DBG
  39. if ( BreakPointOnEntry ) {
  40. DbgBreakPoint();
  41. }
  42. #endif
  43. //
  44. // Limit the capabilities associated with HKEY_PERFORMANCE_DATA.
  45. //
  46. if( hKey == HKEY_PERFORMANCE_DATA ) {
  47. return ERROR_INVALID_HANDLE;
  48. }
  49. //
  50. // Check the value type for compatability w/Win 3.1
  51. //
  52. if( (dwType != REG_SZ) || (lpData == NULL) ) {
  53. return ERROR_INVALID_PARAMETER;
  54. }
  55. hKey = MapPredefinedHandle( hKey, &TempHandle );
  56. if( hKey == NULL ) {
  57. Error = ERROR_INVALID_HANDLE;
  58. goto ExitCleanup;
  59. }
  60. //
  61. // Win3.1ism - Win 3.1 ignores the cbData parameter so it is computed
  62. // here instead as the length of the string plus the NUL character.
  63. //
  64. cbData = strlen( lpData ) + 1;
  65. //
  66. // If the sub-key is NULL or points to an empty string then the value is
  67. // set in this key (i.e. hKey) otherwise the sub-key needs to be
  68. // opened/created.
  69. //
  70. if(( lpSubKey == NULL ) || ( *lpSubKey == '\0' )) {
  71. ChildKey = hKey;
  72. } else {
  73. //
  74. // The sub-key was supplied so attempt to open/create it.
  75. //
  76. Error = RegCreateKeyExA(
  77. hKey,
  78. lpSubKey,
  79. 0,
  80. WIN31_CLASS,
  81. 0,
  82. KEY_SET_VALUE,
  83. NULL,
  84. &ChildKey,
  85. NULL
  86. );
  87. if( Error != ERROR_SUCCESS ) {
  88. goto ExitCleanup;
  89. }
  90. }
  91. //
  92. // ChildKey contains an HKEY which may be the one supplied (hKey) or
  93. // returned from RegCreateKeyA. Set the value using the special value
  94. // name NULL.
  95. //
  96. Error = RegSetValueExA(
  97. ChildKey,
  98. NULL,
  99. 0,
  100. dwType,
  101. lpData,
  102. cbData
  103. );
  104. //
  105. // If the sub key was opened, close it.
  106. //
  107. if( ChildKey != hKey ) {
  108. Error = RegCloseKey( ChildKey );
  109. ASSERT( Error == ERROR_SUCCESS );
  110. }
  111. //
  112. // Return the results of setting the value.
  113. //
  114. ExitCleanup:
  115. CLOSE_LOCAL_HANDLE(TempHandle);
  116. return Error;
  117. }
  118. LONG
  119. RegSetValueW (
  120. HKEY hKey,
  121. LPCWSTR lpSubKey,
  122. DWORD dwType,
  123. LPCWSTR lpData,
  124. DWORD cbData
  125. )
  126. /*++
  127. Routine Description:
  128. Win 3.1 Unicode RPC wrapper for setting a value.
  129. --*/
  130. {
  131. HKEY ChildKey;
  132. LONG Error;
  133. HKEY TempHandle = NULL;
  134. #if DBG
  135. if ( BreakPointOnEntry ) {
  136. DbgBreakPoint();
  137. }
  138. #endif
  139. //
  140. // Limit the capabilities associated with HKEY_PERFORMANCE_DATA.
  141. //
  142. if( hKey == HKEY_PERFORMANCE_DATA ) {
  143. return ERROR_INVALID_HANDLE;
  144. }
  145. //
  146. // Check the value type for compatability w/Win 3.1
  147. //
  148. if( (dwType != REG_SZ) || (lpData == NULL) ) {
  149. return ERROR_INVALID_PARAMETER;
  150. }
  151. hKey = MapPredefinedHandle( hKey, &TempHandle);
  152. if( hKey == NULL ) {
  153. Error = ERROR_INVALID_HANDLE;
  154. goto ExitCleanup;
  155. }
  156. //
  157. // Win3.1ism - Win 3.1 ignores the cbData parameter so it is computed
  158. // here instead as the length of the string plus the UNICODE_NUL
  159. // character.
  160. //
  161. cbData = wcslen( lpData ) * sizeof( WCHAR ) + sizeof( UNICODE_NULL );;
  162. //
  163. // If the sub-key is NULL or points to an empty string then the value is
  164. // set in this key (i.e. hKey) otherwise the sub-key needs to be
  165. // opened/created.
  166. //
  167. if(( lpSubKey == NULL ) || ( *lpSubKey == '\0' )) {
  168. ChildKey = hKey;
  169. } else {
  170. //
  171. // The sub-key was supplied attempt to open/create it.
  172. //
  173. Error = RegCreateKeyExW(
  174. hKey,
  175. lpSubKey,
  176. 0,
  177. WIN31_CLASS,
  178. 0,
  179. KEY_SET_VALUE,
  180. NULL,
  181. &ChildKey,
  182. NULL
  183. );
  184. if( Error != ERROR_SUCCESS ) {
  185. goto ExitCleanup;
  186. }
  187. }
  188. //
  189. // ChildKey contains an HKEY which may be the one supplied (hKey) or
  190. // returned from RegCreateKeyW. Set the value using the special value
  191. // name NULL.
  192. //
  193. Error = RegSetValueExW(
  194. ChildKey,
  195. NULL,
  196. 0,
  197. dwType,
  198. ( LPBYTE ) lpData,
  199. cbData
  200. );
  201. //
  202. // If the sub key was opened/created, close it.
  203. //
  204. if( ChildKey != hKey ) {
  205. RegCloseKey( ChildKey );
  206. }
  207. //
  208. // Return the results of querying the value.
  209. //
  210. ExitCleanup:
  211. CLOSE_LOCAL_HANDLE(TempHandle);
  212. return Error;
  213. }
  214. LONG
  215. APIENTRY
  216. RegSetValueExA (
  217. HKEY hKey,
  218. LPCSTR lpValueName,
  219. DWORD Reserved,
  220. DWORD dwType,
  221. CONST BYTE* lpData,
  222. DWORD cbData
  223. )
  224. /*++
  225. Routine Description:
  226. Win32 ANSI RPC wrapper for setting a value.
  227. RegSetValueExA converts the lpValueName argument to a counted Unicode
  228. string and then calls BaseRegSetValue.
  229. --*/
  230. {
  231. PUNICODE_STRING ValueName;
  232. UNICODE_STRING TempValueName;
  233. UNICODE_STRING UnicodeString;
  234. NTSTATUS Status;
  235. LPBYTE ValueData;
  236. PSTR AnsiValueBuffer;
  237. ULONG AnsiValueLength;
  238. PWSTR UnicodeValueBuffer;
  239. ULONG UnicodeValueLength;
  240. ULONG Index;
  241. LONG Error;
  242. HKEY TempHandle = NULL;
  243. #if DBG
  244. if ( BreakPointOnEntry ) {
  245. DbgBreakPoint();
  246. }
  247. #endif
  248. //
  249. // Limit the capabilities associated with HKEY_PERFORMANCE_DATA.
  250. //
  251. if( hKey == HKEY_PERFORMANCE_DATA ) {
  252. return ERROR_INVALID_HANDLE;
  253. }
  254. //
  255. // Ensure Reserved is zero to avoid future compatability problems.
  256. //
  257. if( Reserved != 0 ) {
  258. return ERROR_INVALID_PARAMETER;
  259. }
  260. hKey = MapPredefinedHandle( hKey, &TempHandle );
  261. if( hKey == NULL ) {
  262. Error = ERROR_INVALID_HANDLE;
  263. goto ExitCleanup;
  264. }
  265. //
  266. // Convert the value name to a counted Unicode string
  267. //
  268. if ( lpValueName ) {
  269. //
  270. // Convert the SubKey name to a counted Unicode
  271. //
  272. if( !RtlCreateUnicodeStringFromAsciiz(&TempValueName,lpValueName) ) {
  273. Status = STATUS_NO_MEMORY;
  274. Error = RtlNtStatusToDosError( Status );
  275. goto ExitCleanup;
  276. }
  277. ValueName = &TempValueName;
  278. //
  279. // Add the NULL to the Length, so that RPC will transmit it
  280. //
  281. ValueName->Length += sizeof( UNICODE_NULL );
  282. if( ValueName->Length == 0 ) {
  283. //
  284. // overflow in RtlCreateUnicodeStringFromAsciiz
  285. //
  286. Error = ERROR_INVALID_PARAMETER;
  287. goto ExitCleanup;
  288. }
  289. } else {
  290. //
  291. // No name was passed. Use our internal UNICODE string
  292. // and set its fields to NULL. We don't use the static
  293. // unicode string in the TEB in this case because we
  294. // can't mess with its Buffer and MaximumLength fields.
  295. //
  296. ValueName = &UnicodeString;
  297. ValueName->Length = 0;
  298. ValueName->MaximumLength = 0;
  299. ValueName->Buffer = NULL;
  300. }
  301. //
  302. // If type is one of the null terminated string types, then do the ANSI to
  303. // UNICODE translation into an allocated buffer.
  304. //
  305. ValueData = ( LPBYTE )lpData;
  306. if( (ValueData != NULL) && (dwType == REG_SZ || dwType == REG_EXPAND_SZ || dwType == REG_MULTI_SZ)) {
  307. //
  308. // Special hack to help out all the people who
  309. // believe the length of a NULL terminated string is
  310. // strlen(foo) instead of strlen(foo) + 1.
  311. //
  312. if ((cbData > 0) &&
  313. (lpData[cbData-1] != 0)) {
  314. //
  315. // Do this under an exception handler in case the last
  316. // little bit crosses a page boundary.
  317. //
  318. try {
  319. if (lpData[cbData] == 0) {
  320. cbData += 1; // increase string length to account for NULL terminator
  321. }
  322. } except (EXCEPTION_EXECUTE_HANDLER) {
  323. ; // guess they really really did not want a NULL terminator
  324. }
  325. }
  326. AnsiValueBuffer = ValueData;
  327. AnsiValueLength = cbData;
  328. UnicodeValueLength = cbData * sizeof( WCHAR );
  329. UnicodeValueBuffer = RtlAllocateHeap( RtlProcessHeap(), 0,
  330. UnicodeValueLength
  331. );
  332. if (UnicodeValueBuffer == NULL) {
  333. Error = ERROR_NOT_ENOUGH_MEMORY;
  334. } else {
  335. Status = RtlMultiByteToUnicodeN( UnicodeValueBuffer,
  336. UnicodeValueLength,
  337. &Index,
  338. AnsiValueBuffer,
  339. AnsiValueLength
  340. );
  341. if (!NT_SUCCESS( Status )) {
  342. Error = RtlNtStatusToDosError( Status );
  343. } else {
  344. ValueData = (LPBYTE)UnicodeValueBuffer;
  345. cbData = Index;
  346. Error = ERROR_SUCCESS;
  347. }
  348. }
  349. } else {
  350. Error = ERROR_SUCCESS;
  351. }
  352. if ( Error == ERROR_SUCCESS ) {
  353. //
  354. // Call the Base API, passing it the supplied parameters and the
  355. // counted Unicode strings.
  356. //
  357. if( IsLocalHandle( hKey )) {
  358. Error = (LONG)LocalBaseRegSetValue (
  359. hKey,
  360. ValueName,
  361. dwType,
  362. ValueData,
  363. cbData
  364. );
  365. #if defined(_WIN64)
  366. if ( Error == 0)
  367. Wow64RegSetKeyDirty (hKey);
  368. #endif
  369. } else {
  370. Error = (LONG)BaseRegSetValue (
  371. DereferenceRemoteHandle( hKey ),
  372. ValueName,
  373. dwType,
  374. ValueData,
  375. cbData
  376. );
  377. }
  378. }
  379. if( ValueData != lpData ) {
  380. RtlFreeHeap( RtlProcessHeap(), 0, UnicodeValueBuffer );
  381. }
  382. if ( lpValueName ) {
  383. // free the allocated unicode string
  384. RtlFreeUnicodeString( &TempValueName );
  385. }
  386. ExitCleanup:
  387. CLOSE_LOCAL_HANDLE(TempHandle);
  388. return Error;
  389. }
  390. LONG
  391. APIENTRY
  392. RegSetValueExW (
  393. HKEY hKey,
  394. LPCWSTR lpValueName,
  395. DWORD Reserved,
  396. DWORD dwType,
  397. CONST BYTE* lpData,
  398. DWORD cbData
  399. )
  400. /*++
  401. Routine Description:
  402. Win32 Unicode RPC wrapper for setting a value.
  403. RegSetValueExW converts the lpValueName argument to a counted Unicode
  404. string and then calls BaseRegSetValue.
  405. --*/
  406. {
  407. UNICODE_STRING ValueName;
  408. UNALIGNED WCHAR *String;
  409. DWORD StringLength;
  410. LONG Error;
  411. HKEY TempHandle = NULL;
  412. ULONG Length;
  413. NTSTATUS Status;
  414. #if DBG
  415. if ( BreakPointOnEntry ) {
  416. DbgBreakPoint();
  417. }
  418. #endif
  419. //
  420. // Limit the capabilities associated with HKEY_PERFORMANCE_DATA.
  421. //
  422. if( hKey == HKEY_PERFORMANCE_DATA ) {
  423. return ERROR_INVALID_HANDLE;
  424. }
  425. if ((hKey == HKEY_PERFORMANCE_TEXT) ||
  426. (hKey == HKEY_PERFORMANCE_NLSTEXT)) {
  427. return(PerfRegSetValue(hKey,
  428. ( LPWSTR )lpValueName,
  429. Reserved,
  430. dwType,
  431. ( LPBYTE )lpData,
  432. cbData));
  433. }
  434. //
  435. // Ensure Reserved is zero to avoid future compatability problems.
  436. //
  437. if( Reserved != 0 ) {
  438. return ERROR_INVALID_PARAMETER;
  439. }
  440. hKey = MapPredefinedHandle( hKey, &TempHandle );
  441. if( hKey == NULL ) {
  442. Error = ERROR_INVALID_HANDLE;
  443. goto ExitCleanup;
  444. }
  445. //
  446. // Special hack to help out all the people who
  447. // believe the length of a NULL terminated string is
  448. // strlen(foo) instead of strlen(foo) + 1.
  449. //
  450. String = (UNALIGNED WCHAR *)lpData;
  451. StringLength = cbData/sizeof(WCHAR);
  452. if( ((dwType == REG_SZ) || (dwType == REG_EXPAND_SZ) || (dwType == REG_MULTI_SZ)) &&
  453. (String != NULL) &&
  454. (StringLength > 0) &&
  455. (String[StringLength-1] != 0)) {
  456. //
  457. // Do this under an exception handler in case the last
  458. // little bit crosses a page boundary.
  459. //
  460. try {
  461. if (String[StringLength] == 0) {
  462. cbData += sizeof(WCHAR); // increase string length to account for NULL terminator
  463. }
  464. } except (EXCEPTION_EXECUTE_HANDLER) {
  465. ; // guess they really really did not want a NULL terminator
  466. }
  467. }
  468. if( lpValueName != NULL ) {
  469. Length = wcslen( lpValueName ) * sizeof( WCHAR );
  470. ValueName.Length = (USHORT)Length;
  471. if( Length != (ULONG)ValueName.Length ) {
  472. //
  473. // 32K overflow
  474. //
  475. Error = ERROR_INVALID_PARAMETER;
  476. goto ExitCleanup;
  477. }
  478. }
  479. //
  480. // Convert the value name to a counted Unicode string.
  481. // This also acounts for the NULL we are adding at the end
  482. //
  483. Status = RtlInitUnicodeStringEx(&ValueName, lpValueName);
  484. if( !NT_SUCCESS(Status) ) {
  485. Error = RtlNtStatusToDosError( Status );
  486. goto ExitCleanup;
  487. }
  488. //
  489. // Add the NULL to the Length, so that RPC will transmit it
  490. //
  491. ValueName.Length += sizeof( UNICODE_NULL );
  492. //
  493. // Call the Base API, passing it the supplied parameters and the
  494. // counted Unicode strings.
  495. //
  496. if( IsLocalHandle( hKey )) {
  497. Error = (LONG)LocalBaseRegSetValue (
  498. hKey,
  499. &ValueName,
  500. dwType,
  501. ( LPBYTE )lpData,
  502. cbData
  503. );
  504. #if defined(_WIN64)
  505. if ( Error == 0)
  506. Wow64RegSetKeyDirty (hKey);
  507. #endif
  508. } else {
  509. Error = (LONG)BaseRegSetValue (
  510. DereferenceRemoteHandle( hKey ),
  511. &ValueName,
  512. dwType,
  513. ( LPBYTE )lpData,
  514. cbData
  515. );
  516. }
  517. ExitCleanup:
  518. CLOSE_LOCAL_HANDLE(TempHandle);
  519. return Error;
  520. }