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.

254 lines
7.9 KiB

  1. //
  2. // REGQMVAL.C
  3. //
  4. // Copyright (C) Microsoft Corporation, 1995-1996
  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 (IsDynDataKey(hKey) && !IsNullPtr(hKey-> pProvider-> ipi_R0_allvals)) {
  70. pProvider = hKey-> pProvider;
  71. pValueContext = RgSmAllocMemory(sizeof(struct val_context) * num_vals);
  72. if (IsNullPtr(pValueContext)) {
  73. ErrorCode = ERROR_OUTOFMEMORY;
  74. goto ReturnErrorCode;
  75. }
  76. //
  77. // Compute the required buffer size to hold all the value data and
  78. // check it against the provided buffer size.
  79. //
  80. RequiredSize = 0;
  81. for (Counter = 0, pCurrentValent = val_list; Counter < num_vals;
  82. Counter++, pCurrentValent++) {
  83. if ((ErrorCode = RgLookupValueByName(hKey, pCurrentValent->
  84. ve_valuename, &lpKeyRecord, &lpValueRecord)) != ERROR_SUCCESS)
  85. goto ReturnErrorCode;
  86. // The value data contains only part of a PROVIDER structure.
  87. pProviderValue = CONTAINING_RECORD(&lpValueRecord-> Name +
  88. lpValueRecord-> NameLength, PVALUE, pv_valuelen);
  89. pValueContext[Counter].value_context = pProviderValue->
  90. pv_value_context;
  91. pCurrentValent-> ve_type = pProviderValue-> pv_type;
  92. if (hKey-> Flags & KEYF_PROVIDERHASVALUELENGTH) {
  93. // Must zero it so that some providers don't try to stomp on
  94. // lpData.
  95. pCurrentValent-> ve_valuelen = 0;
  96. ErrorCode = pProvider-> ipi_R0_1val(pProvider-> ipi_key_context,
  97. &pValueContext[Counter], 1, NULL, &(pCurrentValent->
  98. ve_valuelen), 0);
  99. // Providers should really be returning either of these errors
  100. // to us.
  101. ASSERT((ErrorCode == ERROR_SUCCESS) || (ErrorCode ==
  102. ERROR_MORE_DATA));
  103. }
  104. else {
  105. pCurrentValent-> ve_valuelen = pProviderValue-> pv_valuelen;
  106. }
  107. RgUnlockDatablock(hKey-> lpFileInfo, hKey-> BigKeyLockedBlockIndex, FALSE);
  108. pCurrentValent-> ve_valueptr = (DWORD) NULL;
  109. RequiredSize += pCurrentValent-> ve_valuelen;
  110. }
  111. BufferSize = *lpdwTotalSize;
  112. *lpdwTotalSize = RequiredSize;
  113. if (BufferSize < RequiredSize)
  114. ErrorCode = ERROR_MORE_DATA;
  115. else if (pProvider-> ipi_R0_allvals(pProvider-> ipi_key_context,
  116. pValueContext, num_vals, lpValueBuffer, lpdwTotalSize, 0) !=
  117. ERROR_SUCCESS)
  118. ErrorCode = ERROR_CANTREAD;
  119. else {
  120. ErrorCode = ERROR_SUCCESS;
  121. // Copy the pointers to the value data back to the user's buffer.
  122. // Don't ask me why, but the Win95 code copies the value length
  123. // back again if the provider is maintaining it.
  124. for (Counter = 0, pCurrentValent = val_list; Counter < num_vals;
  125. Counter++, pCurrentValent++) {
  126. pCurrentValent-> ve_valueptr = (DWORD)
  127. pValueContext[Counter].val_buff_ptr;
  128. if (hKey-> Flags & KEYF_PROVIDERHASVALUELENGTH)
  129. pCurrentValent-> ve_valuelen = pValueContext[Counter].valuelen;
  130. }
  131. }
  132. RgSmFreeMemory(pValueContext);
  133. goto ReturnErrorCode;
  134. }
  135. #endif
  136. //
  137. // First pass over the value names checks for the existence of the value
  138. // and its size. We check the total size against the provided buffer size
  139. // and bail out if necessary.
  140. //
  141. RequiredSize = 0;
  142. for (Counter = num_vals, pCurrentValent = val_list; Counter > 0; Counter--,
  143. pCurrentValent++) {
  144. if ((ErrorCode = RgLookupValueByName(hKey, pCurrentValent->
  145. ve_valuename, &lpKeyRecord, &lpValueRecord)) != ERROR_SUCCESS)
  146. goto ReturnErrorCode;
  147. ErrorCode = RgCopyFromValueRecord(hKey, lpValueRecord, NULL, NULL,
  148. &(pCurrentValent-> ve_type), NULL, &(pCurrentValent-> ve_valuelen));
  149. RgUnlockDatablock(hKey-> lpFileInfo, hKey-> BigKeyLockedBlockIndex, FALSE);
  150. if (ErrorCode != ERROR_SUCCESS)
  151. goto ReturnErrorCode;
  152. pCurrentValent-> ve_valueptr = (DWORD) NULL;
  153. RequiredSize += pCurrentValent-> ve_valuelen;
  154. }
  155. BufferSize = *lpdwTotalSize;
  156. *lpdwTotalSize = RequiredSize;
  157. if (BufferSize < RequiredSize) {
  158. ErrorCode = ERROR_MORE_DATA;
  159. goto ReturnErrorCode;
  160. }
  161. //
  162. // Second pass copies the value data back to the user's buffer now that we
  163. // know the buffer is large enough to contain the data.
  164. //
  165. lpCurrentBuffer = lpValueBuffer;
  166. for (Counter = num_vals, pCurrentValent = val_list; Counter > 0; Counter--,
  167. pCurrentValent++) {
  168. if ((ErrorCode = RgLookupValueByName(hKey, pCurrentValent->
  169. ve_valuename, &lpKeyRecord, &lpValueRecord)) != ERROR_SUCCESS)
  170. goto ReturnErrorReading;
  171. ErrorCode = RgCopyFromValueRecord(hKey, lpValueRecord, NULL, NULL, NULL,
  172. lpCurrentBuffer, &(pCurrentValent-> ve_valuelen));
  173. RgUnlockDatablock(hKey-> lpFileInfo, hKey-> BigKeyLockedBlockIndex, FALSE);
  174. if (ErrorCode != ERROR_SUCCESS) {
  175. ReturnErrorReading:
  176. TRAP(); // Registry is internally inconsistent?
  177. ErrorCode = ERROR_CANTREAD;
  178. goto ReturnErrorCode;
  179. }
  180. pCurrentValent-> ve_valueptr = (DWORD) lpCurrentBuffer;
  181. lpCurrentBuffer += pCurrentValent-> ve_valuelen;
  182. }
  183. ErrorCode = ERROR_SUCCESS;
  184. ReturnErrorCode:
  185. RgUnlockRegistry();
  186. return ErrorCode;
  187. }
  188. #endif