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.

480 lines
9.7 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. Regekey.c
  5. Abstract:
  6. This module contains the client side wrappers for the Win32 Registry
  7. enumerate key APIs. That is:
  8. - RegEnumKeyA
  9. - RegEnumKeyW
  10. - RegEnumKeyExA
  11. - RegEnumKeyExW
  12. Author:
  13. David J. Gilman (davegi) 18-Mar-1992
  14. Notes:
  15. See the notes in server\regekey.c.
  16. --*/
  17. #include <rpc.h>
  18. #include "regrpc.h"
  19. #include "client.h"
  20. LONG
  21. APIENTRY
  22. RegEnumKeyA (
  23. HKEY hKey,
  24. DWORD dwIndex,
  25. LPSTR lpName,
  26. DWORD cbName
  27. )
  28. /*++
  29. Routine Description:
  30. Win 3.1 ANSI RPC wrapper for enumerating keys.
  31. --*/
  32. {
  33. #if DBG
  34. if ( BreakPointOnEntry ) {
  35. DbgBreakPoint();
  36. }
  37. #endif
  38. //
  39. // Limit the capabilities associated with HKEY_PERFORMANCE_DATA.
  40. //
  41. if( hKey == HKEY_PERFORMANCE_DATA ) {
  42. return ERROR_INVALID_HANDLE;
  43. }
  44. return RegEnumKeyExA (
  45. hKey,
  46. dwIndex,
  47. lpName,
  48. &cbName,
  49. NULL,
  50. NULL,
  51. NULL,
  52. NULL
  53. );
  54. }
  55. LONG
  56. APIENTRY
  57. RegEnumKeyW (
  58. HKEY hKey,
  59. DWORD dwIndex,
  60. LPWSTR lpName,
  61. DWORD cbName
  62. )
  63. /*++
  64. Routine Description:
  65. Win 3.1 Unicode RPC wrapper for enumerating keys.
  66. --*/
  67. {
  68. #if DBG
  69. if ( BreakPointOnEntry ) {
  70. DbgBreakPoint();
  71. }
  72. #endif
  73. //
  74. // Limit the capabilities associated with HKEY_PERFORMANCE_DATA.
  75. //
  76. if( hKey == HKEY_PERFORMANCE_DATA ) {
  77. return ERROR_INVALID_HANDLE;
  78. }
  79. return RegEnumKeyExW (
  80. hKey,
  81. dwIndex,
  82. lpName,
  83. &cbName,
  84. NULL,
  85. NULL,
  86. NULL,
  87. NULL
  88. );
  89. }
  90. LONG
  91. APIENTRY
  92. RegEnumKeyExA (
  93. HKEY hKey,
  94. DWORD dwIndex,
  95. LPSTR lpName,
  96. LPDWORD lpcbName,
  97. LPDWORD lpReserved,
  98. LPSTR lpClass,
  99. LPDWORD lpcbClass,
  100. PFILETIME lpftLastWriteTime
  101. )
  102. /*++
  103. Routine Description:
  104. Win32 ANSI API for enumerating keys.
  105. --*/
  106. {
  107. UNICODE_STRING Name;
  108. UNICODE_STRING Class;
  109. WCHAR ClassBuffer[ MAX_PATH ];
  110. PUNICODE_STRING ClassPointer;
  111. ANSI_STRING AnsiString;
  112. NTSTATUS Status;
  113. LONG Error = ERROR_SUCCESS;
  114. HKEY TempHandle = NULL;
  115. #if DBG
  116. if ( BreakPointOnEntry ) {
  117. DbgBreakPoint();
  118. }
  119. #endif
  120. //
  121. // Validate dependency between lpClass and lpcbClass parameters.
  122. //
  123. if( ARGUMENT_PRESENT( lpReserved ) ||
  124. (ARGUMENT_PRESENT( lpClass ) && ( ! ARGUMENT_PRESENT( lpcbClass )))) {
  125. return ERROR_INVALID_PARAMETER;
  126. }
  127. hKey = MapPredefinedHandle( hKey,&TempHandle );
  128. if( hKey == NULL ) {
  129. Error = ERROR_INVALID_HANDLE;
  130. goto ExitCleanup;
  131. }
  132. //
  133. // Allocate temporary buffer for the Name
  134. //
  135. Name.Length = 0;
  136. Name.MaximumLength = (USHORT)((*lpcbName + 1) * sizeof( WCHAR ));
  137. Name.Buffer = RtlAllocateHeap( RtlProcessHeap(), 0, Name.MaximumLength );
  138. if( Name.Buffer == NULL ) {
  139. Error = ERROR_NOT_ENOUGH_MEMORY;
  140. goto ExitCleanup;
  141. }
  142. //
  143. // If the class string is to be returned, initialize a UNICODE_STRING
  144. //
  145. ClassPointer = &Class;
  146. ClassPointer->Length = 0;
  147. if( ARGUMENT_PRESENT( lpClass )) {
  148. ClassPointer->MaximumLength = MAX_PATH;
  149. ClassPointer->Buffer = ( PVOID ) ClassBuffer;
  150. } else {
  151. ClassPointer->MaximumLength = 0;
  152. ClassPointer->Buffer = NULL;
  153. }
  154. //
  155. // Call the Base API passing it a pointer to the counted Unicode
  156. // strings for the name and class.
  157. //
  158. if( IsLocalHandle( hKey )) {
  159. Error = (LONG)LocalBaseRegEnumKey (
  160. hKey,
  161. dwIndex,
  162. &Name,
  163. ClassPointer,
  164. lpftLastWriteTime
  165. );
  166. } else {
  167. Error = (LONG)BaseRegEnumKey (
  168. DereferenceRemoteHandle( hKey ),
  169. dwIndex,
  170. &Name,
  171. ClassPointer,
  172. lpftLastWriteTime
  173. );
  174. }
  175. //
  176. // If the information was not succesfully queried return the error.
  177. //
  178. if( Error != ERROR_SUCCESS ) {
  179. // free allocated buffer
  180. RtlFreeHeap( RtlProcessHeap(), 0, Name.Buffer );
  181. goto ExitCleanup;
  182. }
  183. //
  184. // Subtact the NULL from Length, which was added by the server
  185. // so that RPC would transmit it.
  186. //
  187. Name.Length -= sizeof( UNICODE_NULL );
  188. if ( ClassPointer->Length > 0 ) {
  189. ClassPointer->Length -= sizeof( UNICODE_NULL );
  190. }
  191. //
  192. // Convert the name to ANSI.
  193. //
  194. // If somebody passed in a really big buffer, pretend it's
  195. // not quite so big so that it doesn't get truncated to zero.
  196. //
  197. if (*lpcbName > 0xFFFF) {
  198. AnsiString.MaximumLength = ( USHORT ) 0xFFFF;
  199. } else {
  200. AnsiString.MaximumLength = ( USHORT ) *lpcbName;
  201. }
  202. AnsiString.Buffer = lpName;
  203. Status = RtlUnicodeStringToAnsiString(
  204. &AnsiString,
  205. &Name,
  206. FALSE
  207. );
  208. // free allocated buffer
  209. RtlFreeHeap( RtlProcessHeap(), 0, Name.Buffer );
  210. //
  211. // If the name conversion failed, map and return the error.
  212. //
  213. if( ! NT_SUCCESS( Status )) {
  214. Error = RtlNtStatusToDosError( Status );
  215. goto ExitCleanup;
  216. }
  217. //
  218. // Update the name length return parameter.
  219. //
  220. *lpcbName = AnsiString.Length;
  221. //
  222. // If requested, convert the class to ANSI.
  223. //
  224. if( ARGUMENT_PRESENT( lpClass )) {
  225. AnsiString.MaximumLength = ( USHORT ) *lpcbClass;
  226. AnsiString.Buffer = lpClass;
  227. Status = RtlUnicodeStringToAnsiString(
  228. &AnsiString,
  229. ClassPointer,
  230. FALSE
  231. );
  232. //
  233. // If the class conversion failed, map and return the error.
  234. //
  235. if( ! NT_SUCCESS( Status )) {
  236. Error = RtlNtStatusToDosError( Status );
  237. goto ExitCleanup;
  238. }
  239. //
  240. // If requested, return the class length parameter w/o the NUL.
  241. //
  242. if( ARGUMENT_PRESENT( lpcbClass )) {
  243. *lpcbClass = AnsiString.Length;
  244. }
  245. //
  246. // It is possible to ask for the size of the class w/o asking for the
  247. // class itself.
  248. //
  249. } else if( ARGUMENT_PRESENT( lpcbClass )) {
  250. *lpcbClass = ( ClassPointer->Length >> 1 );
  251. }
  252. ExitCleanup:
  253. CLOSE_LOCAL_HANDLE(TempHandle);
  254. return Error;
  255. }
  256. LONG
  257. APIENTRY
  258. RegEnumKeyExW (
  259. HKEY hKey,
  260. DWORD dwIndex,
  261. LPWSTR lpName,
  262. LPDWORD lpcbName,
  263. LPDWORD lpReserved,
  264. LPWSTR lpClass,
  265. LPDWORD lpcbClass,
  266. PFILETIME lpftLastWriteTime
  267. )
  268. /*++
  269. Routine Description:
  270. Win32 Unicode RPC wrapper for enumerating keys.
  271. --*/
  272. {
  273. LONG Error;
  274. UNICODE_STRING Name;
  275. UNICODE_STRING Class;
  276. PUNICODE_STRING ClassPointer;
  277. HKEY TempHandle = NULL;
  278. #if DBG
  279. if ( BreakPointOnEntry ) {
  280. DbgBreakPoint();
  281. }
  282. #endif
  283. //
  284. // Validate dependency between lpClass and lpcbClass parameters.
  285. //
  286. if( ARGUMENT_PRESENT( lpReserved ) ||
  287. (ARGUMENT_PRESENT( lpClass ) && ( ! ARGUMENT_PRESENT( lpcbClass )))) {
  288. return ERROR_INVALID_PARAMETER;
  289. }
  290. hKey = MapPredefinedHandle( hKey, &TempHandle );
  291. if( hKey == NULL ) {
  292. Error = ERROR_INVALID_HANDLE;
  293. goto ExitCleanup;
  294. }
  295. //
  296. // Use the supplied name string buffer as the buffer in a counted
  297. // Unicode string.
  298. //
  299. Name.Length = 0;
  300. if ((*lpcbName << 1) > 0xFFFE) {
  301. Name.MaximumLength = ( USHORT ) 0xFFFE;
  302. } else {
  303. Name.MaximumLength = ( USHORT )( *lpcbName << 1 );
  304. }
  305. Name.Buffer = lpName;
  306. //
  307. // If supplied use the supplied name string buffer as the buffer in a
  308. // counted Unicode string.
  309. //
  310. ClassPointer = &Class;
  311. if( ARGUMENT_PRESENT( lpClass )) {
  312. Class.Length = 0;
  313. Class.MaximumLength = ( USHORT )( *lpcbClass << 1 );
  314. Class.Buffer = lpClass;
  315. } else {
  316. Class.Length = 0;
  317. Class.MaximumLength = 0;
  318. Class.Buffer = NULL;
  319. }
  320. //
  321. // Call the Base API passing it a pointer to the counted Unicode
  322. // strings for the name and class and return the results.
  323. //
  324. if( IsLocalHandle( hKey )) {
  325. Error = (LONG)LocalBaseRegEnumKey (
  326. hKey,
  327. dwIndex,
  328. &Name,
  329. ClassPointer,
  330. lpftLastWriteTime
  331. );
  332. } else {
  333. Error = (LONG)BaseRegEnumKey (
  334. DereferenceRemoteHandle( hKey ),
  335. dwIndex,
  336. &Name,
  337. ClassPointer,
  338. lpftLastWriteTime
  339. );
  340. }
  341. //
  342. // Subtact the NULL from Length, which was added by the server
  343. // so that RPC would transmit it.
  344. //
  345. if ( Name.Length > 0 ) {
  346. Name.Length -= sizeof( UNICODE_NULL );
  347. }
  348. if ( ClassPointer->Length > 0 ) {
  349. ClassPointer->Length -= sizeof( UNICODE_NULL );
  350. }
  351. //
  352. // Return the name length parameter w/o the NUL.
  353. //
  354. if( Error == ERROR_SUCCESS ) {
  355. *lpcbName = ( Name.Length >> 1 );
  356. }
  357. //
  358. // If requested, return the class length parameter w/o the NUL.
  359. //
  360. if( ARGUMENT_PRESENT( lpcbClass )) {
  361. *lpcbClass = ( Class.Length >> 1 );
  362. }
  363. ExitCleanup:
  364. CLOSE_LOCAL_HANDLE(TempHandle);
  365. return Error;
  366. }