Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1453 lines
40 KiB

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1997 - 1999
//
// File: misc.cpp
//
//--------------------------------------------------------------------------
#include <stdafx.h>
#include <float.h>
#include "certsrv.h"
#include "misc.h"
#include "clibres.h"
#include "setupids.h"
#include "csresstr.h"
#include <activeds.h>
#include <dsgetdc.h>
#include <lm.h>
#include <common.ver>
#include "urls.h"
#include "csdisp.h"
#define __dwFILE__ __dwFILE_CERTMMC_MISC_CPP__
bool operator==(
const struct _QUERY_RESTRICTION& lhs,
const struct _QUERY_RESTRICTION& rhs)
{
return
0==_wcsicmp(lhs.szField, rhs.szField) &&
lhs.iOperation==rhs.iOperation &&
variant_t(&lhs.varValue)==variant_t(&rhs.varValue);
}
PQUERY_RESTRICTION QueryRestrictionFound(
PQUERY_RESTRICTION pQR,
PQUERY_RESTRICTION pQRListHead)
{
while(pQRListHead)
{
if(*pQR==*pQRListHead)
return pQRListHead;
pQRListHead = pQRListHead->pNext;
}
return NULL;
}
// returns (if cstr.IsEmpty()) ? NULL : cstr)
LPCWSTR GetNullMachineName(CString* pcstr)
{
LPCWSTR szMachine = (pcstr->IsEmpty()) ? NULL : (LPCWSTR)*pcstr;
return szMachine;
}
BOOL FIsCurrentMachine(LPCWSTR str)
{
BOOL fIsCurrentMachine = FALSE;
LPWSTR szName1 = NULL, szName2 = NULL;
DWORD dwErr;
dwErr = myGetComputerNames(&szName1, &szName2);
_JumpIfError(dwErr, error, "myGetComputerNames");
if ((str != NULL) &&
(wcslen(str) > 2) &&
(str[0] == '\\') &&
(str[1] == '\\') )
str = &str[2]; // skip whackwhack
// if machine specified as not current machine
if ( (NULL == str) ||
(str[0] == '\0') ||
(0 == mylstrcmpiL(str, szName1)) ||
(0 == mylstrcmpiL(str, szName2)) )
fIsCurrentMachine = TRUE;
error:
if (szName1)
LocalFree(szName1);
if (szName2)
LocalFree(szName2);
return fIsCurrentMachine;
}
/////////////////////////////////////////
// fxns to load/save cstrings to a streams
STDMETHODIMP CStringLoad(CString& cstr, IStream *pStm)
{
ASSERT(pStm);
HRESULT hr;
DWORD cbSize=0;
// get cbSize (bytes)
hr = ReadOfSize(pStm, &cbSize, sizeof(cbSize));
_JumpIfError(hr, Ret, "ReadOfSize cbSize");
// get string
hr = ReadOfSize(
pStm,
cstr.GetBuffer(cbSize/sizeof(WCHAR)-1), // less terminator, GetBuffer adds 1 for it
cbSize);
cstr.ReleaseBuffer(); // not clear why we do this...
_JumpIfError(hr, Ret, "Read cstr.GetBuffer");
if(!cstr.IsZeroTerminated())
{
hr = ERROR_FILE_CORRUPT;
_JumpError(hr, Ret, "zero terminated string expected");
}
Ret:
return hr;
}
STDMETHODIMP
CStringSave(
CString& cstr,
IStream *pStm,
BOOL /* fClearDirty */ )
{
ASSERT(pStm);
HRESULT hr;
// Write the string (null cstr will return 0 chars, output nullstr "")
DWORD cbSize = (cstr.GetLength()+1)*sizeof(WCHAR);
// write size in bytes
hr = WriteOfSize(pStm, &cbSize, sizeof(cbSize));
_JumpIfError(hr, error, "WriteOfSize cbSize");
// write string (null cstr will return 0 chars, output nullstr "")
hr = WriteOfSize(pStm, (LPWSTR)(LPCWSTR)cstr, cbSize);
_JumpIfError(hr, error, "Write cstr");
error:
return hr;
}
STDMETHODIMP CStringGetSizeMax(CString& cstr, int* piSize)
{
*piSize = sizeof(DWORD);
*piSize += (cstr.GetLength()+1)* sizeof(WCHAR);
return S_OK;
}
STDMETHODIMP VariantLoad(VARIANT& var, IStream *pStm)
{
HRESULT hr;
VARIANT varTmp;
DWORD dwSize;
VariantInit(&varTmp);
VariantInit(&var);
// get target variant type
hr = ReadOfSize(pStm, &var.vt, sizeof(var.vt));
_JumpIfError(hr, error, "Read type");
// get cb
hr = ReadOfSize(pStm, &dwSize, sizeof(DWORD));
_JumpIfError(hr, error, "Read cb");
varTmp.vt = VT_BSTR;
varTmp.bstrVal = SysAllocStringByteLen(NULL, dwSize);
_JumpIfOutOfMemory(hr, error, varTmp.bstrVal);
// get pb
hr = ReadOfSize(pStm, varTmp.bstrVal, dwSize);
_JumpIfError(hr, error, "Read pb");
// change type to target type var.vt
hr = VariantChangeType(&var, &varTmp, 0, var.vt);
_JumpIfError(hr, error, "VariantChangeType");
error:
VariantClear(&varTmp);
return hr;
}
STDMETHODIMP
VariantSave(
VARIANT& var,
IStream *pStm,
BOOL /* fClearDirty */ )
{
HRESULT hr;
DWORD dwSize;
VARIANT varTmp;
VariantInit(&varTmp);
// write variant type
hr = WriteOfSize(pStm, &var.vt, sizeof(var.vt));
_JumpIfError(hr, error, "Write type");
// convert to bstr
hr = VariantChangeType(&varTmp, &var, 0, VT_BSTR);
_JumpIfError(hr, error, "VariantChangeType");
// write cb
dwSize = SysStringByteLen(varTmp.bstrVal);
hr = WriteOfSize(pStm, &dwSize, sizeof(DWORD));
_JumpIfError(hr, error, "Write cb");
// write pb
hr = WriteOfSize(pStm, varTmp.bstrVal, dwSize);
_JumpIfError(hr, error, "Write pb");
error:
VariantClear(&varTmp);
return hr;
}
STDMETHODIMP VariantGetSizeMax(VARIANT& var, int* piSize)
{
HRESULT hr;
VARIANT varTmp;
VariantInit(&varTmp);
// write var type, cb
*piSize = sizeof(var.vt) + sizeof(DWORD);
// write pb len: convert to bstr
hr = VariantChangeType(&varTmp, &var, 0, VT_BSTR);
_JumpIfError(hr, error, "VariantChangeType");
*piSize += SysStringByteLen(varTmp.bstrVal);
error:
VariantClear(&varTmp);
return hr;
}
DWORD AllocAndReturnConfigValue(HKEY hKey, LPCWSTR szConfigEntry, PBYTE* ppbOut, DWORD* pcbOut, DWORD* pdwType)
{
DWORD dwRet;
dwRet = RegQueryValueExW(
hKey,
szConfigEntry,
NULL,
pdwType,
NULL,
pcbOut);
_JumpIfError(dwRet, Ret, "RegQueryValueExW");
ASSERT(ppbOut != NULL);
*ppbOut = new BYTE[*pcbOut];
if (NULL == *ppbOut)
{
dwRet = (DWORD) E_OUTOFMEMORY;
_JumpError(dwRet, Ret, "new");
}
dwRet = RegQueryValueExW(
hKey,
szConfigEntry,
NULL,
pdwType,
*ppbOut,
pcbOut);
if (dwRet != ERROR_SUCCESS)
{
delete [] *ppbOut;
*ppbOut = NULL;
_JumpError(dwRet, Ret, "RegQueryValueExW");
}
Ret:
return dwRet;
}
//////////////////////////////////////////////////////////////////
// given an error code and a console pointer, will pop error dlg
void DisplayCertSrvErrorWithContext(HWND hwnd, DWORD dwErr, UINT iRscContext)
{
CString cstrContext;
cstrContext.LoadString(iRscContext);
DisplayCertSrvErrorWithContext(hwnd, dwErr, (LPCWSTR)cstrContext);
}
void DisplayCertSrvErrorWithContext(HWND hwnd, DWORD dwErr, LPCWSTR szContext)
{
CString cstrTitle, cstrFullText;
cstrTitle.LoadString(IDS_MSG_TITLE);
cstrFullText = szContext;
if (dwErr != ERROR_SUCCESS)
{
if (!cstrFullText.IsEmpty())
cstrFullText += L"\n\n";
WCHAR const *pwszError = myGetErrorMessageText(dwErr, TRUE);
cstrFullText += pwszError;
// Free the buffer
if (NULL != pwszError)
{
LocalFree(const_cast<WCHAR *>(pwszError));
}
}
::MessageBoxW(hwnd, cstrFullText, cstrTitle,
MB_OK|
(S_OK!=dwErr?MB_ICONERROR:MB_ICONINFORMATION));
}
void DisplayGenericCertSrvError(HWND hwnd, DWORD dwErr)
{
DisplayCertSrvErrorWithContext(hwnd, dwErr, (UINT)0);
}
void DisplayGenericCertSrvError(LPCONSOLE pConsole, DWORD dwErr)
{
ASSERT(pConsole);
WCHAR const *pwszError = myGetErrorMessageText(dwErr, TRUE);
// ...
// Display the string.
CString cstrTitle;
cstrTitle.LoadString(IDS_MSG_TITLE);
pConsole->MessageBoxW(pwszError, cstrTitle, MB_OK, NULL);
// Free the buffer.
if (NULL != pwszError)
{
LocalFree(const_cast<WCHAR *>(pwszError));
}
}
enum ENUM_PERIOD DurationEnumFromNonLocalizedString(LPCWSTR szPeriod)
{
if (0 == LSTRCMPIS(szPeriod, wszPERIODYEARS))
return ENUM_PERIOD_YEARS;
if (0 == LSTRCMPIS(szPeriod, wszPERIODMONTHS))
return ENUM_PERIOD_MONTHS;
if (0 == LSTRCMPIS(szPeriod, wszPERIODWEEKS))
return ENUM_PERIOD_WEEKS;
if (0 == LSTRCMPIS(szPeriod, wszPERIODDAYS))
return ENUM_PERIOD_DAYS;
if (0 == LSTRCMPIS(szPeriod, wszPERIODHOURS))
return ENUM_PERIOD_HOURS;
if (0 == LSTRCMPIS(szPeriod, wszPERIODMINUTES))
return ENUM_PERIOD_MINUTES;
if (0 == LSTRCMPIS(szPeriod, wszPERIODSECONDS))
return ENUM_PERIOD_SECONDS;
return ENUM_PERIOD_INVALID;
}
BOOL StringFromDurationEnum(int iEnum, CString* pcstr, BOOL fLocalized)
{
if (NULL == pcstr)
return FALSE;
switch (iEnum)
{
case(ENUM_PERIOD_YEARS):
if (fLocalized)
*pcstr = g_pResources->m_szPeriod_Years;
else
*pcstr = wszPERIODYEARS;
break;
case(ENUM_PERIOD_MONTHS):
if (fLocalized)
*pcstr = g_pResources->m_szPeriod_Months;
else
*pcstr = wszPERIODMONTHS;
break;
case(ENUM_PERIOD_WEEKS):
if (fLocalized)
*pcstr = g_pResources->m_szPeriod_Weeks;
else
*pcstr = wszPERIODWEEKS;
break;
case(ENUM_PERIOD_DAYS):
if (fLocalized)
*pcstr = g_pResources->m_szPeriod_Days;
else
*pcstr = wszPERIODDAYS;
break;
case(ENUM_PERIOD_HOURS):
if (fLocalized)
*pcstr = g_pResources->m_szPeriod_Hours;
else
*pcstr = wszPERIODHOURS;
break;
case(ENUM_PERIOD_MINUTES):
if (fLocalized)
*pcstr = g_pResources->m_szPeriod_Minutes;
else
*pcstr = wszPERIODMINUTES;
break;
case(ENUM_PERIOD_SECONDS):
if (fLocalized)
*pcstr = g_pResources->m_szPeriod_Seconds;
else
*pcstr = wszPERIODSECONDS;
break;
}
if (! (pcstr->IsEmpty()) )
return TRUE;
return FALSE;
}
LPCWSTR OperationToStr(int iOperation)
{
switch(iOperation)
{
case CVR_SEEK_EQ:
return L"=";
case CVR_SEEK_LT:
return L"<";
case CVR_SEEK_LE:
return L"<=";
case CVR_SEEK_GE:
return L">=";
case CVR_SEEK_GT:
return L">";
}
return NULL;
}
int StrToOperation(LPCWSTR szOperation)
{
if (0 == wcscmp(szOperation, L"="))
return CVR_SEEK_EQ;
else if (0 == wcscmp(szOperation, L"<"))
return CVR_SEEK_LT;
else if (0 == wcscmp(szOperation, L"<="))
return CVR_SEEK_LE;
else if (0 == wcscmp(szOperation, L">="))
return CVR_SEEK_GE;
else if (0 == wcscmp(szOperation, L">"))
return CVR_SEEK_GT;
return 0;
}
// returns localized string time (even for date!)
BOOL MakeDisplayStrFromDBVariant(VARIANT* pvt, VARIANT* pvOut)
{
HRESULT hr;
VariantInit(pvOut);
LPWSTR szLocalTime = NULL;
ASSERT(pvt);
ASSERT(pvOut);
if ((NULL == pvt) || (NULL == pvOut))
return FALSE;
if (pvt->vt == VT_DATE)
{
hr = myGMTDateToWszLocalTime(
&pvt->date,
FALSE,
&szLocalTime);
_JumpIfError(hr, error, "myGMTDateToWszLocalTime");
pvOut->bstrVal = ::SysAllocString(szLocalTime);
_JumpIfOutOfMemory(hr, error, pvOut->bstrVal);
pvOut->vt = VT_BSTR;
}
else
{
hr = VariantChangeType(pvOut, pvt, 0, VT_BSTR);
_JumpIfError(hr, error, "VariantChangeType");
}
error:
if (szLocalTime)
LocalFree(szLocalTime);
return (pvOut->vt == VT_BSTR);
}
DWORD CryptAlgToStr(CString* pcstrAlgName, LPCWSTR szProv, DWORD dwProvType, DWORD dwAlg)
{
DWORD dwRet;
HCRYPTPROV hCrypt = NULL;
DWORD Flags = CRYPT_FIRST;
DWORD cb;
PROV_ENUMALGS Alg;
pcstrAlgName->Empty();
if (!CryptAcquireContext(
&hCrypt,
NULL,
szProv,
dwProvType,
CRYPT_VERIFYCONTEXT))
{
dwRet = GetLastError();
_JumpError(dwRet, Ret, "CryptAcquireContext");
}
while (TRUE)
{
cb = sizeof(Alg);
if (!CryptGetProvParam(hCrypt, PP_ENUMALGS, (BYTE *) &Alg, &cb, Flags))
break;
if (Alg.aiAlgid == dwAlg)
{
*pcstrAlgName = Alg.szName;
break;
}
Flags = 0;
}
dwRet = ERROR_SUCCESS;
Ret:
if (hCrypt)
CryptReleaseContext(hCrypt, 0);
return dwRet;
}
LPCWSTR FindUnlocalizedColName(LPCWSTR strColumn)
{
HRESULT hr = S_OK;
LPCWSTR szTrial = NULL;
for(DWORD dwIndex=0; (S_OK == hr); dwIndex++)
{
hr = myGetColumnName(
dwIndex,
FALSE, // unlocalized
&szTrial);
_PrintIfError(hr, "myGetColumnName");
if ((S_OK == hr) && (NULL != szTrial))
{
if (0 == wcscmp(strColumn, szTrial))
return szTrial;
}
}
return NULL;
}
// given field, op, variant, copies into data struct
PQUERY_RESTRICTION NewQueryRestriction(LPCWSTR szField, UINT iOp, VARIANT* pvarValue)
{
DWORD dwLen = sizeof(QUERY_RESTRICTION);
dwLen += WSZ_BYTECOUNT(szField);
PQUERY_RESTRICTION pNew = (QUERY_RESTRICTION*)LocalAlloc(LPTR, dwLen);
if (NULL == pNew)
return NULL;
PBYTE pCurWrite = ((PBYTE)pNew) + sizeof(QUERY_RESTRICTION) ;
pNew->szField = (LPWSTR)pCurWrite;
wcscpy(pNew->szField, szField);
pNew->iOperation = iOp;
// copy data pointed to by pvarValue
CopyMemory(&pNew->varValue, pvarValue, sizeof(VARIANT));
// good enough except for string -- alloc for it
if (VT_BSTR == pvarValue->vt)
{
pNew->varValue.bstrVal = SysAllocString(pvarValue->bstrVal);
if (NULL == pNew->varValue.bstrVal)
{
// failed!
FreeQueryRestriction(pNew);
pNew = NULL;
}
}
return pNew;
}
void FreeQueryRestriction(PQUERY_RESTRICTION pQR)
{
VariantClear(&pQR->varValue);
LocalFree(pQR);
}
void FreeQueryRestrictionList(PQUERY_RESTRICTION pQR)
{
PQUERY_RESTRICTION pTmp;
while(pQR)
{
pTmp = pQR->pNext;
FreeQueryRestriction(pQR);
pQR = pTmp;
}
}
void ListInsertAtEnd(void** ppList, void* pElt)
{
if (pElt != NULL)
{
// he's always at the end of the list
((PELT_PTR)pElt)->pNext = NULL;
void* pCurPtr = *ppList;
if (*ppList == NULL)
{
*ppList = pElt;
}
else
{
while( ((PELT_PTR)pCurPtr)->pNext != NULL )
{
pCurPtr = ((PELT_PTR)pCurPtr)->pNext;
}
((PELT_PTR)pCurPtr)->pNext = (PELT_PTR) pElt;
}
}
return;
}
// dwIndex should be zero at first, then passed in for each consecutive call
LPWSTR RegEnumKeyContaining(
HKEY hBaseKey,
LPCWSTR szContainsString,
DWORD* pdwIndex)
{
HRESULT hr = S_OK;
LPWSTR szBuf = NULL;
DWORD cbBuf = 0, cbBufUsed;
FILETIME ft;
ASSERT(pdwIndex);
hr = RegQueryInfoKey(
hBaseKey,
NULL,
NULL, // classes
NULL, // reserved
NULL, // cSubkeys
&cbBuf, // maxsubkeylen in chars (not counting null term)
NULL, // max class len
NULL, // num values
NULL, // max value name len
NULL, // max value len
NULL, // sec descr
NULL // last filetime
);
_JumpIfError(hr, Ret, "RegQueryInfoKey");
cbBuf += 1;
cbBuf *= sizeof(WCHAR);
szBuf = (LPWSTR)LocalAlloc(LMEM_FIXED, cbBuf);
_JumpIfOutOfMemory(hr, Ret, szBuf);
for (; ; (*pdwIndex)++)
{
// tell api how much memory we have (incl NULL char)
cbBufUsed = cbBuf;
hr = RegEnumKeyEx(
hBaseKey,
*pdwIndex,
szBuf,
&cbBufUsed, // doesn't get updated in small buffer case?!
NULL,
NULL,
NULL,
&ft);
_JumpIfError2(hr, Ret, "RegEnumKeyEx", ERROR_NO_MORE_ITEMS);
// we have data, check if it is one we're interested in
if (NULL != wcsstr(szBuf, szContainsString))
break;
}
// don't point at this one again
(*pdwIndex)++;
hr = S_OK;
Ret:
if (S_OK != hr)
{
LocalFree(szBuf);
szBuf = NULL;
}
return ( szBuf );
}
DISPLAYSTRING_EXPANSION g_displayStrings[11] =
{
{ wszFCSAPARM_SERVERDNSNAME, IDS_TOKEN_SERVERDNSNAME, IDS_TOKENDESC_SERVERDNSNAME }, //%1
{ wszFCSAPARM_SERVERSHORTNAME, IDS_TOKEN_SERVERSHORTNAME, IDS_TOKENDESC_SERVERSHORTNAME }, //%2
{ wszFCSAPARM_SANITIZEDCANAME, IDS_TOKEN_SANITIZEDCANAME, IDS_TOKENDESC_SANITIZEDCANAME }, //%3
{ wszFCSAPARM_CERTFILENAMESUFFIX, IDS_TOKEN_CERTFILENAMESUFFIX, IDS_TOKENDESC_CERTFILENAMESUFFIX }, //%4
{ L"", IDS_DESCR_UNKNOWN, IDS_DESCR_UNKNOWN }, // %5 not available
{ wszFCSAPARM_CONFIGDN, IDS_TOKEN_CONFIGDN, IDS_TOKENDESC_CONFIGDN }, //%6
{ wszFCSAPARM_SANITIZEDCANAMEHASH, IDS_TOKEN_SANITIZEDCANAMEHASH, IDS_TOKENDESC_SANITIZEDCANAMEHASH }, //%7
{ wszFCSAPARM_CRLFILENAMESUFFIX, IDS_TOKEN_CRLFILENAMESUFFIX, IDS_TOKENDESC_CRLFILENAMESUFFIX }, //%8
{ wszFCSAPARM_CRLDELTAFILENAMESUFFIX, IDS_TOKEN_CRLDELTAFILENAMESUFFIX,IDS_TOKENDESC_CRLDELTAFILENAMESUFFIX}, //%9
{ wszFCSAPARM_DSCRLATTRIBUTE, IDS_TOKEN_DSCRLATTRIBUTE, IDS_TOKENDESC_DSCRLATTRIBUTE }, //%10
{ wszFCSAPARM_DSCACERTATTRIBUTE, IDS_TOKEN_DSCACERTATTRIBUTE, IDS_TOKENDESC_DSCACERTATTRIBUTE }, //%11
};
/////////////////////////////////////////
// fxns to load resources automatically
CLocalizedResources *g_pResources = NULL;
CLocalizedResources::CLocalizedResources()
{
m_fLoaded = FALSE;
}
BOOL CLocalizedResources::Load()
{
if (!m_fLoaded)
{
HINSTANCE hRsrc = AfxGetResourceHandle();
myVerifyResourceStrings(g_hInstance);
// Load strings from resources
m_ColumnHead_Name.LoadString(IDS_COLUMN_NAME);
m_ColumnHead_Size.LoadString(IDS_COLUMN_SIZE);
m_ColumnHead_Type.LoadString(IDS_COLUMN_TYPE);
m_ColumnHead_Description.LoadString(IDS_COLUMN_DESCRIPTION);
m_DescrStr_CA.LoadString(IDS_DESCR_CA);
m_DescrStr_Unknown.LoadString(IDS_DESCR_UNKNOWN);
m_szFilterApplied.LoadString(IDS_STATUSBAR_FILTER_APPLIED);
m_szSortedAscendingTemplate.LoadString(IDS_STATUSBAR_SORTEDBY_ASCEND);
m_szSortedDescendingTemplate.LoadString(IDS_STATUSBAR_SORTEDBY_DESCEND);
m_szStoppedServerMsg.LoadString(IDS_STOPPED_SERVER_MSG);
m_szStatusBarErrorFormat.LoadString(IDS_STATUSBAR_ERRORTEMPLATE);
m_szRevokeReason_Unspecified.LoadString(IDS_CRL_REASON_UNSPECIFIED);
m_szRevokeReason_KeyCompromise.LoadString(IDS_CRL_REASON_KEY_COMPROMISE);
m_szRevokeReason_CaCompromise.LoadString(IDS_CRL_REASON_CA_COMPROMISE);
m_szRevokeReason_Affiliation.LoadString(IDS_CRL_REASON_AFFILIATION_CHANGED);
m_szRevokeReason_Superseded.LoadString(IDS_CRL_REASON_SUPERSEDED);
m_szRevokeReason_Cessatation.LoadString(IDS_CRL_REASON_CESSATION_OF_OPERATION);
m_szRevokeReason_CertHold.LoadString(IDS_CRL_REASON_CERTIFICATE_HOLD);
m_szRevokeReason_RemoveFromCRL.LoadString(IDS_CRL_REASON_REMOVE_FROM_CRL);
m_szPeriod_Seconds.LoadString(IDS_PERIOD_SECONDS);
m_szPeriod_Minutes.LoadString(IDS_PERIOD_MINUTES);
m_szPeriod_Hours.LoadString(IDS_PERIOD_HOURS);
m_szPeriod_Days.LoadString(IDS_PERIOD_DAYS);
m_szPeriod_Weeks.LoadString(IDS_PERIOD_WEEKS);
m_szPeriod_Months.LoadString(IDS_PERIOD_MONTHS);
m_szPeriod_Years.LoadString(IDS_PERIOD_YEARS);
m_szYes.LoadString(IDS_YES);
// Load the bitmaps from the dll
m_bmpSvrMgrToolbar1.LoadBitmap(IDB_TOOLBAR_SVRMGR1);
// load view strings to struct members, point to struct members
int i;
// viewResult items
for(i=0; ((viewResultItems[i].item.strName != NULL) && (viewResultItems[i].item.strStatusBarText != NULL)); i++)
{
LoadString(hRsrc, viewResultItems[i].uiString1, viewResultItems[i].szString1, ARRAYSIZE(viewResultItems[i].szString1));
viewResultItems[i].item.strName = viewResultItems[i].szString1;
LoadString(hRsrc, viewResultItems[i].uiString2, viewResultItems[i].szString2, ARRAYSIZE(viewResultItems[i].szString2));
viewResultItems[i].item.strStatusBarText = viewResultItems[i].szString2;
}
// taskResultItemsSingleSel
for(i=0; ((taskResultItemsSingleSel[i].myitem.item.strName != NULL) && (taskResultItemsSingleSel[i].myitem.item.strStatusBarText != NULL)); i++)
{
LoadString(hRsrc, taskResultItemsSingleSel[i].myitem.uiString1, taskResultItemsSingleSel[i].myitem.szString1, ARRAYSIZE(taskResultItemsSingleSel[i].myitem.szString1));
taskResultItemsSingleSel[i].myitem.item.strName = taskResultItemsSingleSel[i].myitem.szString1;
LoadString(hRsrc, taskResultItemsSingleSel[i].myitem.uiString2, taskResultItemsSingleSel[i].myitem.szString2, ARRAYSIZE(taskResultItemsSingleSel[i].myitem.szString2));
taskResultItemsSingleSel[i].myitem.item.strStatusBarText = taskResultItemsSingleSel[i].myitem.szString2;
}
// task start/stop
for(i=0; ((taskStartStop[i].item.strName != NULL) && (taskStartStop[i].item.strStatusBarText != NULL)); i++)
{
LoadString(hRsrc, taskStartStop[i].uiString1, taskStartStop[i].szString1, ARRAYSIZE(taskStartStop[i].szString1));
taskStartStop[i].item.strName = taskStartStop[i].szString1;
LoadString(hRsrc, taskStartStop[i].uiString2, taskStartStop[i].szString2, ARRAYSIZE(taskStartStop[i].szString2));
taskStartStop[i].item.strStatusBarText = taskStartStop[i].szString2;
}
// taskitems
for(i=0; ((taskItems[i].myitem.item.strName != NULL) && (taskItems[i].myitem.item.strStatusBarText != NULL)); i++)
{
LoadString(hRsrc, taskItems[i].myitem.uiString1, taskItems[i].myitem.szString1, ARRAYSIZE(taskItems[i].myitem.szString1));
taskItems[i].myitem.item.strName = taskItems[i].myitem.szString1;
LoadString(hRsrc, taskItems[i].myitem.uiString2, taskItems[i].myitem.szString2, ARRAYSIZE(taskItems[i].myitem.szString2));
taskItems[i].myitem.item.strStatusBarText = taskItems[i].myitem.szString2;
}
// topitems
for(i=0; ((topItems[i].myitem.item.strName != NULL) && (topItems[i].myitem.item.strStatusBarText != NULL)); i++)
{
LoadString(hRsrc, topItems[i].myitem.uiString1, topItems[i].myitem.szString1, ARRAYSIZE(topItems[i].myitem.szString1));
topItems[i].myitem.item.strName = topItems[i].myitem.szString1;
LoadString(hRsrc, topItems[i].myitem.uiString2, topItems[i].myitem.szString2, ARRAYSIZE(topItems[i].myitem.szString2));
topItems[i].myitem.item.strStatusBarText = topItems[i].myitem.szString2;
}
for (i=0; ((SvrMgrToolbar1Buttons[i].item.lpButtonText != NULL) && (SvrMgrToolbar1Buttons[i].item.lpTooltipText != NULL)); i++)
{
LoadString(hRsrc, SvrMgrToolbar1Buttons[i].uiString1, SvrMgrToolbar1Buttons[i].szString1, ARRAYSIZE(SvrMgrToolbar1Buttons[i].szString1));
SvrMgrToolbar1Buttons[i].item.lpButtonText = SvrMgrToolbar1Buttons[i].szString1;
LoadString(hRsrc, SvrMgrToolbar1Buttons[i].uiString2, SvrMgrToolbar1Buttons[i].szString2, ARRAYSIZE(SvrMgrToolbar1Buttons[i].szString2));
SvrMgrToolbar1Buttons[i].item.lpTooltipText = SvrMgrToolbar1Buttons[i].szString2;
}
// load replacement tokens
for (i=0; i<DISPLAYSTRINGS_TOKEN_COUNT; i++)
{
g_displayStrings[i].pcstrExpansionString = new CString;
if (g_displayStrings[i].pcstrExpansionString != NULL)
g_displayStrings[i].pcstrExpansionString->LoadString(g_displayStrings[i].uTokenID);
g_displayStrings[i].pcstrExpansionStringDescr = new CString;
if (g_displayStrings[i].pcstrExpansionStringDescr != NULL)
g_displayStrings[i].pcstrExpansionStringDescr->LoadString(g_displayStrings[i].uTokenDescrID);
}
m_fLoaded = TRUE;
}
return m_fLoaded;
}
CLocalizedResources::~CLocalizedResources()
{
m_fLoaded = FALSE;
for (int i=0; i<DISPLAYSTRINGS_TOKEN_COUNT; i++)
{
if (g_displayStrings[i].pcstrExpansionString)
delete g_displayStrings[i].pcstrExpansionString;
if (g_displayStrings[i].pcstrExpansionStringDescr)
delete g_displayStrings[i].pcstrExpansionStringDescr;
}
}
HRESULT ReadOfSize(IStream* pStm, void* pbData, ULONG cbData)
{
HRESULT hr;
ULONG nBytesRead;
hr = pStm->Read(pbData, cbData, &nBytesRead);
if ((hr == S_OK) && (nBytesRead != cbData))
hr = HRESULT_FROM_WIN32(ERROR_HANDLE_EOF);
return hr;
}
HRESULT WriteOfSize(IStream* pStm, void* pbData, ULONG cbData)
{
HRESULT hr;
ULONG nBytesWritten;
hr = pStm->Write(pbData, cbData, &nBytesWritten);
if ((hr == S_OK) && (nBytesWritten != cbData))
hr = HRESULT_FROM_WIN32(ERROR_HANDLE_DISK_FULL);
return hr;
}
HRESULT
myOIDToName(
IN WCHAR const *pwszObjId,
OUT LPWSTR* pszName)
{
HRESULT hr = S_OK;
WCHAR const *pwszName1 = L"";
WCHAR const *pwszName2;
WCHAR *pwszT = NULL;
WCHAR rgwchName[64];
if (pszName == NULL)
{
hr = E_POINTER;
_JumpError(hr, error, "pszName NULL");
}
pwszT = (LPWSTR) LocalAlloc(LMEM_FIXED, (1 + 1 + wcslen(pwszObjId)) * sizeof(WCHAR));
if (NULL == pwszT)
{
hr = E_OUTOFMEMORY;
_JumpError(hr, error, "no memory for skip counts array");
}
wcscpy(&pwszT[1], pwszObjId);
*pwszT = L'+';
pwszName1 = myGetOIDName(pwszT); // Group OID lookup
*pwszT = L'-';
pwszName2 = myGetOIDName(pwszT); // Generic OID lookup
if (0 == mylstrcmpiL(pwszName1, pwszName2))
{
pwszName2 = L""; // display only one if they're the same
}
if (L'\0' == *pwszName1)
{
pwszName1 = pwszName2;
pwszName2 = L"";
}
if (L'\0' != *pwszName2 &&
ARRAYSIZE(rgwchName) > wcslen(pwszName1) + wcslen(pwszName2) + 3)
{
wcscpy(rgwchName, pwszName1);
wcscat(rgwchName, L" " wszLPAREN);
wcscat(rgwchName, pwszName2);
wcscat(rgwchName, wszRPAREN);
pwszName1 = rgwchName;
}
*pszName = (LPWSTR)LocalAlloc(LMEM_FIXED, (wcslen(pwszName1)+1)*sizeof(WCHAR));
if (NULL == *pszName)
{
hr = E_OUTOFMEMORY;
_JumpError(hr, error, "pszName");
}
wcscpy(*pszName, pwszName1);
error:
if (NULL != pwszT)
{
LocalFree(pwszT);
}
return hr;
}
#include "csdisp.h"
HRESULT
myDumpFormattedObject(
IN WCHAR const *pwszObjId,
IN BYTE const *pbObject,
IN DWORD cbObject,
OUT LPWSTR* ppwszFormatted)
{
HRESULT hr = S_OK;
char * pszObjId = NULL;
DWORD cbFormatted;
if (ppwszFormatted == NULL)
{
hr = E_POINTER;
_JumpError(hr, error, "NULL param");
}
if (!ConvertWszToSz(&pszObjId, pwszObjId, -1))
{
hr = E_OUTOFMEMORY;
_JumpError(hr, error, "ConvertWszToSz");
}
// format the object using the installed formatting function
if (!CryptFormatObject(
X509_ASN_ENCODING,
0,
CRYPT_FORMAT_STR_MULTI_LINE | CRYPT_FORMAT_STR_NO_HEX,
NULL,
pszObjId,
pbObject,
cbObject,
NULL,
&cbFormatted))
{
hr = myHLastError();
_JumpIfError(hr, error, "CryptFormatObject");
}
*ppwszFormatted = (WCHAR *) LocalAlloc(LMEM_FIXED, cbFormatted);
if (NULL == *ppwszFormatted)
{
hr = E_OUTOFMEMORY;
_JumpError(hr, error, "LocalAlloc");
}
if (!CryptFormatObject(
X509_ASN_ENCODING,
0,
CRYPT_FORMAT_STR_MULTI_LINE | CRYPT_FORMAT_STR_NO_HEX,
NULL,
pszObjId,
pbObject,
cbObject,
*ppwszFormatted,
&cbFormatted))
{
hr = myHLastError();
_JumpError(hr, error, "CryptFormatObject");
}
/*
if (g_fVerbose)
{
if (0 == strcmp(szOID_SUBJECT_ALT_NAME, pszObjId) ||
0 == strcmp(szOID_SUBJECT_ALT_NAME2, pszObjId) ||
0 == strcmp(szOID_ISSUER_ALT_NAME, pszObjId) ||
0 == strcmp(szOID_ISSUER_ALT_NAME2, pszObjId))
{
DumpAltName(pbObject, cbObject);
}
}
*/
error:
if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr || CRYPT_E_ASN1_BADTAG == hr)
{
// fix up nonfatal errors
CString cstrUnknown;
cstrUnknown.LoadString(IDS_UNKNOWN_EXTENSION);
hr = myDupString((LPCWSTR)cstrUnknown, ppwszFormatted);
_PrintIfError(hr, "myDupString failure");
}
if (pszObjId)
LocalFree(pszObjId);
return hr;
}
void
InplaceStripControlChars(WCHAR* szString)
{
// remove \r and \n AND \t formatting through end-of-string
if (NULL != szString)
{
while (*szString != L'\0')
{
switch(*szString)
{
case L'\r':
case L'\n':
case L'\t':
*szString = L' ';
break;
}
szString++;
}
}
}
HANDLE EnablePrivileges(LPCWSTR ppcwszPrivileges[], ULONG cPrivileges)
{
BOOL fResult = FALSE;
HANDLE hToken = INVALID_HANDLE_VALUE;
HANDLE hOriginalThreadToken = INVALID_HANDLE_VALUE;
PTOKEN_PRIVILEGES ptp;
ULONG nBufferSize;
// Note that TOKEN_PRIVILEGES includes a single LUID_AND_ATTRIBUTES
nBufferSize = sizeof(TOKEN_PRIVILEGES) + (cPrivileges - 1)*sizeof(LUID_AND_ATTRIBUTES);
ptp = (PTOKEN_PRIVILEGES)LocalAlloc(LPTR, nBufferSize);
if (!ptp)
return INVALID_HANDLE_VALUE;
//
// Initialize the Privileges Structure
//
ptp->PrivilegeCount = cPrivileges;
for (ULONG i = 0; i < cPrivileges; i++)
{
fResult = LookupPrivilegeValue(NULL, ppcwszPrivileges[i], &ptp->Privileges[i].Luid);
if (!fResult)
break;
ptp->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED;
}
if(fResult)
{
//
// Open the Token
//
hToken = hOriginalThreadToken = INVALID_HANDLE_VALUE;
fResult = OpenThreadToken(GetCurrentThread(), TOKEN_DUPLICATE, FALSE, &hToken);
if (fResult)
hOriginalThreadToken = hToken; // Remember the thread token
else
fResult = OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE, &hToken);
}
if (fResult)
{
HANDLE hNewToken;
//
// Duplicate that Token
//
fResult = DuplicateTokenEx(hToken,
TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
NULL, // PSECURITY_ATTRIBUTES
SecurityImpersonation, // SECURITY_IMPERSONATION_LEVEL
TokenImpersonation, // TokenType
&hNewToken); // Duplicate token
if (fResult)
{
//
// Add new privileges
//
fResult = AdjustTokenPrivileges(hNewToken, // TokenHandle
FALSE, // DisableAllPrivileges
ptp, // NewState
0, // BufferLength
NULL, // PreviousState
NULL); // ReturnLength
if (fResult)
{
//
// Begin impersonating with the new token
//
fResult = SetThreadToken(NULL, hNewToken);
}
CloseHandle(hNewToken);
}
}
// If something failed, don't return a token
if (!fResult)
hOriginalThreadToken = INVALID_HANDLE_VALUE;
// Close the original token if we aren't returning it
if (hOriginalThreadToken == INVALID_HANDLE_VALUE && hToken != INVALID_HANDLE_VALUE)
CloseHandle(hToken);
// If we succeeded, but there was no original thread token,
// return NULL to indicate we need to do SetThreadToken(NULL, NULL)
// to release privs.
if (fResult && hOriginalThreadToken == INVALID_HANDLE_VALUE)
hOriginalThreadToken = NULL;
LocalFree(ptp);
return hOriginalThreadToken;
}
void ReleasePrivileges(HANDLE hToken)
{
BOOL fResult;
if (INVALID_HANDLE_VALUE != hToken)
{
fResult = SetThreadToken(NULL, hToken);
if (hToken)
CloseHandle(hToken);
}
}
HRESULT
myGetActiveModule(
CertSvrCA *pCA,
IN BOOL fPolicyModule,
IN DWORD Index,
OPTIONAL OUT LPOLESTR *ppwszProgIdModule, // CoTaskMem*
OPTIONAL OUT CLSID *pclsidModule)
{
HRESULT hr;
WCHAR *pwsz;
variant_t var;
hr = pCA->GetConfigEntry(
fPolicyModule?wszREGKEYPOLICYMODULES:wszREGKEYEXITMODULES,
wszREGACTIVE,
&var);
_JumpIfError(hr, error, "GetConfigEntry");
hr = HRESULT_FROM_WIN32(ERROR_MOD_NOT_FOUND);
if(V_VT(&var)==VT_BSTR)
{
pwsz = V_BSTR(&var);
}
else if(V_VT(&var)==(VT_ARRAY|VT_BSTR))
{
SafeArrayEnum<BSTR> saenum(V_ARRAY(&var));
hr = saenum.GetAt(Index, pwsz);
_JumpIfError(hr, error, "GetConfigEntry");
}
else
{
_JumpError(hr, error, "Bad active entry type");
}
if(!pwsz)
{
_JumpError(hr, error, "empty entry");
}
if (NULL != pclsidModule)
{
hr = CLSIDFromProgID(pwsz, pclsidModule);
_JumpIfError(hr, error, "CLSIDFromProgID");
}
if (NULL != ppwszProgIdModule)
{
*ppwszProgIdModule = (LPOLESTR) CoTaskMemAlloc(
(wcslen(pwsz) + 1) * sizeof(WCHAR));
if (NULL == *ppwszProgIdModule)
{
hr = E_OUTOFMEMORY;
_JumpError(hr, error, "CoTaskMemAlloc");
}
wcscpy(*ppwszProgIdModule, pwsz);
}
hr = S_OK; // not reset after ERROR_MOD_NOT_FOUND in all cases
error:
return(hr);
}
HRESULT FindComputerObjectSid(
LPCWSTR pcwszCAComputerDNSName,
PSID &pSid)
{
HRESULT hr = S_OK;
ADS_SEARCHPREF_INFO asi[1];
IDirectorySearch *pSearch = NULL;
LPWSTR pwszAttr = L"objectSid";
ADS_SEARCH_HANDLE hADS = NULL;
static LPCWSTR pwszgc = L"GC://";
static LPCWSTR pwszformat = L"(&(objectClass=computer)(servicePrincipalName=host/%ws))";
LPWSTR pwszSearchFilter = NULL;
LPWSTR pwszGC = NULL;
DWORD dwres;
PDOMAIN_CONTROLLER_INFO pdci = NULL;
ADS_SEARCH_COLUMN col;
dwres = DsGetDcName(
NULL,
NULL,
NULL,
NULL,
DS_RETURN_DNS_NAME|DS_DIRECTORY_SERVICE_REQUIRED,
&pdci);
if(NO_ERROR != dwres)
{
hr = myHError(dwres);
_JumpIfError(hr, error, "DsGetDcName");
}
pwszGC = (LPWSTR)LocalAlloc(LMEM_FIXED,
sizeof(WCHAR)*(wcslen(pwszgc)+wcslen(pdci->DnsForestName)+1));
_JumpIfAllocFailed(pwszGC, error);
wcscpy(pwszGC, pwszgc);
wcscat(pwszGC, pdci->DnsForestName);
hr = ADsGetObject(pwszGC, IID_IDirectorySearch, (void**)&pSearch);
_JumpIfError(hr, error, "ADsGetObject(GC:)");
asi[0].dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE;
asi[0].vValue.dwType = ADSTYPE_INTEGER;
asi[0].vValue.Integer = ADS_SCOPE_SUBTREE;
hr = pSearch->SetSearchPreference(asi, 1);
_JumpIfError(hr, error, "SetSearchPreference");
pwszSearchFilter = (LPWSTR)LocalAlloc(LMEM_FIXED,
sizeof(WCHAR)*(wcslen(pwszformat)+wcslen(pcwszCAComputerDNSName)+1));
wsprintf(pwszSearchFilter, pwszformat, pcwszCAComputerDNSName);
hr = pSearch->ExecuteSearch(
pwszSearchFilter,
&pwszAttr,
1,
&hADS);
_JumpIfErrorStr(hr, error, "ExecuteSearch", pwszSearchFilter);
hr = pSearch->GetFirstRow(hADS);
_JumpIfError(hr, error, "GetFirstRow");
hr = pSearch->GetColumn(hADS, pwszAttr, &col);
_JumpIfErrorStr(hr, error, "GetColumn", pwszAttr);
CSASSERT(IsValidSid(col.pADsValues[0].OctetString.lpValue));
CSASSERT(GetLengthSid(col.pADsValues[0].OctetString.lpValue)==
col.pADsValues[0].OctetString.dwLength);
pSid = LocalAlloc(LMEM_FIXED, col.pADsValues[0].OctetString.dwLength);
_JumpIfAllocFailed(pSid, error);
CopySid(col.pADsValues[0].OctetString.dwLength,
pSid,
col.pADsValues[0].OctetString.lpValue);
error:
if(pdci)
NetApiBufferFree(pdci);
if(pSearch)
{
pSearch->FreeColumn(&col);
if(hADS)
pSearch->CloseSearchHandle(hADS);
pSearch->Release();
}
LOCAL_FREE(pwszSearchFilter);
LOCAL_FREE(pwszGC);
return hr;
}
HRESULT IsUserDomainAdministrator(BOOL* pfIsAdministrator)
{
HRESULT hr = S_OK;
*pfIsAdministrator = FALSE;
PSID psidAdministrators;
SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY;
BOOL bResult = AllocateAndInitializeSid (&siaNtAuthority, 2,
SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS,
0, 0, 0, 0, 0, 0, &psidAdministrators);
if ( bResult )
{
bResult = CheckTokenMembership (0, psidAdministrators,
pfIsAdministrator);
ASSERT (bResult);
if ( !bResult )
{
hr = myHLastError ();
_PrintError(hr, "CheckTokenMembership");
}
FreeSid (psidAdministrators);
}
else
{
hr = myHLastError ();
_PrintError(hr, "AllocateAndInitializeSid");
}
return hr;
}
BOOL RestartService(HWND hWnd, CertSvrMachine* pMachine)
{
// notify user we can't apply immediately
CString cstrText;
cstrText.LoadString(IDS_CONFIRM_SERVICE_RESTART);
if (IDYES == ::MessageBox(hWnd, (LPCWSTR)cstrText, (LPCWSTR)g_pResources->m_DescrStr_CA, MB_YESNO | MB_ICONWARNING ))
{
DWORD dwErr;
// stop the service
if (pMachine->IsCertSvrServiceRunning())
pMachine->CertSvrStartStopService(hWnd, FALSE);
// start the serviec
dwErr = pMachine->CertSvrStartStopService(hWnd, TRUE);
if (S_OK != dwErr)
DisplayGenericCertSrvError(hWnd, dwErr);
return TRUE;
}
return FALSE; // didn't restart
}
static BOOL s_fLogOpened = FALSE;
VOID
LogOpen(
IN BOOL fForceOpen)
{
BOOL fOpenLog;
DbgPrintfInit("+"); // reinitialize debug print mask first
fOpenLog = DbgIsSSActive(DBG_SS_OPENLOG);
if (fOpenLog || fForceOpen)
{
if (!s_fLogOpened)
{
csiLogOpen("+certmmc.log");
s_fLogOpened = TRUE;
CSILOGFILEVERSION(0, L"certmmc.dll", szCSVER_STR);
}
}
}
VOID
LogClose()
{
if (s_fLogOpened)
{
csiLogClose();
s_fLogOpened = FALSE;
}
}