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.

583 lines
12 KiB

  1. /*++
  2. Copyright (c) 1997, Microsoft Corporation
  3. Module Name:
  4. infoapi.c
  5. Abstract:
  6. This module contains code for management of configuration information
  7. stored in RTR_INFO_BLOCK_HEADER structures.
  8. Author:
  9. Abolade Gbadegesin (t-abolag) 6-August-1997
  10. Revision History:
  11. --*/
  12. #include <nt.h>
  13. #include <ntrtl.h>
  14. #include <nturtl.h>
  15. #include <windows.h>
  16. #include <mprapi.h>
  17. #include <mprerror.h>
  18. #include <rtinfo.h>
  19. DWORD APIENTRY
  20. MprInfoCreate(
  21. IN DWORD dwVersion,
  22. OUT LPVOID* lplpNewHeader
  23. )
  24. {
  25. PRTR_INFO_BLOCK_HEADER Header;
  26. PRTR_INFO_BLOCK_HEADER* NewHeader = (PRTR_INFO_BLOCK_HEADER*)lplpNewHeader;
  27. //
  28. // Validate parameters
  29. //
  30. if (!lplpNewHeader) { return ERROR_INVALID_PARAMETER; }
  31. *lplpNewHeader = NULL;
  32. //
  33. // Perform the requested allocation
  34. //
  35. *NewHeader =
  36. HeapAlloc(
  37. GetProcessHeap(),
  38. 0,
  39. FIELD_OFFSET(RTR_INFO_BLOCK_HEADER, TocEntry)
  40. );
  41. if (!*NewHeader) { return ERROR_NOT_ENOUGH_MEMORY; }
  42. ZeroMemory(*NewHeader, FIELD_OFFSET(RTR_INFO_BLOCK_HEADER, TocEntry));
  43. //
  44. // Initialize the new header
  45. //
  46. (*NewHeader)->Version = dwVersion;
  47. (*NewHeader)->Size = FIELD_OFFSET(RTR_INFO_BLOCK_HEADER, TocEntry);
  48. (*NewHeader)->TocEntriesCount = 0;
  49. return NO_ERROR;
  50. } // MprInfoCreate
  51. DWORD APIENTRY
  52. MprInfoDelete(
  53. IN LPVOID lpHeader
  54. )
  55. {
  56. if (!lpHeader) { return ERROR_INVALID_PARAMETER; }
  57. HeapFree(GetProcessHeap(), 0, lpHeader);
  58. return NO_ERROR;
  59. } // MprInfoDelete
  60. DWORD APIENTRY
  61. MprInfoRemoveAll(
  62. IN LPVOID lpHeader,
  63. OUT LPVOID* lplpNewHeader
  64. )
  65. {
  66. PRTR_INFO_BLOCK_HEADER Header = (PRTR_INFO_BLOCK_HEADER)lpHeader;
  67. DWORD dwErr;
  68. //
  69. // Validate parameters
  70. //
  71. if (!lpHeader) { return ERROR_INVALID_PARAMETER; }
  72. //
  73. // Create the new header
  74. //
  75. dwErr = MprInfoCreate(Header->Version, lplpNewHeader);
  76. return dwErr;
  77. } // MprInfoRemoveAll
  78. DWORD APIENTRY
  79. MprInfoDuplicate(
  80. IN LPVOID lpHeader,
  81. OUT LPVOID* lplpNewHeader
  82. )
  83. {
  84. PRTR_INFO_BLOCK_HEADER Header = (PRTR_INFO_BLOCK_HEADER)lpHeader;
  85. //
  86. // Validate parameters
  87. //
  88. if (!lpHeader || !lplpNewHeader) { return ERROR_INVALID_PARAMETER; }
  89. *lplpNewHeader = NULL;
  90. //
  91. // Allocate a new block
  92. //
  93. *lplpNewHeader = HeapAlloc(GetProcessHeap(), 0, Header->Size);
  94. if (!*lplpNewHeader) { return ERROR_NOT_ENOUGH_MEMORY; }
  95. //
  96. // Make the copy
  97. //
  98. RtlCopyMemory(*lplpNewHeader, lpHeader, Header->Size);
  99. return NO_ERROR;
  100. } // MprInfoDuplicate
  101. DWORD APIENTRY
  102. MprInfoBlockAdd(
  103. IN LPVOID lpHeader,
  104. IN DWORD dwInfoType,
  105. IN DWORD dwItemSize,
  106. IN DWORD dwItemCount,
  107. IN LPBYTE lpItemData,
  108. OUT LPVOID* lplpNewHeader
  109. )
  110. {
  111. PRTR_INFO_BLOCK_HEADER Header = (PRTR_INFO_BLOCK_HEADER)lpHeader;
  112. PRTR_INFO_BLOCK_HEADER* NewHeader = (PRTR_INFO_BLOCK_HEADER*)lplpNewHeader;
  113. DWORD i;
  114. LPBYTE Offset;
  115. DWORD Size;
  116. //
  117. // Validate parameters
  118. //
  119. if (!lpHeader ||
  120. !lplpNewHeader ||
  121. MprInfoBlockExists(lpHeader, dwInfoType) ||
  122. ((dwItemSize * dwItemCount) && !lpItemData)
  123. ) {
  124. return ERROR_INVALID_PARAMETER;
  125. }
  126. *lplpNewHeader = NULL;
  127. //
  128. // Work out the new size
  129. //
  130. Size = Header->Size;
  131. ALIGN_LENGTH(Size);
  132. Size += sizeof(RTR_TOC_ENTRY);
  133. ALIGN_LENGTH(Size);
  134. Size += dwItemSize * dwItemCount;
  135. ALIGN_LENGTH(Size);
  136. //
  137. // Allocate the new header
  138. //
  139. *lplpNewHeader = HeapAlloc(GetProcessHeap(), 0, Size);
  140. if (!*lplpNewHeader) { return ERROR_NOT_ENOUGH_MEMORY; }
  141. ZeroMemory(*lplpNewHeader, Size);
  142. //
  143. // Copy the old header's table of contents
  144. //
  145. RtlCopyMemory(
  146. *lplpNewHeader,
  147. lpHeader,
  148. FIELD_OFFSET(RTR_INFO_BLOCK_HEADER, TocEntry) +
  149. Header->TocEntriesCount * sizeof(RTR_TOC_ENTRY)
  150. );
  151. //
  152. // Initialize the new block's TOC entry as the last entry
  153. //
  154. (*NewHeader)->TocEntry[Header->TocEntriesCount].InfoType = dwInfoType;
  155. (*NewHeader)->TocEntry[Header->TocEntriesCount].InfoSize = dwItemSize;
  156. (*NewHeader)->TocEntry[Header->TocEntriesCount].Count = dwItemCount;
  157. ++(*NewHeader)->TocEntriesCount;
  158. //
  159. // Now copy the data for the old header's TOC entries
  160. //
  161. Offset = (LPBYTE)&(*NewHeader)->TocEntry[(*NewHeader)->TocEntriesCount];
  162. ALIGN_POINTER(Offset);
  163. for (i = 0; i < Header->TocEntriesCount; i++) {
  164. RtlCopyMemory(
  165. Offset,
  166. GetInfoFromTocEntry(Header, &Header->TocEntry[i]),
  167. Header->TocEntry[i].InfoSize * Header->TocEntry[i].Count
  168. );
  169. (*NewHeader)->TocEntry[i].Offset = (DWORD)(Offset - (LPBYTE)*NewHeader);
  170. Offset += Header->TocEntry[i].InfoSize * Header->TocEntry[i].Count;
  171. ALIGN_POINTER(Offset);
  172. }
  173. //
  174. // Copy the new user-supplied data
  175. //
  176. RtlCopyMemory(Offset, lpItemData, dwItemSize * dwItemCount);
  177. (*NewHeader)->TocEntry[i].Offset = (DWORD)(Offset - (LPBYTE)*NewHeader);
  178. Offset += dwItemSize * dwItemCount;
  179. ALIGN_POINTER(Offset);
  180. //
  181. // Set the total size of the new header
  182. //
  183. (*NewHeader)->Size = (DWORD)(Offset - (LPBYTE)*NewHeader);
  184. return NO_ERROR;
  185. } // MprInfoBlockAdd
  186. DWORD APIENTRY
  187. MprInfoBlockRemove(
  188. IN LPVOID lpHeader,
  189. IN DWORD dwInfoType,
  190. OUT LPVOID* lplpNewHeader
  191. )
  192. {
  193. PRTR_INFO_BLOCK_HEADER Header = (PRTR_INFO_BLOCK_HEADER)lpHeader;
  194. PRTR_INFO_BLOCK_HEADER* NewHeader = (PRTR_INFO_BLOCK_HEADER*)lplpNewHeader;
  195. DWORD Index;
  196. DWORD i;
  197. DWORD j;
  198. LPBYTE Offset;
  199. DWORD Size;
  200. //
  201. // Validate parameters
  202. //
  203. if (!lpHeader || !lplpNewHeader) { return ERROR_INVALID_PARAMETER; }
  204. *lplpNewHeader = NULL;
  205. //
  206. // Find the block to be removed
  207. //
  208. for (Index = 0; Index < Header->TocEntriesCount; Index++) {
  209. if (Header->TocEntry[Index].InfoType == dwInfoType) { break; }
  210. }
  211. if (Index >= Header->TocEntriesCount) { return ERROR_INVALID_PARAMETER; }
  212. //
  213. // Work out the new size
  214. //
  215. Size = Header->Size;
  216. ALIGN_LENGTH(Size);
  217. Size -= sizeof(RTR_TOC_ENTRY);
  218. ALIGN_LENGTH(Size);
  219. Size -= Header->TocEntry[Index].InfoSize * Header->TocEntry[Index].Count;
  220. ALIGN_LENGTH(Size);
  221. //
  222. // Allocate the new header
  223. //
  224. *NewHeader = HeapAlloc(GetProcessHeap(), 0, Size);
  225. if (!*NewHeader) { return ERROR_NOT_ENOUGH_MEMORY; }
  226. ZeroMemory(*NewHeader, Size);
  227. //
  228. // Copy the old header's table of contents header
  229. //
  230. (*NewHeader)->Version = Header->Version;
  231. (*NewHeader)->TocEntriesCount = Header->TocEntriesCount - 1;
  232. //
  233. // Copy the actual TOC entries, leaving out the deleted one
  234. //
  235. for (i = 0, j = 0; i < Header->TocEntriesCount; i++) {
  236. if (i == Index) { continue; }
  237. RtlCopyMemory(
  238. &(*NewHeader)->TocEntry[j++],
  239. &Header->TocEntry[i],
  240. sizeof(RTR_TOC_ENTRY)
  241. );
  242. }
  243. //
  244. // Now copy the data for the old header's TOC entries,
  245. // again leaving out the deleted one's data
  246. //
  247. Offset = (LPBYTE)&(*NewHeader)->TocEntry[(*NewHeader)->TocEntriesCount];
  248. ALIGN_POINTER(Offset);
  249. for (i = 0, j = 0; i < Header->TocEntriesCount; i++) {
  250. if (i == Index) { continue; }
  251. RtlCopyMemory(
  252. Offset,
  253. GetInfoFromTocEntry(Header, &Header->TocEntry[i]),
  254. Header->TocEntry[i].InfoSize * Header->TocEntry[i].Count
  255. );
  256. (*NewHeader)->TocEntry[j++].Offset =
  257. (DWORD)(Offset - (LPBYTE)*NewHeader);
  258. Offset += Header->TocEntry[i].InfoSize * Header->TocEntry[i].Count;
  259. ALIGN_POINTER(Offset);
  260. }
  261. //
  262. // Set the total size of the new header
  263. //
  264. (*NewHeader)->Size = (DWORD)(Offset - (LPBYTE)*NewHeader);
  265. return NO_ERROR;
  266. } // MprInfoBlockRemove
  267. DWORD APIENTRY
  268. MprInfoBlockSet(
  269. IN LPVOID lpHeader,
  270. IN DWORD dwInfoType,
  271. IN DWORD dwItemSize,
  272. IN DWORD dwItemCount,
  273. IN LPBYTE lpItemData,
  274. OUT LPVOID* lplpNewHeader
  275. )
  276. {
  277. PRTR_INFO_BLOCK_HEADER Header = (PRTR_INFO_BLOCK_HEADER)lpHeader;
  278. PRTR_INFO_BLOCK_HEADER* NewHeader = (PRTR_INFO_BLOCK_HEADER*)lplpNewHeader;
  279. DWORD Index;
  280. DWORD i;
  281. DWORD j;
  282. LPBYTE Offset;
  283. DWORD Size;
  284. //
  285. // Validate parameters
  286. //
  287. if (!lpHeader ||
  288. !lplpNewHeader ||
  289. (dwItemCount && !dwItemSize) ||
  290. ((dwItemSize * dwItemCount) && !lpItemData)) {
  291. return ERROR_INVALID_PARAMETER;
  292. }
  293. *lplpNewHeader = NULL;
  294. //
  295. // Find the block to be changed
  296. //
  297. for (Index = 0; Index < Header->TocEntriesCount; Index++) {
  298. if (Header->TocEntry[Index].InfoType == dwInfoType) { break; }
  299. }
  300. if (Index >= Header->TocEntriesCount) { return ERROR_INVALID_PARAMETER; }
  301. //
  302. // Work out the new size
  303. //
  304. Size = Header->Size;
  305. ALIGN_LENGTH(Size);
  306. Size -= sizeof(RTR_TOC_ENTRY);
  307. ALIGN_LENGTH(Size);
  308. Size -= Header->TocEntry[Index].InfoSize * Header->TocEntry[Index].Count;
  309. ALIGN_LENGTH(Size);
  310. Size += sizeof(RTR_TOC_ENTRY);
  311. ALIGN_LENGTH(Size);
  312. Size += dwItemSize * dwItemCount;
  313. ALIGN_LENGTH(Size);
  314. //
  315. // Allocate the new header
  316. //
  317. *NewHeader = HeapAlloc(GetProcessHeap(), 0, Size);
  318. if (!*NewHeader) { return ERROR_NOT_ENOUGH_MEMORY; }
  319. ZeroMemory(*NewHeader, Size);
  320. //
  321. // Copy the old header's table of contents header
  322. //
  323. (*NewHeader)->Version = Header->Version;
  324. (*NewHeader)->TocEntriesCount = Header->TocEntriesCount;
  325. //
  326. // Copy the actual TOC entries, leaving out the changing one
  327. //
  328. for (i = 0, j = 0; i < Header->TocEntriesCount; i++) {
  329. if (i == Index) { continue; }
  330. RtlCopyMemory(
  331. &(*NewHeader)->TocEntry[j++],
  332. &Header->TocEntry[i],
  333. sizeof(RTR_TOC_ENTRY)
  334. );
  335. }
  336. //
  337. // Initialize the changing block's TOC entry as the last entry
  338. //
  339. (*NewHeader)->TocEntry[j].InfoType = dwInfoType;
  340. (*NewHeader)->TocEntry[j].InfoSize = dwItemSize;
  341. (*NewHeader)->TocEntry[j].Count = dwItemCount;
  342. //
  343. // Now copy the data for the old header's TOC entries,
  344. // similarly leaving out the changing one.
  345. //
  346. Offset = (LPBYTE)&(*NewHeader)->TocEntry[(*NewHeader)->TocEntriesCount];
  347. ALIGN_POINTER(Offset);
  348. for (i = 0, j = 0; i < Header->TocEntriesCount; i++) {
  349. if (i == Index) { continue; }
  350. RtlCopyMemory(
  351. Offset, GetInfoFromTocEntry(Header, &Header->TocEntry[i]),
  352. Header->TocEntry[i].InfoSize * Header->TocEntry[i].Count
  353. );
  354. (*NewHeader)->TocEntry[j++].Offset =
  355. (DWORD)(Offset - (LPBYTE)*NewHeader);
  356. Offset += Header->TocEntry[i].InfoSize * Header->TocEntry[i].Count;
  357. ALIGN_POINTER(Offset);
  358. }
  359. //
  360. // Copy the new user-supplied data
  361. //
  362. RtlCopyMemory(Offset, lpItemData, dwItemSize * dwItemCount);
  363. (*NewHeader)->TocEntry[j].Offset = (DWORD)(Offset - (LPBYTE)*NewHeader);
  364. Offset += dwItemSize * dwItemCount;
  365. ALIGN_POINTER(Offset);
  366. //
  367. // Set the total size of the changed header
  368. //
  369. (*NewHeader)->Size = (DWORD)(Offset - (LPBYTE)*NewHeader);
  370. return NO_ERROR;
  371. } // MprInfoBlockSet
  372. DWORD APIENTRY
  373. MprInfoBlockFind(
  374. IN LPVOID lpHeader,
  375. IN DWORD dwInfoType,
  376. OUT LPDWORD lpdwItemSize,
  377. OUT LPDWORD lpdwItemCount,
  378. OUT LPBYTE* lplpItemData
  379. )
  380. {
  381. PRTR_INFO_BLOCK_HEADER Header = (PRTR_INFO_BLOCK_HEADER)lpHeader;
  382. DWORD i;
  383. //
  384. // Validate parameters
  385. //
  386. if (!lpHeader) { return ERROR_INVALID_PARAMETER; }
  387. //
  388. // Find the block requested
  389. //
  390. for (i = 0; i < Header->TocEntriesCount; i++) {
  391. if (Header->TocEntry[i].InfoType == dwInfoType) { break; }
  392. }
  393. if (i >= Header->TocEntriesCount) { return ERROR_NOT_FOUND; }
  394. //
  395. // The item was found; fill in fields requested by the caller.
  396. //
  397. if (lpdwItemSize) { *lpdwItemSize = Header->TocEntry[i].InfoSize; }
  398. if (lpdwItemCount) { *lpdwItemCount = Header->TocEntry[i].Count; }
  399. if (lplpItemData) {
  400. *lplpItemData = GetInfoFromTocEntry(Header, &Header->TocEntry[i]);
  401. }
  402. return NO_ERROR;
  403. } // MprInfoBlockFind
  404. DWORD APIENTRY
  405. MprInfoBlockQuerySize(
  406. IN LPVOID lpHeader
  407. )
  408. {
  409. PRTR_INFO_BLOCK_HEADER Header = (PRTR_INFO_BLOCK_HEADER)lpHeader;
  410. if(Header == NULL)
  411. {
  412. return 0;
  413. }
  414. return Header->Size;
  415. } // MprInfoBlockQuerySize