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.

512 lines
16 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. Regeval.c
  5. Abstract:
  6. This module contains the server side implementation for the Win32
  7. Registry API to enumerate values. That is:
  8. - BaseRegEnumValue
  9. Author:
  10. David J. Gilman (davegi) 23-Dec-1991
  11. Notes:
  12. See the Notes in Regkey.c.
  13. --*/
  14. #include <rpc.h>
  15. #include "regrpc.h"
  16. #include "localreg.h"
  17. #include "regclass.h"
  18. #include "regvcls.h"
  19. #define DEFAULT_VALUE_SIZE 128
  20. #define DEFAULT_VALUE_NAME_SIZE 64
  21. error_status_t
  22. BaseRegEnumValue(
  23. IN HKEY hKey,
  24. IN DWORD dwIndex,
  25. OUT PUNICODE_STRING lpValueName,
  26. OUT LPDWORD lpType OPTIONAL,
  27. OUT LPBYTE lpData OPTIONAL,
  28. IN OUT LPDWORD lpcbData OPTIONAL,
  29. IN OUT LPDWORD lpcbLen OPTIONAL
  30. )
  31. /*++
  32. Routine Description:
  33. Used to enumerate the ValueNames of an open key. This function copies
  34. the dwIndex-th ValueName of hKey. This function is guaranteed to
  35. operate correctly only if dwIndex starts at 0 and is incremented on
  36. successive calls without intervening calls to other registration APIs
  37. that will change the key. The ValueName (only the ValueName, not the
  38. full path) is copied to lpBuffer. The size of lpBuffer is specified
  39. by dwBufferSize.
  40. Arguments:
  41. hKey - A handle to the open key. The value entries returned are
  42. contained in the key pointed to by this key handle. Any of the
  43. predefined reserved handles or a previously opened key handle may be
  44. used for hKey.
  45. dwIndex - The index of the ValueName to return. Note that this is for
  46. convenience, ValueNames are not ordered (a new ValueName has an
  47. arbitrary index). Indexes start at 0.
  48. lpValueName - Provides a pointer to a buffer to receive the name of
  49. the value (it's Id)
  50. lpType - If present, supplies pointer to variable to receive the type
  51. code of value entry.
  52. lpData - If present, provides a pointer to a buffer to receive the
  53. data of the value entry.
  54. lpcbData - Must be present if lpDatais. Provides pointer to a
  55. variable which on input contains the size of the buffer lpDatapoints
  56. to. On output, the variable will receive the number of bytes returned
  57. in lpData.
  58. lpcbLen - Return the number of bytes to transmit to the client (used
  59. by RPC).
  60. Return Value:
  61. Returns ERROR_SUCCESS (0) for success; error-code for failure.
  62. Notes:
  63. hKey must have been opened for KEY_QUERY_VALUE access.
  64. --*/
  65. {
  66. NTSTATUS Status;
  67. ULONG BufferLength;
  68. KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass;
  69. PVOID KeyValueInformation;
  70. ULONG ResultLength;
  71. BYTE PrivateKeyValueInformation[ sizeof( KEY_VALUE_FULL_INFORMATION ) +
  72. DEFAULT_VALUE_NAME_SIZE +
  73. sizeof(UNICODE_NULL) +
  74. DEFAULT_VALUE_SIZE +
  75. sizeof(UNICODE_NULL) ];
  76. HKEY hkEnum;
  77. #ifdef LOCAL
  78. ValueState* pValState;
  79. pValState = NULL;
  80. #endif // LOCAL
  81. hkEnum = hKey;
  82. //
  83. // If the client gave us a bogus size, patch it.
  84. //
  85. if ( ARGUMENT_PRESENT( lpcbData ) && !ARGUMENT_PRESENT( lpData ) ) {
  86. *lpcbData = 0;
  87. }
  88. //
  89. // Call out to Perflib if the HKEY is HKEY_PERFOMANCE_DATA.
  90. //
  91. if(( hKey == HKEY_PERFORMANCE_DATA ) ||
  92. ( hKey == HKEY_PERFORMANCE_TEXT ) ||
  93. ( hKey == HKEY_PERFORMANCE_NLSTEXT )) {
  94. return (error_status_t)PerfRegEnumValue (
  95. hKey,
  96. dwIndex,
  97. lpValueName,
  98. NULL,
  99. lpType,
  100. lpData,
  101. lpcbData,
  102. lpcbLen
  103. );
  104. }
  105. #ifdef LOCAL
  106. //
  107. // If we are in HKEY_CLASSES_ROOT, then we need to remap
  108. // the key / index pair to take into account merging
  109. //
  110. if (REG_CLASS_IS_SPECIAL_KEY(hKey)) {
  111. //
  112. // Find a key state for this key
  113. //
  114. Status = BaseRegGetClassKeyValueState(
  115. hKey,
  116. dwIndex,
  117. &pValState);
  118. if (!NT_SUCCESS(Status)) {
  119. return (error_status_t)RtlNtStatusToDosError(Status);
  120. }
  121. //
  122. // Now remap to the appropriate key / index
  123. //
  124. ValStateGetPhysicalIndexFromLogical(
  125. pValState,
  126. hKey,
  127. dwIndex,
  128. &hkEnum,
  129. &dwIndex);
  130. }
  131. #endif // LOCAL
  132. //
  133. // First we assume that the information we want will fit on
  134. // PrivateKeyValueInformattion
  135. //
  136. KeyValueInformationClass = ( ARGUMENT_PRESENT( lpcbData ))?
  137. KeyValueFullInformation :
  138. KeyValueBasicInformation;
  139. KeyValueInformation = PrivateKeyValueInformation;
  140. BufferLength = sizeof( PrivateKeyValueInformation );
  141. //
  142. // Query for the necessary information about the supplied value.
  143. //
  144. Status = NtEnumerateValueKey( hkEnum,
  145. dwIndex,
  146. KeyValueInformationClass,
  147. KeyValueInformation,
  148. BufferLength,
  149. &ResultLength
  150. );
  151. //
  152. // A return value of STATUS_BUFFER_TOO_SMALL would mean that there
  153. // was not enough room for even the known (i.e. fixed length portion)
  154. // of the structure.
  155. //
  156. ASSERT( Status != STATUS_BUFFER_TOO_SMALL );
  157. if( Status == STATUS_BUFFER_OVERFLOW ) {
  158. //
  159. // The buffer defined in the stack wasn't big enough to hold
  160. // the Value information.
  161. // If the caller's buffer are big enough to hold the value name
  162. // and value data, then allocate a new buffer, and call the
  163. // NT API again.
  164. //
  165. if( ( ( KeyValueInformationClass == KeyValueBasicInformation ) &&
  166. ( (ULONG)(lpValueName->MaximumLength) >=
  167. (( PKEY_VALUE_BASIC_INFORMATION )
  168. KeyValueInformation )->NameLength + sizeof(UNICODE_NULL)
  169. )
  170. ) ||
  171. ( ( KeyValueInformationClass == KeyValueFullInformation ) &&
  172. ( (ULONG)(lpValueName->MaximumLength) >=
  173. (( PKEY_VALUE_FULL_INFORMATION )
  174. KeyValueInformation )->NameLength + sizeof(UNICODE_NULL)
  175. ) &&
  176. ( !ARGUMENT_PRESENT( lpData ) ||
  177. ( ARGUMENT_PRESENT( lpData ) &&
  178. ARGUMENT_PRESENT( lpcbData ) &&
  179. ( *lpcbData >= (( PKEY_VALUE_FULL_INFORMATION )
  180. KeyValueInformation )->DataLength
  181. )
  182. )
  183. )
  184. )
  185. ) {
  186. BufferLength = ResultLength;
  187. KeyValueInformation = RtlAllocateHeap( RtlProcessHeap( ), 0,
  188. BufferLength
  189. );
  190. //
  191. // If the memory allocation fails, return a Registry error.
  192. //
  193. if( ! KeyValueInformation ) {
  194. #ifdef LOCAL
  195. ValStateRelease(pValState);
  196. #endif // LOCAL
  197. return ERROR_OUTOFMEMORY;
  198. }
  199. //
  200. // Query for the necessary information about the supplied value. This
  201. // may or may not include the data depending on lpcbData as determined
  202. // above.
  203. //
  204. Status = NtEnumerateValueKey( hkEnum,
  205. dwIndex,
  206. KeyValueInformationClass,
  207. KeyValueInformation,
  208. BufferLength,
  209. &ResultLength
  210. );
  211. }
  212. }
  213. #ifdef LOCAL
  214. ValStateRelease(pValState);
  215. #endif // LOCAL
  216. //
  217. // If the API succeeded, try to copy the value name to the client's buffer
  218. //
  219. if( NT_SUCCESS( Status ) ) {
  220. //
  221. // Copy value name
  222. //
  223. if( KeyValueInformationClass == KeyValueBasicInformation ) {
  224. //
  225. // Return the name length and the name of the value.
  226. // Note that the NUL byte is included so that RPC copies the
  227. // correct number of bytes. It is decremented on the client
  228. // side.
  229. //
  230. if( (ULONG)(lpValueName->MaximumLength) >=
  231. (( PKEY_VALUE_BASIC_INFORMATION )
  232. KeyValueInformation )->NameLength + sizeof( UNICODE_NULL )) {
  233. //
  234. // If client's buffer is big enough for the name,
  235. // copy the value name and NUL terminate it
  236. //
  237. lpValueName->Length = ( USHORT )
  238. (( PKEY_VALUE_BASIC_INFORMATION )
  239. KeyValueInformation )->NameLength;
  240. RtlMoveMemory( lpValueName->Buffer,
  241. (( PKEY_VALUE_BASIC_INFORMATION )
  242. KeyValueInformation )->Name,
  243. lpValueName->Length
  244. );
  245. lpValueName->Buffer[ lpValueName->Length >> 1 ] = UNICODE_NULL;
  246. //
  247. // Value name length must include size of UNICODE_NULL.
  248. // It will be decremented in the client side
  249. //
  250. lpValueName->Length += sizeof( UNICODE_NULL );
  251. } else {
  252. //
  253. // If the client's buffer for the value name is not big
  254. // enough, then set status to STATUS_BUFFER_OVERFLOW.
  255. //
  256. // Note that in the remote case, RPC will transmit garbage
  257. // in the buffer back to the client.
  258. // We cannot set the buffer to prevent this transmission,
  259. // because in the local case we would be destroying the
  260. // buffer in the &NtCurrectTeb->StaticUnicodeString.
  261. //
  262. Status = STATUS_BUFFER_OVERFLOW;
  263. }
  264. } else {
  265. //
  266. // Here if KeyValueInformation == KeyValueFullInformation
  267. //
  268. // Return the name length and the name of the value.
  269. // Note that the NUL byte is included so that RPC copies the
  270. // correct number of bytes. It is decremented on the client
  271. // side.
  272. //
  273. if( (ULONG)(lpValueName->MaximumLength) >=
  274. (( PKEY_VALUE_FULL_INFORMATION )
  275. KeyValueInformation )->NameLength + sizeof( UNICODE_NULL )) {
  276. //
  277. // If client's buffer is big enough for the name,
  278. // copy the value name and NUL terminate it
  279. //
  280. lpValueName->Length = ( USHORT )
  281. (( PKEY_VALUE_FULL_INFORMATION )
  282. KeyValueInformation )->NameLength;
  283. RtlMoveMemory( lpValueName->Buffer,
  284. (( PKEY_VALUE_FULL_INFORMATION )
  285. KeyValueInformation )->Name,
  286. lpValueName->Length
  287. );
  288. lpValueName->Buffer[ lpValueName->Length >> 1 ] = UNICODE_NULL;
  289. //
  290. // Value name length must include size of UNICODE_NULL.
  291. // It will be decremented in the client side
  292. //
  293. lpValueName->Length += sizeof( UNICODE_NULL );
  294. } else {
  295. //
  296. // If the client's buffer for the value name is not big
  297. // enough, then set status to STATUS_BUFFER_OVERFLOW.
  298. //
  299. // Note that in the remote case, RPC will transmit garbage
  300. // in the buffer back to the client.
  301. // We cannot set the buffer to prevent this transmission,
  302. // because in the local case we would be destroying the
  303. // buffer in the &NtCurrectTeb->StaticUnicodeString.
  304. //
  305. Status = STATUS_BUFFER_OVERFLOW;
  306. }
  307. }
  308. }
  309. if( NT_SUCCESS( Status ) &&
  310. ARGUMENT_PRESENT( lpData ) ) {
  311. //
  312. // If we were able to copy the value name to the client's buffer
  313. // and the value data is also requested, then try to copy it
  314. // to the client's buffer
  315. //
  316. if( *lpcbData >= (( PKEY_VALUE_FULL_INFORMATION )
  317. KeyValueInformation )->DataLength ) {
  318. //
  319. // If the buffer is big enough to hold the data, copy the data
  320. //
  321. RtlMoveMemory( lpData,
  322. ( PBYTE ) KeyValueInformation
  323. + (( PKEY_VALUE_FULL_INFORMATION )
  324. KeyValueInformation )->DataOffset,
  325. (( PKEY_VALUE_FULL_INFORMATION )
  326. KeyValueInformation )->DataLength
  327. );
  328. } else {
  329. //
  330. // If buffer is not big enough to hold the data, then return
  331. // STATUS_BUFFER_OVERFLOW.
  332. //
  333. // Note that in the remote case, RPC will transmit garbage
  334. // in the buffer back to the client.
  335. // We cannot set the buffer to prevent this transmission,
  336. // because in the local case we would be destroying the
  337. // buffer in the &NtCurrectTeb->StaticUnicodeString.
  338. //
  339. Status = STATUS_BUFFER_OVERFLOW;
  340. }
  341. }
  342. //
  343. // Certain information is returned on success or in the case of
  344. // NtEnumerateValueKey returning STATUS_BUFFER_OVERFLOW. This information
  345. // is always available because we always pass the minimum size required for
  346. // the NtEnumerateValueKey API.
  347. //
  348. if( NT_SUCCESS( Status ) ||
  349. ( Status == STATUS_BUFFER_OVERFLOW ) ) {
  350. if( KeyValueInformationClass == KeyValueBasicInformation ) {
  351. //
  352. // If requested, return the value type.
  353. //
  354. if( ARGUMENT_PRESENT( lpType )) {
  355. *lpType = (( PKEY_VALUE_BASIC_INFORMATION )
  356. KeyValueInformation )->Type;
  357. }
  358. // lpValueName->Length
  359. // = ( USHORT ) ((( PKEY_VALUE_BASIC_INFORMATION )
  360. // KeyValueInformation )->NameLength + sizeof( UNICODE_NULL ) );
  361. } else {
  362. //
  363. // Here if KeyValueInformationClass == KeyValueFullInformation
  364. //
  365. //
  366. // If requested, return the value type.
  367. //
  368. if( ARGUMENT_PRESENT( lpType )) {
  369. *lpType = (( PKEY_VALUE_FULL_INFORMATION )
  370. KeyValueInformation )->Type;
  371. }
  372. // lpValueName->Length
  373. // = ( USHORT ) ((( PKEY_VALUE_FULL_INFORMATION )
  374. // KeyValueInformation )->NameLength + sizeof( UNICODE_NULL ) );
  375. *lpcbData = (( PKEY_VALUE_FULL_INFORMATION )
  376. KeyValueInformation )->DataLength;
  377. }
  378. }
  379. //
  380. // Transmit all of the value data back to the client.
  381. //
  382. if( NT_SUCCESS( Status ) ) {
  383. if( ARGUMENT_PRESENT( lpcbLen ) &&
  384. ARGUMENT_PRESENT( lpcbData ) ) {
  385. *lpcbLen = *lpcbData;
  386. }
  387. } else {
  388. //
  389. // If something failed, don't transmit any data back to the client
  390. //
  391. if( ARGUMENT_PRESENT( lpcbLen ) ) {
  392. *lpcbLen = 0;
  393. }
  394. }
  395. //
  396. // Free memory if it was allocated
  397. //
  398. if( KeyValueInformation != PrivateKeyValueInformation ) {
  399. RtlFreeHeap( RtlProcessHeap( ), 0, KeyValueInformation );
  400. }
  401. return (error_status_t)RtlNtStatusToDosError( Status );
  402. }
  403.