I am using WinVerifyTrust to verify the validity of some Windows executables with the following function, called in a loop from _tmain:
int signature_is_valid(const wchar_t *filepath) {
GUID guid = WINTRUST_ACTION_GENERIC_VERIFY_V2;
WINTRUST_FILE_INFO file_info = { 0 };
WINTRUST_DATA wd;
file_info.cbStruct = sizeof(file_info);
file_info.pcwszFilePath = filepath;
file_info.hFile = NULL;
file_info.pgKnownSubject = NULL;
ZeroMemory(&wd, sizeof(wd));
wd.cbStruct = sizeof(wd);
wd.dwUIChoice = WTD_UI_NONE;
wd.fdwRevocationChecks = WTD_REVOCATION_CHECK_NONE;
wd.dwUnionChoice = WTD_CHOICE_FILE;
wd.dwStateAction = 0;
wd.pFile = &file_info;
wd.dwProvFlags = WTD_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT | WTD_CACHE_ONLY_URL_RETRIEVAL;
return 0 == WinVerifyTrust(NULL, &guid, &wd);
}
However, with every loop the memory keeps growing, a sure sign of a memory leak.
Is there a problem with my understanding of the API or is the WinVerifyTrust function actually leaking? I am testing this on a Windows XP Professional SP3 system.
EDIT:
Here is some output from umdh:
+ 16812 ( 16992 - 180) 472 allocs BackTraceAD1
+ 467 ( 472 - 5) BackTraceAD1 allocations
ntdll!RtlDebugAllocateHeap+000000E1
ntdll!RtlAllocateHeapSlowly+00000044
ntdll!RtlAllocateHeap+00000E64
kernel32!LocalAlloc+00000058
CRYPT32!operator new+00000011
CRYPT32!I_CryptCreateLruEntry+00000011
CRYPT32!CreateAuthRootAutoUpdateMatchCaches+00000107
CRYPT32!CCertChainEngine::FindAuthRootAutoUpdateMatchingCtlEntries+0000004D
CRYPT32!CChainPathObject::GetAuthRootAutoUpdateUrlStore+000000C9
CRYPT32!CChainPathObject::CChainPathObject+0000030E
CRYPT32!ChainCreatePathObject+00000050
CRYPT32!CCertIssuerList::AddIssuer+0000006A
CRYPT32!CChainPathObject::FindAndAddIssuersFromStoreByMatchType+00000182
CRYPT32!CChainPathObject::FindAndAddIssuersByMatchType+00000096
CRYPT32!CChainPathObject::FindAndAddIssuers+00000023
CRYPT32!CChainPathObject::CChainPathObject+000001F9
CRYPT32!ChainCreatePathObject+00000050
CRYPT32!CCertIssuerList::AddIssuer+0000006A
CRYPT32!CChainPathObject::FindAndAddIssuersFromCacheByMatchType+00000084
CRYPT32!CChainPathObject::FindAndAddIssuersByMatchType+00000023
CRYPT32!CChainPathObject::FindAndAddIssuers+00000063
CRYPT32!CChainPathObject::CChainPathObject+000001F9
CRYPT32!ChainCreatePathObject+00000050
CRYPT32!CCertChainEngine::CreateChainContextFromPathGraph+0000019E
CRYPT32!CCertChainEngine::GetChainContext+00000044
CRYPT32!CertGetCertificateChain+00000060
WINTRUST!_WalkChain+0000019C
WINTRUST!WintrustCertificateTrust+000000B7
WINTRUST!_VerifyTrust+00000144
WINTRUST!WinVerifyTrust+0000004E
SigTest!signature_is_valid+000000DD
+ 10984 ( 10984 - 0) 2 allocs BackTraceBB3
+ 2 ( 2 - 0) BackTraceBB3 allocations
ntdll!RtlDebugAllocateHeap+000000E1
ntdll!RtlAllocateHeapSlowly+00000044
ntdll!RtlAllocateHeap+00000E64
kernel32!LocalAlloc+00000058
CRYPT32!PkiDefaultCryptAlloc+00000011
CRYPT32!CertFindCertificateInCRL+00000051
cryptnet!MicrosoftCertDllVerifyRevocation+00000250
CRYPT32!I_CryptRemainingMilliseconds+0000021B
CRYPT32!CertVerifyRevocation+000000B7
CRYPT32!CChainPathObject::CalculateRevocationStatus+000001F2
CRYPT32!CChainPathObject::CalculateAdditionalStatus+00000147
CRYPT32!CCertChainEngine::CreateChainContextFromPathGraph+00000227
CRYPT32!CCertChainEngine::GetChainContext+00000044
CRYPT32!CertGetCertificateChain+00000060
WINTRUST!_WalkChain+0000019C
WINTRUST!WintrustCertificateTrust+000000B7
WINTRUST!_VerifyTrust+00000144
WINTRUST!WinVerifyTrust+0000004E
SigTest!signature_is_valid+000000DD
SigTest!wmain+00000073
SigTest!__tmainCRTStartup+000001A8
SigTest!wmainCRTStartup+0000000F
kernel32!BaseProcessStart+00000023
It seems to me that the CRYPT32 functions are the ones leaking... or I'm missing something.
EDIT2
Here is the memory evolution for some thousand loops:

I don't see any info that this API leaks. perhaps it's just heap fragmentation in the process?
You can verify this for sure using umdh to take snapshots of your process at time X and X+delta, then analyze the comparative heap usage at those times. Make sure all symbols are available for this to be most helpful.