Source code of Windows XP (NT5)
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.

359 lines
7.3 KiB

  1. //============================================================================
  2. // Copyright (c) 1995, Microsoft Corporation
  3. //
  4. // File: ibase.c
  5. //
  6. // History:
  7. // Abolade Gbadegesin Oct-27-1995 Created.
  8. //
  9. // Contains utility for manipulating InfoBase and InfoBlock structures.
  10. //============================================================================
  11. #include <nt.h>
  12. #include <ntrtl.h>
  13. #include <nturtl.h>
  14. #include <windows.h>
  15. #include <stdlib.h>
  16. #include <iprtinfo.h>
  17. #include <rtutils.h>
  18. typedef InfoBase INFOBASE, *PINFOBASE;
  19. typedef InfoBlock INFOBLOCK, *PINFOBLOCK;
  20. DWORD
  21. APIENTRY
  22. InfoBaseAlloc(
  23. IN DWORD dwVersion,
  24. OUT PBYTE *ppInfoBase
  25. ) {
  26. DWORD dwErr;
  27. PINFOBASE pbase;
  28. if (ppInfoBase == NULL) { return ERROR_INVALID_PARAMETER; }
  29. pbase = (PINFOBASE)HeapAlloc(GetProcessHeap(), 0, sizeof(InfoBase));
  30. if (pbase == NULL) {
  31. dwErr = GetLastError();
  32. }
  33. else {
  34. pbase->IB_Version = dwVersion;
  35. pbase->IB_NumInfoBlocks = 0;
  36. dwErr = NO_ERROR;
  37. }
  38. *ppInfoBase = (PBYTE)pbase;
  39. return dwErr;
  40. }
  41. DWORD
  42. APIENTRY
  43. InfoBaseFree(
  44. IN PBYTE pInfoBase
  45. ) {
  46. HeapFree(GetProcessHeap(), 0, pInfoBase);
  47. return NO_ERROR;
  48. }
  49. DWORD
  50. APIENTRY
  51. InfoBaseGetSize(
  52. IN PBYTE pInfoBase
  53. ) {
  54. PINFOBASE pbase;
  55. PINFOBLOCK pblock;
  56. if (pInfoBase == NULL) { return 0; }
  57. pbase = (PINFOBASE)pInfoBase;
  58. if (pbase->IB_NumInfoBlocks == 0) {
  59. return sizeof(InfoBase) - sizeof(InfoBlock);
  60. }
  61. pblock = pbase->IB_InfoBlock + (pbase->IB_NumInfoBlocks - 1);
  62. return pblock->IB_Size + pblock->IB_StartOffset;
  63. }
  64. DWORD
  65. APIENTRY
  66. InfoBaseSet(
  67. IN DWORD dwInfoType,
  68. IN PBYTE pOldInfoBase,
  69. IN PBYTE pNewInfoBlock,
  70. IN PBYTE pNewInfoData,
  71. OUT PBYTE *ppNewInfoBase
  72. ) {
  73. INT i, j;
  74. PBYTE pOldData, pNewData;
  75. PINFOBASE pOldBase, pNewBase;
  76. PINFOBLOCK pOldBlock, pNewBlock;
  77. DWORD dwErr, dwOldSize, dwNewSize, dwOffset;
  78. if (pOldInfoBase == NULL || ppNewInfoBase == NULL) {
  79. return ERROR_INVALID_PARAMETER;
  80. }
  81. *ppNewInfoBase = NULL;
  82. pOldBase = (PINFOBASE)pOldInfoBase;
  83. pNewBlock = (PINFOBLOCK)pNewInfoBlock;
  84. pNewData = pNewInfoData;
  85. do {
  86. //
  87. // get a pointer to the existing block if one exists
  88. //
  89. dwErr = InfoBaseGet(
  90. dwInfoType,
  91. pOldInfoBase,
  92. (PBYTE *)&pOldBlock,
  93. &pOldData
  94. );
  95. //
  96. // get the size of the old infobase
  97. // and adjust to find the new size
  98. //
  99. dwNewSize = dwOldSize = InfoBaseGetSize(pOldInfoBase);
  100. if (pOldBlock != NULL) {
  101. dwNewSize -= pOldBlock->IB_Size;
  102. }
  103. if (pNewBlock != NULL) {
  104. dwNewSize += pNewBlock->IB_Size;
  105. }
  106. pNewBase = (PINFOBASE)HeapAlloc(GetProcessHeap(), 0, dwNewSize);
  107. if (pNewBase == NULL) {
  108. dwErr = GetLastError();
  109. break;
  110. }
  111. //
  112. // initialize the allocated infobase
  113. //
  114. pNewBase->IB_Version = pOldBase->IB_Version;
  115. pNewBase->IB_NumInfoBlocks = 0;
  116. //
  117. // copy the infoblocks to the new base, skipping the one being set;
  118. //
  119. dwOffset = sizeof(INFOBASE) - sizeof(INFOBLOCK) +
  120. (pNewBase->IB_NumInfoBlocks - 1) * sizeof(INFOBLOCK);
  121. for (i = 0, j = 0; i < (INT)pOldBase->IB_NumInfoBlocks; i++) {
  122. if ((pOldBase->IB_InfoBlock + i) == pOldBlock) {
  123. continue;
  124. }
  125. pNewBase->IB_InfoBlock[j] = pOldBase->IB_InfoBlock[i];
  126. pNewBase->IB_InfoBlock[j].IB_StartOffset = dwOffset;
  127. RtlCopyMemory(
  128. (PBYTE)pNewBase + dwOffset,
  129. (PBYTE)pOldBase + pOldBase->IB_InfoBlock[i].IB_StartOffset,
  130. pOldBase->IB_InfoBlock[i].IB_Size
  131. );
  132. ++pNewBase->IB_NumInfoBlocks;
  133. dwOffset += pOldBase->IB_InfoBlock[i].IB_Size;
  134. ++j;
  135. }
  136. //
  137. // if a block was provided for the infotype being set, append it
  138. //
  139. if (pNewBlock != NULL) {
  140. pNewBase->IB_InfoBlock[j] = *pNewBlock;
  141. pNewBase->IB_InfoBlock[j].IB_StartOffset = dwOffset;
  142. RtlCopyMemory(
  143. (PBYTE)pNewBase + dwOffset,
  144. pNewData,
  145. pNewBlock->IB_Size
  146. );
  147. ++pNewBase->IB_NumInfoBlocks;
  148. }
  149. //
  150. // save the new infobase
  151. //
  152. *ppNewInfoBase = (PBYTE)pNewBase;
  153. dwErr = NO_ERROR;
  154. } while(FALSE);
  155. return dwErr;
  156. }
  157. DWORD
  158. APIENTRY
  159. InfoBaseGet(
  160. IN DWORD dwInfoType,
  161. IN PBYTE pInfoBase,
  162. OUT PBYTE *ppInfoBlock,
  163. OUT PBYTE *ppInfoData
  164. ) {
  165. DWORD dwErr;
  166. PINFOBASE pbase;
  167. PINFOBLOCK pblock, pblockend;
  168. if (ppInfoBlock != NULL) { *ppInfoBlock = NULL; }
  169. if (ppInfoData != NULL) { *ppInfoData = NULL; }
  170. if (pInfoBase == NULL) { return ERROR_INVALID_PARAMETER; }
  171. pbase = (PINFOBASE)pInfoBase;
  172. pblock = pbase->IB_InfoBlock;
  173. pblockend = pblock + pbase->IB_NumInfoBlocks;
  174. dwErr = ERROR_NO_DATA;
  175. for ( ; pblock < pblockend; pblock++) {
  176. if (pblock->IB_InfoType == dwInfoType) {
  177. if (ppInfoBlock != NULL) {
  178. *ppInfoBlock = (PBYTE)pblock;
  179. }
  180. if (ppInfoData != NULL) {
  181. *ppInfoData = (PBYTE)pbase + pblock->IB_StartOffset;
  182. }
  183. dwErr = NO_ERROR;
  184. break;
  185. }
  186. }
  187. return dwErr;
  188. }
  189. DWORD
  190. APIENTRY
  191. InfoBaseGetFirst(
  192. IN PBYTE pInfoBase,
  193. OUT PBYTE *ppFirstInfoBlock,
  194. OUT PBYTE *ppFirstInfoData
  195. ) {
  196. DWORD dwErr;
  197. PINFOBASE pbase;
  198. PINFOBLOCK pblock;
  199. if (ppFirstInfoBlock != NULL) { *ppFirstInfoBlock = NULL; }
  200. if (ppFirstInfoData != NULL) { *ppFirstInfoData = NULL; }
  201. if (pInfoBase == NULL) { return ERROR_INVALID_PARAMETER; }
  202. pbase = (PINFOBASE)pInfoBase;
  203. if (pbase->IB_NumInfoBlocks == 0) {
  204. dwErr = ERROR_NO_MORE_ITEMS;
  205. }
  206. else {
  207. pblock = pbase->IB_InfoBlock;
  208. if (ppFirstInfoBlock != NULL) {
  209. *ppFirstInfoBlock = (PBYTE)pblock;
  210. }
  211. if (ppFirstInfoData != NULL) {
  212. *ppFirstInfoData = (PBYTE)pbase + pblock->IB_StartOffset;
  213. }
  214. dwErr = NO_ERROR;
  215. }
  216. return dwErr;
  217. }
  218. DWORD
  219. APIENTRY
  220. InfoBaseGetNext(
  221. IN PBYTE pInfoBase,
  222. IN PBYTE pInfoBlock,
  223. OUT PBYTE *ppNextInfoBlock,
  224. OUT PBYTE *ppNextInfoData
  225. ) {
  226. PINFOBASE pbase;
  227. PINFOBLOCK pblock;
  228. DWORD dwErr, dwNext;
  229. if (ppNextInfoBlock != NULL) { *ppNextInfoBlock = NULL; }
  230. if (ppNextInfoData != NULL) { *ppNextInfoData = NULL; }
  231. if (pInfoBase == NULL || pInfoBlock == NULL) {
  232. return ERROR_INVALID_PARAMETER;
  233. }
  234. pbase = (PINFOBASE)pInfoBase;
  235. pblock = pbase->IB_InfoBlock;
  236. dwNext = ((PINFOBLOCK)pInfoBlock - pblock) + 1;
  237. if (dwNext >= pbase->IB_NumInfoBlocks) {
  238. dwErr = ERROR_NO_MORE_ITEMS;
  239. }
  240. else {
  241. pblock += dwNext;
  242. if (ppNextInfoBlock != NULL) {
  243. *ppNextInfoBlock = (PBYTE)pblock;
  244. }
  245. if (ppNextInfoData != NULL) {
  246. *ppNextInfoData = (PBYTE)pbase + pblock->IB_StartOffset;
  247. }
  248. dwErr = NO_ERROR;
  249. }
  250. return dwErr;
  251. }