/*++ 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 #include #include #include #include #include #include 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