windows-nt/Source/XPSP1/NT/ds/security/cryptoapi/ui/wizards/buildctl.cpp

5764 lines
191 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
//-------------------------------------------------------------
// Copyright (C) Microsoft Corporation, 1996 - 1999
//
// File: buildctl.cpp
//
// Contents: The cpp file to implement the makectl wizard
//
// History: 10-11-1997 xiaohs created
//
//--------------------------------------------------------------
#include "wzrdpvk.h"
#include "buildctl.h"
#include "wintrustp.h"
//***********************************************************************
//
// WinProc helper functions
//**********************************************************************
//--------------------------------------------------------------------------
//
// CheckReplace
//
//--------------------------------------------------------------------------
BOOL CheckReplace(HWND hwndDlg, LPWSTR pwszFileName)
{
BOOL fReplace=FALSE;
WCHAR wszTitle[MAX_STRING_SIZE];
WCHAR wszText[MAX_STRING_SIZE];
WCHAR wszFileText[MAX_STRING_SIZE];
if(NULL == pwszFileName || NULL == hwndDlg)
goto CLEANUP;
//title
#if (0) //DSIE: Bug 160615
if(!LoadStringU(g_hmodThisDll, IDS_BUILDCTL_WIZARD_TITLE, wszTitle, sizeof(wszTitle)))
#else
if(!LoadStringU(g_hmodThisDll, IDS_BUILDCTL_WIZARD_TITLE, wszTitle, sizeof(wszTitle) / sizeof(wszTitle[0])))
#endif
goto CLEANUP;
//text
#if (0) //DSIE: Bug 160616
if(!LoadStringU(g_hmodThisDll, IDS_REPLACE_FILE, wszText, sizeof(wszText)))
#else
if(!LoadStringU(g_hmodThisDll, IDS_REPLACE_FILE, wszText, sizeof(wszText) / sizeof(wszText[0])))
#endif
goto CLEANUP;
if(0 == swprintf(wszFileText, wszText, pwszFileName))
goto CLEANUP;
if(IDNO==MessageBoxExW(hwndDlg, wszFileText, wszTitle,
MB_YESNO|MB_ICONWARNING|MB_DEFBUTTON2|MB_APPLMODAL, 0))
fReplace=FALSE;
else
fReplace=TRUE;
CLEANUP:
return fReplace;
}
//--------------------------------------------------------------------------
//
// DuratioinWithinLimit: We limit the CTL to 99 months.
//
//--------------------------------------------------------------------------
BOOL DurationWithinLimit(DWORD dwMonths, DWORD dwDays)
{
BOOL fResult=FALSE;
FILETIME ThisUpdate;
FILETIME NextUpdate;
DWORD dwNewMonth=0;
DWORD dwNewDay=0;
if((0==dwMonths) && (0==dwDays))
return TRUE;
//This update field
GetSystemTimeAsFileTime(&ThisUpdate);
AddDurationToFileTime(dwMonths,
dwDays,
&ThisUpdate,
&NextUpdate);
SubstractDurationFromFileTime(
&NextUpdate,
&ThisUpdate,
&dwNewMonth,
&dwNewDay);
if((dwNewMonth > 99) ||
(dwNewMonth == 99 && dwNewDay !=0))
return FALSE;
return TRUE;
}
//--------------------------------------------------------------------------
//
// FormatMessageIDSU
//
//--------------------------------------------------------------------------
BOOL FormatMessageIDSU(LPWSTR *ppwszFormat,UINT ids, ...)
{
WCHAR wszFormat[MAX_STRING_SIZE];
LPWSTR pwszMsg=NULL;
BOOL fResult=FALSE;
va_list argList;
va_start(argList, ids);
#if (0) //DSIE: Bug 160614
if(!LoadStringU(g_hmodThisDll, ids, wszFormat, sizeof(wszFormat)))
#else
if(!LoadStringU(g_hmodThisDll, ids, wszFormat, sizeof(wszFormat) / sizeof(wszFormat[0])))
#endif
goto LoadStringError;
if(!FormatMessageU(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
wszFormat,
0,
0,
(LPWSTR)&pwszMsg,
0,
&argList))
goto FormatMessageError;
if(!(*ppwszFormat=WizardAllocAndCopyWStr(pwszMsg)))
goto SZtoWSZError;
fResult=TRUE;
CommonReturn:
va_end(argList);
if(pwszMsg)
LocalFree((HLOCAL)pwszMsg);
return fResult;
ErrorReturn:
fResult=FALSE;
goto CommonReturn;
TRACE_ERROR(LoadStringError);
TRACE_ERROR(FormatMessageError);
TRACE_ERROR(SZtoWSZError);
}
/* // get format string from resources
CHAR szFormat[256];
va_list argList;
LPSTR pszMsg=NULL;
DWORD cbMsg=0;
BOOL fResult=FALSE;
HRESULT hr=S_OK;
if(!LoadStringA(g_hmodThisDll, ids, szFormat, sizeof(szFormat)))
goto LoadStringError;
// format message into requested buffer
va_start(argList, ids);
cbMsg = FormatMessageA(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
szFormat,
0, // dwMessageId
0, // dwLanguageId
(LPSTR) &pszMsg,
0, // minimum size to allocate
&argList);
va_end(argList);
if(!cbMsg)
goto FormatMessageError;
//copy the sz to wsz
if(!(*ppwszFormat=MkWStr(pszMsg)))
goto SZtoWSZError;
fResult=TRUE;
CommonReturn:
if(pszMsg)
LocalFree((HLOCAL)pszMsg);
return fResult;
ErrorReturn:
fResult=FALSE;
goto CommonReturn;
TRACE_ERROR(LoadStringError);
TRACE_ERROR(FormatMessageError);
TRACE_ERROR(SZtoWSZError);
} */
//----------------------------------------------------------------------------
// GetValidityString
//
//----------------------------------------------------------------------------
BOOL GetValidityString(DWORD dwValidMonths,
DWORD dwValidDays,
LPWSTR *ppwszString)
{
BOOL fResult=FALSE;
if(!ppwszString)
return FALSE;
*ppwszString=NULL;
if((0==dwValidMonths) && (0==dwValidDays))
return FALSE;
if(dwValidMonths && dwValidDays)
fResult=FormatMessageIDSU(ppwszString, IDS_CTL_VALID_MONTH_DAY,
dwValidMonths, dwValidDays);
else
{
if(dwValidMonths)
fResult=FormatMessageIDSU(ppwszString, IDS_CTL_VALID_MONTH, dwValidMonths);
else
fResult=FormatMessageIDSU(ppwszString, IDS_CTL_VALID_DAY, dwValidDays);
}
return fResult;
}
//----------------------------------------------------------------------------
// Make sure that user has typed
//
//----------------------------------------------------------------------------
BOOL ValidDuration(LPWSTR pwszDuration)
{
DWORD i=0;
if(NULL==pwszDuration)
return FALSE;
//only numerical numbers should be allowed
for (i=0; i< (DWORD)(wcslen(pwszDuration)); i++)
{
if ((pwszDuration[i] < L'0') || (pwszDuration[i] > L'9'))
return FALSE;
}
return TRUE;
}
//----------------------------------------------------------------------------
// SetStoreName
//
//----------------------------------------------------------------------------
void SetStoreName(HWND hwndControl,
HCERTSTORE hDesStore)
{
LPWSTR pwszStoreName=NULL;
// LV_COLUMNW lvC;
// LV_ITEMW lvItem;
DWORD dwSize=0;
//get the store name
if(!CertGetStoreProperty(
hDesStore,
CERT_STORE_LOCALIZED_NAME_PROP_ID,
NULL,
&dwSize) || (0==dwSize))
{
//DSIE: Prefix bug 427201.
//Get the <Unknown> string
pwszStoreName=(LPWSTR)WizardAlloc(MAX_TITLE_LENGTH * sizeof(WCHAR));
if(pwszStoreName)
{
*pwszStoreName=L'\0';
LoadStringU(g_hmodThisDll, IDS_UNKNOWN, pwszStoreName, MAX_TITLE_LENGTH);
}
}
else
{
pwszStoreName=(LPWSTR)WizardAlloc(dwSize);
if(pwszStoreName)
{
*pwszStoreName=L'\0';
CertGetStoreProperty(
hDesStore,
CERT_STORE_LOCALIZED_NAME_PROP_ID,
pwszStoreName,
&dwSize);
}
}
if(pwszStoreName)
SetWindowTextU(hwndControl,pwszStoreName);
if(pwszStoreName)
WizardFree(pwszStoreName);
/* //clear the ListView
ListView_DeleteAllItems(hwndControl);
//set the store name
//only one column is needed
memset(&lvC, 0, sizeof(LV_COLUMNW));
lvC.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
lvC.fmt = LVCFMT_LEFT; // Left-align the column.
lvC.cx =10; //(wcslen(pwszStoreName)+2)*7; // Width of the column, in pixels.
lvC.pszText = L""; // The text for the column.
lvC.iSubItem=0;
if (ListView_InsertColumnU(hwndControl, 0, &lvC) == -1)
{
if(pwszStoreName)
WizardFree(pwszStoreName);
return;
}
//insert the store name
memset(&lvItem, 0, sizeof(LV_ITEMW));
// set up the fields in the list view item struct that don't change from item to item
lvItem.mask = LVIF_TEXT | LVIF_STATE ;
lvItem.state = 0;
lvItem.stateMask = 0;
lvItem.iItem=0;
lvItem.iSubItem=0;
lvItem.pszText=pwszStoreName;
ListView_InsertItemU(hwndControl, &lvItem);
//automatically resize the column
ListView_SetColumnWidth(hwndControl, 0, LVSCW_AUTOSIZE); */
}
BOOL SameCert(PCCERT_CONTEXT pCertOne, PCCERT_CONTEXT pCertTwo)
{
if(!pCertOne || !pCertTwo)
return FALSE;
if(pCertOne->cbCertEncoded != pCertTwo->cbCertEncoded)
return FALSE;
if(0 == memcmp(pCertOne->pbCertEncoded, pCertTwo->pbCertEncoded, pCertTwo->cbCertEncoded))
return TRUE;
return FALSE;
}
//----------------------------------------------------------------------------
// Delete a certificate from the pCertBuildCTLInfo
//
//----------------------------------------------------------------------------
BOOL DeleteCertFromBuildCTL(CERT_BUILDCTL_INFO *pCertBuildCTLInfo,
PCCERT_CONTEXT pCertContext)
{
//we need to remove the cert from our array
PCCERT_CONTEXT *prgCertContext=NULL;
DWORD dwIndex=0;
DWORD dwNewIndex=0;
int iIndex=-1;
if(!pCertBuildCTLInfo || !pCertContext)
return FALSE;
//consider the case of only one cert left
if(pCertBuildCTLInfo->dwCertCount == 1)
{
pCertBuildCTLInfo->dwCertCount=0;
//free the certificate context
CertFreeCertificateContext(pCertBuildCTLInfo->prgCertContext[0]);
WizardFree(pCertBuildCTLInfo->prgCertContext);
pCertBuildCTLInfo->prgCertContext=NULL;
}
else
{
prgCertContext=pCertBuildCTLInfo->prgCertContext;
//re-allocate the memory
pCertBuildCTLInfo->prgCertContext=(PCCERT_CONTEXT *)WizardAlloc(sizeof(PCCERT_CONTEXT) *
(pCertBuildCTLInfo->dwCertCount-1));
//if we are out of memory
if(NULL==pCertBuildCTLInfo->prgCertContext)
{
//reset
pCertBuildCTLInfo->prgCertContext=prgCertContext;
return FALSE;
}
//copy the certificate context over
dwNewIndex=0;
for(dwIndex=0; dwIndex<pCertBuildCTLInfo->dwCertCount; dwIndex++)
{
//find the cert to delete, and do not copy it to the new array
if(SameCert(prgCertContext[dwIndex], pCertContext))
{
iIndex=dwIndex;
continue;
}
pCertBuildCTLInfo->prgCertContext[dwNewIndex]=prgCertContext[dwIndex];
dwNewIndex++;
}
//remember that we are one cert less
pCertBuildCTLInfo->dwCertCount=dwNewIndex;
if(prgCertContext)
{
//free the certificate context
if(-1 != iIndex)
CertFreeCertificateContext(prgCertContext[iIndex]);
WizardFree(prgCertContext);
}
}
return TRUE;
}
//----------------------------------------------------------------------------
// Add certificate to the pCertBuildCTLInfo
//
//----------------------------------------------------------------------------
BOOL AddCertToBuildCTL(PCCERT_CONTEXT pCertContext,
CERT_BUILDCTL_INFO *pCertBuildCTLInfo)
{
DWORD dwIndex=0;
//check to see if the certificate is alreayd in the CTL
for(dwIndex=0; dwIndex < pCertBuildCTLInfo->dwCertCount; dwIndex++)
{
if(pCertContext->cbCertEncoded ==
(pCertBuildCTLInfo->prgCertContext[dwIndex])->cbCertEncoded)
{
if(0==memcmp(pCertContext->pbCertEncoded,
(pCertBuildCTLInfo->prgCertContext[dwIndex])->pbCertEncoded,
pCertContext->cbCertEncoded))
//return FALSE if a duplicate exists
return FALSE;
}
}
pCertBuildCTLInfo->prgCertContext=(PCCERT_CONTEXT *)WizardRealloc(
pCertBuildCTLInfo->prgCertContext,
sizeof(PCCERT_CONTEXT *)*(pCertBuildCTLInfo->dwCertCount +1));
if(NULL==pCertBuildCTLInfo->prgCertContext)
{
pCertBuildCTLInfo->dwCertCount=0;
return FALSE;
}
pCertBuildCTLInfo->prgCertContext[pCertBuildCTLInfo->dwCertCount]=pCertContext;
pCertBuildCTLInfo->dwCertCount++;
return TRUE;
}
//----------------------------------------------------------------------------
// Add certificate to the ListView
//
//----------------------------------------------------------------------------
BOOL AddCertToList(HWND hwndControl,
PCCERT_CONTEXT pCertContext,
int iItem)
{
BOOL fResult=FALSE;
LV_ITEMW lvItem;
DWORD dwChar=0;
WCHAR wszNone[MAX_TITLE_LENGTH];
LPWSTR pwszName=NULL;
if(!hwndControl || !pCertContext)
return FALSE;
// set up the fields in the list view item struct that don't change from item to item
lvItem.mask = LVIF_TEXT | LVIF_STATE |LVIF_PARAM;
lvItem.state = 0;
lvItem.stateMask = 0;
lvItem.iItem=iItem;
lvItem.iSubItem=0;
lvItem.lParam = (LPARAM)(pCertContext);
//load the string for NONE
if(!LoadStringU(g_hmodThisDll, IDS_NONE, wszNone, MAX_TITLE_LENGTH))
wszNone[0]=L'\0';
//Subject
dwChar=CertGetNameStringW(
pCertContext,
CERT_NAME_SIMPLE_DISPLAY_TYPE,
0,
NULL,
NULL,
0);
if ((dwChar != 0) && (NULL != (pwszName = (LPWSTR)WizardAlloc(dwChar * sizeof(WCHAR)))))
{
CertGetNameStringW(
pCertContext,
CERT_NAME_SIMPLE_DISPLAY_TYPE,
0,
NULL,
pwszName,
dwChar);
lvItem.pszText=pwszName;
ListView_InsertItemU(hwndControl, &lvItem);
}
else
{
lvItem.pszText=wszNone;
ListView_InsertItemU(hwndControl, &lvItem);
}
//WizardFree the memory
if(pwszName)
{
WizardFree(pwszName);
pwszName=NULL;
}
//Issuer
lvItem.iSubItem++;
dwChar=CertGetNameStringW(
pCertContext,
CERT_NAME_SIMPLE_DISPLAY_TYPE,
CERT_NAME_ISSUER_FLAG,
NULL,
NULL,
0);
if ((dwChar != 0) && (NULL != (pwszName = (LPWSTR)WizardAlloc(dwChar * sizeof(WCHAR)))))
{
CertGetNameStringW(
pCertContext,
CERT_NAME_SIMPLE_DISPLAY_TYPE,
CERT_NAME_ISSUER_FLAG,
NULL,
pwszName,
dwChar);
ListView_SetItemTextU(hwndControl, lvItem.iItem, lvItem.iSubItem,
pwszName);
}
else
ListView_SetItemTextU(hwndControl, lvItem.iItem, lvItem.iSubItem,
wszNone);
//free the memory
if(pwszName)
{
WizardFree(pwszName);
pwszName=NULL;
}
//purpose
lvItem.iSubItem++;
if(MyFormatEnhancedKeyUsageString(&pwszName,pCertContext, FALSE, FALSE))
{
ListView_SetItemTextU(hwndControl, lvItem.iItem, lvItem.iSubItem,
pwszName);
}
//free the memory
if(pwszName)
{
WizardFree(pwszName);
pwszName=NULL;
}
//Expiration
lvItem.iSubItem++;
if(WizardFormatDateString(&pwszName,pCertContext->pCertInfo->NotAfter, FALSE))
{
ListView_SetItemTextU(hwndControl, lvItem.iItem, lvItem.iSubItem,
pwszName);
}
else
ListView_SetItemTextU(hwndControl, lvItem.iItem, lvItem.iSubItem,
wszNone);
//free the memory
if(pwszName)
{
WizardFree(pwszName);
pwszName=NULL;
}
return TRUE;
}
//----------------------------------------------------------------------------
// Make sure the cert has the same usage as the ones defined in CTL.
//
//----------------------------------------------------------------------------
BOOL CertMatchCTL(CERT_BUILDCTL_INFO *pCertBuildCTLInfo,
PCCERT_CONTEXT pCertContext)
{
BOOL fResult=FALSE;
int cNumOID=0;
LPSTR *rgOID=NULL;
DWORD cbOID=0;
DWORD dwIndex=0;
DWORD dwOIDIndex=0;
if(!pCertBuildCTLInfo || !pCertContext)
return FALSE;
//we have to have some oids in the list
if(0==pCertBuildCTLInfo->dwPurposeCount || NULL==pCertBuildCTLInfo->prgPurpose)
return FALSE;
//get the OIDs from the cert
if(!CertGetValidUsages(
1,
&pCertContext,
&cNumOID,
NULL,
&cbOID))
return FALSE;
rgOID=(LPSTR *)WizardAlloc(cbOID);
if(NULL==rgOID)
return FALSE;
if(!CertGetValidUsages(
1,
&pCertContext,
&cNumOID,
rgOID,
&cbOID))
goto CLEANUP;
if(-1==cNumOID)
{
fResult=TRUE;
goto CLEANUP;
}
//make sure the array of OIDs match the ones in the CTL
for(dwIndex=0; dwIndex<pCertBuildCTLInfo->dwPurposeCount; dwIndex++)
{
if(NULL==pCertBuildCTLInfo->prgPurpose[dwIndex])
continue;
if(FALSE==pCertBuildCTLInfo->prgPurpose[dwIndex]->fSelected)
continue;
if(NULL==pCertBuildCTLInfo->prgPurpose[dwIndex]->pszOID)
continue;
//we need to find at least one match from the oids supported by the cert
for(dwOIDIndex=0; dwOIDIndex<(DWORD)cNumOID; dwOIDIndex++)
{
if(0==strcmp(pCertBuildCTLInfo->prgPurpose[dwIndex]->pszOID,
rgOID[dwOIDIndex]))
{
fResult=TRUE;
goto CLEANUP;
}
}
}
//we are hopeless at this point
fResult=FALSE;
CLEANUP:
if(rgOID)
WizardFree(rgOID);
return fResult;
}
//----------------------------------------------------------------------------
// Find a cert from stores .
//
//----------------------------------------------------------------------------
static PCCERT_CONTEXT FindCertContextInStores(
PCTL_ENTRY pCtlEntry,
DWORD chStores1,
HCERTSTORE *rghStores1,
DWORD chStores2,
HCERTSTORE *rghStores2,
HCERTSTORE hExtraStore,
DWORD dwFindType)
{
DWORD i;
PCCERT_CONTEXT pCertContext = NULL;
if (dwFindType == 0)
{
return NULL;
}
i = 0;
while ((i<chStores1) && (pCertContext == NULL))
{
pCertContext = CertFindCertificateInStore(
rghStores1[i++],
X509_ASN_ENCODING,
0,
dwFindType,
(void *)&(pCtlEntry->SubjectIdentifier),
NULL);
}
i = 0;
while ((i<chStores2) && (pCertContext == NULL))
{
pCertContext = CertFindCertificateInStore(
rghStores2[i++],
X509_ASN_ENCODING,
0,
dwFindType,
(void *)&(pCtlEntry->SubjectIdentifier),
NULL);
}
if (pCertContext == NULL)
{
pCertContext = CertFindCertificateInStore(
hExtraStore,
X509_ASN_ENCODING,
0,
dwFindType,
(void *)&(pCtlEntry->SubjectIdentifier),
NULL);
}
return pCertContext;
}
//----------------------------------------------------------------------------
// See if the certificate is valid
//
//----------------------------------------------------------------------------
BOOL IsValidCert(HWND hwndDlg,
PCCERT_CONTEXT pCertContext,
CERT_BUILDCTL_INFO *pCertBuildCTLInfo,
BOOL fMsg,
BOOL fFromCTL)
{
//make sure the pCertContext is a self-signed certificate
if(!TrustIsCertificateSelfSigned(pCertContext,
pCertContext->dwCertEncodingType,
0))
{
if(fMsg)
{
if(fFromCTL)
I_MessageBox(hwndDlg, IDS_NOT_SELF_SIGNED_FROM_CTL,
IDS_BUILDCTL_WIZARD_TITLE,
NULL,
MB_ICONEXCLAMATION|MB_OK|MB_APPLMODAL);
else
I_MessageBox(hwndDlg, IDS_NOT_SELF_SIGNED,
IDS_BUILDCTL_WIZARD_TITLE,
NULL,
MB_ICONERROR|MB_OK|MB_APPLMODAL);
}
return FALSE;
}
//make sure the certifcate match what is defined on the CTL list
if(!CertMatchCTL(pCertBuildCTLInfo, pCertContext))
{
if(fMsg)
{
if(fFromCTL)
I_MessageBox(hwndDlg, IDS_NO_MATCH_USAGE_FROM_CTL,
IDS_BUILDCTL_WIZARD_TITLE,
NULL,
MB_ICONEXCLAMATION|MB_OK|MB_APPLMODAL);
else
I_MessageBox(hwndDlg, IDS_NO_MATCH_USAGE,
IDS_BUILDCTL_WIZARD_TITLE,
NULL,
MB_ICONERROR|MB_OK|MB_APPLMODAL);
}
return FALSE;
}
return TRUE;
}
//----------------------------------------------------------------------------
// Cert a ceritifcate from the file
//
//----------------------------------------------------------------------------
static HCERTSTORE GetCertStoreFromFile(HWND hwndDlg,
CERT_BUILDCTL_INFO *pCertBuildCTLInfo)
{
OPENFILENAMEW OpenFileName;
WCHAR szFileName[_MAX_PATH];
WCHAR szFilter[MAX_STRING_SIZE]; //"Certificate File (*.cer)\0*.cer\0Certificate File (*.crt)\0*.crt\0All Files\0*.*\0"
BOOL fResult=FALSE;
HCERTSTORE hCertStore=NULL;
DWORD dwSize=0;
DWORD dwContentType=0;
if(!hwndDlg || !pCertBuildCTLInfo)
return NULL;
memset(&OpenFileName, 0, sizeof(OpenFileName));
*szFileName=L'\0';
OpenFileName.lStructSize = sizeof(OpenFileName);
OpenFileName.hwndOwner = hwndDlg;
OpenFileName.hInstance = NULL;
//load the fileter string
if(LoadFilterString(g_hmodThisDll, IDS_ALL_CER_FILTER, szFilter, MAX_STRING_SIZE))
{
OpenFileName.lpstrFilter = szFilter;
}
OpenFileName.lpstrCustomFilter = NULL;
OpenFileName.nMaxCustFilter = 0;
OpenFileName.nFilterIndex = 1;
OpenFileName.lpstrFile = szFileName;
OpenFileName.nMaxFile = _MAX_PATH;
OpenFileName.lpstrFileTitle = NULL;
OpenFileName.nMaxFileTitle = 0;
OpenFileName.lpstrInitialDir = NULL;
OpenFileName.lpstrTitle = NULL;
OpenFileName.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST;
OpenFileName.nFileOffset = 0;
OpenFileName.nFileExtension = 0;
OpenFileName.lpstrDefExt = L"cer";
OpenFileName.lCustData = NULL;
OpenFileName.lpfnHook = NULL;
OpenFileName.lpTemplateName = NULL;
if (!WizGetOpenFileName(&OpenFileName))
return NULL;
if(!ExpandAndCryptQueryObject(CERT_QUERY_OBJECT_FILE,
szFileName,
CERT_QUERY_CONTENT_FLAG_CERT |
CERT_QUERY_CONTENT_FLAG_CTL |
CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT |
CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE |
CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED,
CERT_QUERY_FORMAT_FLAG_ALL,
0,
NULL,
&dwContentType,
NULL,
&hCertStore,
NULL,
NULL) || (NULL==hCertStore))
{
I_MessageBox(hwndDlg, IDS_INVALID_CERT_FILE,
IDS_BUILDCTL_WIZARD_TITLE,
NULL,
MB_ICONERROR|MB_OK|MB_APPLMODAL);
goto CLEANUP;
}
if(dwContentType & CERT_QUERY_CONTENT_CTL)
{
I_MessageBox(hwndDlg, IDS_INVALID_CERT_FILE,
IDS_BUILDCTL_WIZARD_TITLE,
NULL,
MB_ICONERROR|MB_OK|MB_APPLMODAL);
goto CLEANUP;
}
fResult=TRUE;
CLEANUP:
if(TRUE==fResult)
return hCertStore;
if(hCertStore)
CertCloseStore(hCertStore, 0);
return NULL;
}
//----------------------------------------------------------------------------
// CallBack fro cert selection call back
//
//----------------------------------------------------------------------------
static BOOL WINAPI SelCertCallBack(
PCCERT_CONTEXT pCertContext,
BOOL *pfInitialSelectedCert,
void *pvCallbackData)
{
if(!pvCallbackData || !pCertContext)
return FALSE;
//make sure that this is a valid certificate
return IsValidCert(((CERT_SEL_LIST *)pvCallbackData)->hwndDlg,
pCertContext,
((CERT_SEL_LIST *)pvCallbackData)->pCertBuildCTLInfo,
FALSE,
FALSE);
}
//////////////////////////////////////////////////////////////////////////////////////
// The call back function for enum system stores for the signing certificate
//////////////////////////////////////////////////////////////////////////////////////
static BOOL WINAPI EnumSysStoreSignCertCallBack(
const void* pwszSystemStore,
DWORD dwFlags,
PCERT_SYSTEM_STORE_INFO pStoreInfo,
void *pvReserved,
void *pvArg
)
{
CERT_STORE_LIST *pCertStoreList=NULL;
HCERTSTORE hCertStore=NULL;
if(NULL==pvArg)
return FALSE;
pCertStoreList=(CERT_STORE_LIST *)pvArg;
//open the store
hCertStore=CertOpenStore(CERT_STORE_PROV_SYSTEM_W,
g_dwMsgAndCertEncodingType,
NULL,
CERT_SYSTEM_STORE_CURRENT_USER |CERT_STORE_SET_LOCALIZED_NAME_FLAG,
(LPWSTR)pwszSystemStore);
if(!hCertStore)
return FALSE;
pCertStoreList->prgStore=(HCERTSTORE *)WizardRealloc(
pCertStoreList->prgStore,
sizeof(HCERTSTORE) *(pCertStoreList->dwStoreCount +1));
if(NULL==pCertStoreList->prgStore)
{
CertCloseStore(hCertStore, 0);
pCertStoreList->dwStoreCount=0;
}
pCertStoreList->prgStore[pCertStoreList->dwStoreCount]=hCertStore;
pCertStoreList->dwStoreCount++;
return TRUE;
}
//////////////////////////////////////////////////////////////////////////////////////
// The call back function for enum system stores
//////////////////////////////////////////////////////////////////////////////////////
static BOOL WINAPI EnumSysStoreCallBack(
const void* pwszSystemStore,
DWORD dwFlags,
PCERT_SYSTEM_STORE_INFO pStoreInfo,
void *pvReserved,
void *pvArg
)
{
CERT_STORE_LIST *pCertStoreList=NULL;
HCERTSTORE hCertStore=NULL;
if(NULL==pvArg)
return FALSE;
pCertStoreList=(CERT_STORE_LIST *)pvArg;
//open the store as read-only
hCertStore=CertOpenStore(CERT_STORE_PROV_SYSTEM_W,
g_dwMsgAndCertEncodingType,
NULL,
CERT_SYSTEM_STORE_CURRENT_USER |CERT_STORE_SET_LOCALIZED_NAME_FLAG|CERT_STORE_READONLY_FLAG,
(LPWSTR)pwszSystemStore);
//we can not open the store.
if(!hCertStore)
return TRUE;
pCertStoreList->prgStore=(HCERTSTORE *)WizardRealloc(
pCertStoreList->prgStore,
sizeof(HCERTSTORE) *(pCertStoreList->dwStoreCount +1));
if(NULL==pCertStoreList->prgStore)
{
CertCloseStore(hCertStore, 0);
pCertStoreList->dwStoreCount=0;
}
else // DSIE: Bug 227267
{
pCertStoreList->prgStore[pCertStoreList->dwStoreCount]=hCertStore;
pCertStoreList->dwStoreCount++;
}
return TRUE;
}
//----------------------------------------------------------------------------
// Cert a ceritifcate from the store
//
//----------------------------------------------------------------------------
static HCERTSTORE GetCertsFromStore(HWND hwndDlg,
CERT_BUILDCTL_INFO *pCertBuildCTLInfo)
{
PCCERT_CONTEXT pCertContext=NULL;
CRYPTUI_SELECTCERTIFICATE_STRUCT SelCert;
CERT_SEL_LIST CertSelList;
DWORD dwIndex=0;
HCERTSTORE hCertStore;
CERT_STORE_LIST CertStoreList;
if(!hwndDlg || !pCertBuildCTLInfo)
return NULL;
//init
memset(&CertStoreList, 0, sizeof(CertStoreList));
memset(&SelCert, 0, sizeof(CRYPTUI_SELECTCERTIFICATE_STRUCT));
memset(&CertSelList, 0, sizeof(CERT_SEL_LIST));
//set up the parameter for call back for cert selection dialogue
CertSelList.hwndDlg=hwndDlg;
CertSelList.pCertBuildCTLInfo=pCertBuildCTLInfo;
if (NULL == (hCertStore = CertOpenStore(
CERT_STORE_PROV_MEMORY,
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
NULL,
0,
NULL)))
{
goto CLEANUP;
}
//set up the parameter to get a list of certificate
if (!CertEnumSystemStore(
CERT_SYSTEM_STORE_CURRENT_USER,
NULL,
&CertStoreList,
EnumSysStoreCallBack))
goto CLEANUP;
//set up the parameter for cert selection dialogue
SelCert.dwSize=sizeof(CRYPTUI_SELECTCERTIFICATE_STRUCT);
SelCert.hwndParent=hwndDlg;
SelCert.dwFlags = CRYPTUI_SELECTCERT_MULTISELECT;
SelCert.pFilterCallback=SelCertCallBack;
SelCert.pvCallbackData=&CertSelList;
SelCert.cDisplayStores=CertStoreList.dwStoreCount;
SelCert.rghDisplayStores=CertStoreList.prgStore;
SelCert.hSelectedCertStore = hCertStore;
CryptUIDlgSelectCertificate(&SelCert);
CLEANUP:
for(dwIndex=0; dwIndex<CertStoreList.dwStoreCount; dwIndex++)
CertCloseStore(CertStoreList.prgStore[dwIndex], 0);
if(CertStoreList.prgStore)
WizardFree(CertStoreList.prgStore);
return hCertStore;
}
//---------------------------------------------------------------------
// Get the certificate list for the CTL
//
//---------------------------------------------------------------------
void GetCertForCTL(HWND hwndParent,
BOOL fMsg,
CERT_BUILDCTL_INFO *pCertBuildCTLInfo,
HCERTSTORE hCertStore)
{
DWORD dwIndex=0;
DWORD dwCertIndex=0;
DWORD dwFindType=0;
CTL_INFO *pCTLInfo=NULL;
PCCERT_CONTEXT pCertContext=NULL;
PCCERT_CONTEXT pPreCertContext=NULL;
HCERTSTORE rgHCertStore[4]={NULL, NULL, NULL, NULL};
HCERTSTORE hExtraStore=NULL;
BOOL fInvalidCertMsg=fMsg;
BOOL fFoundInCTLMsg=fMsg;
if(!pCertBuildCTLInfo)
return;
//add the certificate from the old CTL
if(pCertBuildCTLInfo->pSrcCTL)
{
//open my, ca, trust, and root store
if(rgHCertStore[dwIndex]=CertOpenStore(
CERT_STORE_PROV_SYSTEM_W,
g_dwMsgAndCertEncodingType,
NULL,
CERT_SYSTEM_STORE_CURRENT_USER,
L"my"))
dwIndex++;
if(rgHCertStore[dwIndex]=CertOpenStore(
CERT_STORE_PROV_SYSTEM_W,
g_dwMsgAndCertEncodingType,
NULL,
CERT_SYSTEM_STORE_CURRENT_USER,
L"trust"))
dwIndex++;
if(rgHCertStore[dwIndex]=CertOpenStore(
CERT_STORE_PROV_SYSTEM_W,
g_dwMsgAndCertEncodingType,
NULL,
CERT_SYSTEM_STORE_CURRENT_USER,
L"ca"))
dwIndex++;
if(rgHCertStore[dwIndex]=CertOpenStore(
CERT_STORE_PROV_SYSTEM_W,
g_dwMsgAndCertEncodingType,
NULL,
CERT_SYSTEM_STORE_CURRENT_USER,
L"root"))
dwIndex++;
//open the cert store
hExtraStore = CertOpenStore(
CERT_STORE_PROV_MSG,
g_dwMsgAndCertEncodingType,
NULL,
0,
(const void *) (pCertBuildCTLInfo->pSrcCTL->hCryptMsg));
//find the certificate hash
pCTLInfo=pCertBuildCTLInfo->pSrcCTL->pCtlInfo;
if(pCertBuildCTLInfo->dwHashPropID==CERT_SHA1_HASH_PROP_ID)
dwFindType=CERT_FIND_SHA1_HASH;
else
dwFindType=CERT_FIND_MD5_HASH;
//look through each entry in the CTL list
for(dwCertIndex=0; dwCertIndex<pCTLInfo->cCTLEntry; dwCertIndex++)
{
pCertContext=FindCertContextInStores(
&(pCTLInfo->rgCTLEntry[dwCertIndex]),
dwIndex,
rgHCertStore,
0,
NULL,
hExtraStore,
dwFindType);
if(NULL==pCertContext && TRUE==fFoundInCTLMsg)
{
I_MessageBox(hwndParent, IDS_NO_MATCH_IN_CTL,
IDS_BUILDCTL_WIZARD_TITLE,
NULL,
MB_ICONEXCLAMATION|MB_OK|MB_APPLMODAL);
//no need to give the message again
fFoundInCTLMsg=FALSE;
continue;
}
else if (NULL==pCertContext)
{
continue;
}
if(!IsValidCert(hwndParent,
pCertContext,
pCertBuildCTLInfo,
fInvalidCertMsg,
TRUE))
{
CertFreeCertificateContext(pCertContext);
pCertContext=0;
//no need to give message again
fInvalidCertMsg=FALSE;
continue;
}
if(!AddCertToBuildCTL(pCertContext, pCertBuildCTLInfo))
{
CertFreeCertificateContext(pCertContext);
pCertContext=NULL;
continue;
}
}
}
else
{
//add the certificate from the hCertStore to the CTL
if(NULL != hCertStore)
{
while(pCertContext=CertEnumCertificatesInStore(hCertStore, pPreCertContext))
{
if(!IsValidCert(hwndParent,
pCertContext,
pCertBuildCTLInfo,
FALSE, //do not want a message
FALSE)) //not build from a CTL
{
pPreCertContext=pCertContext;
continue;
}
//get a duplicate of the certificate context
pPreCertContext=CertDuplicateCertificateContext(pCertContext);
if(NULL==pPreCertContext)
{
pPreCertContext=pCertContext;
continue;
}
//add the duplicate to the list
if(!AddCertToBuildCTL(pPreCertContext, pCertBuildCTLInfo))
CertFreeCertificateContext(pPreCertContext);
//continue for the next iteration
pPreCertContext=pCertContext;
}
}
}
//free the certificate store
if(hExtraStore)
CertCloseStore(hExtraStore, 0);
for(dwIndex=0; dwIndex < 4; dwIndex++)
{
if(rgHCertStore[dwIndex])
CertCloseStore(rgHCertStore[dwIndex], 0);
}
}
//---------------------------------------------------------------------
// Init the certifcate list from the old CTL
//
//---------------------------------------------------------------------
void InitCertList(HWND hwndControl,
CERT_BUILDCTL_INFO *pCertBuildCTLInfo)
{
DWORD dwIndex=0;
if(!hwndControl || !pCertBuildCTLInfo)
return;
for(dwIndex=0; dwIndex<pCertBuildCTLInfo->dwCertCount; dwIndex++)
{
//add the certificat to the window
AddCertToList(hwndControl,(pCertBuildCTLInfo->prgCertContext)[dwIndex],
dwIndex);
}
}
//-----------------------------------------------------------------------
// The winProc for the new oid dialogue
//-----------------------------------------------------------------------
void FreeCerts(CERT_BUILDCTL_INFO *pCertBuildCTLInfo)
{
DWORD dwIndex=0;
if(!pCertBuildCTLInfo)
return;
if(pCertBuildCTLInfo->prgCertContext)
{
for(dwIndex=0; dwIndex<pCertBuildCTLInfo->dwCertCount; dwIndex++)
{
if(pCertBuildCTLInfo->prgCertContext[dwIndex])
CertFreeCertificateContext(pCertBuildCTLInfo->prgCertContext[dwIndex]);
}
WizardFree(pCertBuildCTLInfo->prgCertContext);
}
pCertBuildCTLInfo->dwCertCount=0;
pCertBuildCTLInfo->prgCertContext=NULL;
}
//////////////////////////////////////////////////////////////////////////////////////
// The winProc for the new oid dialogue
//////////////////////////////////////////////////////////////////////////////////////
INT_PTR APIENTRY CTLOIDDialogProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
DWORD i;
char szText[MAX_STRING_SIZE];
LPSTR pszText=NULL;
int intMsg=0;
CERT_ENHKEY_USAGE KeyUsage;
DWORD cbData = 0;
LPSTR pszCheckOID=NULL;
switch ( msg ) {
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
if (GetDlgItemTextA(
hwndDlg,
IDC_WIZARD_EDIT1,
szText,
MAX_STRING_SIZE-1))
{
//
// make sure there are not weird characters
//
for (i=0; i<(DWORD)strlen(szText); i++)
{
if (((szText[i] < '0') || (szText[i] > '9')) && (szText[i] != '.'))
{
intMsg=I_MessageBox(hwndDlg, IDS_WIZARD_ERROR_OID,
IDS_BUILDCTL_WIZARD_TITLE,
NULL,
MB_OK | MB_ICONERROR|MB_APPLMODAL);
return FALSE;
}
}
//
// check the last char, and for the empty string
//
if ((szText[0] == '.') || (szText[strlen(szText)-1] == '.') || (strcmp(szText, "") == 0))
{
intMsg=I_MessageBox(hwndDlg, IDS_WIZARD_ERROR_OID,
IDS_BUILDCTL_WIZARD_TITLE,
NULL,
MB_OK | MB_ICONERROR|MB_APPLMODAL);
return FALSE;
}
//encode the OID to make sure the format of the OID is correct
pszCheckOID = szText;
KeyUsage.rgpszUsageIdentifier = &pszCheckOID;
KeyUsage.cUsageIdentifier = 1;
if (!CryptEncodeObject(
X509_ASN_ENCODING,
szOID_ENHANCED_KEY_USAGE,
&KeyUsage,
NULL,
&cbData))
{
intMsg=I_MessageBox(hwndDlg, IDS_WIZARD_ERROR_OID,
IDS_BUILDCTL_WIZARD_TITLE,
NULL,
MB_OK | MB_ICONERROR|MB_APPLMODAL);
return FALSE;
}
//
// allocate space for the string and pass the string back
//
pszText = (LPSTR) WizardAlloc(strlen(szText)+1);
if (pszText != NULL)
{
strcpy(pszText, szText);
}
}
EndDialog(hwndDlg, (INT_PTR)pszText);
break;
case IDCANCEL:
EndDialog(hwndDlg, 0);
break;
}
break;
}
return FALSE;
}
//-----------------------------------------------------------------------
//Free the purpose array
//-----------------------------------------------------------------------
void FreePurposeInfo(ENROLL_PURPOSE_INFO **prgPurposeInfo,
DWORD dwOIDCount)
{
DWORD dwIndex=0;
if(dwOIDCount==0 || NULL==prgPurposeInfo)
return;
for(dwIndex=0; dwIndex<dwOIDCount; dwIndex++)
{
if(prgPurposeInfo[dwIndex])
{
if(TRUE==prgPurposeInfo[dwIndex]->fFreeOID)
{
if((prgPurposeInfo[dwIndex])->pszOID)
WizardFree((prgPurposeInfo[dwIndex])->pszOID);
}
if(TRUE==prgPurposeInfo[dwIndex]->fFreeName)
{
//the name was obtained viz MkWstr
if((prgPurposeInfo[dwIndex])->pwszName)
FreeWStr((prgPurposeInfo[dwIndex])->pwszName);
}
WizardFree(prgPurposeInfo[dwIndex]);
}
}
WizardFree(prgPurposeInfo);
}
//-----------------------------------------------------------------------
//Search for the OID in the array
//-----------------------------------------------------------------------
BOOL SearchAndAddOID(LPSTR pszOID,
DWORD *pdwCount,
ENROLL_PURPOSE_INFO ***pprgPurposeInfo,
BOOL *pfFound,
BOOL fAllocateOID,
BOOL fMarkAsSelectedNew,
BOOL fMarkAsSelectedFound
)
{
DWORD dwIndex=0;
if(NULL==pszOID || NULL==pdwCount || NULL==pprgPurposeInfo)
return FALSE;
for(dwIndex=0; dwIndex< *pdwCount; dwIndex++)
{
//no need to go on if we find a match
if(0==strcmp(pszOID, (*pprgPurposeInfo)[dwIndex]->pszOID))
{
if(pfFound)
*pfFound=TRUE;
//mark the selected option
if(TRUE==fMarkAsSelectedFound)
(*pprgPurposeInfo)[dwIndex]->fSelected=TRUE;
return TRUE;
}
}
//we did not find a match
if(pfFound)
*pfFound=FALSE;
//now, we need to add the OID to the list
(*pdwCount)++;
//get more memory for the pointer list
*pprgPurposeInfo=(ENROLL_PURPOSE_INFO **)WizardRealloc(*pprgPurposeInfo,
(*pdwCount) * sizeof(ENROLL_PURPOSE_INFO *));
if(NULL==*pprgPurposeInfo)
return FALSE;
//wizardAlloc for each pointer
(*pprgPurposeInfo)[*pdwCount-1]=(ENROLL_PURPOSE_INFO *)WizardAlloc(sizeof(ENROLL_PURPOSE_INFO));
if(NULL==(*pprgPurposeInfo)[*pdwCount-1])
return FALSE;
memset((*pprgPurposeInfo)[*pdwCount-1], 0, sizeof(ENROLL_PURPOSE_INFO));
if(TRUE==fAllocateOID)
{
(*pprgPurposeInfo)[*pdwCount-1]->pszOID=(LPSTR)WizardAlloc(strlen(pszOID)+1);
if(NULL!=(*pprgPurposeInfo)[*pdwCount-1]->pszOID)
{
strcpy((*pprgPurposeInfo)[*pdwCount-1]->pszOID, pszOID);
(*pprgPurposeInfo)[*pdwCount-1]->fFreeOID=TRUE;
}
}
else
{
(*pprgPurposeInfo)[*pdwCount-1]->pszOID=pszOID;
(*pprgPurposeInfo)[*pdwCount-1]->fFreeOID=FALSE;
}
//get the name for the OID based on the oid string
if((*pprgPurposeInfo)[*pdwCount-1]->pszOID)
{
(*pprgPurposeInfo)[*pdwCount-1]->pwszName=MkWStr(pszOID);
(*pprgPurposeInfo)[*pdwCount-1]->fFreeName=TRUE;
}
//mark the OID as selected if specified
if(TRUE==fMarkAsSelectedNew)
(*pprgPurposeInfo)[*pdwCount-1]->fSelected=TRUE;
else
(*pprgPurposeInfo)[*pdwCount-1]->fSelected=FALSE;
return TRUE;
}
//-----------------------------------------------------------------------
//The call back function for enum
//-----------------------------------------------------------------------
static BOOL WINAPI EnumInfoCallback(
IN PCCRYPT_OID_INFO pInfo,
IN void *pvArg
)
{
PURPOSE_INFO_CALL_BACK *pCallBackInfo=NULL;
DWORD dwError=0;
pCallBackInfo=(PURPOSE_INFO_CALL_BACK *)pvArg;
if(NULL==pvArg || NULL==pInfo)
return FALSE;
//increment the oid list
(*(pCallBackInfo->pdwCount))++;
//get more memory for the pointer list
*(pCallBackInfo->pprgPurpose)=(ENROLL_PURPOSE_INFO **)WizardRealloc(*(pCallBackInfo->pprgPurpose),
(*(pCallBackInfo->pdwCount)) * sizeof(ENROLL_PURPOSE_INFO *));
if(NULL==*(pCallBackInfo->pprgPurpose))
{
dwError=GetLastError();
return FALSE;
}
//wizardAlloc for each pointer
(*(pCallBackInfo->pprgPurpose))[*(pCallBackInfo->pdwCount)-1]=(ENROLL_PURPOSE_INFO *)WizardAlloc(sizeof(ENROLL_PURPOSE_INFO));
if(NULL==(*(pCallBackInfo->pprgPurpose))[*(pCallBackInfo->pdwCount)-1])
return FALSE;
memset((*(pCallBackInfo->pprgPurpose))[*(pCallBackInfo->pdwCount)-1], 0, sizeof(ENROLL_PURPOSE_INFO));
(*(pCallBackInfo->pprgPurpose))[*(pCallBackInfo->pdwCount)-1]->pszOID=(LPSTR)(pInfo->pszOID);
(*(pCallBackInfo->pprgPurpose))[*(pCallBackInfo->pdwCount)-1]->pwszName=(LPWSTR)(pInfo->pwszName);
return TRUE;
}
//-----------------------------------------------------------------------
//Initialize usage OID to display
//-----------------------------------------------------------------------
BOOL GetOIDForCTL(CERT_BUILDCTL_INFO *pCertBuildCTLInfo,
DWORD cUsageID,
LPSTR *rgpszUsageID)
{
BOOL fResult=FALSE;
PURPOSE_INFO_CALL_BACK PurposeCallBack;
PCTL_INFO pCTLInfo=NULL;
DWORD dwIndex=0;
DWORD dwCount=0;
ENROLL_PURPOSE_INFO **prgPurposeInfo=NULL;
//init
memset(&PurposeCallBack, 0, sizeof(PURPOSE_INFO_CALL_BACK));
if(NULL==pCertBuildCTLInfo)
return FALSE;
//init
PurposeCallBack.pdwCount=&dwCount;
PurposeCallBack.pprgPurpose=&prgPurposeInfo;
//enum all the enhanced key usages
if(!CryptEnumOIDInfo(
CRYPT_ENHKEY_USAGE_OID_GROUP_ID,
0,
&PurposeCallBack,
EnumInfoCallback))
goto CLEANUP;
//add the existing ones in the old CTL if they do not exist
//from the enum list
if(pCertBuildCTLInfo->pSrcCTL)
{
if(pCertBuildCTLInfo->pSrcCTL->pCtlInfo)
{
pCTLInfo=pCertBuildCTLInfo->pSrcCTL->pCtlInfo;
for(dwIndex=0; dwIndex<pCTLInfo->SubjectUsage.cUsageIdentifier; dwIndex++)
{
if(!SearchAndAddOID(pCTLInfo->SubjectUsage.rgpszUsageIdentifier[dwIndex],
&dwCount,
&prgPurposeInfo,
NULL,
FALSE,
TRUE, //mark as selected if new oid
TRUE)) //mark as selected if existing oid
goto CLEANUP;
}
}
}
else
{
//add the pre-defined OIDs
if((0!=cUsageID) && (NULL!=rgpszUsageID))
{
for(dwIndex=0; dwIndex<cUsageID; dwIndex++)
{
if(!SearchAndAddOID(rgpszUsageID[dwIndex],
&dwCount,
&prgPurposeInfo,
NULL,
FALSE, //do not allocate for the OID
TRUE, //mark as selected if new oid
TRUE)) //mark as selected if existing oid
goto CLEANUP;
}
}
}
fResult=TRUE;
CLEANUP:
if(FALSE==fResult)
{
if(prgPurposeInfo)
FreePurposeInfo(prgPurposeInfo, dwCount);
}
else
{
pCertBuildCTLInfo->dwPurposeCount=dwCount;
pCertBuildCTLInfo->prgPurpose=prgPurposeInfo;
}
return fResult;
}
//-----------------------------------------------------------------------
//Initialize the usage OID list
//-----------------------------------------------------------------------
BOOL InitBuildCTLOID(HWND hwndList,
CERT_BUILDCTL_INFO *pCertBuildCTLInfo)
{
DWORD dwCount=0;
ENROLL_PURPOSE_INFO **prgPurposeInfo=NULL;
DWORD dwIndex=0;
LV_ITEMW lvItem;
LV_COLUMNW lvC;
int dwMaxSize=0;
if(!hwndList || !pCertBuildCTLInfo)
return FALSE;
//get the list of OIDs from the old CTL and all possibilities
dwCount=pCertBuildCTLInfo->dwPurposeCount;
prgPurposeInfo=pCertBuildCTLInfo->prgPurpose;
//mark the list is selected by a check box
ListView_SetExtendedListViewStyle(hwndList, LVS_EX_CHECKBOXES);
//get the max length of the column
for(dwIndex=0; dwIndex<dwCount; dwIndex++)
{
if(dwMaxSize < wcslen((prgPurposeInfo[dwIndex])->pwszName))
dwMaxSize=wcslen((prgPurposeInfo[dwIndex])->pwszName);
}
//insert a column into the list view
memset(&lvC, 0, sizeof(LV_COLUMNW));
lvC.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
lvC.fmt = LVCFMT_LEFT; // Left-align the column.
lvC.cx =10; // (dwMaxSize+2)*7; // Width of the column, in pixels.
lvC.pszText = L""; // The text for the column.
lvC.iSubItem=0;
if (ListView_InsertColumnU(hwndList, 0, &lvC) == -1)
return FALSE;
//populate the list
memset(&lvItem, 0, sizeof(LV_ITEMW));
lvItem.mask=LVIF_TEXT | LVIF_STATE;
for(dwIndex=0; dwIndex<dwCount; dwIndex++)
{
lvItem.iItem=dwIndex;
lvItem.pszText=(prgPurposeInfo[dwIndex])->pwszName;
lvItem.cchTextMax=sizeof(WCHAR)*(1+wcslen((prgPurposeInfo[dwIndex])->pwszName));
lvItem.stateMask = LVIS_STATEIMAGEMASK;
lvItem.state = (prgPurposeInfo[dwIndex])->fSelected ? 0x00002000 : 0x00001000;
//insert the list
// insert and set state
ListView_SetItemState(hwndList,
ListView_InsertItemU(hwndList, &lvItem),
(prgPurposeInfo[dwIndex])->fSelected ? 0x00002000 : 0x00001000,
LVIS_STATEIMAGEMASK);
}
//autosize the column
ListView_SetColumnWidth(hwndList, 0, LVSCW_AUTOSIZE);
return TRUE;
}
//-----------------------------------------------------------------------
//populate the list box in the order of
//Purpose, FileName, StoreName, FriendlyName,
//and any other things signing wizard display
//-----------------------------------------------------------------------
void DisplayBuildCTLConfirmation(HWND hwndControl,
CERT_BUILDCTL_INFO *pCertBuildCTLInfo)
{
DWORD dwIndex=0;
LPWSTR pwszStoreName=NULL;
WCHAR wszNone[MAX_TITLE_LENGTH];
BOOL fNewItem=FALSE;
DWORD dwSize=0;
LPWSTR pwszValidityString=NULL;
LV_COLUMNW lvC;
LV_ITEMW lvItem;
//pCertBuildCTLInfo has to be valid
if(!pCertBuildCTLInfo)
return;
//delete all the old items in the listView
ListView_DeleteAllItems(hwndControl);
//load the string <none>
if(!LoadStringU(g_hmodThisDll, IDS_NONE, wszNone, MAX_TITLE_LENGTH))
*wszNone=L'\0';
//get the storename
if(pCertBuildCTLInfo->hDesStore)
{
if(!CertGetStoreProperty(
pCertBuildCTLInfo->hDesStore,
CERT_STORE_LOCALIZED_NAME_PROP_ID,
NULL,
&dwSize) || (0==dwSize))
{
//Get the <Unknown> string
pwszStoreName=(LPWSTR)WizardAlloc(MAX_TITLE_LENGTH * sizeof(WCHAR));
if(pwszStoreName)
{
*pwszStoreName=L'\0';
LoadStringU(g_hmodThisDll, IDS_UNKNOWN, pwszStoreName, MAX_TITLE_LENGTH);
}
}
else
{
pwszStoreName=(LPWSTR)WizardAlloc(dwSize);
if(pwszStoreName)
{
*pwszStoreName=L'\0';
CertGetStoreProperty(
pCertBuildCTLInfo->hDesStore,
CERT_STORE_LOCALIZED_NAME_PROP_ID,
pwszStoreName,
&dwSize);
}
}
}
//insert row by row
memset(&lvItem, 0, sizeof(LV_ITEMW));
// set up the fields in the list view item struct that don't change from item to item
lvItem.mask = LVIF_TEXT | LVIF_STATE ;
lvItem.state = 0;
lvItem.stateMask = 0;
lvItem.iItem=0;
lvItem.iSubItem=0;
//Purpose. We are guaranteed to have at least one item in the purpose list
ListView_InsertItemU_IDS(hwndControl, &lvItem, IDS_CTL_PURPOSE, NULL);
for(dwIndex=0; dwIndex<pCertBuildCTLInfo->dwPurposeCount; dwIndex++)
{
if(TRUE==((pCertBuildCTLInfo->prgPurpose)[dwIndex]->fSelected))
{
if(TRUE==fNewItem)
{
//increase the row
lvItem.iItem++;
lvItem.pszText=L"";
lvItem.iSubItem=0;
ListView_InsertItemU(hwndControl, &lvItem);
}
else
fNewItem=TRUE;
lvItem.iSubItem++;
ListView_SetItemTextU(hwndControl, lvItem.iItem, lvItem.iSubItem,
(pCertBuildCTLInfo->prgPurpose)[dwIndex]->pwszName);
}
}
//list ID
lvItem.iItem++;
lvItem.iSubItem=0;
ListView_InsertItemU_IDS(hwndControl, &lvItem, IDS_CTL_ID, NULL);
//content
lvItem.iSubItem++;
if(pCertBuildCTLInfo->pwszListID)
ListView_SetItemTextU(hwndControl, lvItem.iItem, lvItem.iSubItem,pCertBuildCTLInfo->pwszListID);
else
ListView_SetItemTextU(hwndControl, lvItem.iItem, lvItem.iSubItem,wszNone);
//validity
lvItem.iItem++;
lvItem.iSubItem=0;
ListView_InsertItemU_IDS(hwndControl, &lvItem, IDS_CTL_VALIDITY, NULL);
//content
lvItem.iSubItem++;
if(pCertBuildCTLInfo->dwValidMonths || pCertBuildCTLInfo->dwValidDays)
{
GetValidityString(pCertBuildCTLInfo->dwValidMonths, pCertBuildCTLInfo->dwValidDays,
&pwszValidityString);
ListView_SetItemTextU(hwndControl, lvItem.iItem, lvItem.iSubItem,pwszValidityString);
}
else
ListView_SetItemTextU(hwndControl, lvItem.iItem, lvItem.iSubItem,wszNone);
//only show the file name or store name if the destination page
//is not skipped
if(0 == (pCertBuildCTLInfo->dwFlag & CRYPTUI_WIZ_BUILDCTL_SKIP_DESTINATION))
{
//file name
if(pCertBuildCTLInfo->pwszFileName && (TRUE==(pCertBuildCTLInfo->fSelectedFileName)))
{
lvItem.iItem++;
lvItem.iSubItem=0;
ListView_InsertItemU_IDS(hwndControl, &lvItem, IDS_FILE_NAME, NULL);
//content
lvItem.iSubItem++;
ListView_SetItemTextU(hwndControl, lvItem.iItem, lvItem.iSubItem,
pCertBuildCTLInfo->pwszFileName);
}
//StoreName
if(pCertBuildCTLInfo->hDesStore && (TRUE==pCertBuildCTLInfo->fSelectedDesStore))
{
if(pwszStoreName)
{
lvItem.iItem++;
lvItem.iSubItem=0;
ListView_InsertItemU_IDS(hwndControl, &lvItem, IDS_STORE_NAME, NULL);
//content
lvItem.iSubItem++;
ListView_SetItemTextU(hwndControl, lvItem.iItem, lvItem.iSubItem,
pwszStoreName);
}
}
}
//FriendlyName and descripton will be displayed if the hDesStore is not NULL
// if(pCertBuildCTLInfo->hDesStore && (TRUE==pCertBuildCTLInfo->fSelectedDesStore))
// {
//friendlyName
lvItem.iItem++;
lvItem.iSubItem=0;
ListView_InsertItemU_IDS(hwndControl, &lvItem, IDS_FRIENDLY_NAME, NULL);
//content
lvItem.iSubItem++;
if(pCertBuildCTLInfo->pwszFriendlyName)
ListView_SetItemTextU(hwndControl, lvItem.iItem, lvItem.iSubItem,pCertBuildCTLInfo->pwszFriendlyName);
else
ListView_SetItemTextU(hwndControl, lvItem.iItem, lvItem.iSubItem,wszNone);
//description
lvItem.iItem++;
lvItem.iSubItem=0;
ListView_InsertItemU_IDS(hwndControl, &lvItem, IDS_DESCRIPTION, NULL);
//content
lvItem.iSubItem++;
if(pCertBuildCTLInfo->pwszDescription)
ListView_SetItemTextU(hwndControl, lvItem.iItem, lvItem.iSubItem,pCertBuildCTLInfo->pwszDescription);
else
ListView_SetItemTextU(hwndControl, lvItem.iItem, lvItem.iSubItem,wszNone);
//}
//autosize the columns
ListView_SetColumnWidth(hwndControl, 0, LVSCW_AUTOSIZE);
ListView_SetColumnWidth(hwndControl, 1, LVSCW_AUTOSIZE);
//free the memory
if(pwszStoreName)
WizardFree(pwszStoreName);
if(pwszValidityString)
WizardFree(pwszValidityString);
return;
}
//**************************************************************************
//
// The winProcs for the buildCtl wizard
//**************************************************************************
//-----------------------------------------------------------------------
//BuildCTL_Welcome
//-----------------------------------------------------------------------
INT_PTR APIENTRY BuildCTL_Welcome(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
CERT_BUILDCTL_INFO *pCertBuildCTLInfo=NULL;
PROPSHEETPAGEW *pPropSheet=NULL;
switch (msg)
{
case WM_INITDIALOG:
//set the wizard information so that it can be shared
pPropSheet = (PROPSHEETPAGEW *) lParam;
pCertBuildCTLInfo = (CERT_BUILDCTL_INFO *) (pPropSheet->lParam);
//make sure pCertBuildCTLInfo is a valid pointer
if(NULL==pCertBuildCTLInfo)
break;
SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pCertBuildCTLInfo);
SetControlFont(pCertBuildCTLInfo->hBigBold, hwndDlg,IDC_WIZARD_STATIC_BIG_BOLD1);
SetControlFont(pCertBuildCTLInfo->hBold, hwndDlg,IDC_WIZARD_STATIC_BOLD1);
break;
case WM_NOTIFY:
switch (((NMHDR FAR *) lParam)->code)
{
case PSN_KILLACTIVE:
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE);
return TRUE;
break;
case PSN_RESET:
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE);
break;
case PSN_SETACTIVE:
PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT);
break;
case PSN_WIZBACK:
break;
case PSN_WIZNEXT:
if(NULL==(pCertBuildCTLInfo=(CERT_BUILDCTL_INFO *)GetWindowLongPtr(hwndDlg, DWLP_USER)))
break;
//check if we need to skip the 1st page
if(CRYPTUI_WIZ_BUILDCTL_SKIP_PURPOSE & pCertBuildCTLInfo->dwFlag)
{
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, IDD_BUILDCTL_CERTS);
}
break;
default:
return FALSE;
}
break;
default:
return FALSE;
}
return TRUE;
}
//-----------------------------------------------------------------------
//BuildCTL_Purpose
//-----------------------------------------------------------------------
INT_PTR APIENTRY BuildCTL_Purpose(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
CERT_BUILDCTL_INFO *pCertBuildCTLInfo=NULL;
PROPSHEETPAGEW *pPropSheet=NULL;
HWND hwndControl=NULL;
DWORD dwCount=0;
DWORD dwIndex=0;
NM_LISTVIEW FAR * pnmv=NULL;
int intMsg=0;
LPSTR pszNewOID;
BOOL fFound=FALSE;
LV_ITEMW lvItem;
DWORD dwChar=0;
WCHAR wszMonth[BUILDCTL_DURATION_SIZE];
WCHAR wszDay[BUILDCTL_DURATION_SIZE];
BOOL fUserTypeDuration=FALSE;
LPWSTR pwszDuration=NULL;
switch (msg)
{
case WM_INITDIALOG:
//set the wizard information so that it can be shared
pPropSheet = (PROPSHEETPAGEW *) lParam;
pCertBuildCTLInfo = (CERT_BUILDCTL_INFO *) (pPropSheet->lParam);
//make sure pCertBuildCTLInfo is a valid pointer
if(NULL==pCertBuildCTLInfo)
break;
SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pCertBuildCTLInfo);
SetControlFont(pCertBuildCTLInfo->hBold, hwndDlg,IDC_WIZARD_STATIC_BOLD1);
//initizialize the OID list
InitBuildCTLOID(GetDlgItem(hwndDlg, IDC_WIZARD_LIST1),
pCertBuildCTLInfo);
//initialize the ListID
if(pCertBuildCTLInfo->pwszListID)
SetDlgItemTextU(hwndDlg, IDC_WIZARD_EDIT1, pCertBuildCTLInfo->pwszListID);
//mark that we are done with the init OID ListView
//if user de-select OIDs from now on, they will be prompted for the
//warning
pCertBuildCTLInfo->fCompleteInit=TRUE;
//init the dwValidMonth and dwValidDays
if(pCertBuildCTLInfo->dwValidMonths != 0)
{
_ltow(pCertBuildCTLInfo->dwValidMonths, wszMonth, 10);
SetDlgItemTextU(hwndDlg, IDC_WIZARD_EDIT_MONTH, wszMonth);
}
if(pCertBuildCTLInfo->dwValidDays != 0)
{
_ltow(pCertBuildCTLInfo->dwValidDays, wszDay, 10);
SetDlgItemTextU(hwndDlg, IDC_WIZARD_EDIT_DAY, wszDay);
}
break;
case WM_COMMAND:
if(HIWORD(wParam) == BN_CLICKED)
{
switch (LOWORD(wParam))
{
case IDC_WIZARD_BUTTON1:
if(NULL==(pCertBuildCTLInfo=(CERT_BUILDCTL_INFO *)GetWindowLongPtr(hwndDlg, DWLP_USER)))
{
break;
}
//get the window handle of the cert list view
if(NULL==(hwndControl=GetDlgItem(hwndDlg, IDC_WIZARD_LIST1)))
break;
//prompt user to enter the user OID
pszNewOID = (LPSTR) DialogBoxU(
g_hmodThisDll,
(LPCWSTR)MAKEINTRESOURCE(IDD_BUILDCTL_USER_PURPOSE),
hwndDlg,
CTLOIDDialogProc);
//add the OID to the list
if(NULL != pszNewOID)
{
SearchAndAddOID(
pszNewOID,
&(pCertBuildCTLInfo->dwPurposeCount),
&(pCertBuildCTLInfo->prgPurpose),
&fFound,
TRUE,
TRUE, //mark as selected if new oid
FALSE); //do not mark as selected if existing oid
if(fFound==TRUE)
{
I_MessageBox(hwndDlg, IDS_EXISTING_OID,
IDS_BUILDCTL_WIZARD_TITLE,
NULL,
MB_ICONINFORMATION|MB_OK|MB_APPLMODAL);
}
else
{
//add the item to the list view
//populate the list
memset(&lvItem, 0, sizeof(LV_ITEMW));
lvItem.mask=LVIF_TEXT | LVIF_STATE;
lvItem.iItem=pCertBuildCTLInfo->dwPurposeCount-1;
lvItem.pszText=(pCertBuildCTLInfo->prgPurpose[pCertBuildCTLInfo->dwPurposeCount-1])->pwszName;
lvItem.cchTextMax=sizeof(WCHAR)*(1+wcslen
((pCertBuildCTLInfo->prgPurpose[pCertBuildCTLInfo->dwPurposeCount-1])->pwszName));
lvItem.stateMask = LVIS_STATEIMAGEMASK;
lvItem.state = (pCertBuildCTLInfo->prgPurpose[pCertBuildCTLInfo->dwPurposeCount-1])->fSelected ? 0x00002000 : 0x00001000;
// insert and set state
//mark no warning for the user
pCertBuildCTLInfo->fCompleteInit=FALSE;
ListView_SetItemState(hwndControl,
ListView_InsertItemU(hwndControl, &lvItem),
(pCertBuildCTLInfo->prgPurpose[pCertBuildCTLInfo->dwPurposeCount-1])->fSelected ? 0x00002000 : 0x00001000,
LVIS_STATEIMAGEMASK);
//mark the end of setting
pCertBuildCTLInfo->fCompleteInit=TRUE;
//autosize the column
ListView_SetColumnWidth(hwndControl, 0, LVSCW_AUTOSIZE);
}
}
//free the pszNewOID
if(pszNewOID)
WizardFree(pszNewOID);
break;
}
}
break;
case WM_NOTIFY:
switch (((NMHDR FAR *) lParam)->code)
{
case PSN_KILLACTIVE:
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE);
return TRUE;
break;
case PSN_RESET:
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE);
break;
case PSN_SETACTIVE:
PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT|PSWIZB_BACK);
break;
case PSN_WIZBACK:
break;
case LVN_ITEMCHANGING:
if(NULL==(pCertBuildCTLInfo=(CERT_BUILDCTL_INFO *)GetWindowLongPtr(hwndDlg, DWLP_USER)))
{
break;
}
//the item has been chagned.
pnmv = (NM_LISTVIEW FAR *) lParam;
if(NULL==pnmv)
break;
//ingore if we have not complete the init yet
if(NULL == pCertBuildCTLInfo->prgPurpose)
//we allow change
return FALSE;
//ignore if we are not complete with the
//init yet
if(FALSE==pCertBuildCTLInfo->fCompleteInit)
return FALSE;
//see if the new item is de-selected
if(pnmv->uChanged & LVIF_STATE)
{
if(FALSE==(((pnmv->uNewState & LVIS_STATEIMAGEMASK)>> 12) -1))
{
if(TRUE==(pCertBuildCTLInfo->prgPurpose[pnmv->iItem])->fSelected)
{
//check to see if the user has selected any certs
if(0!=pCertBuildCTLInfo->dwCertCount)
{
//ask user if they are sure to change the subject
//of the CTL, thus the whole cert list will be gone
intMsg=I_MessageBox(hwndDlg, IDS_SURE_CERT_GONE,
IDS_BUILDCTL_WIZARD_TITLE,
NULL,
MB_ICONEXCLAMATION|MB_YESNO|MB_APPLMODAL);
if(IDYES==intMsg)
{
//free all the certificate context and
//clear the listView of the ceritificate
pCertBuildCTLInfo->fClearCerts=TRUE;
//we allow change
return FALSE;
}
//we disallow the change
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, TRUE);
return TRUE;
}
}
}
}
//we allow the chagne
return FALSE;
break;
case PSN_WIZNEXT:
if(NULL==(pCertBuildCTLInfo=(CERT_BUILDCTL_INFO *)GetWindowLongPtr(hwndDlg, DWLP_USER)))
break;
//get the window handle of the purpose list view
if(NULL==(hwndControl=GetDlgItem(hwndDlg, IDC_WIZARD_LIST1)))
break;
//get the count of selected OIDs and mark them
dwCount=0;
for(dwIndex=0; dwIndex<pCertBuildCTLInfo->dwPurposeCount; dwIndex++)
{
//mark the selected OIDS. Keep track of
//if the OID selections have been changed
if(ListView_GetCheckState(hwndControl, dwIndex))
{
((pCertBuildCTLInfo->prgPurpose)[dwIndex])->fSelected=TRUE;
dwCount++;
}
else
{
((pCertBuildCTLInfo->prgPurpose)[dwIndex])->fSelected=FALSE;
}
}
if(0==dwCount)
{
I_MessageBox(hwndDlg, IDS_NO_SELECTED_CTL_PURPOSE,
IDS_BUILDCTL_WIZARD_TITLE,
NULL,
MB_ICONERROR|MB_OK|MB_APPLMODAL);
//the page should stay
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1);
break;
}
//get the list ID if user has specified it.
if(pCertBuildCTLInfo->pwszListID)
{
WizardFree(pCertBuildCTLInfo->pwszListID);
pCertBuildCTLInfo->pwszListID=NULL;
}
if(0!=(dwChar=(DWORD)SendDlgItemMessage(hwndDlg,
IDC_WIZARD_EDIT1,
WM_GETTEXTLENGTH, 0, 0)))
{
pCertBuildCTLInfo->pwszListID=(LPWSTR)WizardAlloc(sizeof(WCHAR)*(dwChar+1));
if(NULL!=pCertBuildCTLInfo->pwszListID)
{
GetDlgItemTextU(hwndDlg, IDC_WIZARD_EDIT1,
pCertBuildCTLInfo->pwszListID,
dwChar+1);
}
else
//we are out of memory and out of hope
break;
}
//get the valid month and valid days that user specified
if(0!=(dwChar=(DWORD)SendDlgItemMessage(hwndDlg,
IDC_WIZARD_EDIT_MONTH,
WM_GETTEXTLENGTH, 0, 0)))
{
fUserTypeDuration=TRUE;
pwszDuration=(LPWSTR)WizardAlloc(sizeof(WCHAR)*(dwChar+1));
if(NULL!=pwszDuration)
{
GetDlgItemTextU(hwndDlg, IDC_WIZARD_EDIT_MONTH,
pwszDuration,
dwChar+1);
}
else
//we are out of memory and out of hope
break;
//make sure the character are valid
/*if(!ValidDuration(pwszDuration))
{
I_MessageBox(hwndDlg, IDS_INVALID_MONTHS,
IDS_BUILDCTL_WIZARD_TITLE,
NULL,
MB_ICONERROR|MB_OK|MB_APPLMODAL);
WizardFree(pwszDuration);
pwszDuration=NULL;
//the page should stay
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1);
break;
}*/
pCertBuildCTLInfo->dwValidMonths=_wtol(pwszDuration);
/*if( (0 == pCertBuildCTLInfo->dwValidMonths && !ValidZero(pwszDuration)) ||
(0 > _wtol(pwszDuration))
)
{
if(!ValidZero(pwszDuration))
{
I_MessageBox(hwndDlg, IDS_INVALID_MONTHS,
IDS_BUILDCTL_WIZARD_TITLE,
NULL,
MB_ICONERROR|MB_OK|MB_APPLMODAL);
WizardFree(pwszDuration);
pwszDuration=NULL;
//the page should stay
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1);
break;
}
} */
}
else
pCertBuildCTLInfo->dwValidMonths=0;
//Free the memory
if(pwszDuration)
{
WizardFree(pwszDuration);
pwszDuration=NULL;
}
//valid days
if(0!=(dwChar=(DWORD)SendDlgItemMessage(hwndDlg,
IDC_WIZARD_EDIT_DAY,
WM_GETTEXTLENGTH, 0, 0)))
{
fUserTypeDuration=TRUE;
pwszDuration=(LPWSTR)WizardAlloc(sizeof(WCHAR)*(dwChar+1));
if(NULL!=pwszDuration)
{
GetDlgItemTextU(hwndDlg, IDC_WIZARD_EDIT_DAY,
pwszDuration,
dwChar+1);
}
else
//we are out of memory and out of hope
break;
//make sure the character are valid
/*if(!ValidDuration(pwszDuration))
{
I_MessageBox(hwndDlg, IDS_INVALID_DAYS,
IDS_BUILDCTL_WIZARD_TITLE,
NULL,
MB_ICONERROR|MB_OK|MB_APPLMODAL);
WizardFree(pwszDuration);
pwszDuration=NULL;
//the page should stay
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1);
break;
}*/
pCertBuildCTLInfo->dwValidDays=_wtol(pwszDuration);
/*if( (0 == pCertBuildCTLInfo->dwValidDays && !ValidZero(pwszDuration)) ||
(0 > _wtol(pwszDuration))
)
{
I_MessageBox(hwndDlg, IDS_INVALID_DAYS,
IDS_BUILDCTL_WIZARD_TITLE,
NULL,
MB_ICONERROR|MB_OK|MB_APPLMODAL);
WizardFree(pwszDuration);
pwszDuration=NULL;
//the page should stay
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1);
break;
}*/
}
else
pCertBuildCTLInfo->dwValidDays=0;
//Free the memory
if(pwszDuration)
{
WizardFree(pwszDuration);
pwszDuration=NULL;
}
//make sure that user did type in some valid duration
if(0 == pCertBuildCTLInfo->dwValidDays &&
0 == pCertBuildCTLInfo->dwValidMonths &&
TRUE== fUserTypeDuration)
{
I_MessageBox(hwndDlg, IDS_INVALID_DURATION,
IDS_BUILDCTL_WIZARD_TITLE,
NULL,
MB_ICONERROR|MB_OK|MB_APPLMODAL);
//the page should stay
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1);
break;
}
//make sure that the dwValidMonth + dwValidDays
//will not exceed 99 month + some extra days
if(pCertBuildCTLInfo->dwValidDays ||
pCertBuildCTLInfo->dwValidMonths)
{
if(!DurationWithinLimit(pCertBuildCTLInfo->dwValidMonths,
pCertBuildCTLInfo->dwValidDays))
{
I_MessageBox(hwndDlg, IDS_EXCEED_LIMIT,
IDS_BUILDCTL_WIZARD_TITLE,
NULL,
MB_ICONERROR|MB_OK|MB_APPLMODAL);
//the page should stay
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1);
break;
}
}
break;
default:
return FALSE;
}
break;
default:
return FALSE;
}
return TRUE;
}
//-----------------------------------------------------------------------
//BuildCTL_Certs
//-----------------------------------------------------------------------
INT_PTR APIENTRY BuildCTL_Certs(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
CERT_BUILDCTL_INFO *pCertBuildCTLInfo=NULL;
PROPSHEETPAGEW *pPropSheet=NULL;
HCERTSTORE hCertStore=NULL;
PCCERT_CONTEXT pCertContext=NULL;
PCCERT_CONTEXT pPreCertContext=NULL;
BOOL fSelfSigned=TRUE;
BOOL fCTLUsage=TRUE;
BOOL fEmptyStore=TRUE;
BOOL fDuplicateCert=TRUE;
HWND hwndControl=NULL;
DWORD dwCount=0;
DWORD dwIndex=0;
int listIndex=0;
WCHAR wszText[MAX_STRING_SIZE];
UINT rgIDS[]={IDS_COLUMN_SUBJECT,
IDS_COLUMN_ISSUER,
IDS_COLUMN_PURPOSE,
IDS_COLUMN_EXPIRE};
LV_COLUMNW lvC;
CRYPTUI_VIEWCERTIFICATE_STRUCT CertViewStruct;
DWORD dwSortParam=0;
LV_ITEM lvItem;
NM_LISTVIEW FAR * pnmv=NULL;
BOOL fErrorDisplayed=FALSE;
int i;
switch (msg)
{
case WM_INITDIALOG:
//set the wizard information so that it can be shared
pPropSheet = (PROPSHEETPAGEW *) lParam;
pCertBuildCTLInfo = (CERT_BUILDCTL_INFO *) (pPropSheet->lParam);
//make sure pCertBuildCTLInfo is a valid pointer
if(NULL==pCertBuildCTLInfo)
{
break;
}
SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pCertBuildCTLInfo);
SetControlFont(pCertBuildCTLInfo->hBold, hwndDlg,IDC_WIZARD_STATIC_BOLD1);
// set the style in the list view so that it highlights an entire line
SendMessageA(GetDlgItem(hwndDlg, IDC_WIZARD_LIST1), LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT);
//insert columns with headers into the listView control
dwCount=sizeof(rgIDS)/sizeof(rgIDS[0]);
//get the window handle of the cert list view
if(NULL==(hwndControl=GetDlgItem(hwndDlg, IDC_WIZARD_LIST1)))
break;
//set up the common info for the column
memset(&lvC, 0, sizeof(LV_COLUMNW));
lvC.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
lvC.fmt = LVCFMT_LEFT; // Left-align the column.
lvC.cx = 145; // Width of the column, in pixels.
lvC.iSubItem=0;
lvC.pszText = wszText; // The text for the column.
//inser the column one at a time
for(dwIndex=0; dwIndex<dwCount; dwIndex++)
{
//get the column header
wszText[0]=L'\0';
LoadStringU(g_hmodThisDll, rgIDS[dwIndex], wszText, MAX_STRING_SIZE);
ListView_InsertColumnU(hwndControl, dwIndex, &lvC);
}
//initlize the ListView by populate the original certs
//from the existing CTL
InitCertList(
hwndControl,
pCertBuildCTLInfo);
//get the item count
if(ListView_GetItemCount(hwndControl))
{
//sort the certificates by the 1st column
dwSortParam=pCertBuildCTLInfo->rgdwSortParam[0];
if(0!=dwSortParam)
{
//sort the 1st column
SendDlgItemMessage(hwndDlg,
IDC_WIZARD_LIST1,
LVM_SORTITEMS,
(WPARAM) (LPARAM) dwSortParam,
(LPARAM) (PFNLVCOMPARE)CompareCertificate);
}
}
else
{
//we reset the ordering order
pCertBuildCTLInfo->rgdwSortParam[0]=SORT_COLUMN_SUBJECT | SORT_COLUMN_DESCEND;
}
//Disable the Buttons for View or Delete if no selection
//has been made
//get the window handle of the cert list view
if(NULL==(hwndControl=GetDlgItem(hwndDlg, IDC_WIZARD_LIST1)))
break;
//get the selected item
listIndex = ListView_GetNextItem(
hwndControl,
-1,
LVNI_SELECTED
);
if(-1 == listIndex)
{
EnableWindow(GetDlgItem(hwndDlg, IDC_WIZARD_BUTTON3), FALSE);
EnableWindow(GetDlgItem(hwndDlg, IDC_WIZARD_BUTTON4), FALSE);
}
break;
case WM_COMMAND:
if(HIWORD(wParam) == BN_CLICKED)
{
switch (LOWORD(wParam))
{
//add a certificate from a store
case IDC_WIZARD_BUTTON1:
if(NULL==(pCertBuildCTLInfo=(CERT_BUILDCTL_INFO *)GetWindowLongPtr(hwndDlg, DWLP_USER)))
break;
//get the window handle of the cert list view
if(NULL==(hwndControl=GetDlgItem(hwndDlg, IDC_WIZARD_LIST1)))
break;
//get the certificate from the stores
if(hCertStore=GetCertsFromStore(hwndDlg, pCertBuildCTLInfo))
{
pCertContext = NULL;
while (NULL != (pCertContext = CertEnumCertificatesInStore(
hCertStore,
pCertContext)))
{
if(AddCertToBuildCTL(
CertDuplicateCertificateContext(pCertContext),
pCertBuildCTLInfo))
{
//add the certificat to the window
AddCertToList(hwndControl,pCertContext,
pCertBuildCTLInfo->dwCertCount-1);
}
else if (!fErrorDisplayed)
{
fErrorDisplayed = TRUE;
//warn the user that the certificate already exists
I_MessageBox(hwndDlg, IDS_EXIT_CERT_IN_CTL,
IDS_BUILDCTL_WIZARD_TITLE,
NULL,
MB_ICONINFORMATION|MB_OK|MB_APPLMODAL);
}
}
CertCloseStore(hCertStore, 0);
}
break;
//add a certificate from a file
case IDC_WIZARD_BUTTON2:
if(NULL==(pCertBuildCTLInfo=(CERT_BUILDCTL_INFO *)GetWindowLongPtr(hwndDlg, DWLP_USER)))
break;
//get the window handle of the cert list view
if(NULL==(hwndControl=GetDlgItem(hwndDlg, IDC_WIZARD_LIST1)))
break;
//get the file name. Make sure the cert is correct
if(hCertStore=GetCertStoreFromFile(hwndDlg, pCertBuildCTLInfo))
{
while(pCertContext=CertEnumCertificatesInStore(
hCertStore,
pPreCertContext))
{
fEmptyStore=FALSE;
//make sure this is a valid certificate
//make sure the pCertContext is a self-signed certificate
if(!TrustIsCertificateSelfSigned(pCertContext, pCertContext->dwCertEncodingType, 0))
{
if(fSelfSigned)
{
I_MessageBox(hwndDlg, IDS_SOME_NOT_SELF_SIGNED,
IDS_BUILDCTL_WIZARD_TITLE,
NULL,
MB_ICONEXCLAMATION|MB_OK|MB_APPLMODAL);
//no need to pop up the information anymore
fSelfSigned=FALSE;
}
pPreCertContext=pCertContext;
continue;
}
//make sure the certifcate match what is defined on the CTL list
if(!CertMatchCTL(pCertBuildCTLInfo, pCertContext))
{
if(fCTLUsage)
{
I_MessageBox(hwndDlg, IDS_SOME_NO_MATCH_USAGE,
IDS_BUILDCTL_WIZARD_TITLE,
NULL,
MB_ICONEXCLAMATION|MB_OK|MB_APPLMODAL);
//no need to pop up the information anymore
fCTLUsage=FALSE;
}
pPreCertContext=pCertContext;
continue;
}
//get a duplicate copy
pPreCertContext=CertDuplicateCertificateContext(pCertContext);
if(NULL==pPreCertContext)
{
pPreCertContext=pCertContext;
continue;
}
if(AddCertToBuildCTL(pPreCertContext, pCertBuildCTLInfo))
{
//add the certificat to the window
AddCertToList(hwndControl,pPreCertContext,
pCertBuildCTLInfo->dwCertCount-1);
}
else
{
if(fDuplicateCert)
{
//warn the user that the certificate already exists
I_MessageBox(hwndDlg, IDS_EXIT_CERT_IN_CTL,
IDS_BUILDCTL_WIZARD_TITLE,
NULL,
MB_ICONINFORMATION|MB_OK|MB_APPLMODAL);
fDuplicateCert=FALSE;
}
CertFreeCertificateContext(pPreCertContext);
}
pPreCertContext=pCertContext;
}
//warn the user that the store is empty
if(TRUE == fEmptyStore)
{
I_MessageBox(hwndDlg, IDS_EMPTY_CERT_IN_FILE,
IDS_BUILDCTL_WIZARD_TITLE,
NULL,
MB_ICONEXCLAMATION|MB_OK|MB_APPLMODAL);
}
}
pPreCertContext=NULL;
pCertContext=NULL;
if(hCertStore)
CertCloseStore(hCertStore, 0);
hCertStore=NULL;
break;
//remove a certificate from the store
case IDC_WIZARD_BUTTON3:
if(NULL==(pCertBuildCTLInfo=(CERT_BUILDCTL_INFO *)GetWindowLongPtr(hwndDlg, DWLP_USER)))
break;
//get the window handle of the cert list view
if(NULL==(hwndControl=GetDlgItem(hwndDlg, IDC_WIZARD_LIST1)))
break;
memset(&lvItem, 0, sizeof(lvItem));
lvItem.mask = LVIF_STATE | LVIF_PARAM;
lvItem.stateMask = LVIS_SELECTED;
for (i=(ListView_GetItemCount(hwndControl) - 1); i >=0; i--)
{
lvItem.iItem = i;
if (ListView_GetItem(hwndControl, &lvItem) &&
(lvItem.state & LVIS_SELECTED))
{
if(DeleteCertFromBuildCTL(pCertBuildCTLInfo, (PCCERT_CONTEXT)(lvItem.lParam)))
{
//delete the item from the list
ListView_DeleteItem(hwndControl, lvItem.iItem);
}
}
}
/* else
//output the message
I_MessageBox(hwndDlg, IDS_HAS_TO_SELECT_CERT,
IDS_BUILDCTL_WIZARD_TITLE,
NULL,
MB_ICONERROR|MB_OK|MB_APPLMODAL);*/
break;
//view a certificate
case IDC_WIZARD_BUTTON4:
if(NULL==(pCertBuildCTLInfo=(CERT_BUILDCTL_INFO *)GetWindowLongPtr(hwndDlg, DWLP_USER)))
{
break;
}
//get the window handle of the cert list view
if(NULL==(hwndControl=GetDlgItem(hwndDlg, IDC_WIZARD_LIST1)))
break;
//get the selected cert
listIndex = ListView_GetNextItem(
hwndControl,
-1,
LVNI_SELECTED
);
if (listIndex != -1)
{
//get the selected certificate
memset(&lvItem, 0, sizeof(LV_ITEM));
lvItem.mask=LVIF_PARAM;
lvItem.iItem=listIndex;
if(ListView_GetItem(hwndControl, &lvItem))
{
//view certiificate
if(pCertBuildCTLInfo->dwCertCount > (DWORD)listIndex)
{
memset(&CertViewStruct, 0, sizeof(CRYPTUI_VIEWCERTIFICATE_STRUCT));
CertViewStruct.dwSize=sizeof(CRYPTUI_VIEWCERTIFICATE_STRUCT);
CertViewStruct.pCertContext=(PCCERT_CONTEXT)(lvItem.lParam);
CertViewStruct.hwndParent=hwndDlg;
CertViewStruct.dwFlags=CRYPTUI_DISABLE_EDITPROPERTIES;
CryptUIDlgViewCertificate(&CertViewStruct, NULL);
}
}
}
else
//output the message
I_MessageBox(hwndDlg, IDS_HAS_TO_SELECT_CERT,
IDS_BUILDCTL_WIZARD_TITLE,
NULL,
MB_ICONERROR|MB_OK|MB_APPLMODAL);
break;
default:
break;
}
}
break;
case WM_NOTIFY:
switch (((NMHDR FAR *) lParam)->code)
{
//the column has been clicked
case LVN_COLUMNCLICK:
if(NULL==(pCertBuildCTLInfo=(CERT_BUILDCTL_INFO *)GetWindowLongPtr(hwndDlg, DWLP_USER)))
break;
//get the window handle of the purpose list view
if(NULL==(hwndControl=GetDlgItem(hwndDlg, IDC_WIZARD_LIST1)))
break;
pnmv = (NM_LISTVIEW FAR *) lParam;
//get the column number
dwSortParam=0;
switch(pnmv->iSubItem)
{
case 0:
case 1:
case 2:
case 3:
dwSortParam=pCertBuildCTLInfo->rgdwSortParam[pnmv->iSubItem];
break;
default:
dwSortParam=0;
break;
}
if(0!=dwSortParam)
{
//remember to flip the ascend ording
if(dwSortParam & SORT_COLUMN_ASCEND)
{
dwSortParam &= 0x0000FFFF;
dwSortParam |= SORT_COLUMN_DESCEND;
}
else
{
if(dwSortParam & SORT_COLUMN_DESCEND)
{
dwSortParam &= 0x0000FFFF;
dwSortParam |= SORT_COLUMN_ASCEND;
}
}
//sort the column
SendDlgItemMessage(hwndDlg,
IDC_WIZARD_LIST1,
LVM_SORTITEMS,
(WPARAM) (LPARAM) dwSortParam,
(LPARAM) (PFNLVCOMPARE)CompareCertificate);
pCertBuildCTLInfo->rgdwSortParam[pnmv->iSubItem]=dwSortParam;
}
break;
case PSN_KILLACTIVE:
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE);
return TRUE;
break;
case PSN_RESET:
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE);
break;
case PSN_SETACTIVE:
PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT|PSWIZB_BACK);
if(NULL==(pCertBuildCTLInfo=(CERT_BUILDCTL_INFO *)GetWindowLongPtr(hwndDlg, DWLP_USER)))
{
break;
}
//get the window handle of the purpose list view
if(NULL==(hwndControl=GetDlgItem(hwndDlg, IDC_WIZARD_LIST1)))
break;
//see if we need to clear the certs
if(TRUE==pCertBuildCTLInfo->fClearCerts)
{
pCertBuildCTLInfo->fClearCerts=FALSE;
//clear the list view
ListView_DeleteAllItems(hwndControl);
//free all the certificate context
FreeCerts(pCertBuildCTLInfo);
}
break;
case PSN_WIZBACK:
if(NULL==(pCertBuildCTLInfo=(CERT_BUILDCTL_INFO *)GetWindowLongPtr(hwndDlg, DWLP_USER)))
break;
//check if we need to skip the 1st page
if(CRYPTUI_WIZ_BUILDCTL_SKIP_PURPOSE & pCertBuildCTLInfo->dwFlag)
{
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, IDD_BUILDCTL_WELCOME);
}
break;
case PSN_WIZNEXT:
if(NULL==(pCertBuildCTLInfo=(CERT_BUILDCTL_INFO *)GetWindowLongPtr(hwndDlg, DWLP_USER)))
{
break;
}
if(0==pCertBuildCTLInfo->dwCertCount)
{
I_MessageBox(hwndDlg, IDS_HAS_TO_SELECT_CERT,
IDS_BUILDCTL_WIZARD_TITLE,
NULL,
MB_ICONERROR|MB_OK|MB_APPLMODAL);
//the page should stay
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1);
}
break;
case NM_DBLCLK:
switch (((NMHDR FAR *) lParam)->idFrom)
{
case IDC_WIZARD_LIST1:
if(NULL==(pCertBuildCTLInfo=(CERT_BUILDCTL_INFO *)GetWindowLongPtr(hwndDlg, DWLP_USER)))
break;
//get the window handle of the cert list view
if(NULL==(hwndControl=GetDlgItem(hwndDlg, IDC_WIZARD_LIST1)))
break;
//get the selected cert
listIndex = ListView_GetNextItem(
hwndControl,
-1,
LVNI_SELECTED
);
if (listIndex != -1)
{
//get the selected certificate
memset(&lvItem, 0, sizeof(LV_ITEM));
lvItem.mask=LVIF_PARAM;
lvItem.iItem=listIndex;
if(ListView_GetItem(hwndControl, &lvItem))
{
//view certiificate
if(pCertBuildCTLInfo->dwCertCount > (DWORD)listIndex)
{
memset(&CertViewStruct, 0, sizeof(CRYPTUI_VIEWCERTIFICATE_STRUCT));
CertViewStruct.dwSize=sizeof(CRYPTUI_VIEWCERTIFICATE_STRUCT);
CertViewStruct.pCertContext=(PCCERT_CONTEXT)(lvItem.lParam);
CertViewStruct.hwndParent=hwndDlg;
CertViewStruct.dwFlags=CRYPTUI_DISABLE_EDITPROPERTIES;
CryptUIDlgViewCertificate(&CertViewStruct, NULL);
}
}
}
else
//output the message
I_MessageBox(hwndDlg, IDS_HAS_TO_SELECT_CERT,
IDS_BUILDCTL_WIZARD_TITLE,
NULL,
MB_ICONERROR|MB_OK|MB_APPLMODAL);
break;
default:
break;
}
break;
/* case NM_CLICK:
{
switch (((NMHDR FAR *) lParam)->idFrom)
{
case IDC_WIZARD_LIST1:
//get the window handle of the cert list view
if(NULL==(hwndControl=GetDlgItem(hwndDlg, IDC_WIZARD_LIST1)))
break;
//get the selected item
listIndex = ListView_GetNextItem(
hwndControl,
-1,
LVNI_SELECTED
);
if(-1 != listIndex)
{
EnableWindow(GetDlgItem(hwndDlg, IDC_WIZARD_BUTTON3), TRUE);
EnableWindow(GetDlgItem(hwndDlg, IDC_WIZARD_BUTTON4), TRUE);
}
break;
}
}
break; */
//the item has been selected
case LVN_ITEMCHANGED:
//
// if an item is selected, then enable the remove button, otherwise
// disable it
//
if (ListView_GetSelectedCount(GetDlgItem(hwndDlg,IDC_WIZARD_LIST1)) == 0)
{
EnableWindow(GetDlgItem(hwndDlg, IDC_WIZARD_BUTTON3), FALSE);
EnableWindow(GetDlgItem(hwndDlg, IDC_WIZARD_BUTTON4), FALSE);
}
else
{
EnableWindow(GetDlgItem(hwndDlg, IDC_WIZARD_BUTTON3), TRUE);
EnableWindow(GetDlgItem(hwndDlg, IDC_WIZARD_BUTTON4), TRUE);
}
break;
default:
return FALSE;
}
break;
default:
return FALSE;
}
return TRUE;
}
//-----------------------------------------------------------------------
// BuildCTL_Destination
//-----------------------------------------------------------------------
INT_PTR APIENTRY BuildCTL_Destination(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
CERT_BUILDCTL_INFO *pCertBuildCTLInfo=NULL;
PROPSHEETPAGEW *pPropSheet=NULL;
HWND hwndControl=NULL;
OPENFILENAMEW OpenFileName;
WCHAR szFileName[_MAX_PATH];
static WCHAR wszFileName[_MAX_PATH];
WCHAR szFilter[MAX_STRING_SIZE]; //"Certificate Trust List (*.ctl)\0*.ctl\0All Files\0*.*\0"
DWORD dwSize=0;
LPWSTR pwszStoreName=NULL;
CRYPTUI_SELECTSTORE_STRUCT CertStoreSelect;
STORENUMERATION_STRUCT StoreEnumerationStruct;
STORESFORSELCTION_STRUCT StoresForSelectionStruct;
DWORD dwChar=0;
HCERTSTORE hCertStore=NULL;
LV_COLUMNW lvC;
LV_ITEMW lvItem;
HDC hdc=NULL;
COLORREF colorRef;
BOOL fAppendExt=FALSE;
switch (msg)
{
case WM_INITDIALOG:
//set the wizard information so that it can be shared
pPropSheet = (PROPSHEETPAGEW *) lParam;
pCertBuildCTLInfo = (CERT_BUILDCTL_INFO *) (pPropSheet->lParam);
//make sure pCertBuildCTLInfo is a valid pointer
if(NULL==pCertBuildCTLInfo)
break;
SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pCertBuildCTLInfo);
SetControlFont(pCertBuildCTLInfo->hBold, hwndDlg,IDC_WIZARD_STATIC_BOLD1);
//getthe background color of the parent window
//the background of the list view for store name is grayed
/*
if(hdc=GetWindowDC(hwndDlg))
{
if(CLR_INVALID!=(colorRef=GetBkColor(hdc)))
{
ListView_SetBkColor(GetDlgItem(hwndDlg, IDC_WIZARD_LIST1), CLR_NONE);
ListView_SetTextBkColor(GetDlgItem(hwndDlg, IDC_WIZARD_LIST1), CLR_NONE);
}
} */
//pre-set the selections for the destinations
//set the store name if pre-selected
if(pCertBuildCTLInfo->hDesStore)
{
//select the 1st radio button
SendMessage(GetDlgItem(hwndDlg, IDC_WIZARD_RADIO1), BM_SETCHECK, 1, 0);
SendMessage(GetDlgItem(hwndDlg, IDC_WIZARD_RADIO2), BM_SETCHECK, 0, 0);
//disable the windows for select a file
EnableWindow(GetDlgItem(hwndDlg, IDC_WIZARD_EDIT1), FALSE);
EnableWindow(GetDlgItem(hwndDlg, IDC_WIZARD_BUTTON2), FALSE);
//set the store name if pre-selected
//get the hwndControl for the list view
hwndControl=GetDlgItem(hwndDlg, IDC_WIZARD_LIST1);
if(hwndControl)
SetStoreName(hwndControl,pCertBuildCTLInfo->hDesStore);
}
else
{
//select the 2nd radio button
SendMessage(GetDlgItem(hwndDlg, IDC_WIZARD_RADIO1), BM_SETCHECK, 0, 0);
SendMessage(GetDlgItem(hwndDlg, IDC_WIZARD_RADIO2), BM_SETCHECK, 1, 0);
//disable the controls to select a store
EnableWindow(GetDlgItem(hwndDlg, IDC_WIZARD_BUTTON1), FALSE);
EnableWindow(GetDlgItem(hwndDlg, IDC_WIZARD_LIST1), FALSE);
if(pCertBuildCTLInfo->pwszFileName)
{
//pre-initialize the file name
SetDlgItemTextU(hwndDlg, IDC_WIZARD_EDIT1, pCertBuildCTLInfo->pwszFileName);
}
}
//init
memset(&wszFileName, 0, sizeof(wszFileName));
*wszFileName='\0';
break;
case WM_COMMAND:
if(HIWORD(wParam) == BN_CLICKED)
{
switch (LOWORD(wParam))
{
case IDC_WIZARD_RADIO1:
//select the 1st radio button
SendMessage(GetDlgItem(hwndDlg, IDC_WIZARD_RADIO1), BM_SETCHECK, 1, 0);
//enable the controls to select a store
EnableWindow(GetDlgItem(hwndDlg, IDC_WIZARD_BUTTON1), TRUE);
EnableWindow(GetDlgItem(hwndDlg, IDC_WIZARD_LIST1), TRUE);
//disable raio2
SendMessage(GetDlgItem(hwndDlg, IDC_WIZARD_RADIO2), BM_SETCHECK, 0, 0);
//disable controls to select a file
EnableWindow(GetDlgItem(hwndDlg, IDC_WIZARD_BUTTON2), FALSE);
EnableWindow(GetDlgItem(hwndDlg, IDC_WIZARD_EDIT1), FALSE);
break;
case IDC_WIZARD_RADIO2:
//disable the 1st radio button
SendMessage(GetDlgItem(hwndDlg, IDC_WIZARD_RADIO1), BM_SETCHECK, 0, 0);
//disable the controls to select a store
EnableWindow(GetDlgItem(hwndDlg, IDC_WIZARD_BUTTON1), FALSE);
EnableWindow(GetDlgItem(hwndDlg, IDC_WIZARD_LIST1), FALSE);
//enable raio2
SendMessage(GetDlgItem(hwndDlg, IDC_WIZARD_RADIO2), BM_SETCHECK, 1, 0);
//enable controls to select a file
EnableWindow(GetDlgItem(hwndDlg, IDC_WIZARD_BUTTON2), TRUE);
EnableWindow(GetDlgItem(hwndDlg, IDC_WIZARD_EDIT1), TRUE);
break;
case IDC_WIZARD_BUTTON1:
//the browse for store button is selected
if(NULL==(pCertBuildCTLInfo=(CERT_BUILDCTL_INFO *)GetWindowLongPtr(hwndDlg, DWLP_USER)))
{
break;
}
//get the hwndControl for the list view
hwndControl=GetDlgItem(hwndDlg, IDC_WIZARD_LIST1);
//call the store selection dialogue
memset(&CertStoreSelect, 0, sizeof(CertStoreSelect));
memset(&StoresForSelectionStruct, 0, sizeof(StoresForSelectionStruct));
memset(&StoreEnumerationStruct, 0, sizeof(StoreEnumerationStruct));
StoreEnumerationStruct.dwFlags=CERT_STORE_MAXIMUM_ALLOWED_FLAG | CERT_SYSTEM_STORE_CURRENT_USER;
StoreEnumerationStruct.pvSystemStoreLocationPara=NULL;
StoresForSelectionStruct.cEnumerationStructs = 1;
StoresForSelectionStruct.rgEnumerationStructs = &StoreEnumerationStruct;
CertStoreSelect.dwSize=sizeof(CRYPTUI_SELECTSTORE_STRUCT);
CertStoreSelect.hwndParent=hwndDlg;
CertStoreSelect.dwFlags=CRYPTUI_VALIDATE_STORES_AS_WRITABLE | CRYPTUI_ALLOW_PHYSICAL_STORE_VIEW | CRYPTUI_DISPLAY_WRITE_ONLY_STORES;
CertStoreSelect.pStoresForSelection = &StoresForSelectionStruct;
hCertStore=CryptUIDlgSelectStore(&CertStoreSelect);
if(hCertStore)
{
//delete the old destination certificate store
if(pCertBuildCTLInfo->hDesStore && (TRUE==pCertBuildCTLInfo->fFreeDesStore))
{
CertCloseStore(pCertBuildCTLInfo->hDesStore, 0);
pCertBuildCTLInfo->hDesStore=NULL;
}
pCertBuildCTLInfo->hDesStore=hCertStore;
pCertBuildCTLInfo->fFreeDesStore=TRUE;
//get the store name
SetStoreName(hwndControl,
pCertBuildCTLInfo->hDesStore);
}
break;
case IDC_WIZARD_BUTTON2:
//the browse file button is clicked. Open the FileOpen dialogue
memset(&OpenFileName, 0, sizeof(OpenFileName));
*szFileName=L'\0';
OpenFileName.lStructSize = sizeof(OpenFileName);
OpenFileName.hwndOwner = hwndDlg;
OpenFileName.hInstance = NULL;
//load the fileter string
if(LoadFilterString(g_hmodThisDll, IDS_CTL_FILTER, szFilter, MAX_STRING_SIZE))
{
OpenFileName.lpstrFilter = szFilter;
}
OpenFileName.lpstrCustomFilter = NULL;
OpenFileName.nMaxCustFilter = 0;
OpenFileName.nFilterIndex = 1;
OpenFileName.lpstrFile = szFileName;
OpenFileName.nMaxFile = _MAX_PATH;
OpenFileName.lpstrFileTitle = NULL;
OpenFileName.nMaxFileTitle = 0;
OpenFileName.lpstrInitialDir = NULL;
OpenFileName.lpstrTitle = NULL;
OpenFileName.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST;
OpenFileName.nFileOffset = 0;
OpenFileName.nFileExtension = 0;
OpenFileName.lpstrDefExt = L"ctl";
OpenFileName.lCustData = NULL;
OpenFileName.lpfnHook = NULL;
OpenFileName.lpTemplateName = NULL;
if (WizGetSaveFileName(&OpenFileName))
{
//set the edit box
SetDlgItemTextU(hwndDlg, IDC_WIZARD_EDIT1, szFileName);
//copy the selected file name
wcscpy(wszFileName, szFileName);
}
break;
default:
break;
}
}
break;
case WM_NOTIFY:
switch (((NMHDR FAR *) lParam)->code)
{
case PSN_KILLACTIVE:
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE);
return TRUE;
break;
case PSN_RESET:
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE);
break;
case PSN_SETACTIVE:
PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT|PSWIZB_BACK);
if(NULL==(pCertBuildCTLInfo=(CERT_BUILDCTL_INFO *)GetWindowLongPtr(hwndDlg, DWLP_USER)))
break;
if(pCertBuildCTLInfo->pwszFileName)
{
//pre-initialize the file name since extension might have been added
SetDlgItemTextU(hwndDlg, IDC_WIZARD_EDIT1, pCertBuildCTLInfo->pwszFileName);
}
break;
case PSN_WIZBACK:
break;
case PSN_WIZNEXT:
if(NULL==(pCertBuildCTLInfo=(CERT_BUILDCTL_INFO *)GetWindowLongPtr(hwndDlg, DWLP_USER)))
{
break;
}
//make sure that we have select some store
if(TRUE==SendMessage(GetDlgItem(hwndDlg, IDC_WIZARD_RADIO1), BM_GETCHECK, 0, 0))
{
if(NULL==pCertBuildCTLInfo->hDesStore)
{
//output the message
I_MessageBox(hwndDlg, IDS_HAS_TO_SELECT_STORE,
IDS_BUILDCTL_WIZARD_TITLE,
NULL,
MB_ICONERROR|MB_OK|MB_APPLMODAL);
//make the file page stay
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1);
break;
}
else
{
//mark the hDesStore should be used
pCertBuildCTLInfo->fSelectedDesStore=TRUE;
pCertBuildCTLInfo->fSelectedFileName=FALSE;
}
}
else
{
//make sure a file is selected
if(0==(dwChar=(DWORD)SendDlgItemMessage(hwndDlg,
IDC_WIZARD_EDIT1,
WM_GETTEXTLENGTH, 0, 0)))
{
I_MessageBox(hwndDlg, IDS_HAS_TO_SELECT_FILE,
IDS_BUILDCTL_WIZARD_TITLE,
NULL,
MB_ICONERROR|MB_OK|MB_APPLMODAL);
//make the file page stay
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1);
break;
}
else
{
//mark the file name should be used
pCertBuildCTLInfo->fSelectedDesStore=FALSE;
pCertBuildCTLInfo->fSelectedFileName=TRUE;
//get the file name
if(pCertBuildCTLInfo->pwszFileName)
{
//delete the old file name
if(TRUE==pCertBuildCTLInfo->fFreeFileName)
{
WizardFree(pCertBuildCTLInfo->pwszFileName);
pCertBuildCTLInfo->pwszFileName=NULL;
}
}
pCertBuildCTLInfo->pwszFileName=(LPWSTR)WizardAlloc((dwChar+1)*sizeof(WCHAR));
if(NULL==pCertBuildCTLInfo->pwszFileName)
break;
pCertBuildCTLInfo->fFreeFileName=TRUE;
GetDlgItemTextU(hwndDlg, IDC_WIZARD_EDIT1,
pCertBuildCTLInfo->pwszFileName,
dwChar+1);
//we append .ctl file extension if user has not specify it
fAppendExt=FALSE;
if(wcslen(pCertBuildCTLInfo->pwszFileName) < 4)
fAppendExt=TRUE;
else
{
if (_wcsicmp(L".stl", &(pCertBuildCTLInfo->pwszFileName[wcslen(pCertBuildCTLInfo->pwszFileName)-4])) != 0)
fAppendExt=TRUE;
else
fAppendExt=FALSE;
}
if(TRUE == fAppendExt)
{
pCertBuildCTLInfo->pwszFileName = (LPWSTR)WizardRealloc(pCertBuildCTLInfo->pwszFileName,
(wcslen(pCertBuildCTLInfo->pwszFileName) + 4 + 1) * sizeof(WCHAR));
if(NULL==pCertBuildCTLInfo->pwszFileName)
break;
wcscat(pCertBuildCTLInfo->pwszFileName, L".stl");
}
//confirm to over write
if(0 != _wcsicmp(wszFileName, pCertBuildCTLInfo->pwszFileName))
{
if(FileExist(pCertBuildCTLInfo->pwszFileName))
{
if(FALSE == CheckReplace(hwndDlg, pCertBuildCTLInfo->pwszFileName))
{
//make the file page stay
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1);
break;
}
}
}
}
}
//decide if we need to skip to the friendly name page
if(pCertBuildCTLInfo->hDesStore && (TRUE==pCertBuildCTLInfo->fSelectedDesStore))
{
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, IDD_BUILDCTL_NAME);
}
else
{
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, IDD_BUILDCTL_COMPLETION);
}
break;
default:
return FALSE;
}
break;
default:
return FALSE;
}
return TRUE;
}
//-----------------------------------------------------------------------
// BuildCTL_Name
//-----------------------------------------------------------------------
INT_PTR APIENTRY BuildCTL_Name(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
CERT_BUILDCTL_INFO *pCertBuildCTLInfo=NULL;
PROPSHEETPAGEW *pPropSheet=NULL;
HWND hwndControl=NULL;
DWORD dwChar;
switch (msg)
{
case WM_INITDIALOG:
//set the wizard information so that it can be shared
pPropSheet = (PROPSHEETPAGEW *) lParam;
pCertBuildCTLInfo = (CERT_BUILDCTL_INFO *) (pPropSheet->lParam);
//make sure pCertBuildCTLInfo is a valid pointer
if(NULL==pCertBuildCTLInfo)
break;
SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pCertBuildCTLInfo);
SetControlFont(pCertBuildCTLInfo->hBold, hwndDlg,IDC_WIZARD_STATIC_BOLD1);
//set the FriedlyName and description field
//if pwszFriendlyName is NULL, use the list ID
if(pCertBuildCTLInfo->pwszFriendlyName)
SetDlgItemTextU(hwndDlg, IDC_WIZARD_EDIT1, pCertBuildCTLInfo->pwszFriendlyName);
else
{
if(pCertBuildCTLInfo->pwszListID)
SetDlgItemTextU(hwndDlg, IDC_WIZARD_EDIT1, pCertBuildCTLInfo->pwszListID);
}
if(pCertBuildCTLInfo->pwszDescription)
SetDlgItemTextU(hwndDlg, IDC_WIZARD_EDIT2, pCertBuildCTLInfo->pwszDescription);
break;
case WM_COMMAND:
break;
case WM_NOTIFY:
switch (((NMHDR FAR *) lParam)->code)
{
case PSN_KILLACTIVE:
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE);
return TRUE;
break;
case PSN_RESET:
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE);
break;
case PSN_SETACTIVE:
PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT|PSWIZB_BACK);
break;
case PSN_WIZBACK:
break;
case PSN_WIZNEXT:
if(NULL==(pCertBuildCTLInfo=(CERT_BUILDCTL_INFO *)GetWindowLongPtr(hwndDlg, DWLP_USER)))
{
break;
}
//free the friendly name and description
if(pCertBuildCTLInfo->pwszFriendlyName)
{
WizardFree(pCertBuildCTLInfo->pwszFriendlyName);
pCertBuildCTLInfo->pwszFriendlyName=NULL;
}
if(pCertBuildCTLInfo->pwszDescription)
{
WizardFree(pCertBuildCTLInfo->pwszDescription);
pCertBuildCTLInfo->pwszDescription=NULL;
}
//get the friendly name
if(0!=(dwChar=(DWORD)SendDlgItemMessage(hwndDlg,
IDC_WIZARD_EDIT1,
WM_GETTEXTLENGTH, 0, 0)))
{
pCertBuildCTLInfo->pwszFriendlyName=(LPWSTR)WizardAlloc(sizeof(WCHAR)*(dwChar+1));
if(NULL!=pCertBuildCTLInfo->pwszFriendlyName)
{
GetDlgItemTextU(hwndDlg, IDC_WIZARD_EDIT1,
pCertBuildCTLInfo->pwszFriendlyName,
dwChar+1);
}
else
//we are out of memory and out of hope
break;
}
//get the description
if(0!=(dwChar=(DWORD)SendDlgItemMessage(hwndDlg,
IDC_WIZARD_EDIT2,
WM_GETTEXTLENGTH, 0, 0)))
{
pCertBuildCTLInfo->pwszDescription=(LPWSTR)WizardAlloc(sizeof(WCHAR)*(dwChar+1));
if(NULL!=pCertBuildCTLInfo->pwszDescription)
{
GetDlgItemTextU(hwndDlg, IDC_WIZARD_EDIT2,
pCertBuildCTLInfo->pwszDescription,
dwChar+1);
}
else
//we are out of memory and out of hope
break;
}
break;
default:
return FALSE;
}
break;
default:
return FALSE;
}
return TRUE;
}
//-----------------------------------------------------------------------
// BuildCTL_Completion
//-----------------------------------------------------------------------
INT_PTR APIENTRY BuildCTL_Completion(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
CERT_BUILDCTL_INFO *pCertBuildCTLInfo=NULL;
PROPSHEETPAGEW *pPropSheet=NULL;
HWND hwndControl=NULL;
LV_COLUMNW lvC;
HDC hdc=NULL;
COLORREF colorRef;
DWORD dwEncodedCTL=0;
BYTE *pbEncodedCTL=NULL;
DWORD cbEncodedCTL=0;
UINT ids=0;
switch (msg)
{
case WM_INITDIALOG:
//set the wizard information so that it can be shared
pPropSheet = (PROPSHEETPAGEW *) lParam;
pCertBuildCTLInfo = (CERT_BUILDCTL_INFO *) (pPropSheet->lParam);
//make sure pCertBuildCTLInfo is a valid pointer
if(NULL==pCertBuildCTLInfo)
break;
SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pCertBuildCTLInfo);
SetControlFont(pCertBuildCTLInfo->hBigBold, hwndDlg,IDC_WIZARD_STATIC_BIG_BOLD1);
//getthe background color of the parent window
/*
if(hdc=GetWindowDC(hwndDlg))
{
if(CLR_INVALID!=(colorRef=GetBkColor(hdc)))
{
ListView_SetBkColor(GetDlgItem(hwndDlg, IDC_WIZARD_LIST1), CLR_NONE);
ListView_SetTextBkColor(GetDlgItem(hwndDlg, IDC_WIZARD_LIST1), CLR_NONE);
}
} */
//insert two columns
hwndControl=GetDlgItem(hwndDlg, IDC_WIZARD_LIST1);
if(NULL==hwndControl)
break;
//1st one is the label for the confirmation
memset(&lvC, 0, sizeof(LV_COLUMNW));
lvC.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
lvC.fmt = LVCFMT_LEFT; // Left-align the column.
lvC.cx = 20; // Width of the column, in pixels.We will autosize later
lvC.pszText = L""; // The text for the column.
lvC.iSubItem=0;
if (ListView_InsertColumnU(hwndControl, 0, &lvC) == -1)
break;
//2nd column is the content
memset(&lvC, 0, sizeof(LV_COLUMNW));
lvC.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
lvC.fmt = LVCFMT_LEFT; // Left-align the column.
lvC.cx = 10; //(dwMaxSize+2)*7; // Width of the column, in pixels.
//the width will be autosized later
lvC.pszText = L""; // The text for the column.
lvC.iSubItem= 1;
if (ListView_InsertColumnU(hwndControl, 1, &lvC) == -1)
break;
break;
case WM_COMMAND:
break;
case WM_NOTIFY:
switch (((NMHDR FAR *) lParam)->code)
{
case PSN_KILLACTIVE:
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE);
return TRUE;
break;
case PSN_RESET:
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE);
break;
case PSN_SETACTIVE:
PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK|PSWIZB_FINISH);
if(NULL==(pCertBuildCTLInfo=(CERT_BUILDCTL_INFO *)GetWindowLongPtr(hwndDlg, DWLP_USER)))
{
break;
}
//populate the list box in the order of
//FileName, StoreName, Purpose, FriendlyName, Description
//and any other things signing wizard display
if(hwndControl=GetDlgItem(hwndDlg, IDC_WIZARD_LIST1))
DisplayBuildCTLConfirmation(hwndControl, pCertBuildCTLInfo);
break;
case PSN_WIZBACK:
if(NULL==(pCertBuildCTLInfo=(CERT_BUILDCTL_INFO *)GetWindowLongPtr(hwndDlg, DWLP_USER)))
{
break;
}
//no need to worry if the pages are not included in the wizards
if(0==(pCertBuildCTLInfo->dwFlag & CRYPTUI_WIZ_BUILDCTL_SKIP_DESTINATION))
{
//skip the friendly name page if the desination does no include
//a store
if(pCertBuildCTLInfo->hDesStore && (TRUE==pCertBuildCTLInfo->fSelectedDesStore))
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, IDD_BUILDCTL_NAME);
else
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, IDD_BUILDCTL_DESTINATION);
}
break;
case PSN_WIZFINISH:
if(NULL==(pCertBuildCTLInfo=(CERT_BUILDCTL_INFO *)GetWindowLongPtr(hwndDlg, DWLP_USER)))
break;
//we need to build the CTL and return the pbEncoded and cbEncoded
if(!I_BuildCTL(pCertBuildCTLInfo,
&ids,
&pbEncodedCTL,
&cbEncodedCTL))
{
if(ids!=0)
I_MessageBox(hwndDlg, ids, IDS_BUILDCTL_WIZARD_TITLE,
NULL, MB_OK|MB_ICONINFORMATION);
}
else
{
if(0!=cbEncodedCTL && NULL!=pbEncodedCTL)
{
//set up the signing information
((CRYPTUI_WIZ_DIGITAL_SIGN_BLOB_INFO *)(pCertBuildCTLInfo->pGetSignInfo->pDigitalSignInfo->pSignBlobInfo))->cbBlob=cbEncodedCTL;
((CRYPTUI_WIZ_DIGITAL_SIGN_BLOB_INFO *)(pCertBuildCTLInfo->pGetSignInfo->pDigitalSignInfo->pSignBlobInfo))->pbBlob=pbEncodedCTL;
}
}
break;
default:
return FALSE;
}
break;
default:
return FALSE;
}
return TRUE;
}
//**************************************************************************
//
// The entry point for buildCTL wizard
//**************************************************************************
//----------------------------------------------------------------------------
// Check to see if the certificate is a valid signing CTL cert
//
//----------------------------------------------------------------------------
BOOL IsValidSigningCTLCert(PCCERT_CONTEXT pCertContext)
{
BOOL fResult=FALSE;
int cNumOID=0;
LPSTR *rgOID=NULL;
DWORD cbOID=0;
DWORD dwIndex=0;
DWORD cbData=0;
if(!pCertContext)
return FALSE;
//the certificate has to have the CERT_KEY_PROV_INFO_PROP_ID
if(!CertGetCertificateContextProperty(pCertContext,
CERT_KEY_PROV_INFO_PROP_ID,
NULL,
&cbData))
return FALSE;
if(0==cbData)
return FALSE;
//get the OIDs from the cert
if(!CertGetValidUsages(
1,
&pCertContext,
&cNumOID,
NULL,
&cbOID))
return FALSE;
rgOID=(LPSTR *)WizardAlloc(cbOID);
if(NULL==rgOID)
return FALSE;
if(!CertGetValidUsages(
1,
&pCertContext,
&cNumOID,
rgOID,
&cbOID))
goto CLEANUP;
//-1 means the certiifcate is food for everything
if(-1==cNumOID)
{
fResult=TRUE;
goto CLEANUP;
}
for(dwIndex=0; dwIndex<(DWORD)cNumOID; dwIndex++)
{
//the only good cert is the one with CTL signing OID
if(0==strcmp(szOID_KP_CTL_USAGE_SIGNING,
rgOID[dwIndex]))
{
fResult=TRUE;
goto CLEANUP;
}
}
//we are hopeless at this point
fResult=FALSE;
CLEANUP:
if(rgOID)
WizardFree(rgOID);
return fResult;
}
//----------------------------------------------------------------------------
// CallBack fro cert selection call back
//
//----------------------------------------------------------------------------
static BOOL WINAPI SelectCTLSignCertCallBack(
PCCERT_CONTEXT pCertContext,
BOOL *pfInitialSelectedCert,
void *pvCallbackData)
{
if(!pCertContext)
return FALSE;
//make sure that this is a valid certificate
return IsValidSigningCTLCert(pCertContext);
}
//-----------------------------------------------------------------------
//
// CryptUIWizBuildCTL
//
// Build a new CTL or modify an existing CTL. The UI for wizard will
// always show in this case
//
//
// dwFlags: IN Reserved: flags. Must be set 0
// hwndParnet: IN Optional: The parent window handle
// pwszWizardTitle: IN Optional: The title of the wizard
// pBuildCTLSrc: IN Optional: The source from which the CTL will be built
// pBuildCTLDest: IN Optional: The desination where the newly
// built CTL will be stored
// ppCTLContext: OUT Optaionl: The newly build CTL
//
//------------------------------------------------------------------------
BOOL
WINAPI
CryptUIWizBuildCTL(
DWORD dwFlags,
HWND hwndParent,
LPCWSTR pwszWizardTitle,
PCCRYPTUI_WIZ_BUILDCTL_SRC_INFO pBuildCTLSrc,
PCCRYPTUI_WIZ_BUILDCTL_DEST_INFO pBuildCTLDest,
PCCTL_CONTEXT *ppCTLContext
)
{
BOOL fResult=FALSE;
HRESULT hr=E_FAIL;
DWORD dwError=0;
CERT_BUILDCTL_INFO CertBuildCTLInfo;
UINT ids=IDS_INVALID_WIZARD_INPUT;
FILETIME CurrentFileTime;
PROPSHEETPAGEW *prgBuildCTLSheet=NULL;
PROPSHEETHEADERW buildCTLHeader;
ENROLL_PAGE_INFO rgBuildCTLPageInfo[]=
{(LPCWSTR)MAKEINTRESOURCE(IDD_BUILDCTL_WELCOME), BuildCTL_Welcome,
(LPCWSTR)MAKEINTRESOURCE(IDD_BUILDCTL_PURPOSE), BuildCTL_Purpose,
(LPCWSTR)MAKEINTRESOURCE(IDD_BUILDCTL_CERTS), BuildCTL_Certs,
(LPCWSTR)MAKEINTRESOURCE(IDD_BUILDCTL_DESTINATION), BuildCTL_Destination,
(LPCWSTR)MAKEINTRESOURCE(IDD_BUILDCTL_NAME), BuildCTL_Name,
(LPCWSTR)MAKEINTRESOURCE(IDD_BUILDCTL_COMPLETION), BuildCTL_Completion,
};
DWORD dwIndex=0;
DWORD dwPropCount=0;
WCHAR wszTitle[MAX_TITLE_LENGTH];
PCCRYPT_OID_INFO pOIDInfo;
PCCTL_CONTEXT pCTLContext=NULL;
PCCTL_CONTEXT pBldCTL=NULL;
PCCRYPTUI_WIZ_BUILDCTL_NEW_CTL_INFO pNewCTLInfo=NULL;
LPWSTR pwszListID=NULL;
PCERT_ENHKEY_USAGE pSubjectUsage=NULL;
DWORD cbData=0;
CRYPTUI_WIZ_GET_SIGN_PAGE_INFO GetSignInfo;
DWORD dwPages=0;
CRYPTUI_WIZ_DIGITAL_SIGN_INFO DigitalSignInfo;
PROPSHEETPAGEW *pwPages=NULL;
CRYPTUI_WIZ_DIGITAL_SIGN_BLOB_INFO SignBlob;
CRYPTUI_WIZ_DIGITAL_SIGN_STORE_INFO SignStoreInfo;
GUID CTLGuid=CRYPT_SUBJTYPE_CTL_IMAGE;
CRYPT_DATA_BLOB PropertyBlob;
HCERTSTORE hMyStore=NULL;
INT_PTR iReturn=-1;
// CERT_STORE_LIST CertStoreList;
//init
memset(&CertBuildCTLInfo, 0, sizeof(CERT_BUILDCTL_INFO));
memset(&buildCTLHeader, 0, sizeof(PROPSHEETHEADERW));
memset(&GetSignInfo, 0, sizeof(CRYPTUI_WIZ_GET_SIGN_PAGE_INFO));
memset(&DigitalSignInfo, 0, sizeof(CRYPTUI_WIZ_DIGITAL_SIGN_INFO));
memset(&SignBlob, 0, sizeof(CRYPTUI_WIZ_DIGITAL_SIGN_BLOB_INFO));
memset(&SignStoreInfo, 0, sizeof(CRYPTUI_WIZ_DIGITAL_SIGN_STORE_INFO));
memset(&PropertyBlob, 0, sizeof(CRYPT_DATA_BLOB));
//open all the system store system store
//memset(&CertStoreList, 0, sizeof(CertStoreList));
//input checking
if(ppCTLContext)
*ppCTLContext=NULL;
//get the basic information from the src info struct
if(pBuildCTLSrc)
{
if(pBuildCTLSrc->dwSize != sizeof(CRYPTUI_WIZ_BUILDCTL_SRC_INFO))
goto InvalidArgErr;
if(CRYPTUI_WIZ_BUILDCTL_SRC_EXISTING_CTL==pBuildCTLSrc->dwSourceChoice)
{
if(NULL==pBuildCTLSrc->pCTLContext)
goto InvalidArgErr;
pCTLContext=pBuildCTLSrc->pCTLContext;
CertBuildCTLInfo.pSrcCTL=pCTLContext;
}
else
{
if(CRYPTUI_WIZ_BUILDCTL_SRC_NEW_CTL==pBuildCTLSrc->dwSourceChoice)
{
if(NULL==pBuildCTLSrc->pNewCTLInfo)
goto InvalidArgErr;
pNewCTLInfo=pBuildCTLSrc->pNewCTLInfo;
}
else
goto InvalidArgErr;
}
}
//init the private structure based on input parameters
CertBuildCTLInfo.hwndParent=hwndParent;
CertBuildCTLInfo.dwFlag=dwFlags;
CertBuildCTLInfo.rgdwSortParam[0]=SORT_COLUMN_SUBJECT | SORT_COLUMN_ASCEND;
CertBuildCTLInfo.rgdwSortParam[1]=SORT_COLUMN_ISSUER | SORT_COLUMN_DESCEND;
CertBuildCTLInfo.rgdwSortParam[2]=SORT_COLUMN_PURPOSE | SORT_COLUMN_DESCEND;
CertBuildCTLInfo.rgdwSortParam[3]=SORT_COLUMN_EXPIRATION | SORT_COLUMN_DESCEND;
//get the listIdentifier
if(pCTLContext)
{
//copy the listID if it is the wchar format
if(0!=(pCTLContext->pCtlInfo->ListIdentifier.cbData))
{
//get the string presentation of the listID
if(ValidString(&(pCTLContext->pCtlInfo->ListIdentifier)))
{
CertBuildCTLInfo.pwszListID=WizardAllocAndCopyWStr((LPWSTR)(pCTLContext->pCtlInfo->ListIdentifier.pbData));
if(NULL==CertBuildCTLInfo.pwszListID)
goto MemoryErr;
}
else
{
//get the hex presentation of the listID
cbData=0;
if(CryptFormatObject(
X509_ASN_ENCODING,
0,
0,
NULL,
0,
pCTLContext->pCtlInfo->ListIdentifier.pbData,
pCTLContext->pCtlInfo->ListIdentifier.cbData,
NULL,
&cbData) && (0!= cbData))
{
CertBuildCTLInfo.pwszListID=(LPWSTR)WizardAlloc(cbData);
if(NULL==CertBuildCTLInfo.pwszListID)
goto MemoryErr;
if(!CryptFormatObject(
X509_ASN_ENCODING,
0,
0,
NULL,
0,
pCTLContext->pCtlInfo->ListIdentifier.pbData,
pCTLContext->pCtlInfo->ListIdentifier.cbData,
CertBuildCTLInfo.pwszListID,
&cbData))
goto Win32Err;
}
}
}
}
else
{
if(pNewCTLInfo)
{
if(pNewCTLInfo->pwszListIdentifier)
{
CertBuildCTLInfo.pwszListID=WizardAllocAndCopyWStr(pNewCTLInfo->pwszListIdentifier);
if(NULL==CertBuildCTLInfo.pwszListID)
goto MemoryErr;
}
}
}
//get the hash algorithm and dwHashPropID from the source CTL
if(pCTLContext)
{
//make sure we have the correct algorithm
if(NULL==pCTLContext->pCtlInfo->SubjectAlgorithm.pszObjId)
{
ids=IDS_INVALID_ALGORITHM_IN_CTL;
goto InvalidArgErr;
}
CertBuildCTLInfo.pszSubjectAlgorithm=(LPSTR)(pCTLContext->pCtlInfo->SubjectAlgorithm.pszObjId);
}
else
{
if(pNewCTLInfo)
CertBuildCTLInfo.pszSubjectAlgorithm=(LPSTR)(pNewCTLInfo->pszSubjectAlgorithm);
}
if(CertBuildCTLInfo.pszSubjectAlgorithm)
{
pOIDInfo = CryptFindOIDInfo(
CRYPT_OID_INFO_OID_KEY,
CertBuildCTLInfo.pszSubjectAlgorithm,
CRYPT_HASH_ALG_OID_GROUP_ID);
if(NULL==pOIDInfo)
{
ids=IDS_INVALID_ALGORITHM_IN_CTL;
goto Crypt32Err;
}
if (pOIDInfo->Algid == CALG_MD5)
{
CertBuildCTLInfo.dwHashPropID=CERT_MD5_HASH_PROP_ID;
}
else
{
if (pOIDInfo->Algid == CALG_SHA1)
{
CertBuildCTLInfo.dwHashPropID=CERT_SHA1_HASH_PROP_ID;
}
else
{
ids=IDS_INVALID_ALGORITHM_IN_CTL;
goto InvalidArgErr;
}
}
}
else
CertBuildCTLInfo.dwHashPropID=CERT_SHA1_HASH_PROP_ID;
//get the pSubjectUsage
if(pNewCTLInfo)
{
if(pNewCTLInfo->pSubjectUsage)
pSubjectUsage=pNewCTLInfo->pSubjectUsage;
}
//add the subject Usage and pre-select them from either
//the exising CTL or the user defined ones
if(!GetOIDForCTL(&CertBuildCTLInfo,
(pSubjectUsage) ? pSubjectUsage->cUsageIdentifier : 0,
(pSubjectUsage) ? pSubjectUsage->rgpszUsageIdentifier : NULL))
goto InvalidArgErr;
//get the Certficate contexts from either the existing CTL
//of the user defined one
GetCertForCTL(hwndParent,
TRUE, //always UI mode for now
&CertBuildCTLInfo,
(pNewCTLInfo)? pNewCTLInfo->hCertStore : NULL);
//get the dwValidMonths and dwValidDays
if(pCTLContext)
CertBuildCTLInfo.pNextUpdate=&(pCTLContext->pCtlInfo->NextUpdate);
else
{
if(pNewCTLInfo)
CertBuildCTLInfo.pNextUpdate=(FILETIME *)(&(pNewCTLInfo->NextUpdate));
}
//get the current FileTime
GetSystemTimeAsFileTime(&CurrentFileTime);
//get the difference
if(CertBuildCTLInfo.pNextUpdate)
{
SubstractDurationFromFileTime(
CertBuildCTLInfo.pNextUpdate,
&CurrentFileTime,
&(CertBuildCTLInfo.dwValidMonths),
&(CertBuildCTLInfo.dwValidDays));
//we limit to 99 month
if((CertBuildCTLInfo.dwValidMonths > 99) ||
(CertBuildCTLInfo.dwValidMonths == 99 && CertBuildCTLInfo.dwValidDays !=0))
{
CertBuildCTLInfo.dwValidMonths=0;
CertBuildCTLInfo.dwValidDays=0;
}
}
//get the FriendlyName and Description
if(pCTLContext)
{
//friendly Name
cbData=0;
if(CertGetCTLContextProperty(
pCTLContext,
CERT_FRIENDLY_NAME_PROP_ID,
NULL,
&cbData) && (0!=cbData))
{
CertBuildCTLInfo.pwszFriendlyName=(LPWSTR)WizardAlloc(cbData);
if(NULL==CertBuildCTLInfo.pwszFriendlyName)
goto MemoryErr;
if(!CertGetCTLContextProperty(
pCTLContext,
CERT_FRIENDLY_NAME_PROP_ID,
CertBuildCTLInfo.pwszFriendlyName,
&cbData))
goto Win32Err;
}
//Description
cbData=0;
if(CertGetCTLContextProperty(
pCTLContext,
CERT_DESCRIPTION_PROP_ID,
NULL,
&cbData) && (0!=cbData))
{
CertBuildCTLInfo.pwszDescription=(LPWSTR)WizardAlloc(cbData);
if(NULL==CertBuildCTLInfo.pwszDescription)
goto MemoryErr;
if(!CertGetCTLContextProperty(
pCTLContext,
CERT_DESCRIPTION_PROP_ID,
CertBuildCTLInfo.pwszDescription,
&cbData))
goto Win32Err;
}
}
else
{
if(pNewCTLInfo)
{
if(pNewCTLInfo->pwszFriendlyName)
{
CertBuildCTLInfo.pwszFriendlyName=WizardAllocAndCopyWStr(pNewCTLInfo->pwszFriendlyName);
if(NULL==CertBuildCTLInfo.pwszFriendlyName)
goto MemoryErr;
}
if(pNewCTLInfo->pwszDescription)
{
CertBuildCTLInfo.pwszDescription=WizardAllocAndCopyWStr(pNewCTLInfo->pwszDescription);
if(NULL==CertBuildCTLInfo.pwszDescription)
goto MemoryErr;
}
}
}
//get the destination
if(pBuildCTLDest)
{
CertBuildCTLInfo.fKnownDes=TRUE;
if(pBuildCTLDest->dwSize != sizeof(CRYPTUI_WIZ_BUILDCTL_DEST_INFO))
goto InvalidArgErr;
switch(pBuildCTLDest->dwDestinationChoice)
{
case CRYPTUI_WIZ_BUILDCTL_DEST_CERT_STORE:
if(NULL==pBuildCTLDest->hCertStore)
goto InvalidArgErr;
CertBuildCTLInfo.hDesStore=pBuildCTLDest->hCertStore;
CertBuildCTLInfo.fFreeDesStore=FALSE;
CertBuildCTLInfo.fSelectedDesStore=TRUE;
break;
case CRYPTUI_WIZ_BUILDCTL_DEST_FILE:
if(NULL==pBuildCTLDest->pwszFileName)
goto InvalidArgErr;
CertBuildCTLInfo.pwszFileName=(LPWSTR)(pBuildCTLDest->pwszFileName);
CertBuildCTLInfo.fFreeFileName=FALSE;
CertBuildCTLInfo.fSelectedFileName=TRUE;
break;
default:
goto InvalidArgErr;
break;
}
}
else
CertBuildCTLInfo.fKnownDes=FALSE;
//set up the fonts
if(!SetupFonts(g_hmodThisDll,
NULL,
&(CertBuildCTLInfo.hBigBold),
&(CertBuildCTLInfo.hBold)))
{
ids=IDS_FAIL_INIT_BUILDCTL;
goto Win32Err;
}
//init the common control
if(!WizardInit() ||
(sizeof(rgBuildCTLPageInfo)/sizeof(rgBuildCTLPageInfo[0])!=BUILDCTL_PROP_SHEET)
)
{
ids=IDS_FAIL_INIT_BUILDCTL;
goto InvalidArgErr;
}
//set up the parameter to get a list of certificate
//open the my store
if(NULL == (hMyStore=CertOpenStore(CERT_STORE_PROV_SYSTEM_W,
g_dwMsgAndCertEncodingType,
NULL,
CERT_SYSTEM_STORE_CURRENT_USER |CERT_STORE_SET_LOCALIZED_NAME_FLAG,
L"my")))
goto Win32Err;
/* if (!CertEnumSystemStore(
CERT_SYSTEM_STORE_CURRENT_USER,
NULL,
&CertStoreList,
EnumSysStoreSignCertCallBack))
goto Win32Err; */
//set up GetSignInfo
GetSignInfo.dwSize=sizeof(CRYPTUI_WIZ_GET_SIGN_PAGE_INFO);
GetSignInfo.dwPageChoice=CRYPTUI_WIZ_DIGITAL_SIGN_MINIMAL_SIGNING_OPTION_PAGES;
if(pwszWizardTitle)
GetSignInfo.pwszPageTitle=(LPWSTR)pwszWizardTitle;
else
{
if(LoadStringU(g_hmodThisDll, IDS_BUILDCTL_WIZARD_TITLE, wszTitle, sizeof(wszTitle)/sizeof(wszTitle[0])))
GetSignInfo.pwszPageTitle=wszTitle;
}
GetSignInfo.pDigitalSignInfo=&DigitalSignInfo;
//set up DigitalSignInfo
DigitalSignInfo.dwSize=sizeof(CRYPTUI_WIZ_DIGITAL_SIGN_INFO);
//we are always signing a BLOB
DigitalSignInfo.dwSubjectChoice=CRYPTUI_WIZ_DIGITAL_SIGN_SUBJECT_BLOB;
DigitalSignInfo.pSignBlobInfo=&SignBlob;
DigitalSignInfo.dwSigningCertChoice=CRYPTUI_WIZ_DIGITAL_SIGN_STORE;
DigitalSignInfo.pSigningCertStore=&SignStoreInfo;
DigitalSignInfo.dwAdditionalCertChoice=CRYPTUI_WIZ_DIGITAL_SIGN_ADD_CHAIN;
//set up SignStoreInfo
SignStoreInfo.dwSize=sizeof(CRYPTUI_WIZ_DIGITAL_SIGN_STORE_INFO);
SignStoreInfo.cCertStore=1; //CertStoreList.dwStoreCount;
SignStoreInfo.rghCertStore=&hMyStore; //CertStoreList.prgStore;
SignStoreInfo.pFilterCallback=SelectCTLSignCertCallBack;
//set up SignBlobInfo
SignBlob.dwSize=sizeof(CRYPTUI_WIZ_DIGITAL_SIGN_BLOB_INFO);
SignBlob.pGuidSubject=&CTLGuid;
//copy the GetSignInfo into the private data
CertBuildCTLInfo.pGetSignInfo=&GetSignInfo;
//we set up the wizard in two ways: with the signing page or without the
//signing page
if(dwFlags & CRYPTUI_WIZ_BUILDCTL_SKIP_SIGNING)
{
//set up the property sheet without signing
prgBuildCTLSheet=(PROPSHEETPAGEW *)WizardAlloc(sizeof(PROPSHEETPAGEW) *
BUILDCTL_PROP_SHEET);
if(NULL==prgBuildCTLSheet)
goto MemoryErr;
memset(prgBuildCTLSheet, 0, sizeof(PROPSHEETPAGEW) * BUILDCTL_PROP_SHEET);
dwPropCount=0;
for(dwIndex=0; dwIndex<BUILDCTL_PROP_SHEET; dwIndex++)
{
//skip the destination page is required
if(3 == dwIndex )
{
if(dwFlags & CRYPTUI_WIZ_BUILDCTL_SKIP_DESTINATION)
continue;
}
//skip the friendly name page if the desination page is skipped and the destination
//is a file name
if(4== dwIndex)
{
if(dwFlags & CRYPTUI_WIZ_BUILDCTL_SKIP_DESTINATION)
{
if(NULL==ppCTLContext)
{
if(pBuildCTLDest)
{
if(CRYPTUI_WIZ_BUILDCTL_DEST_FILE == pBuildCTLDest->dwDestinationChoice)
continue;
}
else
continue;
}
}
}
prgBuildCTLSheet[dwPropCount].dwSize=sizeof(prgBuildCTLSheet[dwPropCount]);
if(pwszWizardTitle)
prgBuildCTLSheet[dwPropCount].dwFlags=PSP_USETITLE;
else
prgBuildCTLSheet[dwPropCount].dwFlags=0;
prgBuildCTLSheet[dwPropCount].hInstance=g_hmodThisDll;
prgBuildCTLSheet[dwPropCount].pszTemplate=(LPCWSTR)(rgBuildCTLPageInfo[dwIndex].pszTemplate);
if(pwszWizardTitle)
{
prgBuildCTLSheet[dwPropCount].pszTitle=pwszWizardTitle;
}
else
prgBuildCTLSheet[dwPropCount].pszTitle=NULL;
prgBuildCTLSheet[dwPropCount].pfnDlgProc=rgBuildCTLPageInfo[dwIndex].pfnDlgProc;
prgBuildCTLSheet[dwPropCount].lParam=(LPARAM)&CertBuildCTLInfo;
dwPropCount++;
}
}
else
{
//get the pages
if(!CryptUIWizGetDigitalSignPages(&GetSignInfo,
&pwPages,
&dwPages))
goto Win32Err;
//set up the property sheet and the property header
prgBuildCTLSheet=(PROPSHEETPAGEW *)WizardAlloc(sizeof(PROPSHEETPAGEW) * (
BUILDCTL_PROP_SHEET + dwPages));
if(NULL==prgBuildCTLSheet)
goto MemoryErr;
memset(prgBuildCTLSheet, 0, sizeof(PROPSHEETPAGEW) * (BUILDCTL_PROP_SHEET + dwPages));
dwPropCount=0;
for(dwIndex=0; dwIndex<BUILDCTL_PROP_SHEET + dwPages; dwIndex++)
{
//copying the signing pages
if(dwIndex>=3 && dwIndex < (3+dwPages))
{
memcpy(&(prgBuildCTLSheet[dwPropCount]), &(pwPages[dwPropCount-3]), sizeof(PROPSHEETPAGEW));
dwPropCount++;
continue;
}
//skip the destination page is required
if((3+dwPages) == dwIndex )
{
if(dwFlags & CRYPTUI_WIZ_BUILDCTL_SKIP_DESTINATION)
continue;
}
//skip the friendly name page if the desination page is skipped and the destination
//is a file name
if((4+dwPages) == dwIndex)
{
if(dwFlags & CRYPTUI_WIZ_BUILDCTL_SKIP_DESTINATION)
{
if(NULL==ppCTLContext)
{
if(pBuildCTLDest)
{
if(CRYPTUI_WIZ_BUILDCTL_DEST_FILE == pBuildCTLDest->dwDestinationChoice)
continue;
}
else
continue;
}
}
}
prgBuildCTLSheet[dwPropCount].dwSize=sizeof(prgBuildCTLSheet[dwPropCount]);
if(pwszWizardTitle)
prgBuildCTLSheet[dwPropCount].dwFlags=PSP_USETITLE;
else
prgBuildCTLSheet[dwPropCount].dwFlags=0;
prgBuildCTLSheet[dwPropCount].hInstance=g_hmodThisDll;
prgBuildCTLSheet[dwPropCount].pszTemplate=(LPCWSTR)(rgBuildCTLPageInfo[dwIndex >= 3 ? dwIndex-dwPages : dwIndex].pszTemplate);
if(pwszWizardTitle)
{
prgBuildCTLSheet[dwPropCount].pszTitle=pwszWizardTitle;
}
else
prgBuildCTLSheet[dwPropCount].pszTitle=NULL;
prgBuildCTLSheet[dwPropCount].pfnDlgProc=rgBuildCTLPageInfo[dwIndex >= 3 ? dwIndex-dwPages : dwIndex].pfnDlgProc;
prgBuildCTLSheet[dwPropCount].lParam=(LPARAM)&CertBuildCTLInfo;
dwPropCount++;
}
}
//set up the header information
buildCTLHeader.dwSize=sizeof(buildCTLHeader);
buildCTLHeader.dwFlags=PSH_PROPSHEETPAGE | PSH_WIZARD | PSH_NOAPPLYNOW;
buildCTLHeader.hwndParent=hwndParent;
buildCTLHeader.hInstance=g_hmodThisDll;
if(pwszWizardTitle)
buildCTLHeader.pszCaption=pwszWizardTitle;
else
{
if(LoadStringU(g_hmodThisDll, IDS_BUILDCTL_WIZARD_TITLE, wszTitle, sizeof(wszTitle)/sizeof(wszTitle[0])))
buildCTLHeader.pszCaption=wszTitle;
}
buildCTLHeader.nPages=dwPropCount;
buildCTLHeader.nStartPage=0;
buildCTLHeader.ppsp=prgBuildCTLSheet;
//create the wizard
iReturn = PropertySheetU(&buildCTLHeader);
if(-1 == iReturn)
goto Win32Err;
if(0 == iReturn)
{
//user clicks cancel
fResult=TRUE;
//no need to say anything if the wizard is cancelled
ids=0;
if(ppCTLContext)
*ppCTLContext=NULL;
goto CommonReturn;
}
//get the resulting nonsigned CTL or signed CTL
if(dwFlags & CRYPTUI_WIZ_BUILDCTL_SKIP_SIGNING)
{
//get the created BLOB of the CTL
if( (0 == SignBlob.cbBlob) || (NULL==SignBlob.pbBlob) )
{
//the error msg should have shown.
ids=0;
goto CTLBlobErr;
}
//the CTL context from the encoded CTL
pBldCTL=CertCreateCTLContext(
g_dwMsgAndCertEncodingType,
SignBlob.pbBlob,
SignBlob.cbBlob);
}
else
{
//get the signing result
fResult=GetSignInfo.fResult;
if(!fResult || !(GetSignInfo.pSignContext))
{
ids=IDS_SIGN_CTL_FAILED;
if(0 == GetSignInfo.dwError)
GetSignInfo.dwError=E_FAIL;
goto SignErr;
}
//the CTL context from the encoded CTL
pBldCTL=CertCreateCTLContext(
g_dwMsgAndCertEncodingType,
(GetSignInfo.pSignContext)->pbBlob,
(GetSignInfo.pSignContext)->cbBlob);
}
if(NULL==pBldCTL)
goto Win32Err;
//set the properties
if(CertBuildCTLInfo.pwszFriendlyName)
{
PropertyBlob.cbData=sizeof(WCHAR)*(wcslen(CertBuildCTLInfo.pwszFriendlyName)+1);
PropertyBlob.pbData=(BYTE *)(CertBuildCTLInfo.pwszFriendlyName);
CertSetCTLContextProperty(
pBldCTL,
CERT_FRIENDLY_NAME_PROP_ID,
0,
&PropertyBlob);
}
if(CertBuildCTLInfo.pwszDescription)
{
PropertyBlob.cbData=sizeof(WCHAR)*(wcslen(CertBuildCTLInfo.pwszDescription)+1);
PropertyBlob.pbData=(BYTE *)(CertBuildCTLInfo.pwszDescription);
CertSetCTLContextProperty(
pBldCTL,
CERT_DESCRIPTION_PROP_ID,
0,
&PropertyBlob);
}
//save to the destination
if(CertBuildCTLInfo.hDesStore && (TRUE==CertBuildCTLInfo.fSelectedDesStore))
{
if(!CertAddCTLContextToStore(CertBuildCTLInfo.hDesStore,
pBldCTL,
CERT_STORE_ADD_REPLACE_EXISTING,
NULL))
{
ids=IDS_FAIL_TO_ADD_CTL_TO_STORE;
goto Win32Err;
}
}
//save to the file
if(CertBuildCTLInfo.pwszFileName && (TRUE==CertBuildCTLInfo.fSelectedFileName))
{
if(S_OK != OpenAndWriteToFile(
CertBuildCTLInfo.pwszFileName,
pBldCTL->pbCtlEncoded,
pBldCTL->cbCtlEncoded))
{
ids=IDS_FAIL_TO_ADD_CTL_TO_FILE;
goto Win32Err;
}
}
if(ppCTLContext)
{
*ppCTLContext=pBldCTL;
pBldCTL=NULL;
}
fResult=TRUE;
ids=IDS_BUILDCTL_SUCCEEDED;
CommonReturn:
//preserve the last error
dwError=GetLastError();
//pop up the confirmation box for failure
if(ids)
{
//set the message of inable to gather enough info for PKCS10
if(IDS_BUILDCTL_SUCCEEDED == ids)
I_MessageBox(hwndParent, ids, IDS_BUILDCTL_WIZARD_TITLE,
NULL, MB_OK|MB_ICONINFORMATION);
else
I_MessageBox(hwndParent, ids, IDS_BUILDCTL_WIZARD_TITLE,
NULL, MB_OK|MB_ICONERROR);
}
//free the BLOB to be signed. It is the encoded CTL BLOB without the
//signature
if(SignBlob.pbBlob)
WizardFree(SignBlob.pbBlob);
//free the signing context
if(GetSignInfo.pSignContext)
CryptUIWizFreeDigitalSignContext(GetSignInfo.pSignContext);
//free the store lsit
//free my store
if(hMyStore)
CertCloseStore(hMyStore, 0);
/* if(CertStoreList.prgStore)
{
for(dwIndex=0; dwIndex<CertStoreList.dwStoreCount; dwIndex++)
CertCloseStore(CertStoreList.prgStore[dwIndex], 0);
WizardFree(CertStoreList.prgStore);
} */
if(pwPages)
CryptUIWizFreeDigitalSignPages(pwPages, dwPages);
if(pBldCTL)
CertFreeCTLContext(pBldCTL);
//destroy the hFont object
DestroyFonts(CertBuildCTLInfo.hBigBold,
CertBuildCTLInfo.hBold);
//free the pCertBUILDCTLInfo struct
if(CertBuildCTLInfo.pwszFileName && (TRUE==CertBuildCTLInfo.fFreeFileName))
WizardFree(CertBuildCTLInfo.pwszFileName);
if(CertBuildCTLInfo.hDesStore && (TRUE==CertBuildCTLInfo.fFreeDesStore))
CertCloseStore(CertBuildCTLInfo.hDesStore, 0);
//free the friendly name and description
if(CertBuildCTLInfo.pwszFriendlyName)
WizardFree(CertBuildCTLInfo.pwszFriendlyName);
if(CertBuildCTLInfo.pwszDescription)
WizardFree(CertBuildCTLInfo.pwszDescription);
//free the listID
if(CertBuildCTLInfo.pwszListID)
WizardFree(CertBuildCTLInfo.pwszListID);
//free the certificates
FreeCerts(&CertBuildCTLInfo);
//free the purpose OID
FreePurposeInfo(CertBuildCTLInfo.prgPurpose,
CertBuildCTLInfo.dwPurposeCount);
if(prgBuildCTLSheet)
WizardFree(prgBuildCTLSheet);
//reset the error
SetLastError(dwError);
return fResult;
ErrorReturn:
fResult=FALSE;
goto CommonReturn;
SET_ERROR(InvalidArgErr, E_INVALIDARG);
TRACE_ERROR(Crypt32Err);
TRACE_ERROR(Win32Err);
SET_ERROR(MemoryErr, E_OUTOFMEMORY);
SET_ERROR(SignErr, GetSignInfo.dwError);
TRACE_ERROR(CTLBlobErr);
}
//****************************************************************************
// Helper functions for BuildCTL wizards
//
//*****************************************************************************
//----------------------------------------------------------------------------
//
//Get the hash of the certificates from the list
//----------------------------------------------------------------------------
BOOL GetCertHash(CERT_BUILDCTL_INFO *pCertBuildCTLInfo,
BYTE ***prgpHash,
DWORD **prgcbHash,
DWORD *pdwCount)
{
BOOL fResult=FALSE;
BYTE *pbData=NULL;
DWORD cbData=0;
DWORD dwIndex=0;
//init
*prgpHash=NULL;
*prgcbHash=NULL;
*pdwCount=0;
if(!pCertBuildCTLInfo->prgCertContext)
return FALSE;
//now, we need to enum all the certs in the store
for(dwIndex=0; dwIndex<pCertBuildCTLInfo->dwCertCount; dwIndex++)
{
if(NULL==pCertBuildCTLInfo->prgCertContext[dwIndex])
continue;
//get the SHA1 hash of the certificate
if(!CertGetCertificateContextProperty(
pCertBuildCTLInfo->prgCertContext[dwIndex],
pCertBuildCTLInfo->dwHashPropID,
NULL,&cbData))
goto CLEANUP;
pbData=(BYTE *)WizardAlloc(cbData);
if(!pbData)
goto CLEANUP;
//get the SHA1 hash of the certificate
if(!CertGetCertificateContextProperty(
pCertBuildCTLInfo->prgCertContext[dwIndex],
pCertBuildCTLInfo->dwHashPropID,
pbData,&cbData))
goto CLEANUP;
//add to our global list
(*pdwCount)++;
//re-alloc memory
*prgpHash=(BYTE **)WizardRealloc(*prgpHash, sizeof(BYTE *)*(*pdwCount));
*prgcbHash=(DWORD *)WizardRealloc(*prgcbHash, sizeof(DWORD)*(*pdwCount));
if((!(*prgpHash)) || (!(*prgcbHash)))
goto CLEANUP;
(*prgpHash)[*pdwCount-1]=pbData;
(*prgcbHash)[*pdwCount-1]=cbData;
}
fResult=TRUE;
CLEANUP:
if(!fResult)
{
if(*prgpHash)
{
for(dwIndex=0; dwIndex<*pdwCount; dwIndex++)
WizardFree((*prgpHash)[dwIndex]);
WizardFree(*prgpHash);
*prgpHash=NULL;
}
if(*prgcbHash)
{
WizardFree(*prgcbHash);
*prgcbHash=NULL;
}
}
return fResult;
}
//-----------------------------------------------------------------------
//
// I_BuildCTL
//
// Build a new CTL or modify an existing CTL.
//------------------------------------------------------------------------
BOOL I_BuildCTL(CERT_BUILDCTL_INFO *pCertBuildCTLInfo,
UINT *pIDS,
BYTE **ppbEncodedCTL,
DWORD *pcbEncodedCTL)
{
BOOL fResult=FALSE;
CMSG_SIGNED_ENCODE_INFO sSignInfo;
CTL_INFO CTLInfo;
DWORD dwIndex=0;
DWORD cbEncodedCTL=0;
UINT ids=IDS_FAIL_TO_BUILD_CTL;
GUID guid;
PCCRYPT_OID_INFO pOIDInfo=NULL;
ALG_ID AlgID=0;
DWORD dwCount=0;
BYTE **rgpHash=NULL;
DWORD *rgcbHash=NULL;
unsigned char * pGUID=NULL;
LPWSTR pwszGUID=NULL;
BYTE *pbEncodedCTL=NULL;
//init
memset(&sSignInfo, 0, sizeof(CMSG_SIGNED_ENCODE_INFO));
sSignInfo.cbSize = sizeof(CMSG_SIGNED_ENCODE_INFO);
memset(&CTLInfo, 0, sizeof(CTL_INFO));
if(pbEncodedCTL)
*pbEncodedCTL=NULL;
//set up CTL
CTLInfo.dwVersion=CTL_V1;
//set up the subject Usage
for(dwIndex=0; dwIndex<pCertBuildCTLInfo->dwPurposeCount; dwIndex++)
{
if(pCertBuildCTLInfo->prgPurpose[dwIndex]->fSelected)
{
CTLInfo.SubjectUsage.cUsageIdentifier++;
CTLInfo.SubjectUsage.rgpszUsageIdentifier=(LPSTR *)WizardRealloc(
CTLInfo.SubjectUsage.rgpszUsageIdentifier,
sizeof(LPSTR) * CTLInfo.SubjectUsage.cUsageIdentifier);
if(!CTLInfo.SubjectUsage.rgpszUsageIdentifier)
goto MemoryErr;
CTLInfo.SubjectUsage.rgpszUsageIdentifier[CTLInfo.SubjectUsage.cUsageIdentifier-1]=
pCertBuildCTLInfo->prgPurpose[dwIndex]->pszOID;
}
}
//Set up ListIdentifier
//copy the listID if user has specified it
if(NULL==pCertBuildCTLInfo->pwszListID)
{
if(RPC_S_OK != UuidCreate(&guid))
goto TraceErr;
//make a wchar string out of the guid
if(RPC_S_OK != UuidToString(&guid, &pGUID))
goto TraceErr;
//conver the string to wchar
pwszGUID=MkWStr((char *)pGUID);
if(!pwszGUID)
goto TraceErr;
CTLInfo.ListIdentifier.cbData=sizeof(WCHAR)*(wcslen(pwszGUID)+1);
CTLInfo.ListIdentifier.pbData=(BYTE *)WizardAlloc(CTLInfo.ListIdentifier.cbData);
if(NULL==CTLInfo.ListIdentifier.pbData)
goto MemoryErr;
memcpy(CTLInfo.ListIdentifier.pbData,
pwszGUID,
CTLInfo.ListIdentifier.cbData);
}
else
{
CTLInfo.ListIdentifier.cbData=sizeof(WCHAR)*(wcslen(pCertBuildCTLInfo->pwszListID)+1);
CTLInfo.ListIdentifier.pbData=(BYTE *)WizardAlloc(CTLInfo.ListIdentifier.cbData);
if(NULL==CTLInfo.ListIdentifier.pbData)
goto MemoryErr;
memcpy(CTLInfo.ListIdentifier.pbData,
pCertBuildCTLInfo->pwszListID,
CTLInfo.ListIdentifier.cbData);
}
//This update field
GetSystemTimeAsFileTime(&(CTLInfo.ThisUpdate));
//Next Update field
//do not specify any value if user did not enter any
if(pCertBuildCTLInfo->dwValidMonths != 0 || pCertBuildCTLInfo->dwValidDays != 0)
{
AddDurationToFileTime(pCertBuildCTLInfo->dwValidMonths,
pCertBuildCTLInfo->dwValidDays,
&(CTLInfo.ThisUpdate),
&(CTLInfo.NextUpdate));
}
//subject Algorithm
if(pCertBuildCTLInfo->dwHashPropID==CERT_MD5_HASH_PROP_ID)
AlgID=CALG_MD5;
else
AlgID=CALG_SHA1;
pOIDInfo=CryptFindOIDInfo(
CRYPT_OID_INFO_ALGID_KEY,
&AlgID,
CRYPT_HASH_ALG_OID_GROUP_ID);
if(pOIDInfo)
CTLInfo.SubjectAlgorithm.pszObjId=(LPSTR)(pOIDInfo->pszOID);
else
goto FailErr;
//set up the list of entries
//get the array of hash of the certificate
if(!GetCertHash(pCertBuildCTLInfo,
&rgpHash,
&rgcbHash,
&dwCount))
goto FailErr;
CTLInfo.cCTLEntry=dwCount;
CTLInfo.rgCTLEntry=(CTL_ENTRY *)WizardAlloc(sizeof(CTL_ENTRY)*dwCount);
if(!(CTLInfo.rgCTLEntry))
goto MemoryErr;
//memset
memset(CTLInfo.rgCTLEntry, 0, sizeof(CTL_ENTRY)*dwCount);
for(dwIndex=0; dwIndex<dwCount; dwIndex++)
{
CTLInfo.rgCTLEntry[dwIndex].SubjectIdentifier.cbData=rgcbHash[dwIndex];
CTLInfo.rgCTLEntry[dwIndex].SubjectIdentifier.pbData=rgpHash[dwIndex];
}
//include all the certificates in the signer info
sSignInfo.cCertEncoded=pCertBuildCTLInfo->dwCertCount;
sSignInfo.rgCertEncoded=(PCERT_BLOB)WizardAlloc(sizeof(CERT_BLOB)*
sSignInfo.cCertEncoded);
if(NULL==sSignInfo.rgCertEncoded)
goto MemoryErr;
for(dwIndex=0; dwIndex<sSignInfo.cCertEncoded; dwIndex++)
{
sSignInfo.rgCertEncoded[dwIndex].cbData=pCertBuildCTLInfo->prgCertContext[dwIndex]->cbCertEncoded;
sSignInfo.rgCertEncoded[dwIndex].pbData=pCertBuildCTLInfo->prgCertContext[dwIndex]->pbCertEncoded;
}
//encode and sign the CTL
if(!CryptMsgEncodeAndSignCTL(g_dwMsgAndCertEncodingType,
&CTLInfo,
&sSignInfo,
0,
NULL,
&cbEncodedCTL))
goto TraceErr;
//memory allocation
pbEncodedCTL=(BYTE *)WizardAlloc(cbEncodedCTL);
if(!(pbEncodedCTL))
goto MemoryErr;
if(!CryptMsgEncodeAndSignCTL(g_dwMsgAndCertEncodingType,
&CTLInfo,
&sSignInfo,
0,
pbEncodedCTL,
&cbEncodedCTL))
goto TraceErr;
if(ppbEncodedCTL && pcbEncodedCTL)
{
*ppbEncodedCTL=pbEncodedCTL;
*pcbEncodedCTL=cbEncodedCTL;
pbEncodedCTL=NULL;
}
ids=IDS_BUILDCTL_SUCCEEDED;
fResult=TRUE;
CommonReturn:
if(CTLInfo.ListIdentifier.pbData)
WizardFree(CTLInfo.ListIdentifier.pbData);
if(CTLInfo.SubjectUsage.rgpszUsageIdentifier)
WizardFree(CTLInfo.SubjectUsage.rgpszUsageIdentifier);
if(pGUID)
RpcStringFree(&pGUID);
if(pwszGUID)
FreeWStr(pwszGUID);
if(CTLInfo.rgCTLEntry)
WizardFree(CTLInfo.rgCTLEntry);
if(sSignInfo.rgCertEncoded)
WizardFree(sSignInfo.rgCertEncoded);
if(rgpHash)
{
for(dwIndex=0; dwIndex<dwCount; dwIndex++)
WizardFree(rgpHash[dwIndex]);
WizardFree(rgpHash);
}
if(rgcbHash)
WizardFree(rgcbHash);
if(pbEncodedCTL)
WizardFree(pbEncodedCTL);
if(pIDS)
*pIDS=ids;
return fResult;
ErrorReturn:
fResult=FALSE;
goto CommonReturn;
SET_ERROR(MemoryErr, E_OUTOFMEMORY);
TRACE_ERROR(TraceErr);
SET_ERROR(FailErr, E_FAIL);
}
//////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////
BOOL WizardGetOIDInfo(LPWSTR string, DWORD stringSize, LPSTR pszObjId)
{
PCCRYPT_OID_INFO pOIDInfo;
pOIDInfo = CryptFindOIDInfo(
CRYPT_OID_INFO_OID_KEY,
pszObjId,
0);
if (pOIDInfo != NULL)
{
if ((DWORD)(wcslen(pOIDInfo->pwszName)+1) <= stringSize)
{
wcscpy(string, pOIDInfo->pwszName);
}
else
{
return FALSE;
}
}
else
{
return (MultiByteToWideChar(CP_ACP, 0, pszObjId, -1, string, stringSize) != 0);
}
return TRUE;
}
//////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////
LPWSTR WizardAllocAndCopyWStr(LPWSTR pwsz)
{
LPWSTR pwszReturn;
if (NULL == (pwszReturn = (LPWSTR) WizardAlloc((wcslen(pwsz)+1) * sizeof(WCHAR))))
{
return NULL;
}
wcscpy(pwszReturn, pwsz);
return(pwszReturn);
}
//////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////
BOOL WizardFormatDateString(LPWSTR *ppString, FILETIME ft, BOOL fIncludeTime)
{
int cch=0;
int cch2=0;
LPWSTR psz=NULL;
SYSTEMTIME st;
FILETIME localTime;
if (!FileTimeToLocalFileTime(&ft, &localTime))
{
return FALSE;
}
if (!FileTimeToSystemTime(&localTime, &st))
{
//
// if the conversion to local time failed, then just use the original time
//
if (!FileTimeToSystemTime(&ft, &st))
{
return FALSE;
}
}
cch = (GetTimeFormatU(LOCALE_USER_DEFAULT, 0, &st, NULL, NULL, 0) +
GetDateFormatU(LOCALE_USER_DEFAULT, 0, &st, NULL, NULL, 0) + 5);
if (NULL == (psz = (LPWSTR) WizardAlloc((cch+5) * sizeof(WCHAR))))
{
return FALSE;
}
cch2 = GetDateFormatU(LOCALE_USER_DEFAULT, 0, &st, NULL, psz, cch);
if (fIncludeTime)
{
psz[cch2-1] = ' ';
GetTimeFormatU(LOCALE_USER_DEFAULT, 0, &st, NULL,
&psz[cch2], cch-cch2);
}
*ppString = psz;
return TRUE;
}
//+-------------------------------------------------------------------------
// Write a blob to a file
//--------------------------------------------------------------------------
HRESULT OpenAndWriteToFile(
LPCWSTR pwszFileName,
PBYTE pb,
DWORD cb
)
{
HRESULT hr=E_FAIL;
HANDLE hFile=NULL;
DWORD dwBytesWritten=0;
if(!pwszFileName || !pb || (cb==0))
return E_INVALIDARG;
hFile = ExpandAndCreateFileU(pwszFileName,
GENERIC_WRITE,
0, // fdwShareMode
NULL, // lpsa
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, // fdwAttrsAndFlags
0); // TemplateFile
if (INVALID_HANDLE_VALUE == hFile)
{
hr=HRESULT_FROM_WIN32(GetLastError());
}
else
{
if (!WriteFile(
hFile,
pb,
cb,
&dwBytesWritten,
NULL // lpOverlapped
))
{
hr=HRESULT_FROM_WIN32(GetLastError());
}
else
{
if(dwBytesWritten != cb)
hr=E_FAIL;
else
hr=S_OK;
}
CloseHandle(hFile);
}
return hr;
}
//--------------------------------------------------------------------------------
// See if the DATA blob is a valid wchar string
//--------------------------------------------------------------------------------
BOOL ValidString(CRYPT_DATA_BLOB *pDataBlob)
{
LPWSTR pwsz=NULL;
DWORD dwIndex=0;
if(NULL==pDataBlob)
return FALSE;
if(pDataBlob->cbData < sizeof(WCHAR))
return FALSE;
//has to be NULL-terminated
pwsz=(LPWSTR)((DWORD_PTR)(pDataBlob->pbData)+(pDataBlob->cbData)-sizeof(WCHAR));
if(*pwsz != '\0')
return FALSE;
//has to include the exact number of wchars
if(0 != ((pDataBlob->cbData)%sizeof(WCHAR)))
return FALSE;
//each character, with exception of the last NULL terminater,
//has to be printable (20-7e) range
for(dwIndex=0; dwIndex<(pDataBlob->cbData)-sizeof(WCHAR); dwIndex=dwIndex+sizeof(WCHAR))
{
pwsz=(LPWSTR)((DWORD_PTR)(pDataBlob->pbData)+dwIndex);
if(0==iswprint(*pwsz))
return FALSE;
}
return TRUE;
}
//--------------------------------------------------------------------------------
// See if the user input is an 0 in the form of {white spaces}{sign}{0}
// pwszInput has to be NULL terminated
//--------------------------------------------------------------------------------
BOOL ValidZero(LPWSTR pwszInput)
{
BOOL fSpace=TRUE;
BOOL fSign=TRUE;
if(NULL==pwszInput)
return FALSE;
while(*pwszInput != L'\0')
{
if(iswspace(*pwszInput))
{
if(fSpace)
pwszInput++;
else
return FALSE;
}
else
{
if((L'+'==*pwszInput) || (L'-'==*pwszInput))
{
if(fSign)
{
fSign=FALSE;
fSpace=FALSE;
pwszInput++;
}
else
return FALSE;
}
else
{
if(L'0'==*pwszInput)
{
fSign=FALSE;
fSpace=FALSE;
pwszInput++;
}
else
return FALSE;
}
}
}
return TRUE;
}
//--------------------------------------------------------------------------------
// Get the number of days in a particular month of a particular year
//--------------------------------------------------------------------------------
DWORD DaysInMonth(DWORD dwYear, DWORD dwMonth)
{
switch (dwMonth)
{
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
return 31;
break;
case 4:
case 6:
case 9:
case 11:
return 30;
break;
case 2:
//leap year
if((0 == dwYear % 4 && 0!= dwYear % 100) || 0 == dwYear % 400)
return 29;
else
return 28;
default:
return 0;
}
return 0;
}
//--------------------------------------------------------------------------------
// Substract the next update time from the current time
//--------------------------------------------------------------------------------
void SubstractDurationFromFileTime(
FILETIME *pNextUpdateTime,
FILETIME *pCurrentTime,
DWORD *pdwValidMonths,
DWORD *pdwValidDays)
{
SYSTEMTIME SystemNext;
SYSTEMTIME SystemCurrent;
*pdwValidMonths=0;
*pdwValidDays=0;
//return if the NextUpdateTime is NULL
if(0 ==pNextUpdateTime->dwLowDateTime && 0==pNextUpdateTime->dwHighDateTime)
return;
//the NextUpateTime has to be more than the current time
if((*(LONGLONG *)pNextUpdateTime) <= (*(LONGLONG *)pCurrentTime) )
return;
//convert to system time
if(!FileTimeToSystemTime(pNextUpdateTime, &SystemNext) ||
!FileTimeToSystemTime(pCurrentTime, &SystemCurrent))
return;
//compute the difference between the two systemtime
//in terms of month and days
if(SystemNext.wDay >= SystemCurrent.wDay)
*pdwValidDays=SystemNext.wDay - SystemCurrent.wDay;
else
{
SystemNext.wMonth--;
//consider the 1st month of the year
if(0 == SystemNext.wMonth)
{
SystemNext.wMonth=12;
SystemNext.wYear--;
}
*pdwValidDays=SystemNext.wDay + DaysInMonth(SystemNext.wYear, SystemNext.wMonth) - SystemCurrent.wDay;
}
*pdwValidMonths=(SystemNext.wYear * 12 + SystemNext.wMonth) -
(SystemCurrent.wYear * 12 + SystemCurrent.wMonth);
//if the resolution for day is too small, we just use one day
if((*pdwValidDays == 0) && (*pdwValidMonths==0))
*pdwValidDays=1;
}
//--------------------------------------------------------------------------------
// GetDaysForMonth
//--------------------------------------------------------------------------------
BOOL GetDaysForMonth(DWORD dwYear, DWORD dwMonth, DWORD *pdwDays)
{
BOOL fResult=FALSE;
if(NULL == pdwDays)
goto CLEANUP;
*pdwDays=0;
switch(dwMonth)
{
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
*pdwDays=31;
break;
case 4:
case 6:
case 9:
case 11:
*pdwDays=30;
break;
case 2:
if((dwYear % 4 == 0 && dwYear % 100 !=0 ) ||
(dwYear % 400 ==0))
*pdwDays=29;
else
*pdwDays=28;
break;
default:
goto CLEANUP;
}
fResult=TRUE;
CLEANUP:
return fResult;
}
//--------------------------------------------------------------------------------
// Add the duration to the current fileTime
//--------------------------------------------------------------------------------
void AddDurationToFileTime(DWORD dwValidMonths,
DWORD dwValidDays,
FILETIME *pCurrentFileTime,
FILETIME *pNextFileTime)
{
SYSTEMTIME SystemCurrent;
FILETIME FileAdded;
LARGE_INTEGER dwSeconds;
LARGE_INTEGER StartTime;
DWORD dwActualdDays=0;
//init
memset(pNextFileTime, 0, sizeof(FILETIME));
//conver to the system time
if(!FileTimeToSystemTime(pCurrentFileTime, &SystemCurrent))
return;
//conver the month to year
while(dwValidMonths >= 12)
{
SystemCurrent.wYear++;
dwValidMonths=dwValidMonths-12;
}
SystemCurrent.wMonth = (WORD)(SystemCurrent.wMonth + dwValidMonths);
if(SystemCurrent.wMonth > 12)
{
SystemCurrent.wYear++;
SystemCurrent.wMonth = SystemCurrent.wMonth -12;
}
//make sure the number of days in a month is within the limit
if(GetDaysForMonth(SystemCurrent.wYear, SystemCurrent.wMonth, &dwActualdDays))
{
if(SystemCurrent.wDay > dwActualdDays)
{
SystemCurrent.wMonth++;
SystemCurrent.wDay = SystemCurrent.wDay- (WORD)(dwActualdDays);
}
}
//convert the system file to fileTime
if(!SystemTimeToFileTime(&SystemCurrent, &FileAdded))
return;
//convert the nan-seconds based on the file time
//// FILETIME is in units of 100 nanoseconds (10**-7)
dwSeconds.QuadPart=dwValidDays * 24 * 3600;
dwSeconds.QuadPart=dwSeconds.QuadPart * 10000000;
StartTime.LowPart=FileAdded.dwLowDateTime;
StartTime.HighPart=FileAdded.dwHighDateTime;
StartTime.QuadPart = StartTime.QuadPart + dwSeconds.QuadPart;
//copy the fileAdded value to *pNextFileTime
pNextFileTime->dwLowDateTime=StartTime.LowPart;
pNextFileTime->dwHighDateTime=StartTime.HighPart;
return;
}