584 lines
12 KiB
C
584 lines
12 KiB
C
|
/*++
|
|||
|
|
|||
|
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
|