方法一、二兼容XP,三不兼容XP。
方法一:
/*
* An example of file signature verification using WinTrust API
* Derived from the sample vertrust.cpp in the Platform SDK
*
* Copyright (c) 2009 Mounir IDRASSI . All rights reserved.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE.
*
*/
#ifndef UNICODE
#define UNICODE
#endif
#ifndef _UNICODE
#define _UNICODE
#endif
#define _WIN32_WINNT 0x0500
#define WINVER 0x0500
#include
#include
#include
#include
#include
#pragma comment(lib, "Crypt32.lib")
#pragma comment(lib, "Wintrust.lib")
LPTSTR GetCertificateDescription(PCCERT_CONTEXT pCertCtx)
{
DWORD dwStrType;
DWORD dwCount;
LPTSTR szSubjectRDN = NULL;
dwStrType = CERT_X500_NAME_STR;
dwCount = CertGetNameString(pCertCtx,
CERT_NAME_RDN_TYPE,
0,
&dwStrType,
NULL,
0);
if (dwCount)
{
szSubjectRDN = (LPTSTR) LocalAlloc(0, dwCount * sizeof(TCHAR));
CertGetNameString(pCertCtx,
CERT_NAME_RDN_TYPE,
0,
&dwStrType,
szSubjectRDN,
dwCount);
}
return szSubjectRDN;
}
int _tmain(int argc, _TCHAR* argv[])
{
GUID guidAction = WINTRUST_ACTION_GENERIC_VERIFY_V2;
WINTRUST_FILE_INFO sWintrustFileInfo;
WINTRUST_DATA sWintrustData;
HRESULT hr;
if (argc != 2)
{
_tprintf(_T("Usage: VerifyExeSignature file_name\n"));
return -1;
}
memset((void*)&sWintrustFileInfo, 0x00, sizeof(WINTRUST_FILE_INFO));
memset((void*)&sWintrustData, 0x00, sizeof(WINTRUST_DATA));
sWintrustFileInfo.cbStruct = sizeof(WINTRUST_FILE_INFO);
sWintrustFileInfo.pcwszFilePath = argv[1];
sWintrustFileInfo.hFile = NULL;
sWintrustData.cbStruct = sizeof(WINTRUST_DATA);
sWintrustData.dwUIChoice = WTD_UI_NONE;
sWintrustData.fdwRevocationChecks = WTD_REVOKE_NONE;
sWintrustData.dwUnionChoice = WTD_CHOICE_FILE;
sWintrustData.pFile = &sWintrustFileInfo;
sWintrustData.dwStateAction = WTD_STATEACTION_VERIFY;
hr = WinVerifyTrust((HWND)INVALID_HANDLE_VALUE, &guidAction, &sWintrustData);
if (TRUST_E_NOSIGNATURE == hr)
{
_tprintf(_T("No signature found on the file.\n"));
}
else if (TRUST_E_BAD_DIGEST == hr)
{
_tprintf(_T("The signature of the file is invalid\n"));
}
else if (TRUST_E_PROVIDER_UNKNOWN == hr)
{
_tprintf(_T("No trust provider on this machine can verify this type of files.\n"));
}
else if (S_OK != hr)
{
_tprintf(_T("WinVerifyTrust failed with error 0x%.8X\n"), hr);
}
else
{
_tprintf(_T("File signature is OK.\n"));
// retreive the signer certificate and display its information
CRYPT_PROVIDER_DATA const *psProvData = NULL;
CRYPT_PROVIDER_SGNR *psProvSigner = NULL;
CRYPT_PROVIDER_CERT *psProvCert = NULL;
FILETIME localFt;
SYSTEMTIME sysTime;
psProvData = WTHelperProvDataFromStateData(sWintrustData.hWVTStateData);
if (psProvData)
{
psProvSigner = WTHelperGetProvSignerFromChain((PCRYPT_PROVIDER_DATA)psProvData, 0 , FALSE, 0);
if (psProvSigner)
{
FileTimeToLocalFileTime(&psProvSigner->sftVerifyAsOf, &localFt);
FileTimeToSystemTime(&localFt, &sysTime);
_tprintf(_T("Signature Date = %.2d/%.2d/%.4d at %.2d:%2.d:%.2d\n"), sysTime.wDay, sysTime.wMonth,sysTime.wYear, sysTime.wHour,sysTime.wMinute,sysTime.wSecond);
psProvCert = WTHelperGetProvCertFromChain(psProvSigner, 0);
if (psProvCert)
{
LPTSTR szCertDesc = GetCertificateDescription(psProvCert->pCert);
if (szCertDesc)
{
_tprintf(_T("File Signer = %s\n"), szCertDesc);
LocalFree(szCertDesc);
}
}
if (psProvSigner->csCounterSigners)
{
_tprintf(_T("\n"));
// Timestamp information
FileTimeToLocalFileTime(&psProvSigner->pasCounterSigners[0].sftVerifyAsOf, &localFt);
FileTimeToSystemTime(&localFt, &sysTime);
_tprintf(_T("Timestamp Date = %.2d/%.2d/%.4d at %.2d:%2.d:%.2d\n"), sysTime.wDay, sysTime.wMonth,sysTime.wYear, sysTime.wHour,sysTime.wMinute,sysTime.wSecond);
psProvCert = WTHelperGetProvCertFromChain(&psProvSigner->pasCounterSigners[0], 0);
if (psProvCert)
{
LPTSTR szCertDesc = GetCertificateDescription(psProvCert->pCert);
if (szCertDesc)
{
_tprintf(_T("Timestamp Signer = %s\n"), szCertDesc);
LocalFree(szCertDesc);
}
}
}
}
}
}
sWintrustData.dwUIChoice = WTD_UI_NONE;
sWintrustData.dwStateAction = WTD_STATEACTION_CLOSE;
WinVerifyTrust((HWND)INVALID_HANDLE_VALUE, &guidAction, &sWintrustData);
return 0;
}
#include
#include
#include
#include
#include
#include
#pragma comment(lib, "wintrust")
BOOLEAN IsFileDigitallySigned(PWCHAR FilePath)
{
//Author: AD, 2009
PVOID Context;
HANDLE FileHandle;
DWORD HashSize = 0;
PBYTE Buffer;
PVOID CatalogContext;
CATALOG_INFO InfoStruct;
WINTRUST_DATA WintrustStructure;
WINTRUST_CATALOG_INFO WintrustCatalogStructure;
WINTRUST_FILE_INFO WintrustFileStructure;
PWCHAR MemberTag;
BOOLEAN ReturnFlag = FALSE;
ULONG ReturnVal;
GUID ActionGuid = WINTRUST_ACTION_GENERIC_VERIFY_V2;
//Zero our structures.
memset(&InfoStruct, 0, sizeof(CATALOG_INFO));
InfoStruct.cbStruct = sizeof(CATALOG_INFO);
memset(&WintrustCatalogStructure, 0, sizeof(WINTRUST_CATALOG_INFO));
WintrustCatalogStructure.cbStruct = sizeof(WINTRUST_CATALOG_INFO);
memset(&WintrustFileStructure, 0, sizeof(WINTRUST_FILE_INFO));
WintrustFileStructure.cbStruct = sizeof(WINTRUST_FILE_INFO);
//Get a context for signature verification.
if (!CryptCATAdminAcquireContext(&Context, NULL, 0))
{
return FALSE;
}
//Open file.
FileHandle = CreateFileW(FilePath, GENERIC_READ, 7, NULL, OPEN_EXISTING, 0, NULL);
if (INVALID_HANDLE_VALUE == FileHandle)
{
CryptCATAdminReleaseContext(Context, 0);
return FALSE;
}
//Get the size we need for our hash.
CryptCATAdminCalcHashFromFileHandle(FileHandle, &HashSize, NULL, 0);
if (HashSize == 0)
{
//0-sized has means error!
CryptCATAdminReleaseContext(Context, 0);
CloseHandle(FileHandle);
return FALSE;
}
//Allocate memory.
Buffer = (PBYTE)calloc(HashSize, 1);
//Actually calculate the hash
if (!CryptCATAdminCalcHashFromFileHandle(FileHandle, &HashSize, Buffer, 0))
{
CryptCATAdminReleaseContext(Context, 0);
free(Buffer);
CloseHandle(FileHandle);
return FALSE;
}
//Convert the hash to a string.
MemberTag = (PWCHAR)calloc((HashSize * 2) + 1, sizeof(WCHAR));
for (unsigned int i = 0; i < HashSize; i++)
{
swprintf(&MemberTag[i * 2],100, L"%02X", Buffer[i]);
}
//Get catalog for our context.
CatalogContext = CryptCATAdminEnumCatalogFromHash(Context, Buffer, HashSize, 0, NULL);
if (CatalogContext)
{
//If we couldn't get information
if (!CryptCATCatalogInfoFromContext(CatalogContext, &InfoStruct, 0))
{
//Release the context and set the context to null so it gets picked up below.
CryptCATAdminReleaseCatalogContext(Context, CatalogContext, 0);
CatalogContext = NULL;
}
}
//If we have a valid context, we got our info.
//Otherwise, we attempt to verify the internal signature.
if (!CatalogContext)
{
WintrustFileStructure.cbStruct = sizeof(WINTRUST_FILE_INFO);
WintrustFileStructure.pcwszFilePath = FilePath;
WintrustFileStructure.hFile = NULL;
WintrustFileStructure.pgKnownSubject = NULL;
WintrustStructure.cbStruct = sizeof(WINTRUST_DATA);
WintrustStructure.dwUnionChoice = WTD_CHOICE_FILE;
WintrustStructure.pFile = &WintrustFileStructure;
WintrustStructure.dwUIChoice = WTD_UI_NONE;
WintrustStructure.fdwRevocationChecks = WTD_REVOKE_NONE;
WintrustStructure.dwStateAction = WTD_STATEACTION_IGNORE;
WintrustStructure.dwProvFlags = WTD_SAFER_FLAG;
WintrustStructure.hWVTStateData = NULL;
WintrustStructure.pwszURLReference = NULL;
}
else
{
//If we get here, we have catalog info! Verify it.
WintrustStructure.cbStruct = sizeof(WINTRUST_DATA);
WintrustStructure.pPolicyCallbackData = 0;
WintrustStructure.pSIPClientData = 0;
WintrustStructure.dwUIChoice = WTD_UI_NONE;
WintrustStructure.fdwRevocationChecks = WTD_REVOKE_NONE;
WintrustStructure.dwUnionChoice = WTD_CHOICE_CATALOG;
WintrustStructure.pCatalog = &WintrustCatalogStructure;
WintrustStructure.dwStateAction = WTD_STATEACTION_VERIFY;
WintrustStructure.hWVTStateData = NULL;
WintrustStructure.pwszURLReference = NULL;
WintrustStructure.dwProvFlags = 0;
WintrustStructure.dwUIContext = WTD_UICONTEXT_EXECUTE;
//Fill in catalog info structure.
WintrustCatalogStructure.cbStruct = sizeof(WINTRUST_CATALOG_INFO);
WintrustCatalogStructure.dwCatalogVersion = 0;
WintrustCatalogStructure.pcwszCatalogFilePath = InfoStruct.wszCatalogFile;
WintrustCatalogStructure.pcwszMemberTag = MemberTag;
WintrustCatalogStructure.pcwszMemberFilePath = FilePath;
WintrustCatalogStructure.hMemberFile = NULL;
}
//Call our verification function.
ReturnVal = WinVerifyTrust(0, &ActionGuid, &WintrustStructure);
//Check return.
ReturnFlag = SUCCEEDED(ReturnVal);
//Free context.
if (CatalogContext)
CryptCATAdminReleaseCatalogContext(Context, CatalogContext, 0);
//If we successfully verified, we need to free.
if (ReturnFlag)
{
WintrustStructure.dwStateAction = WTD_STATEACTION_CLOSE;
WinVerifyTrust(0, &ActionGuid, &WintrustStructure);
}
//Free memory.
free(MemberTag);
free(Buffer);
CloseHandle(FileHandle);
CryptCATAdminReleaseContext(Context, 0);
return ReturnFlag;
}
int _tmain(int argc, _TCHAR* argv[])
{
IsFileDigitallySigned(L"C:\\Windows\\System32\\svchost.exe");
}
//验证数字签名有效性 xp下不兼容,为使xp下可用,暂不使用此代码
DWORD VerifyEmbeddedSignatures(_In_ PCWSTR FileName,
_In_ HANDLE FileHandle,
_In_ bool UseStrongSigPolicy);
DWORD VerifyCatalogSignature(_In_ HANDLE FileHandle,
_In_ bool UseStrongSigPolicy);
BOOL VerifyFileSig(char *pFileName);
//
// 以下为验证数字签名有效性 xp下不兼容,为使xp下可用,暂不使用此代码
//
BOOL CheckFileTrust2(LPCWSTR lpFileName) //传进来的必须是LPCWSTR型的,不可以是char*
{
BOOL bRet = FALSE;
WINTRUST_DATA wd = { 0 };
WINTRUST_FILE_INFO wfi = { 0 };
WINTRUST_CATALOG_INFO wci = { 0 };
CATALOG_INFO ci = { 0 };
HCATADMIN hCatAdmin = NULL;
if (!CryptCATAdminAcquireContext(&hCatAdmin, NULL, 0))
{
return FALSE;
}
HANDLE hFile = CreateFileW(lpFileName, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, 0, NULL);
if (INVALID_HANDLE_VALUE == hFile)
{
CryptCATAdminReleaseContext(hCatAdmin, 0);
return FALSE;
}
DWORD dwCnt = 100;
BYTE byHash[100];
CryptCATAdminCalcHashFromFileHandle(hFile, &dwCnt, byHash, 0);
CloseHandle(hFile);
LPWSTR pszMemberTag = new WCHAR[dwCnt * 2 + 1];
for (DWORD dw = 0; dw < dwCnt; ++dw)
{
wsprintfW(&pszMemberTag[dw * 2], L"%02X", byHash[dw]);
}
HCATINFO hCatInfo = CryptCATAdminEnumCatalogFromHash(hCatAdmin,
byHash, dwCnt, 0, NULL);
if (NULL == hCatInfo)
{
wfi.cbStruct = sizeof(WINTRUST_FILE_INFO);
wfi.pcwszFilePath = lpFileName;
wfi.hFile = NULL;
wfi.pgKnownSubject = NULL;
wd.cbStruct = sizeof(WINTRUST_DATA);
wd.dwUnionChoice = WTD_CHOICE_FILE;
wd.pFile = &wfi;
wd.dwUIChoice = WTD_UI_NONE;
wd.fdwRevocationChecks = WTD_REVOKE_NONE;
wd.dwStateAction = WTD_STATEACTION_IGNORE;
wd.dwProvFlags = WTD_SAFER_FLAG;
wd.hWVTStateData = NULL;
wd.pwszURLReference = NULL;
}
else
{
CryptCATCatalogInfoFromContext(hCatInfo, &ci, 0);
wci.cbStruct = sizeof(WINTRUST_CATALOG_INFO);
wci.pcwszCatalogFilePath = ci.wszCatalogFile;
wci.pcwszMemberFilePath = lpFileName;
wci.pcwszMemberTag = pszMemberTag;
wd.cbStruct = sizeof(WINTRUST_DATA);
wd.dwUnionChoice = WTD_CHOICE_CATALOG;
wd.pCatalog = &wci;
wd.dwUIChoice = WTD_UI_NONE;
wd.fdwRevocationChecks = WTD_STATEACTION_VERIFY;
wd.dwProvFlags = 0;
wd.hWVTStateData = NULL;
wd.pwszURLReference = NULL;
}
GUID action = WINTRUST_ACTION_GENERIC_VERIFY_V2;
HRESULT hr = WinVerifyTrust(NULL, &action, &wd);
bRet = SUCCEEDED(hr);
if (NULL != hCatInfo)
{
CryptCATAdminReleaseCatalogContext(hCatAdmin, hCatInfo, 0);
}
CryptCATAdminReleaseContext(hCatAdmin, 0);
delete[] pszMemberTag;
return bRet;
}
//----------------------------------------------------------------------------
//
// VerifyEmbeddedSignatures
// Verifies all embedded signatures of a file
//
//----------------------------------------------------------------------------
DWORD VerifyEmbeddedSignatures(_In_ PCWSTR FileName,
_In_ HANDLE FileHandle,
_In_ bool UseStrongSigPolicy)
{
DWORD Error = ERROR_SUCCESS;
bool WintrustCalled = false;
GUID GenericActionId = WINTRUST_ACTION_GENERIC_VERIFY_V2;
WINTRUST_DATA WintrustData = {};
WINTRUST_FILE_INFO FileInfo = {};
WINTRUST_SIGNATURE_SETTINGS SignatureSettings = {};
CERT_STRONG_SIGN_PARA StrongSigPolicy = {};
// Setup data structures for calling WinVerifyTrust
WintrustData.cbStruct = sizeof(WINTRUST_DATA);
WintrustData.dwStateAction = WTD_STATEACTION_VERIFY;
WintrustData.dwUIChoice = WTD_UI_NONE;
WintrustData.fdwRevocationChecks = WTD_REVOKE_NONE;
WintrustData.dwUnionChoice = WTD_CHOICE_FILE;
FileInfo.cbStruct = sizeof(WINTRUST_FILE_INFO_);
FileInfo.hFile = FileHandle;
FileInfo.pcwszFilePath = FileName;
WintrustData.pFile = &FileInfo;
//
// First verify the primary signature (index 0) to determine how many secondary signatures
// are present. We use WSS_VERIFY_SPECIFIC and dwIndex to do this, also setting
// WSS_GET_SECONDARY_SIG_COUNT to have the number of secondary signatures returned.
//
SignatureSettings.cbStruct = sizeof(WINTRUST_SIGNATURE_SETTINGS);
SignatureSettings.dwFlags = WSS_GET_SECONDARY_SIG_COUNT | WSS_VERIFY_SPECIFIC;
SignatureSettings.dwIndex = 0;
WintrustData.pSignatureSettings = &SignatureSettings;
if (UseStrongSigPolicy != false)
{
StrongSigPolicy.cbSize = sizeof(CERT_STRONG_SIGN_PARA);
StrongSigPolicy.dwInfoChoice = CERT_STRONG_SIGN_OID_INFO_CHOICE;
StrongSigPolicy.pszOID = szOID_CERT_STRONG_SIGN_OS_CURRENT;
WintrustData.pSignatureSettings->pCryptoPolicy = &StrongSigPolicy;
}
wprintf(L"Verifying primary signature... ");
Error = WinVerifyTrust(NULL, &GenericActionId, &WintrustData);
WintrustCalled = true;
if (Error != ERROR_SUCCESS)
{
goto Cleanup;
}
wprintf(L"Success!\n");
wprintf(L"Found %d secondary signatures\n", WintrustData.pSignatureSettings->cSecondarySigs);
// Now attempt to verify all secondary signatures that were found
for (DWORD x = 1; x <= WintrustData.pSignatureSettings->cSecondarySigs; x++)
{
wprintf(L"Verify secondary signature at index %d... ", x);
// Need to clear the previous state data from the last call to WinVerifyTrust
WintrustData.dwStateAction = WTD_STATEACTION_CLOSE;
Error = WinVerifyTrust(NULL, &GenericActionId, &WintrustData);
if (Error != ERROR_SUCCESS)
{
//No need to call WinVerifyTrust again
WintrustCalled = false;
goto Cleanup;
}
WintrustData.hWVTStateData = NULL;
// Caller must reset dwStateAction as it may have been changed during the last call
WintrustData.dwStateAction = WTD_STATEACTION_VERIFY;
WintrustData.pSignatureSettings->dwIndex = x;
Error = WinVerifyTrust(NULL, &GenericActionId, &WintrustData);
if (Error != ERROR_SUCCESS)
{
goto Cleanup;
}
wprintf(L"Success!\n");
}
Cleanup:
//
// Caller must call WinVerifyTrust with WTD_STATEACTION_CLOSE to free memory
// allocate by WinVerifyTrust
//
if (WintrustCalled != false)
{
WintrustData.dwStateAction = WTD_STATEACTION_CLOSE;
WinVerifyTrust(NULL, &GenericActionId, &WintrustData);
}
return Error;
}
//----------------------------------------------------------------------------
//
// VerifyCatalogSignature
// Looks up a file by hash in the system catalogs.
//
//----------------------------------------------------------------------------
DWORD VerifyCatalogSignature(_In_ HANDLE FileHandle,
_In_ bool UseStrongSigPolicy)
{
DWORD Error = ERROR_SUCCESS;
bool Found = false;
HCATADMIN CatAdminHandle = NULL;
HCATINFO CatInfoHandle = NULL;
DWORD HashLength = 0;
PBYTE HashData = NULL;
CERT_STRONG_SIGN_PARA SigningPolicy = {};
if (UseStrongSigPolicy != false)
{
SigningPolicy.cbSize = sizeof(CERT_STRONG_SIGN_PARA);
SigningPolicy.dwInfoChoice = CERT_STRONG_SIGN_OID_INFO_CHOICE;
SigningPolicy.pszOID = szOID_CERT_STRONG_SIGN_OS_CURRENT;
if (!CryptCATAdminAcquireContext2(
&CatAdminHandle,
NULL,
BCRYPT_SHA256_ALGORITHM,
&SigningPolicy,
0))
{
Error = GetLastError();
goto Cleanup;
}
}
else
{
if (!CryptCATAdminAcquireContext2(
&CatAdminHandle,
NULL,
BCRYPT_SHA256_ALGORITHM,
NULL,
0))
{
Error = GetLastError();
goto Cleanup;
}
}
// Get size of hash to be used
if (!CryptCATAdminCalcHashFromFileHandle2(
CatAdminHandle,
FileHandle,
&HashLength,
NULL,
NULL))
{
Error = GetLastError();
goto Cleanup;
}
HashData = (PBYTE)HeapAlloc(GetProcessHeap(), 0, HashLength);
if (HashData == NULL)
{
Error = ERROR_OUTOFMEMORY;
goto Cleanup;
}
// Generate hash for a give file
if (!CryptCATAdminCalcHashFromFileHandle2(
CatAdminHandle,
FileHandle,
&HashLength,
HashData,
NULL))
{
Error = GetLastError();
goto Cleanup;
}
// Find the first catalog containing this hash
CatInfoHandle = NULL;
CatInfoHandle = CryptCATAdminEnumCatalogFromHash(
CatAdminHandle,
HashData,
HashLength,
0,
&CatInfoHandle);
while (CatInfoHandle != NULL)
{
CATALOG_INFO catalogInfo = {};
catalogInfo.cbStruct = sizeof(catalogInfo);
Found = true;
if (!CryptCATCatalogInfoFromContext(
CatInfoHandle,
&catalogInfo,
0))
{
Error = GetLastError();
break;
}
wprintf(L"Hash was found in catalog %s\n\n", catalogInfo.wszCatalogFile);
// Look for the next catalog containing the file's hash
CatInfoHandle = CryptCATAdminEnumCatalogFromHash(
CatAdminHandle,
HashData,
HashLength,
0,
&CatInfoHandle);
}
if (Found != true)
{
Error = S_FALSE;
wprintf(L"Hash was not found in any catalogs.\n");
}
Cleanup:
if (CatAdminHandle != NULL)
{
if (CatInfoHandle != NULL)
{
CryptCATAdminReleaseCatalogContext(CatAdminHandle, CatInfoHandle, 0);
}
CryptCATAdminReleaseContext(CatAdminHandle, 0);
}
if (HashData != NULL)
{
HeapFree(GetProcessHeap(), 0, HashData);
}
return Error;
}
BOOL VerifyFileSig(char *pFileName)
{
bool UseStrongSigPolicy = false;
WCHAR FilePathW[MAX_PATH] = { 0 }; //把char型的路径转换成wchar,CheckFileTrust必须传入wchar
if (str::MByteToWChar(pFileName, FilePathW, MAX_PATH))
{
if (CheckFileTrust2(FilePathW))
{
return TRUE;
}
HANDLE FileHandle = CreateFileW(FilePathW,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
0,
NULL);
if (FileHandle == INVALID_HANDLE_VALUE)
{
return FALSE;
}
HRESULT hr = VerifyCatalogSignature(FileHandle, UseStrongSigPolicy);
if (SUCCEEDED(hr))
{
hr = VerifyEmbeddedSignatures(FilePathW, FileHandle, UseStrongSigPolicy);
CloseHandle(FileHandle);
return SUCCEEDED(hr);// ? FALSE : TRUE;
}
else
{
CloseHandle(FileHandle);
return TRUE;
}
}
return FALSE;
}
//int __cdecl wmain(_In_ unsigned int argc, _In_reads_(argc) PCWSTR wargv[])
//{
// DWORD Error = ERROR_SUCCESS;
// HANDLE FileHandle = INVALID_HANDLE_VALUE;
// DWORD ArgStart = 1;
// bool UseStrongSigPolicy = false;
//
// if (argc < 3 || argc > 4)
// {
// PrintUsage(wargv[0]);
// Error = ERROR_INVALID_PARAMETER;
// goto Cleanup;
// }
//
// if (_wcsicmp(wargv[ArgStart], L"-p") == 0)
// {
// UseStrongSigPolicy = true;
// ArgStart++;
// }
//
// if (ArgStart + 1 >= argc)
// {
// PrintUsage(wargv[0]);
// Error = ERROR_INVALID_PARAMETER;
// goto Cleanup;
// }
//
// if ((wcslen(wargv[ArgStart]) != 2) ||
// ((_wcsicmp(wargv[ArgStart], L"-c") != 0) &&
// (_wcsicmp(wargv[ArgStart], L"-e") != 0)))
// {
// PrintUsage(wargv[0]);
// Error = ERROR_INVALID_PARAMETER;
// goto Cleanup;
// }
//
// FileHandle = CreateFileW(wargv[ArgStart + 1],
// GENERIC_READ,
// FILE_SHARE_READ,
// NULL,
// OPEN_EXISTING,
// 0,
// NULL);
// if (FileHandle == INVALID_HANDLE_VALUE)
// {
// Error = GetLastError();
// PrintError(Error);
// goto Cleanup;
// }
//
// if (_wcsicmp(wargv[ArgStart], L"-c") == 0)
// {
// Error = VerifyCatalogSignature(FileHandle, UseStrongSigPolicy);
// }
// else if (_wcsicmp(wargv[ArgStart], L"-e") == 0)
// {
// Error = VerifyEmbeddedSignatures(wargv[ArgStart + 1], FileHandle, UseStrongSigPolicy);
// }
// else
// {
// PrintUsage(wargv[0]);
// Error = ERROR_INVALID_PARAMETER;
// }
//
//Cleanup:
// if (FileHandle != INVALID_HANDLE_VALUE)
// {
// CloseHandle(FileHandle);
// }
//
// return Error;
//}