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.

512 lines
15 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. Regqkey.c
  5. Abstract:
  6. This module contains the client side wrappers for the Win32 Registry
  7. query key APIs. That is:
  8. - RegQueryInfoKeyA
  9. - RegQueryInfoKeyW
  10. Author:
  11. David J. Gilman (davegi) 18-Mar-1992
  12. Notes:
  13. See the notes in server\regqkey.c.
  14. --*/
  15. #include <rpc.h>
  16. #include "regrpc.h"
  17. #include "client.h"
  18. LONG
  19. RegQueryInfoKeyA (
  20. HKEY hKey,
  21. LPSTR lpClass,
  22. LPDWORD lpcbClass,
  23. LPDWORD lpReserved,
  24. LPDWORD lpcSubKeys,
  25. LPDWORD lpcbMaxSubKeyLen,
  26. LPDWORD lpcbMaxClassLen,
  27. LPDWORD lpcValues,
  28. LPDWORD lpcbMaxValueNameLen,
  29. LPDWORD lpcbMaxValueLen,
  30. LPDWORD lpcbSecurityDescriptor,
  31. PFILETIME lpftLastWriteTime
  32. )
  33. /*++
  34. Routine Description:
  35. Win32 ANSI RPC wrapper for querying information about a previously
  36. opened key.
  37. --*/
  38. {
  39. PUNICODE_STRING Class;
  40. UNICODE_STRING UnicodeString;
  41. ANSI_STRING AnsiString;
  42. NTSTATUS Status;
  43. LONG Error;
  44. DWORD cSubKeys;
  45. DWORD cbMaxSubKeyLen;
  46. DWORD cValues;
  47. DWORD cbMaxValueNameLen;
  48. DWORD cbMaxValueLen;
  49. FILETIME ftLastWriteTime;
  50. HKEY TempHandle = NULL;
  51. DWORD cbMaxClassLen;
  52. DWORD cbSecurityDescriptor;
  53. PDWORD pCbMaxClassLen = NULL;
  54. PDWORD pCbSecurityDescriptor = NULL;
  55. #if DBG
  56. if ( BreakPointOnEntry ) {
  57. DbgBreakPoint();
  58. }
  59. #endif
  60. if( ARGUMENT_PRESENT( lpReserved ) ||
  61. (ARGUMENT_PRESENT( lpClass ) && ( ! ARGUMENT_PRESENT( lpcbClass )))) {
  62. return ERROR_INVALID_PARAMETER;
  63. }
  64. hKey = MapPredefinedHandle( hKey, &TempHandle );
  65. if( hKey == NULL ) {
  66. Error = ERROR_INVALID_HANDLE;
  67. goto ExitCleanup;
  68. }
  69. //
  70. // Make sure that the buffer size for lpClass is zero if lpClass is NULL
  71. //
  72. if( !ARGUMENT_PRESENT( lpClass ) && ARGUMENT_PRESENT( lpcbClass ) ) {
  73. *lpcbClass = 0;
  74. }
  75. if( ARGUMENT_PRESENT( lpcbMaxClassLen ) ) {
  76. pCbMaxClassLen = &cbMaxClassLen;
  77. }
  78. if( ARGUMENT_PRESENT( lpcbSecurityDescriptor ) ) {
  79. pCbSecurityDescriptor = &cbSecurityDescriptor;
  80. }
  81. //
  82. // If the count of bytes in the class is 0, pass a NULL pointer
  83. // instead of what was supplied. This ensures that RPC won't
  84. // attempt to copy data to a bogus pointer. Note that in this
  85. // case we use the unicode string allocated on the stack, because
  86. // we must not change the Buffer or MaximumLength fields of the
  87. // static unicode string in the TEB.
  88. //
  89. if ( !ARGUMENT_PRESENT( lpClass ) || *lpcbClass == 0 ) {
  90. Class = &UnicodeString;
  91. Class->Length = 0;
  92. Class->MaximumLength = 0;
  93. Class->Buffer = NULL;
  94. } else {
  95. //
  96. // Use the static Unicode string in the TEB as a temporary for the
  97. // key's class.
  98. //
  99. Class = &NtCurrentTeb( )->StaticUnicodeString;
  100. ASSERT( Class != NULL );
  101. Class->Length = 0;
  102. }
  103. //
  104. // Call the Base API passing it a pointer to a counted Unicode string
  105. // for the class string.
  106. //
  107. if( IsLocalHandle( hKey )) {
  108. Error = (LONG)LocalBaseRegQueryInfoKey(
  109. hKey,
  110. Class,
  111. &cSubKeys,
  112. &cbMaxSubKeyLen,
  113. pCbMaxClassLen,
  114. &cValues,
  115. &cbMaxValueNameLen,
  116. &cbMaxValueLen,
  117. pCbSecurityDescriptor,
  118. &ftLastWriteTime
  119. );
  120. } else {
  121. //
  122. // on RPC always send valid pointers!!!
  123. //
  124. pCbMaxClassLen = &cbMaxClassLen;
  125. pCbSecurityDescriptor = &cbSecurityDescriptor;
  126. Error = (LONG)BaseRegQueryInfoKey(
  127. DereferenceRemoteHandle( hKey ),
  128. Class,
  129. &cSubKeys,
  130. &cbMaxSubKeyLen,
  131. pCbMaxClassLen,
  132. &cValues,
  133. &cbMaxValueNameLen,
  134. &cbMaxValueLen,
  135. pCbSecurityDescriptor,
  136. &ftLastWriteTime
  137. );
  138. if (Error == ERROR_SUCCESS) {
  139. DWORD dwVersion;
  140. //
  141. // Check for a downlevel Win95 server, which requires
  142. // us to work around their BaseRegQueryInfoKey bugs.
  143. // They do not account for Unicode correctly.
  144. //
  145. if (IsWin95Server(DereferenceRemoteHandle(hKey),dwVersion)) {
  146. //
  147. // This is a Win95 server.
  148. // Double the maximum value name length and
  149. // maximum value data length to account for
  150. // the Unicode translation that Win95 forgot
  151. // to account for.
  152. //
  153. cbMaxValueNameLen *= sizeof(WCHAR);
  154. cbMaxValueLen *= sizeof(WCHAR);
  155. }
  156. }
  157. }
  158. //
  159. // MaxSubKeyLen, MaxClassLen, and MaxValueNameLen should be in
  160. // number of characters, without counting the NULL.
  161. // Note that the server side will return the number of bytes,
  162. // without counting the NUL
  163. //
  164. cbMaxSubKeyLen /= sizeof( WCHAR );
  165. if( pCbMaxClassLen != NULL ) {
  166. cbMaxClassLen /= sizeof( WCHAR );
  167. ASSERT( *pCbMaxClassLen == cbMaxClassLen );
  168. }
  169. cbMaxValueNameLen /= sizeof( WCHAR );
  170. //
  171. // Subtract the NULL from the Length. This was added on
  172. // the server side so that RPC would transmit it.
  173. //
  174. if ( Class->Length > 0 ) {
  175. Class->Length -= sizeof( UNICODE_NULL );
  176. }
  177. //
  178. // If all the information was succesfully queried from the key
  179. // convert the class name to ANSI and update the class length value.
  180. //
  181. if( ( Error == ERROR_SUCCESS ) &&
  182. ARGUMENT_PRESENT( lpClass ) && ( *lpcbClass != 0 ) ) {
  183. if (*lpcbClass > (DWORD)0xFFFF) {
  184. AnsiString.MaximumLength = ( USHORT ) 0xFFFF;
  185. } else {
  186. AnsiString.MaximumLength = ( USHORT ) *lpcbClass;
  187. }
  188. AnsiString.Buffer = lpClass;
  189. Status = RtlUnicodeStringToAnsiString(
  190. &AnsiString,
  191. Class,
  192. FALSE
  193. );
  194. ASSERTMSG( "Unicode->ANSI conversion of Class ",
  195. NT_SUCCESS( Status ));
  196. //
  197. // Update the class length return parameter.
  198. //
  199. *lpcbClass = AnsiString.Length;
  200. Error = RtlNtStatusToDosError( Status );
  201. } else {
  202. //
  203. // Not all of the information was succesfully queried, or Class
  204. // doesn't have to be converted from UNICODE to ANSI
  205. //
  206. if( ARGUMENT_PRESENT( lpcbClass ) ) {
  207. if( Class->Length == 0 ) {
  208. *lpcbClass = 0;
  209. } else {
  210. *lpcbClass = ( Class->Length >> 1 );
  211. }
  212. }
  213. }
  214. if( ARGUMENT_PRESENT( lpcSubKeys ) ) {
  215. *lpcSubKeys = cSubKeys;
  216. }
  217. if( ARGUMENT_PRESENT( lpcbMaxSubKeyLen ) ) {
  218. *lpcbMaxSubKeyLen = cbMaxSubKeyLen;
  219. }
  220. if( ARGUMENT_PRESENT( lpcbMaxClassLen ) ) {
  221. *lpcbMaxClassLen = cbMaxClassLen;
  222. ASSERT( *pCbMaxClassLen == cbMaxClassLen );
  223. }
  224. if( ARGUMENT_PRESENT( lpcValues ) ) {
  225. *lpcValues = cValues;
  226. }
  227. if( ARGUMENT_PRESENT( lpcbMaxValueNameLen ) ) {
  228. *lpcbMaxValueNameLen = cbMaxValueNameLen;
  229. }
  230. if( ARGUMENT_PRESENT( lpcbMaxValueLen ) ) {
  231. *lpcbMaxValueLen = cbMaxValueLen;
  232. }
  233. if( ARGUMENT_PRESENT( lpcbSecurityDescriptor ) ) {
  234. *lpcbSecurityDescriptor = cbSecurityDescriptor;
  235. ASSERT( *pCbSecurityDescriptor == cbSecurityDescriptor );
  236. }
  237. if( ARGUMENT_PRESENT( lpftLastWriteTime ) ) {
  238. *lpftLastWriteTime = ftLastWriteTime;
  239. }
  240. ExitCleanup:
  241. CLOSE_LOCAL_HANDLE(TempHandle);
  242. return Error;
  243. }
  244. LONG
  245. RegQueryInfoKeyW (
  246. HKEY hKey,
  247. LPWSTR lpClass,
  248. LPDWORD lpcbClass,
  249. LPDWORD lpReserved,
  250. LPDWORD lpcSubKeys,
  251. LPDWORD lpcbMaxSubKeyLen,
  252. LPDWORD lpcbMaxClassLen,
  253. LPDWORD lpcValues,
  254. LPDWORD lpcbMaxValueNameLen,
  255. LPDWORD lpcbMaxValueLen,
  256. LPDWORD lpcbSecurityDescriptor,
  257. PFILETIME lpftLastWriteTime
  258. )
  259. /*++
  260. Routine Description:
  261. Win32 Unicode RPC wrapper for querying information about a previously
  262. opened key.
  263. --*/
  264. {
  265. UNICODE_STRING Class;
  266. LONG Error;
  267. DWORD cbClass;
  268. DWORD cSubKeys;
  269. DWORD cbMaxSubKeyLen;
  270. DWORD cValues;
  271. DWORD cbMaxValueNameLen;
  272. DWORD cbMaxValueLen;
  273. FILETIME ftLastWriteTime;
  274. HKEY TempHandle = NULL;
  275. DWORD cbMaxClassLen;
  276. DWORD cbSecurityDescriptor;
  277. PDWORD pCbMaxClassLen = NULL;
  278. PDWORD pCbSecurityDescriptor = NULL;
  279. #if DBG
  280. if ( BreakPointOnEntry ) {
  281. DbgBreakPoint();
  282. }
  283. #endif
  284. if( ARGUMENT_PRESENT( lpReserved ) ||
  285. (ARGUMENT_PRESENT( lpClass ) && ( ! ARGUMENT_PRESENT( lpcbClass )))) {
  286. return ERROR_INVALID_PARAMETER;
  287. }
  288. hKey = MapPredefinedHandle( hKey, &TempHandle );
  289. if( hKey == NULL ) {
  290. Error = ERROR_INVALID_HANDLE;
  291. goto ExitCleanup;
  292. }
  293. //
  294. // Make sure that the buffer size for lpClass is zero if lpClass is NULL
  295. //
  296. if( !ARGUMENT_PRESENT( lpClass ) && ARGUMENT_PRESENT( lpcbClass ) ) {
  297. *lpcbClass = 0;
  298. }
  299. if( ARGUMENT_PRESENT( lpcbMaxClassLen ) ) {
  300. pCbMaxClassLen = &cbMaxClassLen;
  301. }
  302. if( ARGUMENT_PRESENT( lpcbSecurityDescriptor ) ) {
  303. pCbSecurityDescriptor = &cbSecurityDescriptor;
  304. }
  305. //
  306. // Use the supplied class Class buffer as the buffer in a counted
  307. // Unicode Class.
  308. //
  309. Class.Length = 0;
  310. if( ARGUMENT_PRESENT( lpcbClass ) && ( *lpcbClass != 0 ) ) {
  311. Class.MaximumLength = ( USHORT )( *lpcbClass << 1 );
  312. Class.Buffer = lpClass;
  313. } else {
  314. //
  315. // If the count of bytes in the class is 0, pass a NULL pointer
  316. // instead of what was supplied. This ensures that RPC won't
  317. // attempt to copy data to a bogus pointer.
  318. //
  319. Class.MaximumLength = 0;
  320. Class.Buffer = NULL;
  321. }
  322. //
  323. // Call the Base API.
  324. //
  325. if( IsLocalHandle( hKey )) {
  326. Error = (LONG)LocalBaseRegQueryInfoKey(
  327. hKey,
  328. &Class,
  329. &cSubKeys,
  330. &cbMaxSubKeyLen,
  331. pCbMaxClassLen,
  332. &cValues,
  333. &cbMaxValueNameLen,
  334. &cbMaxValueLen,
  335. pCbSecurityDescriptor,
  336. &ftLastWriteTime
  337. );
  338. } else {
  339. //
  340. // on RPC always send valid pointers!!!
  341. //
  342. pCbMaxClassLen = &cbMaxClassLen;
  343. pCbSecurityDescriptor = &cbSecurityDescriptor;
  344. Error = (LONG)BaseRegQueryInfoKey(
  345. DereferenceRemoteHandle( hKey ),
  346. &Class,
  347. &cSubKeys,
  348. &cbMaxSubKeyLen,
  349. pCbMaxClassLen,
  350. &cValues,
  351. &cbMaxValueNameLen,
  352. &cbMaxValueLen,
  353. pCbSecurityDescriptor,
  354. &ftLastWriteTime
  355. );
  356. if (Error == ERROR_SUCCESS) {
  357. DWORD dwVersion;
  358. //
  359. // Check for a downlevel Win95 server, which requires
  360. // us to work around their BaseRegQueryInfoKey bugs.
  361. // They do not account for Unicode correctly.
  362. //
  363. if (IsWin95Server(DereferenceRemoteHandle(hKey),dwVersion)) {
  364. //
  365. // This is a Win95 server.
  366. // Double the maximum value name length and
  367. // maximum value data length to account for
  368. // the Unicode translation that Win95 forgot
  369. // to account for.
  370. //
  371. cbMaxValueNameLen *= sizeof(WCHAR);
  372. cbMaxValueLen *= sizeof(WCHAR);
  373. }
  374. }
  375. }
  376. //
  377. // MaxSubKeyLen, MaxClassLen, and MaxValueNameLen should be in
  378. // number of characters, without counting the NULL.
  379. // Note that the server side will return the number of bytes,
  380. // without counting the NUL
  381. //
  382. cbMaxSubKeyLen /= sizeof( WCHAR );
  383. if( pCbMaxClassLen != NULL ) {
  384. cbMaxClassLen /= sizeof( WCHAR );
  385. ASSERT( *pCbMaxClassLen == cbMaxClassLen );
  386. }
  387. cbMaxValueNameLen /= sizeof( WCHAR );
  388. if( ARGUMENT_PRESENT( lpcbClass ) ) {
  389. if( Class.Length == 0 ) {
  390. *lpcbClass = 0;
  391. } else {
  392. *lpcbClass = ( Class.Length >> 1 ) - 1;
  393. }
  394. }
  395. if( ARGUMENT_PRESENT( lpcSubKeys ) ) {
  396. *lpcSubKeys = cSubKeys;
  397. }
  398. if( ARGUMENT_PRESENT( lpcbMaxSubKeyLen ) ) {
  399. *lpcbMaxSubKeyLen = cbMaxSubKeyLen;
  400. }
  401. if( ARGUMENT_PRESENT( lpcbMaxClassLen ) ) {
  402. *lpcbMaxClassLen = cbMaxClassLen;
  403. ASSERT( *pCbMaxClassLen == cbMaxClassLen );
  404. }
  405. if( ARGUMENT_PRESENT( lpcValues ) ) {
  406. *lpcValues = cValues;
  407. }
  408. if( ARGUMENT_PRESENT( lpcbMaxValueNameLen ) ) {
  409. *lpcbMaxValueNameLen = cbMaxValueNameLen;
  410. }
  411. if( ARGUMENT_PRESENT( lpcbMaxValueLen ) ) {
  412. *lpcbMaxValueLen = cbMaxValueLen;
  413. }
  414. if( ARGUMENT_PRESENT( lpcbSecurityDescriptor ) ) {
  415. *lpcbSecurityDescriptor = cbSecurityDescriptor;
  416. ASSERT( *pCbSecurityDescriptor == cbSecurityDescriptor );
  417. }
  418. if( ARGUMENT_PRESENT( lpftLastWriteTime ) ) {
  419. *lpftLastWriteTime = ftLastWriteTime;
  420. }
  421. ExitCleanup:
  422. CLOSE_LOCAL_HANDLE(TempHandle);
  423. return Error;
  424. }