mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
5763 lines
191 KiB
5763 lines
191 KiB
//-------------------------------------------------------------
|
|
// 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;
|
|
}
|