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.

483 lines
10 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. (!ARGUMENT_PRESENT( lpcbName ))
  126. ) {
  127. return ERROR_INVALID_PARAMETER;
  128. }
  129. hKey = MapPredefinedHandle( hKey,&TempHandle );
  130. if( hKey == NULL ) {
  131. Error = ERROR_INVALID_HANDLE;
  132. goto ExitCleanup;
  133. }
  134. //
  135. // Allocate temporary buffer for the Name
  136. //
  137. Name.Length = 0;
  138. Name.MaximumLength = (USHORT)((*lpcbName + 1) * sizeof( WCHAR ));
  139. Name.Buffer = RtlAllocateHeap( RtlProcessHeap(), 0, Name.MaximumLength );
  140. if( Name.Buffer == NULL ) {
  141. Error = ERROR_NOT_ENOUGH_MEMORY;
  142. goto ExitCleanup;
  143. }
  144. //
  145. // If the class string is to be returned, initialize a UNICODE_STRING
  146. //
  147. ClassPointer = &Class;
  148. ClassPointer->Length = 0;
  149. if( ARGUMENT_PRESENT( lpClass )) {
  150. ClassPointer->MaximumLength = MAX_PATH;
  151. ClassPointer->Buffer = ( PVOID ) ClassBuffer;
  152. } else {
  153. ClassPointer->MaximumLength = 0;
  154. ClassPointer->Buffer = NULL;
  155. }
  156. //
  157. // Call the Base API passing it a pointer to the counted Unicode
  158. // strings for the name and class.
  159. //
  160. if( IsLocalHandle( hKey )) {
  161. Error = (LONG)LocalBaseRegEnumKey (
  162. hKey,
  163. dwIndex,
  164. &Name,
  165. ClassPointer,
  166. lpftLastWriteTime
  167. );
  168. } else {
  169. Error = (LONG)BaseRegEnumKey (
  170. DereferenceRemoteHandle( hKey ),
  171. dwIndex,
  172. &Name,
  173. ClassPointer,
  174. lpftLastWriteTime
  175. );
  176. }
  177. //
  178. // If the information was not succesfully queried return the error.
  179. //
  180. if( Error != ERROR_SUCCESS ) {
  181. // free allocated buffer
  182. RtlFreeHeap( RtlProcessHeap(), 0, Name.Buffer );
  183. goto ExitCleanup;
  184. }
  185. //
  186. // Subtact the NULL from Length, which was added by the server
  187. // so that RPC would transmit it.
  188. //
  189. Name.Length -= sizeof( UNICODE_NULL );
  190. if ( ClassPointer->Length > 0 ) {
  191. ClassPointer->Length -= sizeof( UNICODE_NULL );
  192. }
  193. //
  194. // Convert the name to ANSI.
  195. //
  196. // If somebody passed in a really big buffer, pretend it's
  197. // not quite so big so that it doesn't get truncated to zero.
  198. //
  199. if (*lpcbName > 0xFFFF) {
  200. AnsiString.MaximumLength = ( USHORT ) 0xFFFF;
  201. } else {
  202. AnsiString.MaximumLength = ( USHORT ) *lpcbName;
  203. }
  204. AnsiString.Buffer = lpName;
  205. Status = RtlUnicodeStringToAnsiString(
  206. &AnsiString,
  207. &Name,
  208. FALSE
  209. );
  210. // free allocated buffer
  211. RtlFreeHeap( RtlProcessHeap(), 0, Name.Buffer );
  212. //
  213. // If the name conversion failed, map and return the error.
  214. //
  215. if( ! NT_SUCCESS( Status )) {
  216. Error = RtlNtStatusToDosError( Status );
  217. goto ExitCleanup;
  218. }
  219. //
  220. // Update the name length return parameter.
  221. //
  222. *lpcbName = AnsiString.Length;
  223. //
  224. // If requested, convert the class to ANSI.
  225. //
  226. if( ARGUMENT_PRESENT( lpClass )) {
  227. AnsiString.MaximumLength = ( USHORT ) *lpcbClass;
  228. AnsiString.Buffer = lpClass;
  229. Status = RtlUnicodeStringToAnsiString(
  230. &AnsiString,
  231. ClassPointer,
  232. FALSE
  233. );
  234. //
  235. // If the class conversion failed, map and return the error.
  236. //
  237. if( ! NT_SUCCESS( Status )) {
  238. Error = RtlNtStatusToDosError( Status );
  239. goto ExitCleanup;
  240. }
  241. //
  242. // If requested, return the class length parameter w/o the NUL.
  243. //
  244. if( ARGUMENT_PRESENT( lpcbClass )) {
  245. *lpcbClass = AnsiString.Length;
  246. }
  247. //
  248. // It is possible to ask for the size of the class w/o asking for the
  249. // class itself.
  250. //
  251. } else if( ARGUMENT_PRESENT( lpcbClass )) {
  252. *lpcbClass = ( ClassPointer->Length >> 1 );
  253. }
  254. ExitCleanup:
  255. CLOSE_LOCAL_HANDLE(TempHandle);
  256. return Error;
  257. }
  258. LONG
  259. APIENTRY
  260. RegEnumKeyExW (
  261. HKEY hKey,
  262. DWORD dwIndex,
  263. LPWSTR lpName,
  264. LPDWORD lpcbName,
  265. LPDWORD lpReserved,
  266. LPWSTR lpClass,
  267. LPDWORD lpcbClass,
  268. PFILETIME lpftLastWriteTime
  269. )
  270. /*++
  271. Routine Description:
  272. Win32 Unicode RPC wrapper for enumerating keys.
  273. --*/
  274. {
  275. LONG Error;
  276. UNICODE_STRING Name;
  277. UNICODE_STRING Class;
  278. PUNICODE_STRING ClassPointer;
  279. HKEY TempHandle = NULL;
  280. #if DBG
  281. if ( BreakPointOnEntry ) {
  282. DbgBreakPoint();
  283. }
  284. #endif
  285. //
  286. // Validate dependency between lpClass and lpcbClass parameters.
  287. //
  288. if( ARGUMENT_PRESENT( lpReserved ) ||
  289. (ARGUMENT_PRESENT( lpClass ) && ( ! ARGUMENT_PRESENT( lpcbClass ))) ||
  290. (!ARGUMENT_PRESENT( lpcbName ))
  291. ) {
  292. return ERROR_INVALID_PARAMETER;
  293. }
  294. hKey = MapPredefinedHandle( hKey, &TempHandle );
  295. if( hKey == NULL ) {
  296. Error = ERROR_INVALID_HANDLE;
  297. goto ExitCleanup;
  298. }
  299. //
  300. // Use the supplied name string buffer as the buffer in a counted
  301. // Unicode string.
  302. //
  303. Name.Length = 0;
  304. if ((*lpcbName << 1) > 0xFFFE) {
  305. Name.MaximumLength = ( USHORT ) 0xFFFE;
  306. } else {
  307. Name.MaximumLength = ( USHORT )( *lpcbName << 1 );
  308. }
  309. Name.Buffer = lpName;
  310. //
  311. // If supplied use the supplied name string buffer as the buffer in a
  312. // counted Unicode string.
  313. //
  314. ClassPointer = &Class;
  315. if( ARGUMENT_PRESENT( lpClass )) {
  316. Class.Length = 0;
  317. Class.MaximumLength = ( USHORT )( *lpcbClass << 1 );
  318. Class.Buffer = lpClass;
  319. } else {
  320. Class.Length = 0;
  321. Class.MaximumLength = 0;
  322. Class.Buffer = NULL;
  323. }
  324. //
  325. // Call the Base API passing it a pointer to the counted Unicode
  326. // strings for the name and class and return the results.
  327. //
  328. if( IsLocalHandle( hKey )) {
  329. Error = (LONG)LocalBaseRegEnumKey (
  330. hKey,
  331. dwIndex,
  332. &Name,
  333. ClassPointer,
  334. lpftLastWriteTime
  335. );
  336. } else {
  337. Error = (LONG)BaseRegEnumKey (
  338. DereferenceRemoteHandle( hKey ),
  339. dwIndex,
  340. &Name,
  341. ClassPointer,
  342. lpftLastWriteTime
  343. );
  344. }
  345. //
  346. // Subtact the NULL from Length, which was added by the server
  347. // so that RPC would transmit it.
  348. //
  349. if ( Name.Length > 0 ) {
  350. Name.Length -= sizeof( UNICODE_NULL );
  351. }
  352. if ( ClassPointer->Length > 0 ) {
  353. ClassPointer->Length -= sizeof( UNICODE_NULL );
  354. }
  355. //
  356. // Return the name length parameter w/o the NUL.
  357. //
  358. if( Error == ERROR_SUCCESS ) {
  359. *lpcbName = ( Name.Length >> 1 );
  360. }
  361. //
  362. // If requested, return the class length parameter w/o the NUL.
  363. //
  364. if( ARGUMENT_PRESENT( lpcbClass )) {
  365. *lpcbClass = ( Class.Length >> 1 );
  366. }
  367. ExitCleanup:
  368. CLOSE_LOCAL_HANDLE(TempHandle);
  369. return Error;
  370. }