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.

455 lines
12 KiB

  1. //
  2. // REGQVAL.C
  3. //
  4. // Copyright (C) Microsoft Corporation, 1995
  5. //
  6. // Implementation of RegQueryValue, RegQueryValueEx and supporting functions.
  7. //
  8. #include "pch.h"
  9. //
  10. // RgLookupValueByName
  11. // (BIGKEY aware)
  12. //
  13. // Searches for the value with the specified name and returns a pointer to its
  14. // KEY_RECORD and VALUE_RECORD.
  15. //
  16. // This locks the datablock associated with the KEY_RECORD and VALUE_RECORD.
  17. // This is always hKey->BigKeyLockedBlockIndex
  18. // It is the callers responsibility to unlock the datablock.
  19. //
  20. int
  21. INTERNAL
  22. RgLookupValueByName(
  23. HKEY hKey,
  24. LPCSTR lpValueName,
  25. LPKEY_RECORD FAR* lplpKeyRecord,
  26. LPVALUE_RECORD FAR* lplpValueRecord
  27. )
  28. {
  29. int ErrorCode;
  30. HKEY hKeyExtent;
  31. UINT Index;
  32. LPSTR ExtentKeyName;
  33. DWORD cbExtentKeyName;
  34. hKey-> BigKeyLockedBlockIndex = hKey-> BlockIndex;
  35. ErrorCode = RgLookupValueByNameStd(hKey, lpValueName, lplpKeyRecord, lplpValueRecord);
  36. // If this is a big key and we couldn't find it in the first key extent, then
  37. // try the remaining extents.
  38. if (ErrorCode == ERROR_CANTREAD16_FILENOTFOUND32 && (hKey->Flags & KEYF_BIGKEYROOT)) {
  39. if (IsNullPtr(ExtentKeyName = RgSmAllocMemory(MAXIMUM_SUB_KEY_LENGTH)))
  40. return ERROR_OUTOFMEMORY;
  41. Index = 0;
  42. do {
  43. cbExtentKeyName = MAXIMUM_SUB_KEY_LENGTH;
  44. if (RgLookupKeyByIndex(hKey, Index++, ExtentKeyName, &cbExtentKeyName, LK_BIGKEYEXT) != ERROR_SUCCESS) {
  45. ErrorCode = ERROR_CANTREAD16_FILENOTFOUND32;
  46. goto lFreeKeyName;
  47. }
  48. if (RgLookupKey(hKey, ExtentKeyName, &hKeyExtent, LK_OPEN | LK_BIGKEYEXT) != ERROR_SUCCESS) {
  49. ErrorCode = ERROR_CANTREAD16_FILENOTFOUND32;
  50. goto lFreeKeyName;
  51. }
  52. hKey-> BigKeyLockedBlockIndex = hKeyExtent-> BlockIndex;
  53. ErrorCode = RgLookupValueByNameStd(hKeyExtent, lpValueName,
  54. lplpKeyRecord, lplpValueRecord);
  55. RgDestroyKeyHandle(hKeyExtent);
  56. } while (ErrorCode == ERROR_CANTREAD16_FILENOTFOUND32);
  57. lFreeKeyName:
  58. RgSmFreeMemory(ExtentKeyName);
  59. }
  60. return ErrorCode;
  61. }
  62. //
  63. // RgLookupValueByNameStd
  64. //
  65. // Searches for the value with the specified name and returns a pointer to its
  66. // KEY_RECORD and VALUE_RECORD.
  67. //
  68. // This locks the datablock associated with the KEY_RECORD and VALUE_RECORD.
  69. // This is always hKey->BlockIndex.
  70. // It is the callers responsibility to unlock the datablock.
  71. //
  72. int
  73. INTERNAL
  74. RgLookupValueByNameStd(
  75. HKEY hKey,
  76. LPCSTR lpValueName,
  77. LPKEY_RECORD FAR* lplpKeyRecord,
  78. LPVALUE_RECORD FAR* lplpValueRecord
  79. )
  80. {
  81. int ErrorCode;
  82. LPKEY_RECORD lpKeyRecord;
  83. UINT ValueNameLength;
  84. LPVALUE_RECORD lpValueRecord;
  85. UINT ValuesRemaining;
  86. // Handle Win95 registries that don't have a key record for the root key.
  87. if (IsNullBlockIndex(hKey-> BlockIndex))
  88. return ERROR_CANTREAD16_FILENOTFOUND32;
  89. if ((ErrorCode = RgLockKeyRecord(hKey-> lpFileInfo, hKey-> BlockIndex,
  90. hKey-> KeyRecordIndex, &lpKeyRecord)) == ERROR_SUCCESS) {
  91. ValueNameLength = (IsNullPtr(lpValueName) ? 0 : (UINT)
  92. StrLen(lpValueName));
  93. lpValueRecord = (LPVALUE_RECORD) ((LPBYTE) &lpKeyRecord-> Name +
  94. lpKeyRecord-> NameLength + lpKeyRecord-> ClassLength);
  95. ValuesRemaining = lpKeyRecord-> ValueCount;
  96. // Should probably do more sanity checking on lpValueRecord
  97. while (ValuesRemaining) {
  98. if (lpValueRecord-> NameLength == ValueNameLength &&
  99. (ValueNameLength == 0 || RgStrCmpNI(lpValueName, lpValueRecord->
  100. Name, ValueNameLength) == 0)) {
  101. *lplpKeyRecord = lpKeyRecord;
  102. *lplpValueRecord = lpValueRecord;
  103. return ERROR_SUCCESS;
  104. }
  105. lpValueRecord = (LPVALUE_RECORD) ((LPBYTE) &lpValueRecord->
  106. Name + lpValueRecord-> NameLength + lpValueRecord->
  107. DataLength);
  108. ValuesRemaining--;
  109. }
  110. RgUnlockDatablock(hKey-> lpFileInfo, hKey-> BlockIndex, FALSE);
  111. ErrorCode = ERROR_CANTREAD16_FILENOTFOUND32;
  112. }
  113. return ErrorCode;
  114. }
  115. //
  116. // RgCopyFromValueRecord
  117. //
  118. // Shared routine for RegQueryValue and RegEnumValue. Copies the information
  119. // from the VALUE_RECORD to the user-provided buffers. All parameters should
  120. // have already been validated.
  121. //
  122. // Because all parameters have been validated, if lpData is valid, then
  123. // lpcbData MUST be valid.
  124. //
  125. int
  126. INTERNAL
  127. RgCopyFromValueRecord(
  128. HKEY hKey,
  129. LPVALUE_RECORD lpValueRecord,
  130. LPSTR lpValueName,
  131. LPDWORD lpcbValueName,
  132. LPDWORD lpType,
  133. LPBYTE lpData,
  134. LPDWORD lpcbData
  135. )
  136. {
  137. int ErrorCode;
  138. UINT BytesToTransfer;
  139. #ifdef WANT_DYNKEY_SUPPORT
  140. PINTERNAL_PROVIDER pProvider;
  141. PPVALUE pProviderValue;
  142. struct val_context ValueContext;
  143. #endif
  144. #ifdef WANT_DYNKEY_SUPPORT
  145. if (IsDynDataKey(hKey)) {
  146. pProvider = hKey-> pProvider;
  147. if (IsNullPtr(pProvider))
  148. return ERROR_CANTOPEN;
  149. // The value data contains only part of a PROVIDER structure.
  150. pProviderValue = CONTAINING_RECORD(&lpValueRecord-> Name +
  151. lpValueRecord-> NameLength, PVALUE, pv_valuelen);
  152. if (!IsNullPtr(lpType))
  153. *lpType = pProviderValue-> pv_type;
  154. if (!(hKey-> Flags & KEYF_PROVIDERHASVALUELENGTH)) {
  155. BytesToTransfer = pProviderValue-> pv_valuelen;
  156. if (IsNullPtr(lpData))
  157. goto ValueDataNotNeeded;
  158. if (BytesToTransfer > *lpcbData) {
  159. *lpcbData = BytesToTransfer;
  160. return ERROR_MORE_DATA;
  161. }
  162. // Win95 compatibility: now that we know the required number of
  163. // bytes, validate the data buffer.
  164. if (IsBadHugeWritePtr(lpData, BytesToTransfer))
  165. return ERROR_INVALID_PARAMETER;
  166. }
  167. ValueContext.value_context = pProviderValue-> pv_value_context;
  168. if (!IsNullPtr(lpcbData)) {
  169. // Zero *lpcbData, if we aren't actually copying any data back to
  170. // the user's buffer. This keeps some providers from stomping on
  171. // lpData.
  172. if (IsNullPtr(lpData))
  173. *lpcbData = 0;
  174. if ((ErrorCode = (int) pProvider-> ipi_R0_1val(pProvider->
  175. ipi_key_context, &ValueContext, 1, lpData, lpcbData, 0)) !=
  176. ERROR_SUCCESS) {
  177. // Win95 compatibility: the old code ignored any errors if
  178. // lpData is NULL. The below ASSERT will verify that we aren't
  179. // dropping errors.
  180. if (!IsNullPtr(lpData))
  181. return ErrorCode;
  182. ASSERT((ErrorCode == ERROR_SUCCESS) || (ErrorCode ==
  183. ERROR_MORE_DATA));
  184. }
  185. }
  186. goto CopyValueName;
  187. }
  188. #endif
  189. if (!IsNullPtr(lpType))
  190. *lpType = lpValueRecord-> DataType;
  191. BytesToTransfer = lpValueRecord-> DataLength;
  192. // The terminating null is not stored in the value record.
  193. if (lpValueRecord-> DataType == REG_SZ)
  194. BytesToTransfer++;
  195. //
  196. // Win32 compatibilty: lpData must be filled in before lpValueName. Word
  197. // NT and Excel NT broke when we validated lpValueName and failed the call
  198. // before filling in lpData which was valid. Don't rearrange this code!
  199. //
  200. if (!IsNullPtr(lpData)) {
  201. ErrorCode = ERROR_SUCCESS;
  202. if (BytesToTransfer > *lpcbData) {
  203. *lpcbData = BytesToTransfer;
  204. return ERROR_MORE_DATA;
  205. }
  206. // Win95 compatibility: now that we know the required number of bytes,
  207. // validate the data buffer.
  208. else if (IsBadHugeWritePtr(lpData, BytesToTransfer))
  209. return ERROR_INVALID_PARAMETER;
  210. else {
  211. MoveMemory(lpData, &lpValueRecord-> Name + lpValueRecord->
  212. NameLength, lpValueRecord-> DataLength);
  213. if (lpValueRecord-> DataType == REG_SZ)
  214. lpData[lpValueRecord-> DataLength] = '\0';
  215. }
  216. }
  217. #ifdef WANT_DYNKEY_SUPPORT
  218. ValueDataNotNeeded:
  219. #endif
  220. if (!IsNullPtr(lpcbData))
  221. *lpcbData = BytesToTransfer;
  222. #ifdef WANT_DYNKEY_SUPPORT
  223. CopyValueName:
  224. #endif
  225. if (!IsNullPtr(lpValueName)) {
  226. ErrorCode = ERROR_SUCCESS;
  227. if (*lpcbValueName <= lpValueRecord-> NameLength) {
  228. // Although we will not touch the lpData buffer if it's too small
  229. // to hold the value data, we will partially fill lpValueName if
  230. // it's too small.
  231. ErrorCode = ERROR_MORE_DATA;
  232. if (*lpcbValueName == 0)
  233. return ErrorCode;
  234. BytesToTransfer = (UINT) *lpcbValueName - 1;
  235. }
  236. else
  237. BytesToTransfer = lpValueRecord-> NameLength;
  238. MoveMemory(lpValueName, &lpValueRecord-> Name, BytesToTransfer);
  239. lpValueName[BytesToTransfer] = '\0';
  240. // Does not include terminating null.
  241. *lpcbValueName = BytesToTransfer;
  242. return ErrorCode;
  243. }
  244. return ERROR_SUCCESS;
  245. }
  246. //
  247. // VMMRegQueryValueEx
  248. //
  249. // See Win32 documentation of RegQueryValueEx.
  250. //
  251. LONG
  252. REGAPI
  253. VMMRegQueryValueEx(
  254. HKEY hKey,
  255. LPCSTR lpValueName,
  256. LPDWORD lpReserved,
  257. LPDWORD lpType,
  258. LPBYTE lpData,
  259. LPDWORD lpcbData
  260. )
  261. {
  262. int ErrorCode;
  263. LPKEY_RECORD lpKeyRecord;
  264. LPVALUE_RECORD lpValueRecord;
  265. if (IsBadOptionalStringPtr(lpValueName, (UINT) -1))
  266. return ERROR_INVALID_PARAMETER;
  267. if (IsBadHugeOptionalWritePtr(lpType, sizeof(DWORD)))
  268. return ERROR_INVALID_PARAMETER;
  269. if (!IsNullPtr(lpType))
  270. *lpType = 0; // assume unknown data type
  271. if (IsNullPtr(lpcbData)) {
  272. if (!IsNullPtr(lpData))
  273. return ERROR_INVALID_PARAMETER;
  274. }
  275. else {
  276. // Win95 compatibility: don't validate lpData is of size *lpcbData.
  277. // Instead of validating the entire buffer, we'll validate just the
  278. // required buffer length in RgCopyFromValueRecord.
  279. if (IsBadHugeWritePtr(lpcbData, sizeof(DWORD)))
  280. return ERROR_INVALID_PARAMETER;
  281. }
  282. if (!RgLockRegistry())
  283. return ERROR_LOCK_FAILED;
  284. if ((ErrorCode = RgValidateAndConvertKeyHandle(&hKey)) == ERROR_SUCCESS) {
  285. if ((ErrorCode = RgLookupValueByName(hKey, lpValueName, &lpKeyRecord,
  286. &lpValueRecord)) == ERROR_SUCCESS) {
  287. ErrorCode = RgCopyFromValueRecord(hKey, lpValueRecord, NULL, NULL,
  288. lpType, lpData, lpcbData);
  289. RgUnlockDatablock(hKey-> lpFileInfo, hKey-> BigKeyLockedBlockIndex, FALSE);
  290. }
  291. else if (ErrorCode == ERROR_CANTREAD16_FILENOTFOUND32) {
  292. //
  293. // Windows 95 compatibility problem. If the "value
  294. // record" didn't exist in Windows 3.1, then it acted like it was
  295. // really a null byte REG_SZ string. This should have only been
  296. // done in RegQueryValue, but we're stuck with it now...
  297. //
  298. if (IsNullPtr(lpValueName) || *lpValueName == '\0') {
  299. if (!IsNullPtr(lpType))
  300. *lpType = REG_SZ;
  301. if (!IsNullPtr(lpData) && *lpcbData > 0)
  302. *lpData = 0;
  303. if (!IsNullPtr(lpcbData))
  304. *lpcbData = sizeof(char);
  305. ErrorCode = ERROR_SUCCESS;
  306. }
  307. }
  308. }
  309. RgUnlockRegistry();
  310. return ErrorCode;
  311. UNREFERENCED_PARAMETER(lpReserved);
  312. }
  313. //
  314. // VMMRegQueryValue
  315. //
  316. // See Win32 documentation of RegQueryValue.
  317. //
  318. LONG
  319. REGAPI
  320. VMMRegQueryValue(
  321. HKEY hKey,
  322. LPCSTR lpSubKey,
  323. LPBYTE lpData,
  324. LPDWORD lpcbData
  325. )
  326. {
  327. LONG ErrorCode;
  328. HKEY hSubKey;
  329. if ((ErrorCode = RgCreateOrOpenKey(hKey, lpSubKey, &hSubKey, LK_OPEN)) ==
  330. ERROR_SUCCESS) {
  331. ErrorCode = VMMRegQueryValueEx(hSubKey, NULL, NULL, NULL, lpData,
  332. lpcbData);
  333. VMMRegCloseKey(hSubKey);
  334. }
  335. return ErrorCode;
  336. }