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

/*++
Copyright (c) 1997, Microsoft Corporation
Module Name:
infoapi.c
Abstract:
This module contains code for management of configuration information
stored in RTR_INFO_BLOCK_HEADER structures.
Author:
Abolade Gbadegesin (t-abolag) 6-August-1997
Revision History:
--*/
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <mprapi.h>
#include <mprerror.h>
#include <rtinfo.h>
DWORD APIENTRY
MprInfoCreate(
IN DWORD dwVersion,
OUT LPVOID* lplpNewHeader
)
{
PRTR_INFO_BLOCK_HEADER Header;
PRTR_INFO_BLOCK_HEADER* NewHeader = (PRTR_INFO_BLOCK_HEADER*)lplpNewHeader;
//
// Validate parameters
//
if (!lplpNewHeader) { return ERROR_INVALID_PARAMETER; }
*lplpNewHeader = NULL;
//
// Perform the requested allocation
//
*NewHeader =
HeapAlloc(
GetProcessHeap(),
0,
FIELD_OFFSET(RTR_INFO_BLOCK_HEADER, TocEntry)
);
if (!*NewHeader) { return ERROR_NOT_ENOUGH_MEMORY; }
ZeroMemory(*NewHeader, FIELD_OFFSET(RTR_INFO_BLOCK_HEADER, TocEntry));
//
// Initialize the new header
//
(*NewHeader)->Version = dwVersion;
(*NewHeader)->Size = FIELD_OFFSET(RTR_INFO_BLOCK_HEADER, TocEntry);
(*NewHeader)->TocEntriesCount = 0;
return NO_ERROR;
} // MprInfoCreate
DWORD APIENTRY
MprInfoDelete(
IN LPVOID lpHeader
)
{
if (!lpHeader) { return ERROR_INVALID_PARAMETER; }
HeapFree(GetProcessHeap(), 0, lpHeader);
return NO_ERROR;
} // MprInfoDelete
DWORD APIENTRY
MprInfoRemoveAll(
IN LPVOID lpHeader,
OUT LPVOID* lplpNewHeader
)
{
PRTR_INFO_BLOCK_HEADER Header = (PRTR_INFO_BLOCK_HEADER)lpHeader;
DWORD dwErr;
//
// Validate parameters
//
if (!lpHeader) { return ERROR_INVALID_PARAMETER; }
//
// Create the new header
//
dwErr = MprInfoCreate(Header->Version, lplpNewHeader);
return dwErr;
} // MprInfoRemoveAll
DWORD APIENTRY
MprInfoDuplicate(
IN LPVOID lpHeader,
OUT LPVOID* lplpNewHeader
)
{
PRTR_INFO_BLOCK_HEADER Header = (PRTR_INFO_BLOCK_HEADER)lpHeader;
//
// Validate parameters
//
if (!lpHeader || !lplpNewHeader) { return ERROR_INVALID_PARAMETER; }
*lplpNewHeader = NULL;
//
// Allocate a new block
//
*lplpNewHeader = HeapAlloc(GetProcessHeap(), 0, Header->Size);
if (!*lplpNewHeader) { return ERROR_NOT_ENOUGH_MEMORY; }
//
// Make the copy
//
RtlCopyMemory(*lplpNewHeader, lpHeader, Header->Size);
return NO_ERROR;
} // MprInfoDuplicate
DWORD APIENTRY
MprInfoBlockAdd(
IN LPVOID lpHeader,
IN DWORD dwInfoType,
IN DWORD dwItemSize,
IN DWORD dwItemCount,
IN LPBYTE lpItemData,
OUT LPVOID* lplpNewHeader
)
{
PRTR_INFO_BLOCK_HEADER Header = (PRTR_INFO_BLOCK_HEADER)lpHeader;
PRTR_INFO_BLOCK_HEADER* NewHeader = (PRTR_INFO_BLOCK_HEADER*)lplpNewHeader;
DWORD i;
LPBYTE Offset;
DWORD Size;
//
// Validate parameters
//
if (!lpHeader ||
!lplpNewHeader ||
MprInfoBlockExists(lpHeader, dwInfoType) ||
((dwItemSize * dwItemCount) && !lpItemData)
) {
return ERROR_INVALID_PARAMETER;
}
*lplpNewHeader = NULL;
//
// Work out the new size
//
Size = Header->Size;
ALIGN_LENGTH(Size);
Size += sizeof(RTR_TOC_ENTRY);
ALIGN_LENGTH(Size);
Size += dwItemSize * dwItemCount;
ALIGN_LENGTH(Size);
//
// Allocate the new header
//
*lplpNewHeader = HeapAlloc(GetProcessHeap(), 0, Size);
if (!*lplpNewHeader) { return ERROR_NOT_ENOUGH_MEMORY; }
ZeroMemory(*lplpNewHeader, Size);
//
// Copy the old header's table of contents
//
RtlCopyMemory(
*lplpNewHeader,
lpHeader,
FIELD_OFFSET(RTR_INFO_BLOCK_HEADER, TocEntry) +
Header->TocEntriesCount * sizeof(RTR_TOC_ENTRY)
);
//
// Initialize the new block's TOC entry as the last entry
//
(*NewHeader)->TocEntry[Header->TocEntriesCount].InfoType = dwInfoType;
(*NewHeader)->TocEntry[Header->TocEntriesCount].InfoSize = dwItemSize;
(*NewHeader)->TocEntry[Header->TocEntriesCount].Count = dwItemCount;
++(*NewHeader)->TocEntriesCount;
//
// Now copy the data for the old header's TOC entries
//
Offset = (LPBYTE)&(*NewHeader)->TocEntry[(*NewHeader)->TocEntriesCount];
ALIGN_POINTER(Offset);
for (i = 0; i < Header->TocEntriesCount; i++) {
RtlCopyMemory(
Offset,
GetInfoFromTocEntry(Header, &Header->TocEntry[i]),
Header->TocEntry[i].InfoSize * Header->TocEntry[i].Count
);
(*NewHeader)->TocEntry[i].Offset = (DWORD)(Offset - (LPBYTE)*NewHeader);
Offset += Header->TocEntry[i].InfoSize * Header->TocEntry[i].Count;
ALIGN_POINTER(Offset);
}
//
// Copy the new user-supplied data
//
RtlCopyMemory(Offset, lpItemData, dwItemSize * dwItemCount);
(*NewHeader)->TocEntry[i].Offset = (DWORD)(Offset - (LPBYTE)*NewHeader);
Offset += dwItemSize * dwItemCount;
ALIGN_POINTER(Offset);
//
// Set the total size of the new header
//
(*NewHeader)->Size = (DWORD)(Offset - (LPBYTE)*NewHeader);
return NO_ERROR;
} // MprInfoBlockAdd
DWORD APIENTRY
MprInfoBlockRemove(
IN LPVOID lpHeader,
IN DWORD dwInfoType,
OUT LPVOID* lplpNewHeader
)
{
PRTR_INFO_BLOCK_HEADER Header = (PRTR_INFO_BLOCK_HEADER)lpHeader;
PRTR_INFO_BLOCK_HEADER* NewHeader = (PRTR_INFO_BLOCK_HEADER*)lplpNewHeader;
DWORD Index;
DWORD i;
DWORD j;
LPBYTE Offset;
DWORD Size;
//
// Validate parameters
//
if (!lpHeader || !lplpNewHeader) { return ERROR_INVALID_PARAMETER; }
*lplpNewHeader = NULL;
//
// Find the block to be removed
//
for (Index = 0; Index < Header->TocEntriesCount; Index++) {
if (Header->TocEntry[Index].InfoType == dwInfoType) { break; }
}
if (Index >= Header->TocEntriesCount) { return ERROR_INVALID_PARAMETER; }
//
// Work out the new size
//
Size = Header->Size;
ALIGN_LENGTH(Size);
Size -= sizeof(RTR_TOC_ENTRY);
ALIGN_LENGTH(Size);
Size -= Header->TocEntry[Index].InfoSize * Header->TocEntry[Index].Count;
ALIGN_LENGTH(Size);
//
// Allocate the new header
//
*NewHeader = HeapAlloc(GetProcessHeap(), 0, Size);
if (!*NewHeader) { return ERROR_NOT_ENOUGH_MEMORY; }
ZeroMemory(*NewHeader, Size);
//
// Copy the old header's table of contents header
//
(*NewHeader)->Version = Header->Version;
(*NewHeader)->TocEntriesCount = Header->TocEntriesCount - 1;
//
// Copy the actual TOC entries, leaving out the deleted one
//
for (i = 0, j = 0; i < Header->TocEntriesCount; i++) {
if (i == Index) { continue; }
RtlCopyMemory(
&(*NewHeader)->TocEntry[j++],
&Header->TocEntry[i],
sizeof(RTR_TOC_ENTRY)
);
}
//
// Now copy the data for the old header's TOC entries,
// again leaving out the deleted one's data
//
Offset = (LPBYTE)&(*NewHeader)->TocEntry[(*NewHeader)->TocEntriesCount];
ALIGN_POINTER(Offset);
for (i = 0, j = 0; i < Header->TocEntriesCount; i++) {
if (i == Index) { continue; }
RtlCopyMemory(
Offset,
GetInfoFromTocEntry(Header, &Header->TocEntry[i]),
Header->TocEntry[i].InfoSize * Header->TocEntry[i].Count
);
(*NewHeader)->TocEntry[j++].Offset =
(DWORD)(Offset - (LPBYTE)*NewHeader);
Offset += Header->TocEntry[i].InfoSize * Header->TocEntry[i].Count;
ALIGN_POINTER(Offset);
}
//
// Set the total size of the new header
//
(*NewHeader)->Size = (DWORD)(Offset - (LPBYTE)*NewHeader);
return NO_ERROR;
} // MprInfoBlockRemove
DWORD APIENTRY
MprInfoBlockSet(
IN LPVOID lpHeader,
IN DWORD dwInfoType,
IN DWORD dwItemSize,
IN DWORD dwItemCount,
IN LPBYTE lpItemData,
OUT LPVOID* lplpNewHeader
)
{
PRTR_INFO_BLOCK_HEADER Header = (PRTR_INFO_BLOCK_HEADER)lpHeader;
PRTR_INFO_BLOCK_HEADER* NewHeader = (PRTR_INFO_BLOCK_HEADER*)lplpNewHeader;
DWORD Index;
DWORD i;
DWORD j;
LPBYTE Offset;
DWORD Size;
//
// Validate parameters
//
if (!lpHeader ||
!lplpNewHeader ||
(dwItemCount && !dwItemSize) ||
((dwItemSize * dwItemCount) && !lpItemData)) {
return ERROR_INVALID_PARAMETER;
}
*lplpNewHeader = NULL;
//
// Find the block to be changed
//
for (Index = 0; Index < Header->TocEntriesCount; Index++) {
if (Header->TocEntry[Index].InfoType == dwInfoType) { break; }
}
if (Index >= Header->TocEntriesCount) { return ERROR_INVALID_PARAMETER; }
//
// Work out the new size
//
Size = Header->Size;
ALIGN_LENGTH(Size);
Size -= sizeof(RTR_TOC_ENTRY);
ALIGN_LENGTH(Size);
Size -= Header->TocEntry[Index].InfoSize * Header->TocEntry[Index].Count;
ALIGN_LENGTH(Size);
Size += sizeof(RTR_TOC_ENTRY);
ALIGN_LENGTH(Size);
Size += dwItemSize * dwItemCount;
ALIGN_LENGTH(Size);
//
// Allocate the new header
//
*NewHeader = HeapAlloc(GetProcessHeap(), 0, Size);
if (!*NewHeader) { return ERROR_NOT_ENOUGH_MEMORY; }
ZeroMemory(*NewHeader, Size);
//
// Copy the old header's table of contents header
//
(*NewHeader)->Version = Header->Version;
(*NewHeader)->TocEntriesCount = Header->TocEntriesCount;
//
// Copy the actual TOC entries, leaving out the changing one
//
for (i = 0, j = 0; i < Header->TocEntriesCount; i++) {
if (i == Index) { continue; }
RtlCopyMemory(
&(*NewHeader)->TocEntry[j++],
&Header->TocEntry[i],
sizeof(RTR_TOC_ENTRY)
);
}
//
// Initialize the changing block's TOC entry as the last entry
//
(*NewHeader)->TocEntry[j].InfoType = dwInfoType;
(*NewHeader)->TocEntry[j].InfoSize = dwItemSize;
(*NewHeader)->TocEntry[j].Count = dwItemCount;
//
// Now copy the data for the old header's TOC entries,
// similarly leaving out the changing one.
//
Offset = (LPBYTE)&(*NewHeader)->TocEntry[(*NewHeader)->TocEntriesCount];
ALIGN_POINTER(Offset);
for (i = 0, j = 0; i < Header->TocEntriesCount; i++) {
if (i == Index) { continue; }
RtlCopyMemory(
Offset, GetInfoFromTocEntry(Header, &Header->TocEntry[i]),
Header->TocEntry[i].InfoSize * Header->TocEntry[i].Count
);
(*NewHeader)->TocEntry[j++].Offset =
(DWORD)(Offset - (LPBYTE)*NewHeader);
Offset += Header->TocEntry[i].InfoSize * Header->TocEntry[i].Count;
ALIGN_POINTER(Offset);
}
//
// Copy the new user-supplied data
//
RtlCopyMemory(Offset, lpItemData, dwItemSize * dwItemCount);
(*NewHeader)->TocEntry[j].Offset = (DWORD)(Offset - (LPBYTE)*NewHeader);
Offset += dwItemSize * dwItemCount;
ALIGN_POINTER(Offset);
//
// Set the total size of the changed header
//
(*NewHeader)->Size = (DWORD)(Offset - (LPBYTE)*NewHeader);
return NO_ERROR;
} // MprInfoBlockSet
DWORD APIENTRY
MprInfoBlockFind(
IN LPVOID lpHeader,
IN DWORD dwInfoType,
OUT LPDWORD lpdwItemSize,
OUT LPDWORD lpdwItemCount,
OUT LPBYTE* lplpItemData
)
{
PRTR_INFO_BLOCK_HEADER Header = (PRTR_INFO_BLOCK_HEADER)lpHeader;
DWORD i;
//
// Validate parameters
//
if (!lpHeader) { return ERROR_INVALID_PARAMETER; }
//
// Find the block requested
//
for (i = 0; i < Header->TocEntriesCount; i++) {
if (Header->TocEntry[i].InfoType == dwInfoType) { break; }
}
if (i >= Header->TocEntriesCount) { return ERROR_NOT_FOUND; }
//
// The item was found; fill in fields requested by the caller.
//
if (lpdwItemSize) { *lpdwItemSize = Header->TocEntry[i].InfoSize; }
if (lpdwItemCount) { *lpdwItemCount = Header->TocEntry[i].Count; }
if (lplpItemData) {
*lplpItemData = GetInfoFromTocEntry(Header, &Header->TocEntry[i]);
}
return NO_ERROR;
} // MprInfoBlockFind
DWORD APIENTRY
MprInfoBlockQuerySize(
IN LPVOID lpHeader
)
{
PRTR_INFO_BLOCK_HEADER Header = (PRTR_INFO_BLOCK_HEADER)lpHeader;
if(Header == NULL)
{
return 0;
}
return Header->Size;
} // MprInfoBlockQuerySize