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.

255 lines
7.9 KiB

  1. //
  2. // REGQMVAL.C
  3. //
  4. // Copyright (C) Microsoft Corporation, 1995
  5. //
  6. // Implementation of RegQueryMultipleValues and supporting functions.
  7. //
  8. #include "pch.h"
  9. #ifdef VXD
  10. #pragma VxD_RARE_CODE_SEG
  11. #endif
  12. #ifdef IS_32
  13. //
  14. // VMMRegQueryMultipleValues
  15. //
  16. // See Win32 documentation of RegQueryMultipleValues. However, the Win95
  17. // implementation breaks many of the rules that are described in the
  18. // documentation:
  19. // * num_vals is a count of VALENT structures, not a size in bytes.
  20. // * data is not DWORD aligned in lpValueBuffer.
  21. // * if lpValueBuffer is too small, lpValueBuffer is not filled to the
  22. // size specified by lpdwTotalSize.
  23. //
  24. // All of this plus dynamic keys makes this an extremely ugly routine, but
  25. // every attempt was made to be compatible with the Win95 semantics.
  26. //
  27. LONG
  28. REGAPI
  29. VMMRegQueryMultipleValues(
  30. HKEY hKey,
  31. PVALENT val_list,
  32. DWORD num_vals,
  33. LPSTR lpValueBuffer,
  34. LPDWORD lpdwTotalSize
  35. )
  36. {
  37. int ErrorCode;
  38. PVALENT pCurrentValent;
  39. DWORD Counter;
  40. DWORD BufferSize;
  41. DWORD RequiredSize;
  42. LPKEY_RECORD lpKeyRecord;
  43. LPVALUE_RECORD lpValueRecord;
  44. LPSTR lpCurrentBuffer;
  45. #ifdef WANT_DYNKEY_SUPPORT
  46. PVALCONTEXT pValueContext;
  47. PINTERNAL_PROVIDER pProvider;
  48. PPVALUE pProviderValue;
  49. #endif
  50. if (IsBadHugeReadPtr(val_list, sizeof(VALENT) * num_vals))
  51. return ERROR_INVALID_PARAMETER;
  52. if (IsBadHugeWritePtr(lpdwTotalSize, sizeof(DWORD)))
  53. return ERROR_INVALID_PARAMETER;
  54. if (IsBadHugeWritePtr(lpValueBuffer, *lpdwTotalSize))
  55. return ERROR_INVALID_PARAMETER;
  56. for (Counter = num_vals, pCurrentValent = val_list; Counter > 0; Counter--,
  57. pCurrentValent++) {
  58. if (IsBadStringPtr(pCurrentValent-> ve_valuename, (UINT) -1))
  59. return ERROR_INVALID_PARAMETER;
  60. }
  61. if (!RgLockRegistry())
  62. return ERROR_LOCK_FAILED;
  63. if ((ErrorCode = RgValidateAndConvertKeyHandle(&hKey)) != ERROR_SUCCESS)
  64. goto ReturnErrorCode;
  65. #ifdef WANT_DYNKEY_SUPPORT
  66. // Check if this a dynamic key that has a "get all" atomic callback. If
  67. // the dynamic key just has "get one" callback, then we'll fall into the
  68. // non-dynamic case.
  69. if ((hKey-> PredefinedKeyIndex == INDEX_DYN_DATA) && !IsNullPtr(hKey->
  70. pProvider-> ipi_R0_allvals)) {
  71. pProvider = hKey-> pProvider;
  72. pValueContext = RgSmAllocMemory(sizeof(struct val_context) * num_vals);
  73. if (IsNullPtr(pValueContext)) {
  74. ErrorCode = ERROR_OUTOFMEMORY;
  75. goto ReturnErrorCode;
  76. }
  77. //
  78. // Compute the required buffer size to hold all the value data and
  79. // check it against the provided buffer size.
  80. //
  81. RequiredSize = 0;
  82. for (Counter = 0, pCurrentValent = val_list; Counter < num_vals;
  83. Counter++, pCurrentValent++) {
  84. if ((ErrorCode = RgLookupValueByName(hKey, pCurrentValent->
  85. ve_valuename, &lpKeyRecord, &lpValueRecord)) != ERROR_SUCCESS)
  86. goto ReturnErrorCode;
  87. // The value data contains only part of a PROVIDER structure.
  88. pProviderValue = CONTAINING_RECORD(&lpValueRecord-> Name +
  89. lpValueRecord-> NameLength, PVALUE, pv_valuelen);
  90. pValueContext[Counter].value_context = pProviderValue->
  91. pv_value_context;
  92. pCurrentValent-> ve_type = pProviderValue-> pv_type;
  93. if (hKey-> Flags & KEYF_PROVIDERHASVALUELENGTH) {
  94. // Must zero it so that some providers don't try to stomp on
  95. // lpData.
  96. pCurrentValent-> ve_valuelen = 0;
  97. ErrorCode = pProvider-> ipi_R0_1val(pProvider-> ipi_key_context,
  98. &pValueContext[Counter], 1, NULL, &(pCurrentValent->
  99. ve_valuelen), 0);
  100. // Providers should really be returning either of these errors
  101. // to us.
  102. ASSERT((ErrorCode == ERROR_SUCCESS) || (ErrorCode ==
  103. ERROR_MORE_DATA));
  104. }
  105. else {
  106. pCurrentValent-> ve_valuelen = pProviderValue-> pv_valuelen;
  107. }
  108. RgUnlockDatablock(hKey-> lpFileInfo, hKey-> BlockIndex, FALSE);
  109. pCurrentValent-> ve_valueptr = (DWORD) NULL;
  110. RequiredSize += pCurrentValent-> ve_valuelen;
  111. }
  112. BufferSize = *lpdwTotalSize;
  113. *lpdwTotalSize = RequiredSize;
  114. if (BufferSize < RequiredSize)
  115. ErrorCode = ERROR_MORE_DATA;
  116. else if (pProvider-> ipi_R0_allvals(pProvider-> ipi_key_context,
  117. pValueContext, num_vals, lpValueBuffer, lpdwTotalSize, 0) !=
  118. ERROR_SUCCESS)
  119. ErrorCode = ERROR_CANTREAD;
  120. else {
  121. ErrorCode = ERROR_SUCCESS;
  122. // Copy the pointers to the value data back to the user's buffer.
  123. // Don't ask me why, but the Win95 code copies the value length
  124. // back again if the provider is maintaining it.
  125. for (Counter = 0, pCurrentValent = val_list; Counter < num_vals;
  126. Counter++, pCurrentValent++) {
  127. pCurrentValent-> ve_valueptr = (DWORD)
  128. pValueContext[Counter].val_buff_ptr;
  129. if (hKey-> Flags & KEYF_PROVIDERHASVALUELENGTH)
  130. pCurrentValent-> ve_valuelen = pValueContext[Counter].valuelen;
  131. }
  132. }
  133. RgSmFreeMemory(pValueContext);
  134. goto ReturnErrorCode;
  135. }
  136. #endif
  137. //
  138. // First pass over the value names checks for the existence of the value
  139. // and its size. We check the total size against the provided buffer size
  140. // and bail out if necessary.
  141. //
  142. RequiredSize = 0;
  143. for (Counter = num_vals, pCurrentValent = val_list; Counter > 0; Counter--,
  144. pCurrentValent++) {
  145. if ((ErrorCode = RgLookupValueByName(hKey, pCurrentValent->
  146. ve_valuename, &lpKeyRecord, &lpValueRecord)) != ERROR_SUCCESS)
  147. goto ReturnErrorCode;
  148. ErrorCode = RgCopyFromValueRecord(hKey, lpValueRecord, NULL, NULL,
  149. &(pCurrentValent-> ve_type), NULL, &(pCurrentValent-> ve_valuelen));
  150. RgUnlockDatablock(hKey-> lpFileInfo, hKey-> BlockIndex, FALSE);
  151. if (ErrorCode != ERROR_SUCCESS)
  152. goto ReturnErrorCode;
  153. pCurrentValent-> ve_valueptr = (DWORD) NULL;
  154. RequiredSize += pCurrentValent-> ve_valuelen;
  155. }
  156. BufferSize = *lpdwTotalSize;
  157. *lpdwTotalSize = RequiredSize;
  158. if (BufferSize < RequiredSize) {
  159. ErrorCode = ERROR_MORE_DATA;
  160. goto ReturnErrorCode;
  161. }
  162. //
  163. // Second pass copies the value data back to the user's buffer now that we
  164. // know the buffer is large enough to contain the data.
  165. //
  166. lpCurrentBuffer = lpValueBuffer;
  167. for (Counter = num_vals, pCurrentValent = val_list; Counter > 0; Counter--,
  168. pCurrentValent++) {
  169. if ((ErrorCode = RgLookupValueByName(hKey, pCurrentValent->
  170. ve_valuename, &lpKeyRecord, &lpValueRecord)) != ERROR_SUCCESS)
  171. goto ReturnErrorReading;
  172. ErrorCode = RgCopyFromValueRecord(hKey, lpValueRecord, NULL, NULL, NULL,
  173. lpCurrentBuffer, &(pCurrentValent-> ve_valuelen));
  174. RgUnlockDatablock(hKey-> lpFileInfo, hKey-> BlockIndex, FALSE);
  175. if (ErrorCode != ERROR_SUCCESS) {
  176. ReturnErrorReading:
  177. TRAP(); // Registry is internally inconsistent?
  178. ErrorCode = ERROR_CANTREAD;
  179. goto ReturnErrorCode;
  180. }
  181. pCurrentValent-> ve_valueptr = (DWORD) lpCurrentBuffer;
  182. lpCurrentBuffer += pCurrentValent-> ve_valuelen;
  183. }
  184. ErrorCode = ERROR_SUCCESS;
  185. ReturnErrorCode:
  186. RgUnlockRegistry();
  187. return ErrorCode;
  188. }
  189. #endif