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.

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